From: "Nick Cheng" <nick.cheng@areca.com.tw>
To: linux-scsi@vger.kernel.org
Cc: James.Bottomley@HansenPartnership.com, linux-kernel@vger.kernel.org
Subject: [PATCH 3/3 ] SCSI: Support Type C RAID controller
Date: Thu, 15 Apr 2010 14:01:28 +0800 [thread overview]
Message-ID: <60FF59AA20D44726B3BB8DCBA9775ADC@areca4e4f859d4> (raw)
In-Reply-To:
[-- Attachment #1: Type: text/plain, Size: 143 bytes --]
1. To support Type C RAID controller, ACB_ADAPTER_TYPE_C, i.e. PCI device
ID: 0x1880.
Signed-off-by: Nick Cheng< nick.cheng@areca.com.tw >
---
[-- Attachment #2: patch3 --]
[-- Type: application/octet-stream, Size: 75187 bytes --]
diff -Naurp --ignore-blank-lines --ignore-all-space --ignore-space-change linux-2.6/drivers/scsi/arcmsr.1.20.00.15-91209/arcmsr.h linux-2.6/drivers/scsi/arcmsr.1.20.00.15-100202/arcmsr.h
--- linux-2.6/drivers/scsi/arcmsr.1.20.00.15-91209/arcmsr.h 2010-04-14 19:25:24.000000000 +0800
+++ linux-2.6/drivers/scsi/arcmsr.1.20.00.15-100202/arcmsr.h 2010-04-14 19:29:02.000000000 +0800
@@ -48,7 +47,7 @@ struct device_attribute;
/*The limit of outstanding scsi command that firmware can handle*/
#define ARCMSR_MAX_OUTSTANDING_CMD 256
#define ARCMSR_MAX_FREECCB_NUM 320
-#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2009/12/09"
+#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2010/02/02"
#define ARCMSR_SCSI_INITIATOR_ID 255
#define ARCMSR_MAX_XFER_SECTORS 512
#define ARCMSR_MAX_XFER_SECTORS_B 4096
@@ -61,6 +60,7 @@ struct device_attribute;
#define ARCMSR_MAX_HBB_POSTQUEUE 264
#define ARCMSR_MAX_XFER_LEN 0x26000 /* 152K */
#define ARCMSR_CDB_SG_PAGE_LENGTH 256
+#define SCSI_CMD_ARECA_SPECIFIC 0xE1
#ifndef PCI_DEVICE_ID_ARECA_1880
#define PCI_DEVICE_ID_ARECA_1880 0x1880
#endif
@@ -223,11 +223,15 @@ struct FIRMWARE_INFO
#define ARCMSR_CCBPOST_FLAG_SGL_BSIZE 0x80000000
#define ARCMSR_CCBPOST_FLAG_IAM_BIOS 0x40000000
#define ARCMSR_CCBREPLY_FLAG_IAM_BIOS 0x40000000
-#define ARCMSR_CCBREPLY_FLAG_ERROR 0x10000000
+#define ARCMSR_CCBREPLY_FLAG_ERROR_MODE0 0x10000000
+#define ARCMSR_CCBREPLY_FLAG_ERROR_MODE1 0x00000001
/* outbound firmware ok */
#define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK 0x80000000
/* ARC-1680 Bus Reset*/
#define ARCMSR_ARC1680_BUS_RESET 0x00000003
+/* ARC-1880 Bus Reset*/
+#define ARCMSR_ARC1880_RESET_ADAPTER 0x00000024
+#define ARCMSR_ARC1880_DiagWrite_ENABLE 0x00000080
/*
************************************************************************
@@ -285,6 +289,61 @@ struct FIRMWARE_INFO
/* iop message_rwbuffer for message command */
#define ARCMSR_MESSAGE_RWBUFFER 0x0000fa00
/*
+************************************************************************
+** SPEC. for Areca HBC adapter
+************************************************************************
+*/
+#define ARCMSR_HBC_ISR_THROTTLING_LEVEL 12
+#define ARCMSR_HBC_ISR_MAX_DONE_QUEUE 20
+/* Host Interrupt Mask */
+#define ARCMSR_HBCMU_UTILITY_A_ISR_MASK 0x00000001 /* When clear, the Utility_A interrupt routes to the host.*/
+#define ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK 0x00000004 /* When clear, the General Outbound Doorbell interrupt routes to the host.*/
+#define ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK 0x00000008 /* When clear, the Outbound Post List FIFO Not Empty interrupt routes to the host.*/
+#define ARCMSR_HBCMU_ALL_INTMASKENABLE 0x0000000D /* disable all ISR */
+/* Host Interrupt Status */
+#define ARCMSR_HBCMU_UTILITY_A_ISR 0x00000001
+ /*
+ ** Set when the Utility_A Interrupt bit is set in the Outbound Doorbell Register.
+ ** It clears by writing a 1 to the Utility_A bit in the Outbound Doorbell Clear Register or through automatic clearing (if enabled).
+ */
+#define ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR 0x00000004
+ /*
+ ** Set if Outbound Doorbell register bits 30:1 have a non-zero
+ ** value. This bit clears only when Outbound Doorbell bits
+ ** 30:1 are ALL clear. Only a write to the Outbound Doorbell
+ ** Clear register clears bits in the Outbound Doorbell register.
+ */
+#define ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR 0x00000008
+ /*
+ ** Set whenever the Outbound Post List Producer/Consumer
+ ** Register (FIFO) is not empty. It clears when the Outbound
+ ** Post List FIFO is empty.
+ */
+#define ARCMSR_HBCMU_SAS_ALL_INT 0x00000010
+ /*
+ ** This bit indicates a SAS interrupt from a source external to
+ ** the PCIe core. This bit is not maskable.
+ */
+/* DoorBell*/
+#define ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK 0x00000002
+#define ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK 0x00000004
+/*inbound message 0 ready*/
+#define ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE 0x00000008
+/*more than 12 request completed in a time*/
+#define ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING 0x00000010
+#define ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK 0x00000002
+/*outbound DATA WRITE isr door bell clear*/
+#define ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_DOORBELL_CLEAR 0x00000002
+#define ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK 0x00000004
+/*outbound DATA READ isr door bell clear*/
+#define ARCMSR_HBCMU_IOP2DRV_DATA_READ_DOORBELL_CLEAR 0x00000004
+/*outbound message 0 ready*/
+#define ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE 0x00000008
+/*outbound message cmd isr door bell clear*/
+#define ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR 0x00000008
+/*ARCMSR_HBAMU_MESSAGE_FIRMWARE_OK*/
+#define ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK 0x80000000
+/*
*******************************************************************************
** ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504)
*******************************************************************************
@@ -321,7 +380,7 @@ struct ARCMSR_CDB
struct SG32ENTRY sg32entry[1];
struct SG64ENTRY sg64entry[1];
} u;
-} __attribute__ ((packed));
+};
/*
*******************************************************************************
** Messaging Unit (MU) of the Intel R 80331 I/O processor(Type A) and Type B processor
@@ -367,7 +426,81 @@ struct MessageUnit_B
uint32_t __iomem *message_wbuffer;
uint32_t __iomem *message_rbuffer;
};
-
+/*
+*********************************************************************
+** LSI
+*********************************************************************
+*/
+struct MessageUnit_C{
+ uint32_t message_unit_status; /*0000 0003*/
+ uint32_t slave_error_attribute; /*0004 0007*/
+ uint32_t slave_error_address; /*0008 000B*/
+ uint32_t posted_outbound_doorbell; /*000C 000F*/
+ uint32_t master_error_attribute; /*0010 0013*/
+ uint32_t master_error_address_low; /*0014 0017*/
+ uint32_t master_error_address_high; /*0018 001B*/
+ uint32_t hcb_size; /*001C 001F*/
+ uint32_t inbound_doorbell; /*0020 0023*/
+ uint32_t diagnostic_rw_data; /*0024 0027*/
+ uint32_t diagnostic_rw_address_low; /*0028 002B*/
+ uint32_t diagnostic_rw_address_high; /*002C 002F*/
+ uint32_t host_int_status; /*0030 0033*/
+ uint32_t host_int_mask; /*0034 0037*/
+ uint32_t dcr_data; /*0038 003B*/
+ uint32_t dcr_address; /*003C 003F*/
+ uint32_t inbound_queueport; /*0040 0043*/
+ uint32_t outbound_queueport; /*0044 0047*/
+ uint32_t hcb_pci_address_low; /*0048 004B*/
+ uint32_t hcb_pci_address_high; /*004C 004F*/
+ uint32_t iop_int_status; /*0050 0053*/
+ uint32_t iop_int_mask; /*0054 0057*/
+ uint32_t iop_inbound_queue_port; /*0058 005B*/
+ uint32_t iop_outbound_queue_port; /*005C 005F*/
+ uint32_t inbound_free_list_index; /*0060 0063*/
+ uint32_t inbound_post_list_index; /*0064 0067*/
+ uint32_t outbound_free_list_index; /*0068 006B*/
+ uint32_t outbound_post_list_index; /*006C 006F*/
+ uint32_t inbound_doorbell_clear; /*0070 0073*/
+ uint32_t i2o_message_unit_control; /*0074 0077*/
+ uint32_t last_used_message_source_address_low; /*0078 007B*/
+ uint32_t last_used_message_source_address_high; /*007C 007F*/
+ uint32_t pull_mode_data_byte_count[4]; /*0080 008F*/
+ uint32_t message_dest_address_index; /*0090 0093*/
+ uint32_t done_queue_not_empty_int_counter_timer; /*0094 0097*/
+ uint32_t utility_A_int_counter_timer; /*0098 009B*/
+ uint32_t outbound_doorbell; /*009C 009F*/
+ uint32_t outbound_doorbell_clear; /*00A0 00A3*/
+ uint32_t message_source_address_index; /*00A4 00A7*/
+ uint32_t message_done_queue_index; /*00A8 00AB*/
+ uint32_t reserved0; /*00AC 00AF*/
+ uint32_t inbound_msgaddr0; /*00B0 00B3*/
+ uint32_t inbound_msgaddr1; /*00B4 00B7*/
+ uint32_t outbound_msgaddr0; /*00B8 00BB*/
+ uint32_t outbound_msgaddr1; /*00BC 00BF*/
+ uint32_t inbound_queueport_low; /*00C0 00C3*/
+ uint32_t inbound_queueport_high; /*00C4 00C7*/
+ uint32_t outbound_queueport_low; /*00C8 00CB*/
+ uint32_t outbound_queueport_high; /*00CC 00CF*/
+ uint32_t iop_inbound_queue_port_low; /*00D0 00D3*/
+ uint32_t iop_inbound_queue_port_high; /*00D4 00D7*/
+ uint32_t iop_outbound_queue_port_low; /*00D8 00DB*/
+ uint32_t iop_outbound_queue_port_high; /*00DC 00DF*/
+ uint32_t message_dest_queue_port_low; /*00E0 00E3*/
+ uint32_t message_dest_queue_port_high; /*00E4 00E7*/
+ uint32_t last_used_message_dest_address_low; /*00E8 00EB*/
+ uint32_t last_used_message_dest_address_high; /*00EC 00EF*/
+ uint32_t message_done_queue_base_address_low; /*00F0 00F3*/
+ uint32_t message_done_queue_base_address_high; /*00F4 00F7*/
+ uint32_t host_diagnostic; /*00F8 00FB*/
+ uint32_t write_sequence; /*00FC 00FF*/
+ uint32_t reserved1[34]; /*0100 0187*/
+ uint32_t reserved2[1950]; /*0188 1FFF*/
+ uint32_t message_wbuffer[32]; /*2000 207F*/
+ uint32_t reserved3[32]; /*2080 20FF*/
+ uint32_t message_rbuffer[32]; /*2100 217F*/
+ uint32_t reserved4[32]; /*2180 21FF*/
+ uint32_t msgcode_rwbuffer[256]; /*2200 23FF*/
+};
/*
*******************************************************************************
** Adapter Control Block
@@ -385,11 +518,14 @@ struct AdapterControlBlock
unsigned long vir2phy_offset;
/* Offset is used in making arc cdb physical to virtual calculations */
uint32_t outbound_int_enable;
+ uint32_t cdb_phyaddr_hi32;
+ uint32_t reg_mu_acc_handle0;
spinlock_t eh_lock;
spinlock_t ccblist_lock;
union {
struct MessageUnit_A __iomem * pmuA;
struct MessageUnit_B * pmuB;
+ struct MessageUnit_C __iomem *pmuC;
};
/* message unit ATU inbound base address0 */
void __iomem *mem_base0;
@@ -410,6 +546,8 @@ struct AdapterControlBlock
/* message clear rqbuffer */
#define ACB_F_MESSAGE_WQBUFFER_READED 0x0040
#define ACB_F_BUS_RESET 0x0080
+ #define ACB_F_BUS_HANG_ON 0x0800/* need hardware reset bus */
+
#define ACB_F_IOP_INITED 0x0100
/* iop init */
#define ACB_F_ABORT 0x0200
@@ -477,7 +615,8 @@ struct CommandControlBlock
struct list_head list; /*x32: 8byte, x64: 16byte*/
struct scsi_cmnd *pcmd; /*8 bytes pointer of linux scsi command */
struct AdapterControlBlock *acb; /*x32: 4byte, x64: 8byte*/
- uint32_t shifted_cdb_phyaddr; /*x32: 4byte, x64: 4byte*/
+ uint32_t cdb_phyaddr_pattern; /*x32: 4byte, x64: 4byte*/
+ uint32_t arc_cdb_size; /*x32:4byte,x64:4byte*/
uint16_t ccb_flags; /*x32: 2byte, x64: 2byte*/
#define CCB_FLAG_READ 0x0000
#define CCB_FLAG_WRITE 0x0001
@@ -491,10 +630,10 @@ struct CommandControlBlock
#define ARCMSR_CCB_ILLEGAL 0xFFFF
#if BITS_PER_LONG == 64
/* ======================512+64 bytes======================== */
- uint32_t reserved[6]; /*24 byte*/
+ uint32_t reserved[5]; /*24 byte*/
#else
/* ======================512+32 bytes======================== */
- uint32_t reserved[2]; /*8 byte*/
+ uint32_t reserved; /*8 byte*/
#endif
/* ======================================================= */
struct ARCMSR_CDB arcmsr_cdb;
diff -Naurp --ignore-blank-lines --ignore-all-space --ignore-space-change linux-2.6/drivers/scsi/arcmsr.1.20.00.15-91209/arcmsr_hba.c linux-2.6/drivers/scsi/arcmsr.1.20.00.15-100202/arcmsr_hba.c
--- linux-2.6/drivers/scsi/arcmsr.1.20.00.15-91209/arcmsr_hba.c 2010-04-14 19:25:15.000000000 +0800
+++ linux-2.6/drivers/scsi/arcmsr.1.20.00.15-100202/arcmsr_hba.c 2010-04-14 19:28:55.000000000 +0800
@@ -71,11 +71,11 @@
#include <scsi/scsicam.h>
#include "arcmsr.h"
MODULE_AUTHOR("Nick Cheng <support@areca.com.tw>");
-MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/16xx) SATA/SAS RAID Host Bus Adapter");
+MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/16xx/1880) SATA/SAS RAID Host Bus Adapter");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_VERSION(ARCMSR_DRIVER_VERSION);
-static int sleeptime = 20;
-static int retrycount = 12;
+static int sleeptime = 10;
+static int retrycount = 30;
wait_queue_head_t wait_q;
static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb,
struct scsi_cmnd *cmd);
@@ -99,10 +99,12 @@ static void arcmsr_flush_hbb_cache(struc
static void arcmsr_request_device_map(unsigned long pacb);
static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb);
static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb);
+static void arcmsr_request_hbc_device_map(struct AdapterControlBlock *acb);
static void arcmsr_message_isr_bh_fn(struct work_struct *work);
static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb);
static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb);
-
+static void arcmsr_hbc_message_isr(struct AdapterControlBlock *pACB);
+static void arcmsr_hardware_reset(struct AdapterControlBlock *acb);
static const char *arcmsr_info(struct Scsi_Host *);
static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev,
@@ -110,13 +112,13 @@ static int arcmsr_adjust_disk_queue_dept
{
if (queue_depth > ARCMSR_MAX_CMD_PERLUN)
queue_depth = ARCMSR_MAX_CMD_PERLUN;
- scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
+ scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), queue_depth);
return queue_depth;
}
static struct scsi_host_template arcmsr_scsi_host_template = {
.module = THIS_MODULE,
- .name = "ARCMSR ARECA SATA/SAS RAID Host Bus Adapter"
+ .name = "ARCMSR ARECA SATA/SAS RAID Controller"
ARCMSR_DRIVER_VERSION,
.info = arcmsr_info,
.queuecommand = arcmsr_queue_command,
@@ -175,17 +177,40 @@ static struct pci_driver arcmsr_pci_driv
.err_handler = &arcmsr_pci_error_handlers,
#endif
};
+/*
+****************************************************************************
+****************************************************************************
+*/
+int arcmsr_sleep_for_bus_reset(struct scsi_cmnd *cmd)
+{
+ struct Scsi_Host *shost = NULL;
+ int i, isleep;
+ shost = cmd->device->host;
+ isleep = sleeptime / 10;
+ if (isleep > 0) {
+ for (i = 0; i < isleep; i++) {
+ msleep(10000);
+ }
+ }
-static void arcmsr_free_mu(struct AdapterControlBlock *acb)
+ isleep = sleeptime % 10;
+ if (isleep > 0) {
+ msleep(isleep*1000);
+ }
+ printk("wake-up\n");
+ return 0;
+}
+
+static void arcmsr_free_hbb_mu(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A:
+ case ACB_ADAPTER_TYPE_C:
break;
case ACB_ADAPTER_TYPE_B:{
- struct MessageUnit_B *reg = acb->pmuB;
dma_free_coherent(&acb->pdev->dev,
sizeof(struct MessageUnit_B),
- reg, acb->dma_coherent_handle_hbb_mu);
+ acb->pmuB, acb->dma_coherent_handle_hbb_mu);
}
}
}
@@ -218,6 +242,19 @@ static bool arcmsr_remap_pciregion(struc
}
acb->mem_base0 = mem_base0;
acb->mem_base1 = mem_base1;
+ break;
+ }
+ case ACB_ADAPTER_TYPE_C:{
+ acb->pmuC = ioremap_nocache(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
+ if (!acb->pmuC) {
+ printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", acb->host->host_no);
+ return false;
+ }
+ if (readl(&acb->pmuC->outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
+ writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, &acb->pmuC->outbound_doorbell_clear);/*clear interrupt*/
+ return TRUE;
+ }
+ break;
}
}
return true;
@@ -229,10 +266,16 @@ static void arcmsr_unmap_pciregion(struc
case ACB_ADAPTER_TYPE_A:{
iounmap(acb->pmuA);
}
+ break;
case ACB_ADAPTER_TYPE_B:{
iounmap(acb->mem_base0);
iounmap(acb->mem_base1);
}
+
+ break;
+ case ACB_ADAPTER_TYPE_C:{
+ iounmap(acb->pmuC);
+ }
}
}
@@ -280,6 +323,10 @@ static void arcmsr_define_adapter_type(s
pci_read_config_word(pdev, PCI_DEVICE_ID, &dev_id);
acb->dev_id = dev_id;
switch (dev_id) {
+ case 0x1880: {
+ acb->adapter_type = ACB_ADAPTER_TYPE_C;
+ }
+ break;
case 0x1201 : {
acb->adapter_type = ACB_ADAPTER_TYPE_B;
}
@@ -301,13 +347,13 @@ static uint8_t arcmsr_hba_wait_msgint_re
ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT,
®->outbound_intstatus);
- return 0x00;
+ return TRUE;
}
msleep(10);
} /*max 1 seconds*/
} while (Retries++ < 20);/*max 20 sec*/
- return 0xff;
+ return FALSE;
}
static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
@@ -323,15 +368,32 @@ static uint8_t arcmsr_hbb_wait_msgint_re
writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN
, reg->iop2drv_doorbell);
writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell);
- return 0x00;
+ return TRUE;
}
msleep(10);
} /*max 1 seconds*/
} while (Retries++ < 20);/*max 20 sec*/
- return 0xff;
+ return FALSE;
}
+static uint8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *pACB)
+{
+ struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)pACB->pmuC;
+ unsigned char Retries = 0x00;
+ uint32_t Index;
+ do {
+ for (Index = 0; Index < 100; Index++) {
+ if (readl(&phbcmu->outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
+ writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, &phbcmu->outbound_doorbell_clear);/*clear interrupt*/
+ return TRUE;
+ }
+ /* one us delay */
+ msleep(10);
+ } /*max 1 seconds*/
+ } while (Retries++ < 20); /*max 20 sec*/
+ return FALSE;
+}
static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb)
{
struct MessageUnit_A __iomem *reg = acb->pmuA;
@@ -336,10 +398,9 @@ static void arcmsr_flush_hba_cache(struc
{
struct MessageUnit_A __iomem *reg = acb->pmuA;
int retry_count = 30;
-
writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0);
do {
- if (!arcmsr_hba_wait_msgint_ready(acb))
+ if (arcmsr_hba_wait_msgint_ready(acb))
break;
else {
retry_count--;
@@ -353,10 +414,9 @@ static void arcmsr_flush_hbb_cache(struc
{
struct MessageUnit_B *reg = acb->pmuB;
int retry_count = 30;
-
writel(ARCMSR_MESSAGE_FLUSH_CACHE, reg->drv2iop_doorbell);
do {
- if (!arcmsr_hbb_wait_msgint_ready(acb))
+ if (arcmsr_hbb_wait_msgint_ready(acb))
break;
else {
retry_count--;
@@ -366,6 +426,23 @@ static void arcmsr_flush_hbb_cache(struc
} while (retry_count != 0);
}
+static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *pACB)
+{
+ struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC;
+ int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
+ writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0);
+ writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell);
+ do {
+ if (arcmsr_hbc_wait_msgint_ready(pACB)) {
+ break;
+ } else {
+ retry_count--;
+ printk(KERN_NOTICE "arcmsr%d: wait 'flush adapter cache' \
+ timeout,retry count down = %d \n", pACB->host->host_no, retry_count);
+ }
+ } while (retry_count != 0);
+ return;
+}
static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
@@ -378,21 +455,22 @@ static void arcmsr_flush_adapter_cache(s
case ACB_ADAPTER_TYPE_B: {
arcmsr_flush_hbb_cache(acb);
}
+ break;
+ case ACB_ADAPTER_TYPE_C: {
+ arcmsr_flush_hbc_cache(acb);
+ }
}
}
static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
{
struct pci_dev *pdev = acb->pdev;
- switch (acb->adapter_type) {
- case ACB_ADAPTER_TYPE_A: {
-
void *dma_coherent;
dma_addr_t dma_coherent_handle;
struct CommandControlBlock *ccb_tmp;
int i = 0, j = 0;
dma_addr_t cdb_phyaddr;
- unsigned long roundup_ccbsize = 0;
+ unsigned long roundup_ccbsize = 0, offset;
unsigned long max_xfer_len;
unsigned long max_sg_entrys;
uint32_t firm_config_version;
@@ -405,26 +482,29 @@ static int arcmsr_alloc_ccb_pool(struct
max_sg_entrys = ARCMSR_DEFAULT_SG_ENTRIES;
firm_config_version = acb->firm_cfg_version;
if ((firm_config_version & 0xFF) >= 3) {
- max_xfer_len = (ARCMSR_CDB_SG_PAGE_LENGTH << ((firm_config_version >> 8) & 0xFF)) * 1024;/* max 16M byte */
+ max_xfer_len = (ARCMSR_CDB_SG_PAGE_LENGTH << ((firm_config_version >> 8) & 0xFF)) * 1024;/* max 4M byte */
max_sg_entrys = (max_xfer_len/4096);
}
acb->host->max_sectors = max_xfer_len/512;
acb->host->sg_tablesize = max_sg_entrys;
- roundup_ccbsize = roundup(sizeof(struct CommandControlBlock) + max_sg_entrys * sizeof(struct SG64ENTRY), 32);
- acb->uncache_size = roundup_ccbsize * ARCMSR_MAX_FREECCB_NUM;
+ roundup_ccbsize = roundup(sizeof(struct CommandControlBlock) + (max_sg_entrys - 1) * sizeof(struct SG64ENTRY), 32);
+ acb->uncache_size = roundup_ccbsize * ARCMSR_MAX_FREECCB_NUM + 32;
dma_coherent = dma_alloc_coherent(&pdev->dev, acb->uncache_size, &dma_coherent_handle, GFP_KERNEL);
if (!dma_coherent) {
printk("arcmsr%d: dma_alloc_coherent got error \n", acb->host->host_no);
return -ENOMEM;
}
- memset(dma_coherent, 0, acb->uncache_size);
acb->dma_coherent = dma_coherent;
acb->dma_coherent_handle = dma_coherent_handle;
- ccb_tmp = (struct CommandControlBlock *)dma_coherent;
+ memset(dma_coherent, 0, acb->uncache_size);
+ offset = roundup((unsigned long)dma_coherent, 32) - (unsigned long)dma_coherent;
+ dma_coherent_handle = dma_coherent_handle + offset;
+ dma_coherent = (struct CommandControlBlock *)dma_coherent + offset;
+ ccb_tmp = dma_coherent;
acb->vir2phy_offset = (unsigned long)dma_coherent - (unsigned long)dma_coherent_handle;
for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++){
cdb_phyaddr = dma_coherent_handle + offsetof(struct CommandControlBlock, arcmsr_cdb);
- ccb_tmp->shifted_cdb_phyaddr = cdb_phyaddr >> 5;
+ ccb_tmp->cdb_phyaddr_pattern = ((acb->adapter_type == ACB_ADAPTER_TYPE_C) ? cdb_phyaddr : (cdb_phyaddr >> 5));
acb->pccb_pool[i] = ccb_tmp;
ccb_tmp->acb = acb;
INIT_LIST_HEAD(&ccb_tmp->list);
@@ -432,68 +512,9 @@ static int arcmsr_alloc_ccb_pool(struct
ccb_tmp = (struct CommandControlBlock *)((unsigned long)ccb_tmp + roundup_ccbsize);
dma_coherent_handle = dma_coherent_handle + roundup_ccbsize;
}
- break;
- }
- case ACB_ADAPTER_TYPE_B: {
-
- void *dma_coherent;
- dma_addr_t dma_coherent_handle;
- struct CommandControlBlock *ccb_tmp;
- uint32_t cdb_phyaddr;
- unsigned int roundup_ccbsize = 0;
- unsigned long max_xfer_len;
- unsigned long max_sg_entrys;
- unsigned long firm_config_version;
- unsigned long max_freeccb_num = 0;
- int i = 0, j = 0;
-
- max_freeccb_num = ARCMSR_MAX_FREECCB_NUM;
- max_xfer_len = ARCMSR_MAX_XFER_LEN;
- max_sg_entrys = ARCMSR_DEFAULT_SG_ENTRIES;
- firm_config_version = acb->firm_cfg_version;
- if ((firm_config_version & 0xFF) >= 3) {
- max_xfer_len = (ARCMSR_CDB_SG_PAGE_LENGTH <<
- ((firm_config_version >> 8) & 0xFF)) * 1024;/* max 16M byte */
- max_sg_entrys = (max_xfer_len/4096);/* max 4097 sg entry*/
- }
- acb->host->max_sectors = max_xfer_len / 512;
- acb->host->sg_tablesize = max_sg_entrys;
- roundup_ccbsize = roundup(sizeof(struct CommandControlBlock)+
- (max_sg_entrys - 1) * sizeof(struct SG64ENTRY), 32);
- acb->uncache_size = roundup_ccbsize * ARCMSR_MAX_FREECCB_NUM;
- dma_coherent = dma_alloc_coherent(&pdev->dev, acb->uncache_size,
- &dma_coherent_handle, GFP_KERNEL);
-
- if (!dma_coherent) {
- printk(KERN_NOTICE "DMA allocation failed...........................\n");
- return -ENOMEM;
- }
- memset(dma_coherent, 0, acb->uncache_size);
- acb->dma_coherent = dma_coherent;
- acb->dma_coherent_handle = dma_coherent_handle;
- ccb_tmp = (struct CommandControlBlock *)dma_coherent;
- acb->vir2phy_offset = (unsigned long)dma_coherent -
- (unsigned long)dma_coherent_handle;
- for(i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++){
- cdb_phyaddr = dma_coherent_handle +
- offsetof(struct CommandControlBlock, arcmsr_cdb);
- ccb_tmp->shifted_cdb_phyaddr = cdb_phyaddr >> 5;
- acb->pccb_pool[i] = ccb_tmp;
- ccb_tmp->acb = acb;
- INIT_LIST_HEAD(&ccb_tmp->list);
- list_add_tail(&ccb_tmp->list, &acb->ccb_free_list);
- ccb_tmp = (struct CommandControlBlock *)((unsigned long)ccb_tmp +
- roundup_ccbsize);
- dma_coherent_handle = dma_coherent_handle + roundup_ccbsize;
- }
- for (i = 0; i < ARCMSR_MAX_TARGETID; i++)
- for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++)
- acb->devstate[i][j] = ARECA_RAID_GONE;
- }
- break;
- }
return 0;
}
+
static void arcmsr_message_isr_bh_fn(struct work_struct *work)
{
struct AdapterControlBlock *acb = container_of(work,struct AdapterControlBlock, arcmsr_do_message_isr_bh);
@@ -573,6 +594,43 @@ static void arcmsr_message_isr_bh_fn(str
}
}
}
+ break;
+ case ACB_ADAPTER_TYPE_C: {
+ struct MessageUnit_C *reg = acb->pmuC;
+ char *acb_dev_map = (char *)acb->device_map;
+ uint32_t __iomem *signature = (uint32_t __iomem *)(®->msgcode_rwbuffer[0]);
+ char __iomem *devicemap = (char __iomem *)(®->msgcode_rwbuffer[21]);
+ int target, lun;
+ struct scsi_device *psdev;
+ char diff;
+
+ atomic_inc(&acb->rq_map_token);
+ if (readl(signature) == ARCMSR_SIGNATURE_GET_CONFIG) {
+ for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) {
+ diff = (*acb_dev_map)^readb(devicemap);
+ if (diff != 0) {
+ char temp;
+ *acb_dev_map = readb(devicemap);
+ temp = *acb_dev_map;
+ for (lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) {
+ if ((temp & 0x01) == 1 && (diff & 0x01) == 1) {
+ scsi_add_device(acb->host, 0, target, lun);
+ } else if ((temp & 0x01) == 0 && (diff & 0x01) == 1) {
+ psdev = scsi_device_lookup(acb->host, 0, target, lun);
+ if (psdev != NULL) {
+ scsi_remove_device(psdev);
+ scsi_device_put(psdev);
+ }
+ }
+ temp >>= 1;
+ diff >>= 1;
+ }
+ }
+ devicemap++;
+ acb_dev_map++;
+ }
+ }
+ }
}
}
@@ -591,9 +648,9 @@ static int arcmsr_probe(struct pci_dev *
if (!host) {
goto pci_disable_dev;
}
- error = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+ error = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
if (error) {
- error = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ error = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (error) {
printk(KERN_WARNING
"scsi%d: No suitable DMA mask available\n",
@@ -675,7 +732,7 @@ static int arcmsr_probe(struct pci_dev *
arcmsr_flush_adapter_cache(acb);
arcmsr_free_ccb_pool(acb);
free_hbb_mu:
- arcmsr_free_mu(acb);
+ arcmsr_free_hbb_mu(acb);
unmap_pci_region:
arcmsr_unmap_pciregion(acb);
pci_release_regs:
@@ -690,15 +747,14 @@ static int arcmsr_probe(struct pci_dev *
static uint8_t arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb)
{
struct MessageUnit_A __iomem *reg = acb->pmuA;
-
writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0);
- if (arcmsr_hba_wait_msgint_ready(acb)){
+ if (!arcmsr_hba_wait_msgint_ready(acb)) {
printk(KERN_NOTICE
"arcmsr%d: wait 'abort all outstanding command' timeout \n"
, acb->host->host_no);
- return 0xff;
+ return FALSE;
}
- return 0x00;
+ return TRUE;
}
static uint8_t arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb)
@@ -706,15 +762,27 @@ static uint8_t arcmsr_abort_hbb_allcmd(s
struct MessageUnit_B *reg = acb->pmuB;
writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell);
- if (arcmsr_hbb_wait_msgint_ready(acb)) {
+ if (!arcmsr_hbb_wait_msgint_ready(acb)) {
printk(KERN_NOTICE
"arcmsr%d: wait 'abort all outstanding command' timeout \n"
, acb->host->host_no);
- return 0xff;
+ return FALSE;
}
- return 0x00;
+ return TRUE;
+}
+static uint8_t arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *pACB)
+{
+ struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC;
+ writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0);
+ writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell);
+ if (!arcmsr_hbc_wait_msgint_ready(pACB)) {
+ printk(KERN_NOTICE
+ "arcmsr%d: wait 'abort all outstanding command' timeout \n"
+ , pACB->host->host_no);
+ return FALSE;
+ }
+ return TRUE;
}
-
static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
{
uint8_t rtnval = 0;
@@ -727,6 +795,11 @@ static uint8_t arcmsr_abort_allcmd(struc
case ACB_ADAPTER_TYPE_B: {
rtnval = arcmsr_abort_hbb_allcmd(acb);
}
+ break;
+
+ case ACB_ADAPTER_TYPE_C: {
+ rtnval = arcmsr_abort_hbc_allcmd(acb);
+ }
}
return rtnval;
}
@@ -734,9 +807,8 @@ static uint8_t arcmsr_abort_allcmd(struc
static bool arcmsr_hbb_enable_driver_mode(struct AdapterControlBlock *pacb)
{
struct MessageUnit_B *reg = pacb->pmuB;
-
writel(ARCMSR_MESSAGE_START_DRIVER_MODE, reg->drv2iop_doorbell);
- if (arcmsr_hbb_wait_msgint_ready(pacb)) {
+ if (!arcmsr_hbb_wait_msgint_ready(pacb)) {
printk(KERN_ERR "arcmsr%d: can't set driver mode. \n", pacb->host->host_no);
return false;
}
@@ -759,7 +830,6 @@ static void arcmsr_ccb_complete(struct C
atomic_dec(&acb->ccboutstandingcount);
arcmsr_pci_unmap_dma(ccb);
ccb->startdone = ARCMSR_CCB_DONE;
- ccb->ccb_flags = 0;
spin_lock_irqsave(&acb->ccblist_lock, flags);
list_add_tail(&ccb->list, &acb->ccb_free_list);
spin_unlock_irqrestore(&acb->ccblist_lock, flags);
@@ -803,14 +870,20 @@ static u32 arcmsr_disable_outbound_ints(
writel(0, reg->iop2drv_doorbell_mask);
}
break;
+ case ACB_ADAPTER_TYPE_C:{
+ struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC;
+ /* disable all outbound interrupt */
+ orig_mask = readl(®->host_int_mask); /* disable outbound message0 int */
+ writel(orig_mask|ARCMSR_HBCMU_ALL_INTMASKENABLE, ®->host_int_mask);
+ }
+ break;
}
return orig_mask;
}
static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb,
- struct CommandControlBlock *ccb, uint32_t flag_ccb)
+ struct CommandControlBlock *ccb, bool error)
{
-
uint8_t id, lun;
id = ccb->pcmd->device->id;
lun = ccb->pcmd->device->lun;
@@ -814,7 +887,7 @@ static void arcmsr_report_ccb_state(stru
uint8_t id, lun;
id = ccb->pcmd->device->id;
lun = ccb->pcmd->device->lun;
- if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) {
+ if (!error) {
if (acb->devstate[id][lun] == ARECA_RAID_GONE)
acb->devstate[id][lun] = ARECA_RAID_GOOD;
ccb->pcmd->result = DID_OK << 16;
@@ -846,9 +919,8 @@ static void arcmsr_report_ccb_state(stru
default:
printk(KERN_NOTICE
- "arcmsr%d: scsi id = %d lun = %d"
- " isr get command error done, "
- "but got unknown DeviceStatus = 0x%x \n"
+ "arcmsr%d: scsi id = %d lun = %d isr get command error done, \
+ but got unknown DeviceStatus = 0x%x \n"
, acb->host->host_no
, id
, lun
@@ -861,25 +933,20 @@ static void arcmsr_report_ccb_state(stru
}
}
-static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, uint32_t flag_ccb)
+static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, struct CommandControlBlock *pCCB, bool error)
{
- struct CommandControlBlock *ccb;
- struct ARCMSR_CDB *arcmsr_cdb;
int id, lun;
-
- arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + (flag_ccb << 5));
- ccb = container_of(arcmsr_cdb, struct CommandControlBlock, arcmsr_cdb);
- if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) {
- if (ccb->startdone == ARCMSR_CCB_ABORTED) {
- struct scsi_cmnd *abortcmd = ccb->pcmd;
+ if ((pCCB->acb != acb) || (pCCB->startdone != ARCMSR_CCB_START)) {
+ if (pCCB->startdone == ARCMSR_CCB_ABORTED) {
+ struct scsi_cmnd *abortcmd = pCCB->pcmd;
if (abortcmd) {
id = abortcmd->device->id;
lun = abortcmd->device->lun;
abortcmd->result |= DID_ABORT << 16;
- arcmsr_ccb_complete(ccb);
- printk(KERN_NOTICE "arcmsr%d: ccb ='0x%p' \
- isr got aborted command \n", acb->host->host_no, ccb);
+ arcmsr_ccb_complete(pCCB);
+ printk(KERN_NOTICE "arcmsr%d: pCCB ='0x%p' isr got aborted command \n",
+ acb->host->host_no, pCCB);
}
}
printk(KERN_NOTICE "arcmsr%d: isr get an illegal ccb command \
@@ -888,20 +955,21 @@ static void arcmsr_drain_donequeue(struc
" ccboutstandingcount = %d \n"
, acb->host->host_no
, acb
- , ccb
- , ccb->acb
- , ccb->startdone
+ , pCCB
+ , pCCB->acb
+ , pCCB->startdone
, atomic_read(&acb->ccboutstandingcount));
}
- else
- arcmsr_report_ccb_state(acb, ccb, flag_ccb);
+ arcmsr_report_ccb_state(acb, pCCB, error);
}
static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
{
int i = 0;
uint32_t flag_ccb;
-
+ struct ARCMSR_CDB *pARCMSR_CDB;
+ bool error;
+ struct CommandControlBlock *pCCB;
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
@@ -913,7 +981,10 @@ static void arcmsr_done4abort_postqueue(
writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/
while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF)
&& (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
- arcmsr_drain_donequeue(acb, flag_ccb);
+ pARCMSR_CDB = (struct ARCMSR_CDB *)(acb->vir2phy_offset + (flag_ccb << 5));/*frame must be 32 bytes aligned*/
+ pCCB = container_of(pARCMSR_CDB, struct CommandControlBlock, arcmsr_cdb);
+ error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE;
+ arcmsr_drain_donequeue(acb, pCCB, error);
}
}
break;
@@ -921,17 +992,37 @@ static void arcmsr_done4abort_postqueue(
case ACB_ADAPTER_TYPE_B: {
struct MessageUnit_B *reg = acb->pmuB;
/*clear all outbound posted Q*/
+ writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, ®->iop2drv_doorbell); /* clear doorbell interrupt */
for (i = 0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) {
if ((flag_ccb = readl(®->done_qbuffer[i])) != 0) {
writel(0, ®->done_qbuffer[i]);
- arcmsr_drain_donequeue(acb, flag_ccb);
+ pARCMSR_CDB = (struct ARCMSR_CDB *)(acb->vir2phy_offset+(flag_ccb << 5));/*frame must be 32 bytes aligned*/
+ pCCB = container_of(pARCMSR_CDB, struct CommandControlBlock, arcmsr_cdb);
+ error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE;
+ arcmsr_drain_donequeue(acb, pCCB, error);
}
- writel(0, ®->post_qbuffer[i]);
+ reg->post_qbuffer[i] = 0;
}
reg->doneq_index = 0;
reg->postq_index = 0;
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ struct MessageUnit_C *reg = acb->pmuC;
+ struct ARCMSR_CDB *pARCMSR_CDB;
+ uint32_t flag_ccb, ccb_cdb_phy;
+ bool error;
+ struct CommandControlBlock *pCCB;
+ while ((readl(®->host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
+ /*need to do*/
+ flag_ccb = readl(®->outbound_queueport_low);
+ ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0);
+ pARCMSR_CDB = (struct ARCMSR_CDB *)(acb->vir2phy_offset+ccb_cdb_phy);/*frame must be 32 bytes aligned*/
+ pCCB = container_of(pARCMSR_CDB, struct CommandControlBlock, arcmsr_cdb);
+ error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
+ arcmsr_drain_donequeue(acb, pCCB, error);
+ }
+ }
}
}
static void arcmsr_remove(struct pci_dev *pdev)
@@ -942,7 +1033,6 @@ static void arcmsr_remove(struct pci_dev
int poll_count = 0;
arcmsr_free_sysfs_attr(acb);
scsi_remove_host(host);
- scsi_host_put(host);
flush_scheduled_work();
del_timer_sync(&acb->eternal_timer);
arcmsr_disable_outbound_ints(acb);
@@ -974,8 +1064,10 @@ static void arcmsr_remove(struct pci_dev
}
free_irq(pdev->irq, acb);
arcmsr_free_ccb_pool(acb);
- arcmsr_free_mu(acb);
+ arcmsr_free_hbb_mu(acb);
+ arcmsr_unmap_pciregion(acb);
pci_release_regions(pdev);
+ scsi_host_put(host);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
}
@@ -1033,6 +1123,13 @@ static void arcmsr_enable_outbound_ints(
writel(mask, reg->iop2drv_doorbell_mask);
acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f;
}
+ break;
+ case ACB_ADAPTER_TYPE_C: {
+ struct MessageUnit_C *reg = acb->pmuC;
+ mask = ~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK|ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK);
+ writel(intmask_org & mask, ®->host_int_mask);
+ acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f;
+ }
}
}
@@ -1044,24 +1141,20 @@ static int arcmsr_build_ccb(struct Adapt
__le32 address_lo, address_hi;
int arccdbsize = 0x30;
__le32 length = 0;
- int i, cdb_sgcount = 0;
+ int i;
struct scatterlist *sg;
int nseg;
-
ccb->pcmd = pcmd;
memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB));
- arcmsr_cdb->Bus = 0;
arcmsr_cdb->TargetID = pcmd->device->id;
arcmsr_cdb->LUN = pcmd->device->lun;
arcmsr_cdb->Function = 1;
- arcmsr_cdb->CdbLength = (uint8_t)pcmd->cmd_len;
arcmsr_cdb->Context = 0;
memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len);
nseg = scsi_dma_map(pcmd);
- if (nseg > acb->host->sg_tablesize || nseg < 0)
+ if (unlikely(nseg > acb->host->sg_tablesize || nseg < 0))
return FAILED;
- /* map stor port SG list to our iop SG List. */
scsi_for_each_sg(pcmd, sg, nseg, i) {
/* Get the physical address of the current data pointer */
length = cpu_to_le32(sg_dma_len(sg));
@@ -1083,23 +1176,22 @@ static int arcmsr_build_ccb(struct Adapt
psge += sizeof (struct SG64ENTRY);
arccdbsize += sizeof (struct SG64ENTRY);
}
- cdb_sgcount++;
}
- arcmsr_cdb->sgcount = (uint8_t)cdb_sgcount;
+ arcmsr_cdb->sgcount = (uint8_t)nseg;
arcmsr_cdb->DataLength = scsi_bufflen(pcmd);
arcmsr_cdb->msgPages = arccdbsize/0x100 + (arccdbsize % 0x100 ? 1 : 0);
if ( arccdbsize > 256)
arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE;
if (pcmd->cmnd[0]|WRITE_6 || pcmd->cmnd[0] | WRITE_10 || pcmd->cmnd[0]|WRITE_12) {
arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
- ccb->ccb_flags |= CCB_FLAG_WRITE;
}
+ ccb->arc_cdb_size = arccdbsize;
return SUCCESS;
}
static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb)
{
- uint32_t shifted_cdb_phyaddr = ccb->shifted_cdb_phyaddr;
+ uint32_t cdb_phyaddr_pattern = ccb->cdb_phyaddr_pattern;
struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb;
atomic_inc(&acb->ccboutstandingcount);
ccb->startdone = ARCMSR_CCB_START;
@@ -1109,10 +1200,10 @@ static void arcmsr_post_ccb(struct Adapt
struct MessageUnit_A __iomem *reg = acb->pmuA;
if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE)
- writel(shifted_cdb_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,
+ writel(cdb_phyaddr_pattern | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,
®->inbound_queueport);
else {
- writel(shifted_cdb_phyaddr, ®->inbound_queueport);
+ writel(cdb_phyaddr_pattern, ®->inbound_queueport);
}
}
break;
@@ -1124,11 +1215,10 @@ static void arcmsr_post_ccb(struct Adapt
ending_index = ((index + 1) % ARCMSR_MAX_HBB_POSTQUEUE);
writel(0, ®->post_qbuffer[ending_index]);
if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
- writel(shifted_cdb_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,\
+ writel(cdb_phyaddr_pattern | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,\
®->post_qbuffer[index]);
- }
- else {
- writel(shifted_cdb_phyaddr, ®->post_qbuffer[index]);
+ } else {
+ writel(cdb_phyaddr_pattern, ®->post_qbuffer[index]);
}
index++;
index %= ARCMSR_MAX_HBB_POSTQUEUE;/*if last index number set it to 0 */
@@ -1136,6 +1226,19 @@ static void arcmsr_post_ccb(struct Adapt
writel(ARCMSR_DRV2IOP_CDB_POSTED, reg->drv2iop_doorbell);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)acb->pmuC;
+ uint32_t ccb_post_stamp, arc_cdb_size;
+
+ arc_cdb_size = (ccb->arc_cdb_size > 0x300) ? 0x300 : ccb->arc_cdb_size;
+ ccb_post_stamp = (cdb_phyaddr_pattern | ((arc_cdb_size - 1) >> 6) | 1);
+ if (acb->cdb_phyaddr_hi32) {
+ writel(acb->cdb_phyaddr_hi32, &phbcmu->inbound_queueport_high);
+ writel(ccb_post_stamp, &phbcmu->inbound_queueport_low);
+ } else {
+ writel(ccb_post_stamp, &phbcmu->inbound_queueport_low);
+ }
+ }
}
}
@@ -1144,8 +1247,7 @@ static void arcmsr_stop_hba_bgrb(struct
struct MessageUnit_A __iomem *reg = acb->pmuA;
acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0);
-
- if (arcmsr_hba_wait_msgint_ready(acb)) {
+ if (!arcmsr_hba_wait_msgint_ready(acb)) {
printk(KERN_NOTICE
"arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
, acb->host->host_no);
@@ -1158,13 +1260,26 @@ static void arcmsr_stop_hbb_bgrb(struct
acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
writel(ARCMSR_MESSAGE_STOP_BGRB, reg->drv2iop_doorbell);
- if (arcmsr_hbb_wait_msgint_ready(acb)) {
+ if (!arcmsr_hbb_wait_msgint_ready(acb)) {
printk(KERN_NOTICE
"arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
, acb->host->host_no);
}
}
+static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *pACB)
+{
+ struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC;
+ pACB->acb_flags &= ~ACB_F_MSG_START_BGRB;
+ writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0);
+ writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell);
+ if (!arcmsr_hbc_wait_msgint_ready(pACB)) {
+ printk(KERN_NOTICE
+ "arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
+ , pACB->host->host_no);
+ }
+ return;
+}
static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
@@ -1177,22 +1292,16 @@ static void arcmsr_stop_adapter_bgrb(str
arcmsr_stop_hbb_bgrb(acb);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ arcmsr_stop_hbc_bgrb(acb);
+ }
}
}
static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb)
{
- switch (acb->adapter_type) {
- case ACB_ADAPTER_TYPE_A: {
- dma_free_coherent(&acb->pdev->dev, acb->uncache_size, acb->dma_coherent, acb->dma_coherent_handle);
- iounmap(acb->pmuA);
- }
- break;
- case ACB_ADAPTER_TYPE_B: {
dma_free_coherent(&acb->pdev->dev, acb->uncache_size, acb->dma_coherent, acb->dma_coherent_handle);
}
- }
-}
void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
{
@@ -1208,6 +1317,10 @@ void arcmsr_iop_message_read(struct Adap
writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ struct MessageUnit_C __iomem *reg = acb->pmuC;
+ writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, ®->inbound_doorbell);
+ }
}
}
@@ -1233,6 +1346,15 @@ static void arcmsr_iop_message_wrote(str
writel(ARCMSR_DRV2IOP_DATA_WRITE_OK, reg->drv2iop_doorbell);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ struct MessageUnit_C __iomem *reg = acb->pmuC;
+ /*
+ ** push inbound doorbell tell iop, driver data write ok
+ ** and wait reply on next hwinterrupt for next Qbuffer post
+ */
+ writel(ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK, ®->inbound_doorbell);
+ }
+ break;
}
}
@@ -1253,6 +1374,10 @@ struct QBUFFER __iomem *arcmsr_get_iop_r
qbuffer = (struct QBUFFER __iomem *)reg->message_rbuffer;
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)acb->pmuC;
+ qbuffer = (struct QBUFFER __iomem *)&phbcmu->message_rbuffer;
+ }
}
return qbuffer;
}
@@ -1274,6 +1398,11 @@ static struct QBUFFER __iomem *arcmsr_ge
pqbuffer = (struct QBUFFER __iomem *)reg->message_wbuffer;
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC;
+ pqbuffer = (struct QBUFFER __iomem *)®->message_wbuffer;
+ }
+
}
return pqbuffer;
}
@@ -1358,14 +1485,42 @@ static void arcmsr_hba_doorbell_isr(stru
arcmsr_iop2drv_data_read_handle(acb);
}
}
-
+static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *pACB)
+{
+ uint32_t outbound_doorbell;
+ struct MessageUnit_C *reg = (struct MessageUnit_C *)pACB->pmuC;
+ /*
+ *******************************************************************
+ ** Maybe here we need to check wrqbuffer_lock is lock or not
+ ** DOORBELL: din! don!
+ ** check if there are any mail need to pack from firmware
+ *******************************************************************
+ */
+ outbound_doorbell = readl(®->outbound_doorbell);
+ writel(outbound_doorbell, ®->outbound_doorbell_clear);/*clear interrupt*/
+ if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) {
+ arcmsr_iop2drv_data_wrote_handle(pACB);
+ }
+ if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) {
+ arcmsr_iop2drv_data_read_handle(pACB);
+ }
+ if (outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
+ arcmsr_hbc_message_isr(pACB); /* messenger of "driver to iop commands" */
+ }
+ return;
+}
static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
{
uint32_t flag_ccb;
struct MessageUnit_A __iomem *reg = acb->pmuA;
-
+ struct ARCMSR_CDB *pARCMSR_CDB;
+ struct CommandControlBlock *pCCB;
+ bool error;
while ((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) {
- arcmsr_drain_donequeue(acb, flag_ccb);
+ pARCMSR_CDB = (struct ARCMSR_CDB *)(acb->vir2phy_offset + (flag_ccb << 5));/*frame must be 32 bytes aligned*/
+ pCCB = container_of(pARCMSR_CDB, struct CommandControlBlock, arcmsr_cdb);
+ error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE;
+ arcmsr_drain_donequeue(acb, pCCB, error);
}
}
@@ -1374,17 +1529,51 @@ static void arcmsr_hbb_postqueue_isr(str
uint32_t index;
uint32_t flag_ccb;
struct MessageUnit_B *reg = acb->pmuB;
-
+ struct ARCMSR_CDB *pARCMSR_CDB;
+ struct CommandControlBlock *pCCB;
+ bool error;
index = reg->doneq_index;
-
while ((flag_ccb = readl(®->done_qbuffer[index])) != 0) {
writel(0, ®->done_qbuffer[index]);
- arcmsr_drain_donequeue(acb, flag_ccb);
+ pARCMSR_CDB = (struct ARCMSR_CDB *)(acb->vir2phy_offset+(flag_ccb << 5));/*frame must be 32 bytes aligned*/
+ pCCB = container_of(pARCMSR_CDB, struct CommandControlBlock, arcmsr_cdb);
+ error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE;
+ arcmsr_drain_donequeue(acb, pCCB, error);
index++;
index %= ARCMSR_MAX_HBB_POSTQUEUE;
reg->doneq_index = index;
}
}
+
+static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb)
+{
+ struct MessageUnit_C *phbcmu;
+ struct ARCMSR_CDB *arcmsr_cdb;
+ struct CommandControlBlock *ccb;
+ uint32_t flag_ccb, ccb_cdb_phy, throttling = 0;
+ int error;
+
+ phbcmu = (struct MessageUnit_C *)acb->pmuC;
+ /* areca cdb command done */
+ /* Use correct offset and size for syncing */
+
+ while (readl(&phbcmu->host_int_status) &
+ ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR){
+ /* check if command done with no error*/
+ flag_ccb = readl(&phbcmu->outbound_queueport_low);
+ ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0);/*frame must be 32 bytes aligned*/
+ arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + ccb_cdb_phy);
+ ccb = container_of(arcmsr_cdb, struct CommandControlBlock, arcmsr_cdb);
+ error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
+ /* check if command done with no error */
+ arcmsr_drain_donequeue(acb, ccb, error);
+ if (throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) {
+ writel(ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING, &phbcmu->inbound_doorbell);
+ break;
+ }
+ throttling++;
+ }
+}
/*
**********************************************************************************
** Handle a message interrupt
@@ -1408,6 +1597,23 @@ static void arcmsr_hbb_message_isr(struc
writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell);
schedule_work(&acb->arcmsr_do_message_isr_bh);
}
+/*
+**********************************************************************************
+** Handle a message interrupt
+**
+** The only message interrupt we expect is in response to a query for the
+** current adapter config.
+** We want this in order to compare the drivemap so that we can detect newly-attached drives.
+**********************************************************************************
+*/
+static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb)
+{
+ struct MessageUnit_C *reg = acb->pmuC;
+ /*clear interrupt and message state*/
+ writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, ®->outbound_doorbell_clear);
+ schedule_work(&acb->arcmsr_do_message_isr_bh);
+}
+
static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb)
{
uint32_t outbound_intstatus;
@@ -1463,6 +1667,31 @@ static int arcmsr_handle_hbb_isr(struct
return 0;
}
+
+static int arcmsr_handle_hbc_isr(struct AdapterControlBlock *pACB)
+{
+ uint32_t host_interrupt_status;
+ struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)pACB->pmuC;
+ /*
+ *********************************************
+ ** check outbound intstatus
+ *********************************************
+ */
+ host_interrupt_status = readl(&phbcmu->host_int_status);
+ if (!host_interrupt_status) {
+ /*it must be share irq*/
+ return FALSE;
+ }
+ /* MU ioctl transfer doorbell interrupts*/
+ if (host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) {
+ arcmsr_hbc_doorbell_isr(pACB); /* messenger of "ioctl message read write" */
+ }
+ /* MU post queue interrupts*/
+ if (host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) {
+ arcmsr_hbc_postqueue_isr(pACB); /* messenger of "scsi commands" */
+ }
+ return TRUE;
+}
static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
@@ -1479,6 +1708,11 @@ static irqreturn_t arcmsr_interrupt(stru
}
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ if (arcmsr_handle_hbc_isr(acb)) {
+ return IRQ_NONE;
+ }
+ }
}
return IRQ_HANDLED;
}
@@ -1890,7 +2119,10 @@ static int arcmsr_queue_command(struct s
if (atomic_read(&acb->ccboutstandingcount) >=
ARCMSR_MAX_OUTSTANDING_CMD)
return SCSI_MLQUEUE_HOST_BUSY;
-
+ if ((scsicmd == SCSI_CMD_ARECA_SPECIFIC)) {
+ printk("Receiveing SCSI_CMD_ARECA_SPECIFIC command..\n");
+ return 0;
+ }
ccb = arcmsr_get_freeccb(acb);
if (!ccb)
return SCSI_MLQUEUE_HOST_BUSY;
@@ -1913,9 +2145,8 @@ static bool arcmsr_get_hba_config(struct
char __iomem *iop_firm_version = (char __iomem *)(®->message_rwbuffer[17]);
char __iomem *iop_device_map = (char __iomem *) (®->message_rwbuffer[21]);
int count;
-
writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0);
- if (arcmsr_hba_wait_msgint_ready(acb)) {
+ if (!arcmsr_hba_wait_msgint_ready(acb)) {
printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \
miscellaneous data' timeout \n", acb->host->host_no);
return false;
@@ -1991,7 +2222,7 @@ static bool arcmsr_get_hbb_config(struct
iop_device_map = (char __iomem *)(®->message_rwbuffer[21]); /*firm_version,21,84-99*/
writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell);
- if (arcmsr_hbb_wait_msgint_ready(acb)){
+ if (!arcmsr_hbb_wait_msgint_ready(acb)) {
printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \
miscellaneous data' timeout \n", acb->host->host_no);
return false;
@@ -2038,12 +2269,73 @@ static bool arcmsr_get_hbb_config(struct
/*firm_ide_channels,4,16-19*/
return true;
}
+
+static bool arcmsr_get_hbc_config(struct AdapterControlBlock *pACB)
+{
+ uint32_t intmask_org, Index, firmware_state = 0;
+ struct MessageUnit_C *reg = pACB->pmuC;
+ char *acb_firm_model = pACB->firm_model;
+ char *acb_firm_version = pACB->firm_version;
+ char *iop_firm_model = (char *)(®->msgcode_rwbuffer[15]); /*firm_model,15,60-67*/
+ char *iop_firm_version = (char *)(®->msgcode_rwbuffer[17]); /*firm_version,17,68-83*/
+ int count;
+ /* disable all outbound interrupt */
+ intmask_org = readl(®->host_int_mask); /* disable outbound message0 int */
+ writel(intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE, ®->host_int_mask);
+ /* wait firmware ready */
+ do {
+ firmware_state = readl(®->outbound_msgaddr1);
+ } while ((firmware_state & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0);
+ /* post "get config" instruction */
+ writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0);
+ writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell);
+ /* wait message ready */
+ for (Index = 0; Index < 2000; Index++) {
+ if (readl(®->outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
+ writel(ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR, ®->outbound_doorbell_clear);/*clear interrupt*/
+ break;
+ }
+ udelay(10);
+ } /*max 1 seconds*/
+ if (Index >= 2000) {
+ printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \
+ miscellaneous data' timeout \n", pACB->host->host_no);
+ return false;
+ }
+ count = 8;
+ while (count) {
+ *acb_firm_model = readb(iop_firm_model);
+ acb_firm_model++;
+ iop_firm_model++;
+ count--;
+ }
+ count = 16;
+ while (count) {
+ *acb_firm_version = readb(iop_firm_version);
+ acb_firm_version++;
+ iop_firm_version++;
+ count--;
+ }
+ printk(KERN_NOTICE "Areca RAID Controller%d: F/W %s & Model %s\n",
+ pACB->host->host_no,
+ pACB->firm_version,
+ pACB->firm_model);
+ pACB->firm_request_len = readl(®->msgcode_rwbuffer[1]); /*firm_request_len,1,04-07*/
+ pACB->firm_numbers_queue = readl(®->msgcode_rwbuffer[2]); /*firm_numbers_queue,2,08-11*/
+ pACB->firm_sdram_size = readl(®->msgcode_rwbuffer[3]); /*firm_sdram_size,3,12-15*/
+ pACB->firm_hd_channels = readl(®->msgcode_rwbuffer[4]); /*firm_ide_channels,4,16-19*/
+ pACB->firm_cfg_version = readl(®->msgcode_rwbuffer[25]); /*firm_cfg_version,25,100-103*/
+ /*all interrupt service will be enable at arcmsr_iop_init*/
+ return true;
+}
static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
{
if (acb->adapter_type == ACB_ADAPTER_TYPE_A)
return arcmsr_get_hba_config(acb);
- else
+ else if (acb->adapter_type == ACB_ADAPTER_TYPE_B)
return arcmsr_get_hbb_config(acb);
+ else
+ return arcmsr_get_hbc_config(acb);
}
static int arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb,
@@ -2054,7 +2346,7 @@ static int arcmsr_polling_hba_ccbdone(st
struct ARCMSR_CDB *arcmsr_cdb;
uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0;
int rtn;
-
+ bool error;
polling_hba_ccb_retry:
poll_count++;
outbound_intstatus = readl(®->outbound_intstatus) & acb->outbound_int_enable;
@@ -2065,6 +2357,7 @@ static int arcmsr_polling_hba_ccbdone(st
rtn = SUCCESS;
break;
} else {
+ msleep(25);
if (poll_count > 100) {
rtn = FAILED;
break;
@@ -2094,9 +2387,9 @@ static int arcmsr_polling_hba_ccbdone(st
, ccb
, atomic_read(&acb->ccboutstandingcount));
continue;
- } else {
- arcmsr_report_ccb_state(acb, ccb, flag_ccb);
}
+ error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE;
+ arcmsr_report_ccb_state(acb, ccb, error);
}
return rtn;
}
@@ -2109,7 +2402,7 @@ static int arcmsr_polling_hbb_ccbdone(st
struct CommandControlBlock *ccb;
uint32_t flag_ccb, poll_ccb_done = 0, poll_count = 0;
int index, rtn;
-
+ bool error;
polling_hbb_ccb_retry:
poll_count++;
/* clear doorbell interrupt */
@@ -2157,13 +2450,69 @@ static int arcmsr_polling_hbb_ccbdone(st
, ccb
, atomic_read(&acb->ccboutstandingcount));
continue;
- } else {
- arcmsr_report_ccb_state(acb, ccb, flag_ccb);
}
- } /*drain reply FIFO*/
+ error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE;
+ arcmsr_report_ccb_state(acb, ccb, error);
+ }
return rtn;
}
+static int arcmsr_polling_hbc_ccbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_ccb)
+{
+ struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC;
+ uint32_t flag_ccb, ccb_cdb_phy;
+ struct ARCMSR_CDB *arcmsr_cdb;
+ bool error;
+ struct CommandControlBlock *pCCB;
+ uint32_t poll_ccb_done = 0, poll_count = 0;
+ int rtn;
+ polling_hbc_ccb_retry:
+ poll_count++;
+ while (1) {
+ if ((readl(®->host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) == 0) {
+ if (poll_ccb_done) {
+ rtn = SUCCESS;
+ break;
+ } else {
+ msleep(25);
+ if (poll_count > 100) {
+ rtn = FAILED;
+ break;
+ }
+ goto polling_hbc_ccb_retry;
+ }
+ }
+ flag_ccb = readl(®->outbound_queueport_low);
+ ccb_cdb_phy = (flag_ccb & 0xFFFFFFF0);
+ arcmsr_cdb = (struct ARCMSR_CDB *)(acb->vir2phy_offset + ccb_cdb_phy);/*frame must be 32 bytes aligned*/
+ pCCB = container_of(arcmsr_cdb, struct CommandControlBlock, arcmsr_cdb);
+ poll_ccb_done = (pCCB == poll_ccb) ? 1 : 0;
+ /* check ifcommand done with no error*/
+ if ((pCCB->acb != acb) || (pCCB->startdone != ARCMSR_CCB_START)) {
+ if (pCCB->startdone == ARCMSR_CCB_ABORTED) {
+ printk(KERN_NOTICE "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'"
+ " poll command abort successfully \n"
+ , acb->host->host_no
+ , pCCB->pcmd->device->id
+ , pCCB->pcmd->device->lun
+ , pCCB);
+ pCCB->pcmd->result = DID_ABORT << 16;
+ arcmsr_ccb_complete(pCCB);
+ continue;
+ }
+ printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb"
+ " command done ccb = '0x%p'"
+ "ccboutstandingcount = %d \n"
+ , acb->host->host_no
+ , pCCB
+ , atomic_read(&acb->ccboutstandingcount));
+ continue;
+ }
+ error = (flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
+ arcmsr_report_ccb_state(acb, pCCB, error);
+ }
+ return rtn;
+}
static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb,
struct CommandControlBlock *poll_ccb)
{
@@ -2178,6 +2527,10 @@ static int arcmsr_polling_ccbdone(struct
case ACB_ADAPTER_TYPE_B: {
rtn = arcmsr_polling_hbb_ccbdone(acb, poll_ccb);
}
+ break;
+ case ACB_ADAPTER_TYPE_C: {
+ rtn = arcmsr_polling_hbc_ccbdone(acb, poll_ccb);
+ }
}
return rtn;
}
@@ -2195,6 +2548,7 @@ static int arcmsr_iop_confirm(struct Ada
dma_coherent_handle = acb->dma_coherent_handle;
cdb_phyaddr = (uint32_t)(dma_coherent_handle);
cdb_phyaddr_hi32 = (uint32_t)((cdb_phyaddr >> 16) >> 16);
+ acb->cdb_phyaddr_hi32 = cdb_phyaddr_hi32;
/*
***********************************************************************
** if adapter type B, set window of "post command Q"
@@ -2212,7 +2566,7 @@ static int arcmsr_iop_confirm(struct Ada
writel(cdb_phyaddr_hi32, ®->message_rwbuffer[1]);
writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, \
®->inbound_msgaddr0);
- if (arcmsr_hba_wait_msgint_ready(acb)) {
+ if (!arcmsr_hba_wait_msgint_ready(acb)) {
printk(KERN_NOTICE "arcmsr%d: ""set ccb high \
part physical address timeout\n",
acb->host->host_no);
@@ -2233,7 +2587,7 @@ static int arcmsr_iop_confirm(struct Ada
reg->postq_index = 0;
reg->doneq_index = 0;
writel(ARCMSR_MESSAGE_SET_POST_WINDOW, reg->drv2iop_doorbell);
- if (arcmsr_hbb_wait_msgint_ready(acb)) {
+ if (!arcmsr_hbb_wait_msgint_ready(acb)) {
printk(KERN_NOTICE "arcmsr%d:can not set diver mode\n", \
acb->host->host_no);
return 1;
@@ -2252,7 +2606,7 @@ static int arcmsr_iop_confirm(struct Ada
writel(1056, rwbuffer);
writel(ARCMSR_MESSAGE_SET_CONFIG, reg->drv2iop_doorbell);
- if (arcmsr_hbb_wait_msgint_ready(acb)) {
+ if (!arcmsr_hbb_wait_msgint_ready(acb)) {
printk(KERN_NOTICE "arcmsr%d: 'set command Q window' \
timeout \n",acb->host->host_no);
return 1;
@@ -2261,6 +2615,27 @@ static int arcmsr_iop_confirm(struct Ada
arcmsr_enable_outbound_ints(acb, intmask_org);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ if (cdb_phyaddr_hi32 != 0) {
+ struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC;
+
+ if (cdb_phyaddr_hi32 != 0) {
+ unsigned char Retries = 0x00;
+ do {
+ printk(KERN_NOTICE "arcmsr%d: cdb_phyaddr_hi32=0x%x \n", acb->adapter_index, cdb_phyaddr_hi32);
+ } while (Retries++ < 100);
+ }
+ writel(ARCMSR_SIGNATURE_SET_CONFIG, ®->msgcode_rwbuffer[0]);
+ writel(cdb_phyaddr_hi32, ®->msgcode_rwbuffer[1]);
+ writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, ®->inbound_msgaddr0);
+ writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell);
+ if (!arcmsr_hbc_wait_msgint_ready(acb)) {
+ printk(KERN_NOTICE "arcmsr%d: 'set command Q window' \
+ timeout \n", acb->host->host_no);
+ return 1;
+ }
+ }
+ }
}
return 0;
}
@@ -2287,6 +2661,12 @@ static void arcmsr_wait_firmware_ready(s
writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC;
+ do {
+ firmware_state = readl(®->outbound_msgaddr1);
+ } while ((firmware_state & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0);
+ }
}
}
@@ -2329,6 +2708,26 @@ static void arcmsr_request_hbb_device_ma
return;
}
+static void arcmsr_request_hbc_device_map(struct AdapterControlBlock *acb)
+{
+ struct MessageUnit_C __iomem *reg = acb->pmuC;
+ if (unlikely(atomic_read(&acb->rq_map_token) == 0) || ((acb->acb_flags & ACB_F_BUS_RESET) != 0) || ((acb->acb_flags & ACB_F_ABORT) != 0)) {
+ return;
+ } else {
+ acb->fw_flag = FW_NORMAL;
+ if (atomic_read(&acb->ante_token_value) == atomic_read(&acb->rq_map_token)) {
+ atomic_set(&acb->rq_map_token, 16);
+ }
+ atomic_set(&acb->ante_token_value, atomic_read(&acb->rq_map_token));
+ if (atomic_dec_and_test(&acb->rq_map_token))
+ return;
+ writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0);
+ writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, ®->inbound_doorbell);
+ mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6 * HZ));
+ }
+ return;
+}
+
static void arcmsr_request_device_map(unsigned long pacb)
{
struct AdapterControlBlock *acb = (struct AdapterControlBlock *)pacb;
@@ -2342,6 +2740,9 @@ static void arcmsr_request_device_map(un
arcmsr_request_hbb_device_map(acb);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ arcmsr_request_hbc_device_map(acb);
+ }
}
}
@@ -2350,7 +2751,7 @@ static void arcmsr_start_hba_bgrb(struct
struct MessageUnit_A __iomem *reg = acb->pmuA;
acb->acb_flags |= ACB_F_MSG_START_BGRB;
writel(ARCMSR_INBOUND_MESG0_START_BGRB, ®->inbound_msgaddr0);
- if (arcmsr_hba_wait_msgint_ready(acb)) {
+ if (!arcmsr_hba_wait_msgint_ready(acb)) {
printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \
rebulid' timeout \n", acb->host->host_no);
}
@@ -2361,12 +2762,24 @@ static void arcmsr_start_hbb_bgrb(struct
struct MessageUnit_B *reg = acb->pmuB;
acb->acb_flags |= ACB_F_MSG_START_BGRB;
writel(ARCMSR_MESSAGE_START_BGRB, reg->drv2iop_doorbell);
- if (arcmsr_hbb_wait_msgint_ready(acb)) {
+ if (!arcmsr_hbb_wait_msgint_ready(acb)) {
printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \
rebulid' timeout \n",acb->host->host_no);
}
}
+static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *pACB)
+{
+ struct MessageUnit_C *phbcmu = (struct MessageUnit_C *)pACB->pmuC;
+ pACB->acb_flags |= ACB_F_MSG_START_BGRB;
+ writel(ARCMSR_INBOUND_MESG0_START_BGRB, &phbcmu->inbound_msgaddr0);
+ writel(ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE, &phbcmu->inbound_doorbell);
+ if (!arcmsr_hbc_wait_msgint_ready(pACB)) {
+ printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \
+ rebulid' timeout \n", pACB->host->host_no);
+ }
+ return;
+}
static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
@@ -2376,6 +2789,8 @@ static void arcmsr_start_adapter_bgrb(st
case ACB_ADAPTER_TYPE_B:
arcmsr_start_hbb_bgrb(acb);
break;
+ case ACB_ADAPTER_TYPE_C:
+ arcmsr_start_hbc_bgrb(acb);
}
}
@@ -2401,6 +2816,14 @@ static void arcmsr_clear_doorbell_queue_
/* let IOP know data has been read */
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ struct MessageUnit_C *reg = (struct MessageUnit_C *)acb->pmuC;
+ uint32_t outbound_doorbell;
+ /* empty doorbell Qbuffer if door bell ringed */
+ outbound_doorbell = readl(®->outbound_doorbell);
+ writel(outbound_doorbell, ®->outbound_doorbell_clear);
+ writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, ®->inbound_doorbell);
+ }
}
}
@@ -2413,12 +2836,14 @@ static void arcmsr_enable_eoi_mode(struc
{
struct MessageUnit_B *reg = acb->pmuB;
writel(ARCMSR_MESSAGE_ACTIVE_EOI_MODE, reg->drv2iop_doorbell);
- if(arcmsr_hbb_wait_msgint_ready(acb)) {
+ if (!arcmsr_hbb_wait_msgint_ready(acb)) {
printk(KERN_NOTICE "ARCMSR IOP enables EOI_MODE TIMEOUT");
return;
}
}
break;
+ case ACB_ADAPTER_TYPE_C:
+ return;
}
return;
}
@@ -2426,21 +2851,33 @@ static void arcmsr_enable_eoi_mode(struc
static void arcmsr_hardware_reset(struct AdapterControlBlock *acb)
{
uint8_t value[64];
- int i;
- struct MessageUnit_A __iomem *reg = acb->pmuA;
-
+ int i, count = 0;
+ struct MessageUnit_A __iomem *pmuA = acb->pmuA;
+ struct MessageUnit_C __iomem *pmuC = acb->pmuC;
+ u32 temp = 0;
/* backup pci config data */
- printk(KERN_ERR "arcmsr%d: executing hw bus reset .....\n", acb->host->host_no);
+ printk("arcmsr%d: executing hw bus reset .....\n", acb->host->host_no);
for (i=0; i<64; i++) {
pci_read_config_byte(acb->pdev, i, &value[i]);
}
/* hardware reset signal */
if ((acb->dev_id == 0x1680)) {
- writel(ARCMSR_ARC1680_BUS_RESET, ®->reserved1[0]);
+ writel(ARCMSR_ARC1680_BUS_RESET, &pmuA->reserved1[0]);
+ } else if ((acb->dev_id == 0x1880)) {
+ do {
+ count++;
+ writel(0xF, &pmuC->write_sequence);
+ writel(0x4, &pmuC->write_sequence);
+ writel(0xB, &pmuC->write_sequence);
+ writel(0x2, &pmuC->write_sequence);
+ writel(0x7, &pmuC->write_sequence);
+ writel(0xD, &pmuC->write_sequence);
+ } while ((((temp = readl(&pmuC->host_diagnostic)) | ARCMSR_ARC1880_DiagWrite_ENABLE) == 0) && (count < 5));
+ writel(ARCMSR_ARC1880_RESET_ADAPTER, &pmuC->host_diagnostic);
} else {
pci_write_config_byte(acb->pdev, 0x84, 0x20);
}
- msleep(1000);
+ msleep(2000);
/* write back pci config data */
for (i=0;i<64;i++) {
pci_write_config_byte(acb->pdev, i, value[i]);
@@ -2448,29 +2885,6 @@ static void arcmsr_hardware_reset(struct
msleep(1000);
return;
}
-/*
-****************************************************************************
-****************************************************************************
-*/
-int arcmsr_sleep_for_bus_reset(struct scsi_cmnd *cmd)
-{
- struct Scsi_Host *shost = NULL;
- int i, isleep;
-
- shost = cmd->device->host;
- isleep = sleeptime / 10;
- if (isleep > 0) {
- for (i = 0; i < isleep; i ++) {
- msleep(10000);
- }
- }
-
- isleep = sleeptime % 10;
- if (isleep > 0) {
- msleep(isleep*1000);
- }
- return 0;
-}
static void arcmsr_iop_init(struct AdapterControlBlock *acb)
{
uint32_t intmask_org;
@@ -2523,37 +2936,35 @@ static int arcmsr_bus_reset(struct scsi_
uint32_t intmask_org, outbound_doorbell;
int retry_count = 0;
int rtn = FAILED;
-
acb = (struct AdapterControlBlock *) cmd->device->host->hostdata;
- printk(KERN_ERR "arcmsr: executing eh bus reset .....num_resets = %d,
- num_aborts = %d \n", acb->num_resets, acb->num_aborts);
+ printk(KERN_ERR "arcmsr: executing bus reset eh.....num_resets = %d, num_aborts = %d \n", acb->num_resets, acb->num_aborts);
acb->num_resets++;
switch(acb->adapter_type){
case ACB_ADAPTER_TYPE_A:{
if (acb->acb_flags & ACB_F_BUS_RESET) {
long timeout;
- timeout = wait_event_timeout(wait_q,
- (acb->acb_flags & ACB_F_BUS_RESET) == 0, 220*HZ);
+ printk(KERN_ERR "arcmsr: there is an bus reset eh proceeding.......\n");
+ timeout = wait_event_timeout(wait_q, (acb->acb_flags & ACB_F_BUS_RESET) == 0, 220*HZ);
if (timeout) {
return SUCCESS;
}
}
acb->acb_flags |= ACB_F_BUS_RESET;
- if (arcmsr_iop_reset(acb)) {
+ if (!arcmsr_iop_reset(acb)) {
struct MessageUnit_A __iomem *reg;
reg = acb->pmuA;
+ spin_unlock_irq(acb->host->host_lock);
arcmsr_hardware_reset(acb);
acb->acb_flags &= ~ACB_F_IOP_INITED;
sleep_again:
arcmsr_sleep_for_bus_reset(cmd);
if ((readl(®->outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) {
- printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return,
- retry=%d \n", acb->host->host_no, retry_count);
+ printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, retry=%d \n", acb->host->host_no, retry_count);
if (retry_count > retrycount) {
acb->fw_flag = FW_DEADLOCK;
- printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return,
- RETRY TERMINATED!! \n", acb->host->host_no);
+ printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, RETRY TERMINATED!! \n", acb->host->host_no);
+ spin_lock_irq(acb->host->host_lock);
return FAILED;
}
retry_count++;
@@ -2580,7 +2991,8 @@ static int arcmsr_bus_reset(struct scsi_
add_timer(&acb->eternal_timer);
acb->acb_flags &= ~ACB_F_BUS_RESET;
rtn = SUCCESS;
- printk(KERN_ERR "arcmsr: scsi eh bus reset succeeds\n");
+ printk(KERN_ERR "arcmsr: scsi bus reset eh returns with success\n");
+ spin_lock_irq(acb->host->host_lock);
} else {
acb->acb_flags &= ~ACB_F_BUS_RESET;
if (atomic_read(&acb->rq_map_token) == 0) {
@@ -2604,7 +3016,7 @@ static int arcmsr_bus_reset(struct scsi_
}
case ACB_ADAPTER_TYPE_B:{
acb->acb_flags |= ACB_F_BUS_RESET;
- if (arcmsr_iop_reset(acb)) {
+ if (!arcmsr_iop_reset(acb)) {
acb->acb_flags &= ~ACB_F_BUS_RESET;
rtn = FAILED;
} else {
@@ -2626,6 +3038,77 @@ static int arcmsr_bus_reset(struct scsi_
}
rtn = SUCCESS;
}
+ break;
+ }
+ case ACB_ADAPTER_TYPE_C:{
+ if (acb->acb_flags & ACB_F_BUS_RESET) {
+ long timeout;
+ printk(KERN_ERR "arcmsr: there is an bus reset eh proceeding.......\n");
+ timeout = wait_event_timeout(wait_q, (acb->acb_flags & ACB_F_BUS_RESET) == 0, 220*HZ);
+ if (timeout) {
+ return SUCCESS;
+ }
+ }
+ acb->acb_flags |= ACB_F_BUS_RESET;
+ if (!arcmsr_iop_reset(acb)) {
+ struct MessageUnit_C __iomem *reg;
+ reg = acb->pmuC;
+ arcmsr_hardware_reset(acb);
+ acb->acb_flags &= ~ACB_F_IOP_INITED;
+ sleep:
+ arcmsr_sleep_for_bus_reset(cmd);
+ if ((readl(®->host_diagnostic) & 0x04) != 0) {
+ printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, retry=%d \n", acb->host->host_no, retry_count);
+ if (retry_count > retrycount) {
+ acb->fw_flag = FW_DEADLOCK;
+ printk(KERN_ERR "arcmsr%d: waiting for hw bus reset return, RETRY TERMINATED!! \n", acb->host->host_no);
+ return FAILED;
+ }
+ retry_count++;
+ goto sleep;
+ }
+ acb->acb_flags |= ACB_F_IOP_INITED;
+ /* disable all outbound interrupt */
+ intmask_org = arcmsr_disable_outbound_ints(acb);
+ arcmsr_get_firmware_spec(acb);
+ arcmsr_start_adapter_bgrb(acb);
+ /* clear Qbuffer if door bell ringed */
+ outbound_doorbell = readl(®->outbound_doorbell);
+ writel(outbound_doorbell, ®->outbound_doorbell_clear); /*clear interrupt */
+ writel(ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK, ®->inbound_doorbell);
+ /* enable outbound Post Queue,outbound doorbell Interrupt */
+ arcmsr_enable_outbound_ints(acb, intmask_org);
+ atomic_set(&acb->rq_map_token, 16);
+ atomic_set(&acb->ante_token_value, 16);
+ acb->fw_flag = FW_NORMAL;
+ init_timer(&acb->eternal_timer);
+ acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6 * HZ);
+ acb->eternal_timer.data = (unsigned long) acb;
+ acb->eternal_timer.function = &arcmsr_request_device_map;
+ add_timer(&acb->eternal_timer);
+ acb->acb_flags &= ~ACB_F_BUS_RESET;
+ rtn = SUCCESS;
+ printk(KERN_ERR "arcmsr: scsi bus reset eh returns with success\n");
+ } else {
+ acb->acb_flags &= ~ACB_F_BUS_RESET;
+ if (atomic_read(&acb->rq_map_token) == 0) {
+ atomic_set(&acb->rq_map_token, 16);
+ atomic_set(&acb->ante_token_value, 16);
+ acb->fw_flag = FW_NORMAL;
+ init_timer(&acb->eternal_timer);
+ acb->eternal_timer.expires = jiffies + msecs_to_jiffies(6*HZ);
+ acb->eternal_timer.data = (unsigned long) acb;
+ acb->eternal_timer.function = &arcmsr_request_device_map;
+ add_timer(&acb->eternal_timer);
+ } else {
+ atomic_set(&acb->rq_map_token, 16);
+ atomic_set(&acb->ante_token_value, 16);
+ acb->fw_flag = FW_NORMAL;
+ mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6*HZ));
+ }
+ rtn = SUCCESS;
+ }
+ break;
}
}
return rtn;
@@ -2635,9 +3118,7 @@ static int arcmsr_abort_one_cmd(struct A
struct CommandControlBlock *ccb)
{
int rtn;
- spin_lock_irq(&acb->eh_lock);
rtn = arcmsr_polling_ccbdone(acb, ccb);
- spin_unlock_irq(&acb->eh_lock);
return rtn;
}
@@ -2663,7 +3143,6 @@ static int arcmsr_abort(struct scsi_cmnd
return rtn;
for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
- printk("%s: loop %d\n", __FUNCTION__, i);
struct CommandControlBlock *ccb = acb->pccb_pool[i];
if (ccb->startdone == ARCMSR_CCB_START && ccb->pcmd == cmd) {
ccb->startdone = ARCMSR_CCB_ABORTED;
@@ -2672,7 +3151,6 @@ static int arcmsr_abort(struct scsi_cmnd
}
}
acb->acb_flags &= ~ACB_F_ABORT;
- printk("%s: leaving\n", __FUNCTION__);
return rtn;
}
@@ -2707,6 +3184,7 @@ static const char *arcmsr_info(struct Sc
case PCI_DEVICE_ID_ARECA_1381:
case PCI_DEVICE_ID_ARECA_1680:
case PCI_DEVICE_ID_ARECA_1681:
+ case PCI_DEVICE_ID_ARECA_1880:
type = "SAS";
break;
default:
next reply other threads:[~2010-04-15 6:01 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-04-15 6:01 Nick Cheng [this message]
-- strict thread matches above, loose matches on Subject: below --
2010-05-03 7:46 [PATCH 3/3 ] SCSI: Support Type C RAID controller Nick Cheng
2010-04-09 2:27 Nick Cheng
2010-04-02 5:55 Nick Cheng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=60FF59AA20D44726B3BB8DCBA9775ADC@areca4e4f859d4 \
--to=nick.cheng@areca.com.tw \
--cc=James.Bottomley@HansenPartnership.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox