[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: Nick Cheng <nick.cheng@areca.com.tw>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
Nick Cheng 2007-09-13 17:26:40 +08:00 committed by James Bottomley
parent bfd129445f
commit 1a4f550a09
6 changed files with 1575 additions and 995 deletions

View file

@ -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
**************************************************************************

View file

@ -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

View file

@ -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);

View file

@ -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);
}

File diff suppressed because it is too large Load diff

View file

@ -2057,6 +2057,9 @@
#define PCI_DEVICE_ID_ARECA_1130 0x1130
#define PCI_DEVICE_ID_ARECA_1160 0x1160
#define PCI_DEVICE_ID_ARECA_1170 0x1170
#define PCI_DEVICE_ID_ARECA_1200 0x1200
#define PCI_DEVICE_ID_ARECA_1201 0x1201
#define PCI_DEVICE_ID_ARECA_1202 0x1202
#define PCI_DEVICE_ID_ARECA_1210 0x1210
#define PCI_DEVICE_ID_ARECA_1220 0x1220
#define PCI_DEVICE_ID_ARECA_1230 0x1230