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

[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
...@@ -53,4 +53,19 @@ ...@@ -53,4 +53,19 @@
** for linux standard list ** for linux standard list
** enable usage of pci message signal interrupt ** enable usage of pci message signal interrupt
** follow Randy.Danlup kindness suggestion cleanup this code ** 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
************************************************************************** **************************************************************************
...@@ -543,19 +543,32 @@ config SCSI_IN2000 ...@@ -543,19 +543,32 @@ config SCSI_IN2000
module will be called in2000. module will be called in2000.
config SCSI_ARCMSR 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 depends on PCI && SCSI
help 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. 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. Areca supports Linux RAID config tools.
Please link <http://www.areca.com.tw>
< http://www.areca.com.tw >
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called arcmsr (modprobe arcmsr). 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" source "drivers/scsi/megaraid/Kconfig.megaraid"
config SCSI_HPTIOP config SCSI_HPTIOP
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved
** **
** Web site: www.areca.com.tw ** 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 ** 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 ** it under the terms of the GNU General Public License version 2 as
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/pci.h>
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h> #include <scsi/scsi_device.h>
...@@ -58,15 +59,11 @@ ...@@ -58,15 +59,11 @@
struct class_device_attribute *arcmsr_host_attrs[]; struct class_device_attribute *arcmsr_host_attrs[];
static ssize_t static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
arcmsr_sysfs_iop_message_read(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{ {
struct class_device *cdev = container_of(kobj,struct class_device,kobj); struct class_device *cdev = container_of(kobj,struct class_device,kobj);
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
struct MessageUnit __iomem *reg = acb->pmu;
uint8_t *pQbuffer,*ptmpQbuffer; uint8_t *pQbuffer,*ptmpQbuffer;
int32_t allxfer_len = 0; int32_t allxfer_len = 0;
...@@ -85,12 +82,13 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj, ...@@ -85,12 +82,13 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj,
allxfer_len++; allxfer_len++;
} }
if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
struct QBUFFER __iomem * prbuffer = (struct QBUFFER __iomem *) struct QBUFFER *prbuffer;
&reg->message_rbuffer; uint8_t *iop_data;
uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data;
int32_t iop_len; int32_t iop_len;
acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 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); iop_len = readl(&prbuffer->data_len);
while (iop_len > 0) { while (iop_len > 0) {
acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data);
...@@ -99,16 +97,12 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj, ...@@ -99,16 +97,12 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj,
iop_data++; iop_data++;
iop_len--; iop_len--;
} }
writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, arcmsr_iop_message_read(acb);
&reg->inbound_doorbell);
} }
return (allxfer_len); return (allxfer_len);
} }
static ssize_t static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
arcmsr_sysfs_iop_message_write(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{ {
struct class_device *cdev = container_of(kobj,struct class_device,kobj); struct class_device *cdev = container_of(kobj,struct class_device,kobj);
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
...@@ -126,7 +120,7 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, ...@@ -126,7 +120,7 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj,
wqbuf_lastindex = acb->wqbuf_lastindex; wqbuf_lastindex = acb->wqbuf_lastindex;
wqbuf_firstindex = acb->wqbuf_firstindex; wqbuf_firstindex = acb->wqbuf_firstindex;
if (wqbuf_lastindex != wqbuf_firstindex) { if (wqbuf_lastindex != wqbuf_firstindex) {
arcmsr_post_Qbuffer(acb); arcmsr_post_ioctldata2iop(acb);
return 0; /*need retry*/ return 0; /*need retry*/
} else { } else {
my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1)
...@@ -144,7 +138,7 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, ...@@ -144,7 +138,7 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj,
if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
acb->acb_flags &= acb->acb_flags &=
~ACB_F_MESSAGE_WQBUFFER_CLEARED; ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
arcmsr_post_Qbuffer(acb); arcmsr_post_ioctldata2iop(acb);
} }
return count; return count;
} else { } else {
...@@ -153,15 +147,11 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, ...@@ -153,15 +147,11 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj,
} }
} }
static ssize_t static ssize_t arcmsr_sysfs_iop_message_clear(struct kobject *kobj, char *buf, loff_t off, size_t count)
arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{ {
struct class_device *cdev = container_of(kobj,struct class_device,kobj); struct class_device *cdev = container_of(kobj,struct class_device,kobj);
struct Scsi_Host *host = class_to_shost(cdev); struct Scsi_Host *host = class_to_shost(cdev);
struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;
struct MessageUnit __iomem *reg = acb->pmu;
uint8_t *pQbuffer; uint8_t *pQbuffer;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
...@@ -169,8 +159,7 @@ arcmsr_sysfs_iop_message_clear(struct kobject *kobj, ...@@ -169,8 +159,7 @@ arcmsr_sysfs_iop_message_clear(struct kobject *kobj,
if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK arcmsr_iop_message_read(acb);
, &reg->inbound_doorbell);
} }
acb->acb_flags |= acb->acb_flags |=
(ACB_F_MESSAGE_WQBUFFER_CLEARED (ACB_F_MESSAGE_WQBUFFER_CLEARED
...@@ -191,6 +180,7 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = { ...@@ -191,6 +180,7 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = {
.attr = { .attr = {
.name = "mu_read", .name = "mu_read",
.mode = S_IRUSR , .mode = S_IRUSR ,
.owner = THIS_MODULE,
}, },
.size = 1032, .size = 1032,
.read = arcmsr_sysfs_iop_message_read, .read = arcmsr_sysfs_iop_message_read,
...@@ -200,6 +190,7 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = { ...@@ -200,6 +190,7 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = {
.attr = { .attr = {
.name = "mu_write", .name = "mu_write",
.mode = S_IWUSR, .mode = S_IWUSR,
.owner = THIS_MODULE,
}, },
.size = 1032, .size = 1032,
.write = arcmsr_sysfs_iop_message_write, .write = arcmsr_sysfs_iop_message_write,
...@@ -209,6 +200,7 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = { ...@@ -209,6 +200,7 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = {
.attr = { .attr = {
.name = "mu_clear", .name = "mu_clear",
.mode = S_IWUSR, .mode = S_IWUSR,
.owner = THIS_MODULE,
}, },
.size = 1, .size = 1,
.write = arcmsr_sysfs_iop_message_clear, .write = arcmsr_sysfs_iop_message_clear,
...@@ -219,31 +211,26 @@ int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb) ...@@ -219,31 +211,26 @@ int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb)
struct Scsi_Host *host = acb->host; struct Scsi_Host *host = acb->host;
int error; int error;
error = sysfs_create_bin_file(&host->shost_classdev.kobj, error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
&arcmsr_sysfs_message_read_attr);
if (error) { if (error) {
printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n"); printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n");
goto error_bin_file_message_read; goto error_bin_file_message_read;
} }
error = sysfs_create_bin_file(&host->shost_classdev.kobj, error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
&arcmsr_sysfs_message_write_attr);
if (error) { if (error) {
printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n"); printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n");
goto error_bin_file_message_write; goto error_bin_file_message_write;
} }
error = sysfs_create_bin_file(&host->shost_classdev.kobj, error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr);
&arcmsr_sysfs_message_clear_attr);
if (error) { if (error) {
printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n"); printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n");
goto error_bin_file_message_clear; goto error_bin_file_message_clear;
} }
return 0; return 0;
error_bin_file_message_clear: error_bin_file_message_clear:
sysfs_remove_bin_file(&host->shost_classdev.kobj, sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr);
&arcmsr_sysfs_message_write_attr);
error_bin_file_message_write: error_bin_file_message_write:
sysfs_remove_bin_file(&host->shost_classdev.kobj, sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
&arcmsr_sysfs_message_read_attr);
error_bin_file_message_read: error_bin_file_message_read:
return error; return error;
} }
...@@ -252,12 +239,9 @@ void ...@@ -252,12 +239,9 @@ void
arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) { arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) {
struct Scsi_Host *host = acb->host; struct Scsi_Host *host = acb->host;
sysfs_remove_bin_file(&host->shost_classdev.kobj, sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr);
&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, sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr);
&arcmsr_sysfs_message_write_attr);
sysfs_remove_bin_file(&host->shost_classdev.kobj,
&arcmsr_sysfs_message_read_attr);
} }
......
This diff is collapsed.
...@@ -2057,6 +2057,9 @@ ...@@ -2057,6 +2057,9 @@
#define PCI_DEVICE_ID_ARECA_1130 0x1130 #define PCI_DEVICE_ID_ARECA_1130 0x1130
#define PCI_DEVICE_ID_ARECA_1160 0x1160 #define PCI_DEVICE_ID_ARECA_1160 0x1160
#define PCI_DEVICE_ID_ARECA_1170 0x1170 #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_1210 0x1210
#define PCI_DEVICE_ID_ARECA_1220 0x1220 #define PCI_DEVICE_ID_ARECA_1220 0x1220
#define PCI_DEVICE_ID_ARECA_1230 0x1230 #define PCI_DEVICE_ID_ARECA_1230 0x1230
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment