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

Commit 1a4f550a authored by Nick Cheng's avatar Nick Cheng Committed by James Bottomley
Browse files

[SCSI] arcmsr: 1.20.00.15: add SATA RAID plus other fixes



Description:
** support ARC1200/1201/1202 SATA RAID adapter, which is named
ACB_ADAPTER_TYPE_B
** modify the arcmsr_pci_slot_reset function
** modify the arcmsr_pci_ers_disconnect_forepart function
** modify the arcmsr_pci_ers_need_reset_forepart function 

Signed-off-by: default avatarNick Cheng <nick.cheng@areca.com.tw>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent bfd12944
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -53,4 +53,19 @@
**						for linux standard list
**						enable usage of pci message signal interrupt
**						follow Randy.Danlup kindness suggestion cleanup this code
** 1.20.00.14   05/02/2007	 Erich Chen & Nick Cheng
**						1.implement PCI-Express error recovery function and AER capability
**						2.implement the selection of ARCMSR_MAX_XFER_SECTORS_B=4096
**				 		if firmware version is newer than 1.42
**						3.modify arcmsr_iop_reset to improve the ability
**						4.modify the ISR, arcmsr_interrupt routine,to prevent the
**						inconsistency with sg_mod driver if application	directly calls
**						the arcmsr driver w/o passing through scsi mid layer
**						specially thanks to Yanmin Zhang's openhanded help about AER
** 1.20.00.15   08/30/2007	 Erich Chen & Nick Cheng
**						1. support ARC1200/1201/1202 SATA RAID adapter, which is named
**						ACB_ADAPTER_TYPE_B
**						2. modify the arcmsr_pci_slot_reset function
**						3. modify the arcmsr_pci_ers_disconnect_forepart function
**						4. modify the arcmsr_pci_ers_need_reset_forepart function
**************************************************************************
+18 −5
Original line number Diff line number Diff line
@@ -543,19 +543,32 @@ config SCSI_IN2000
	  module will be called in2000.

config SCSI_ARCMSR
	tristate "ARECA ARC11X0[PCI-X]/ARC12X0[PCI-EXPRESS] SATA-RAID support"
	tristate "ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID Host Adapter"
	depends on PCI && SCSI
	help
	  This driver supports all of ARECA's SATA RAID controller cards.
	  This driver supports all of ARECA's SATA/SAS RAID controller cards.
	  This is an ARECA-maintained driver by Erich Chen.
	  If you have any problems, please mail to: < erich@areca.com.tw >
	  If you have any problems, please mail to: <erich@areca.com.tw>.
	  Areca supports Linux RAID config tools.

	  < http://www.areca.com.tw >
	  Please link <http://www.areca.com.tw>

	  To compile this driver as a module, choose M here: the
	  module will be called arcmsr (modprobe arcmsr).

config SCSI_ARCMSR_AER
	bool "Enable PCI Error Recovery Capability in Areca Driver(ARCMSR)"
	depends on SCSI_ARCMSR && PCIEAER
	default n
	help
	  The advanced error reporting(AER) capability is "NOT" provided by
	  ARC1200/1201/1202 SATA RAID controllers cards.
	  If your card is one of ARC1200/1201/1202, please use the default setting, n.
	  If your card is other models, you could pick it
	  on condition that the kernel version is greater than 2.6.19.
	  This function is maintained driver by Nick Cheng. If you have any
	  problems or suggestion, you are welcome to contact with <nick.cheng@areca.com.tw>.
	  To enable this function, choose Y here.

source "drivers/scsi/megaraid/Kconfig.megaraid"

config SCSI_HPTIOP
+142 −50
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@
** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved.
**
**     Web site: www.areca.com.tw
**       E-mail: erich@areca.com.tw
**       E-mail: support@areca.com.tw
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License version 2 as
@@ -45,10 +45,10 @@
#include <linux/interrupt.h>

struct class_device_attribute;

/*The limit of outstanding scsi command that firmware can handle*/
#define ARCMSR_MAX_OUTSTANDING_CMD						256
#define ARCMSR_MAX_FREECCB_NUM							288
#define ARCMSR_DRIVER_VERSION				"Driver Version 1.20.00.14"
#define ARCMSR_MAX_FREECCB_NUM							320
#define ARCMSR_DRIVER_VERSION		     "Driver Version 1.20.00.15 2007/08/30"
#define ARCMSR_SCSI_INITIATOR_ID						255
#define ARCMSR_MAX_XFER_SECTORS							512
#define ARCMSR_MAX_XFER_SECTORS_B						4096
@@ -57,7 +57,14 @@ struct class_device_attribute;
#define ARCMSR_MAX_CMD_PERLUN		                 ARCMSR_MAX_OUTSTANDING_CMD
#define ARCMSR_MAX_QBUFFER							4096
#define ARCMSR_MAX_SG_ENTRIES							38

#define ARCMSR_MAX_HBB_POSTQUEUE						264
/*
**********************************************************************************
**
**********************************************************************************
*/
#define ARC_SUCCESS                                                       0
#define ARC_FAILURE                                                       1
/*
*******************************************************************************
**        split 64bits dma addressing
@@ -163,7 +170,7 @@ struct QBUFFER
};
/*
*******************************************************************************
**      FIRMWARE INFO
**      FIRMWARE INFO for Intel IOP R 80331 processor (Type A)
*******************************************************************************
*/
struct FIRMWARE_INFO
@@ -203,6 +210,60 @@ struct FIRMWARE_INFO
#define ARCMSR_CCBREPLY_FLAG_ERROR                    0x10000000
/* outbound firmware ok */
#define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK             0x80000000

/*
************************************************************************
**                SPEC. for Areca Type B adapter
************************************************************************
*/
/* ARECA HBB COMMAND for its FIRMWARE */
/* window of "instruction flags" from driver to iop */
#define ARCMSR_DRV2IOP_DOORBELL                       0x00020400
#define ARCMSR_DRV2IOP_DOORBELL_MASK                  0x00020404
/* window of "instruction flags" from iop to driver */
#define ARCMSR_IOP2DRV_DOORBELL                       0x00020408
#define ARCMSR_IOP2DRV_DOORBELL_MASK                  0x0002040C
/* ARECA FLAG LANGUAGE */
/* ioctl transfer */
#define ARCMSR_IOP2DRV_DATA_WRITE_OK                  0x00000001
/* ioctl transfer */
#define ARCMSR_IOP2DRV_DATA_READ_OK                   0x00000002
#define ARCMSR_IOP2DRV_CDB_DONE                       0x00000004
#define ARCMSR_IOP2DRV_MESSAGE_CMD_DONE               0x00000008

#define ARCMSR_DOORBELL_HANDLE_INT		      0x0000000F
#define ARCMSR_DOORBELL_INT_CLEAR_PATTERN   	      0xFF00FFF0
#define ARCMSR_MESSAGE_INT_CLEAR_PATTERN	      0xFF00FFF7
/* (ARCMSR_INBOUND_MESG0_GET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
#define ARCMSR_MESSAGE_GET_CONFIG		      0x00010008
/* (ARCMSR_INBOUND_MESG0_SET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
#define ARCMSR_MESSAGE_SET_CONFIG		      0x00020008
/* (ARCMSR_INBOUND_MESG0_ABORT_CMD<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
#define ARCMSR_MESSAGE_ABORT_CMD		      0x00030008
/* (ARCMSR_INBOUND_MESG0_STOP_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
#define ARCMSR_MESSAGE_STOP_BGRB		      0x00040008
/* (ARCMSR_INBOUND_MESG0_FLUSH_CACHE<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
#define ARCMSR_MESSAGE_FLUSH_CACHE                    0x00050008
/* (ARCMSR_INBOUND_MESG0_START_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
#define ARCMSR_MESSAGE_START_BGRB		      0x00060008
#define ARCMSR_MESSAGE_START_DRIVER_MODE	      0x000E0008
#define ARCMSR_MESSAGE_SET_POST_WINDOW		      0x000F0008
/* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */
#define ARCMSR_MESSAGE_FIRMWARE_OK		      0x80000000
/* ioctl transfer */
#define ARCMSR_DRV2IOP_DATA_WRITE_OK                  0x00000001
/* ioctl transfer */
#define ARCMSR_DRV2IOP_DATA_READ_OK                   0x00000002
#define ARCMSR_DRV2IOP_CDB_POSTED                     0x00000004
#define ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED             0x00000008

/* data tunnel buffer between user space program and its firmware */
/* user space data to iop 128bytes */
#define ARCMSR_IOCTL_WBUFFER			      0x0000fe00
/* iop data to user space 128bytes */
#define ARCMSR_IOCTL_RBUFFER			      0x0000ff00
/* iop message_rwbuffer for message command */
#define ARCMSR_MSGCODE_RWBUFFER			      0x0000fa00
/*
*******************************************************************************
**    ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504)
@@ -214,7 +275,6 @@ struct ARCMSR_CDB
	uint8_t							TargetID;
	uint8_t							LUN;
	uint8_t							Function;

	uint8_t							CdbLength;
	uint8_t							sgcount;
	uint8_t							Flags;
@@ -224,20 +284,18 @@ struct ARCMSR_CDB
#define ARCMSR_CDB_FLAG_SIMPLEQ            0x00
#define ARCMSR_CDB_FLAG_HEADQ              0x08
#define ARCMSR_CDB_FLAG_ORDEREDQ           0x10
	uint8_t							Reserved1;

	uint8_t							Reserved1;
	uint32_t						Context;
	uint32_t						DataLength;

	uint8_t							Cdb[16];

	uint8_t							DeviceStatus;
#define ARCMSR_DEV_CHECK_CONDITION	    0x02
#define ARCMSR_DEV_SELECT_TIMEOUT	    0xF0
#define ARCMSR_DEV_ABORTED		    0xF1
#define ARCMSR_DEV_INIT_FAIL		    0xF2
	uint8_t							SenseData[15];

	uint8_t							SenseData[15];
	union
	{
		struct SG32ENTRY                sg32entry[ARCMSR_MAX_SG_ENTRIES];
@@ -246,10 +304,10 @@ struct ARCMSR_CDB
};
/*
*******************************************************************************
**     Messaging Unit (MU) of the Intel R 80331 I/O processor (80331)
**     Messaging Unit (MU) of the Intel R 80331 I/O processor(Type A) and Type B processor
*******************************************************************************
*/
struct MessageUnit
struct MessageUnit_A
{
	uint32_t	resrved0[4];			/*0000 000F*/
	uint32_t	inbound_msgaddr0;		/*0010 0013*/
@@ -274,6 +332,30 @@ struct MessageUnit
	uint32_t	message_rbuffer[32];		/*0F00 0F7F  32*/
	uint32_t	reserved6[32];			/*0F80 0FFF  32*/
};

struct MessageUnit_B
{
	uint32_t	post_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE];
	uint32_t	done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE];
	uint32_t	postq_index;
	uint32_t	doneq_index;
	uint32_t	*drv2iop_doorbell_reg;
	uint32_t	*drv2iop_doorbell_mask_reg;
	uint32_t	*iop2drv_doorbell_reg;
	uint32_t	*iop2drv_doorbell_mask_reg;
	uint32_t	*msgcode_rwbuffer_reg;
	uint32_t	*ioctl_wbuffer_reg;
	uint32_t	*ioctl_rbuffer_reg;
};

struct MessageUnit
{
	union
	{
		struct MessageUnit_A	pmu_A;
		struct MessageUnit_B	pmu_B;
	} u;
};
/*
*******************************************************************************
**                 Adapter Control Block
@@ -281,13 +363,18 @@ struct MessageUnit
*/
struct AdapterControlBlock
{
	uint32_t  adapter_type;                /* adapter A,B..... */
	#define ACB_ADAPTER_TYPE_A            0x00000001	/* hba I IOP */
	#define ACB_ADAPTER_TYPE_B            0x00000002	/* hbb M IOP */
	#define ACB_ADAPTER_TYPE_C            0x00000004	/* hbc P IOP */
	#define ACB_ADAPTER_TYPE_D            0x00000008	/* hbd A IOP */
	struct pci_dev *		pdev;
	struct Scsi_Host *		host;
	unsigned long			vir2phy_offset;
	/* Offset is used in making arc cdb physical to virtual calculations */
	uint32_t			outbound_int_enable;

	struct MessageUnit __iomem *		pmu;
	struct MessageUnit *			pmu;
	/* message unit ATU inbound base address0 */

	uint32_t			acb_flags;
@@ -311,7 +398,10 @@ struct AdapterControlBlock
	/* used for memory free */
	struct list_head		ccb_free_list;
	/* head of free ccb list */

	atomic_t			ccboutstandingcount;
	/*The present outstanding command number that in the IOP that
					waiting for being handled by FW*/

	void *				dma_coherent;
	/* dma_coherent used for memory free */
@@ -466,7 +556,9 @@ struct SENSE_DATA
#define     ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE               0x01
#define     ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE                    0x1F

extern void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb);
extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *);
extern void arcmsr_iop_message_read(struct AdapterControlBlock *);
extern struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *);
extern struct class_device_attribute *arcmsr_host_attrs[];
extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb);
extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *);
void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb);
+24 −40
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@
** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved
**
**     Web site: www.areca.com.tw
**       E-mail: erich@areca.com.tw
**       E-mail: support@areca.com.tw
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License version 2 as
@@ -49,6 +49,7 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/pci.h>

#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
@@ -58,15 +59,11 @@

struct class_device_attribute *arcmsr_host_attrs[];

static ssize_t
arcmsr_sysfs_iop_message_read(struct kobject *kobj,
			      struct bin_attribute *bin_attr,
			      char *buf, loff_t off, size_t count)
static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
	struct class_device *cdev = container_of(kobj,struct class_device,kobj);
	struct Scsi_Host *host = class_to_shost(cdev);
	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
	struct MessageUnit __iomem *reg = acb->pmu;
	uint8_t *pQbuffer,*ptmpQbuffer;
	int32_t allxfer_len = 0;

@@ -85,12 +82,13 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj,
		allxfer_len++;
	}
	if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
		struct QBUFFER __iomem * prbuffer = (struct QBUFFER __iomem *)
					&reg->message_rbuffer;
		uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data;
		struct QBUFFER *prbuffer;
		uint8_t *iop_data;
		int32_t iop_len;

		acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
		prbuffer = arcmsr_get_iop_rqbuffer(acb);
		iop_data = (uint8_t *)prbuffer->data;
		iop_len = readl(&prbuffer->data_len);
		while (iop_len > 0) {
			acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data);
@@ -99,16 +97,12 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj,
			iop_data++;
			iop_len--;
		}
		writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK,
				&reg->inbound_doorbell);
		arcmsr_iop_message_read(acb);
	}
	return (allxfer_len);
}

static ssize_t
arcmsr_sysfs_iop_message_write(struct kobject *kobj,
			       struct bin_attribute *bin_attr,
			       char *buf, loff_t off, size_t count)
static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
	struct class_device *cdev = container_of(kobj,struct class_device,kobj);
	struct Scsi_Host *host = class_to_shost(cdev);
@@ -126,7 +120,7 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj,
	wqbuf_lastindex = acb->wqbuf_lastindex;
	wqbuf_firstindex = acb->wqbuf_firstindex;
	if (wqbuf_lastindex != wqbuf_firstindex) {
		arcmsr_post_Qbuffer(acb);
		arcmsr_post_ioctldata2iop(acb);
		return 0;	/*need retry*/
	} else {
		my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1)
@@ -144,7 +138,7 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj,
			if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
				acb->acb_flags &=
					~ACB_F_MESSAGE_WQBUFFER_CLEARED;
				arcmsr_post_Qbuffer(acb);
				arcmsr_post_ioctldata2iop(acb);
			}
			return count;
		} else {
@@ -153,15 +147,11 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj,
	}
}

static ssize_t
arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
			       struct bin_attribute *bin_attr,
			       char *buf, loff_t off, size_t count)
static ssize_t arcmsr_sysfs_iop_message_clear(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
	struct class_device *cdev = container_of(kobj,struct class_device,kobj);
	struct Scsi_Host *host = class_to_shost(cdev);
	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
	struct MessageUnit __iomem *reg = acb->pmu;
	uint8_t *pQbuffer;

	if (!capable(CAP_SYS_ADMIN))
@@ -169,8 +159,7 @@ arcmsr_sysfs_iop_message_clear(struct kobject *kobj,

	if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
		acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
		writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK
				, &reg->inbound_doorbell);
		arcmsr_iop_message_read(acb);
	}
	acb->acb_flags |=
		(ACB_F_MESSAGE_WQBUFFER_CLEARED
@@ -191,6 +180,7 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = {
	.attr = {
		.name = "mu_read",
		.mode = S_IRUSR ,
		.owner = THIS_MODULE,
	},
	.size = 1032,
	.read = arcmsr_sysfs_iop_message_read,
@@ -200,6 +190,7 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = {
	.attr = {
		.name = "mu_write",
		.mode = S_IWUSR,
		.owner = THIS_MODULE,
	},
	.size = 1032,
	.write = arcmsr_sysfs_iop_message_write,
@@ -209,6 +200,7 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = {
	.attr = {
		.name = "mu_clear",
		.mode = S_IWUSR,
		.owner = THIS_MODULE,
	},
	.size = 1,
	.write = arcmsr_sysfs_iop_message_clear,
@@ -219,31 +211,26 @@ int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb)
	struct Scsi_Host *host = acb->host;
	int error;

	error = sysfs_create_bin_file(&host->shost_classdev.kobj,
				&arcmsr_sysfs_message_read_attr);
	error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
	if (error) {
		printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n");
		goto error_bin_file_message_read;
	}
	error = sysfs_create_bin_file(&host->shost_classdev.kobj,
				&arcmsr_sysfs_message_write_attr);
	error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
	if (error) {
		printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n");
		goto error_bin_file_message_write;
	}
	error = sysfs_create_bin_file(&host->shost_classdev.kobj,
				&arcmsr_sysfs_message_clear_attr);
	error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr);
	if (error) {
		printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n");
		goto error_bin_file_message_clear;
	}
	return 0;
error_bin_file_message_clear:
	sysfs_remove_bin_file(&host->shost_classdev.kobj,
				&arcmsr_sysfs_message_write_attr);
	sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
error_bin_file_message_write:
	sysfs_remove_bin_file(&host->shost_classdev.kobj,
				&arcmsr_sysfs_message_read_attr);
	sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
error_bin_file_message_read:
	return error;
}
@@ -252,12 +239,9 @@ void
arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) {
	struct Scsi_Host *host = acb->host;

	sysfs_remove_bin_file(&host->shost_classdev.kobj,
				&arcmsr_sysfs_message_clear_attr);
	sysfs_remove_bin_file(&host->shost_classdev.kobj,
				&arcmsr_sysfs_message_write_attr);
	sysfs_remove_bin_file(&host->shost_classdev.kobj,
				&arcmsr_sysfs_message_read_attr);
	sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr);
	sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
	sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
}


+1368 −895

File changed.

Preview size limit exceeded, changes collapsed.

Loading