mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-02 11:56:40 +07:00
scsi: arcmsr: Add code for ACB_ADAPTER_TYPE_E
Add code for ACB_ADAPTER_TYPE_E to support new adapter ARC-1884. Signed-off-by: Ching Huang <ching2048@areca.com.tw> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
72a7f3130f
commit
235090241c
@ -65,6 +65,7 @@ struct device_attribute;
|
||||
#define ARCMSR_MAX_HBB_POSTQUEUE 264
|
||||
#define ARCMSR_MAX_ARC1214_POSTQUEUE 256
|
||||
#define ARCMSR_MAX_ARC1214_DONEQUEUE 257
|
||||
#define ARCMSR_MAX_HBE_DONEQUEUE 512
|
||||
#define ARCMSR_MAX_XFER_LEN 0x26000 /* 152K */
|
||||
#define ARCMSR_CDB_SG_PAGE_LENGTH 256
|
||||
#define ARCMST_NUM_MSIX_VECTORS 4
|
||||
@ -77,6 +78,9 @@ struct device_attribute;
|
||||
#ifndef PCI_DEVICE_ID_ARECA_1203
|
||||
#define PCI_DEVICE_ID_ARECA_1203 0x1203
|
||||
#endif
|
||||
#ifndef PCI_DEVICE_ID_ARECA_1884
|
||||
#define PCI_DEVICE_ID_ARECA_1884 0x1884
|
||||
#endif
|
||||
/*
|
||||
**********************************************************************************
|
||||
**
|
||||
@ -407,6 +411,31 @@ struct FIRMWARE_INFO
|
||||
#define ARCMSR_ARC1214_OUTBOUND_LIST_INTERRUPT_CLEAR 0x00000001
|
||||
/*
|
||||
*******************************************************************************
|
||||
** SPEC. for Areca Type E adapter
|
||||
*******************************************************************************
|
||||
*/
|
||||
#define ARCMSR_SIGNATURE_1884 0x188417D3
|
||||
|
||||
#define ARCMSR_HBEMU_DRV2IOP_DATA_WRITE_OK 0x00000002
|
||||
#define ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK 0x00000004
|
||||
#define ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE 0x00000008
|
||||
|
||||
#define ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK 0x00000002
|
||||
#define ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK 0x00000004
|
||||
#define ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE 0x00000008
|
||||
|
||||
#define ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK 0x80000000
|
||||
|
||||
#define ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR 0x00000001
|
||||
#define ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR 0x00000008
|
||||
#define ARCMSR_HBEMU_ALL_INTMASKENABLE 0x00000009
|
||||
|
||||
/* ARC-1884 doorbell sync */
|
||||
#define ARCMSR_HBEMU_DOORBELL_SYNC 0x100
|
||||
#define ARCMSR_ARC188X_RESET_ADAPTER 0x00000004
|
||||
#define ARCMSR_ARC1884_DiagWrite_ENABLE 0x00000080
|
||||
/*
|
||||
*******************************************************************************
|
||||
** ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504)
|
||||
*******************************************************************************
|
||||
*/
|
||||
@ -614,6 +643,88 @@ struct MessageUnit_D {
|
||||
u32 __iomem *msgcode_rwbuffer; /* 0x2200 */
|
||||
};
|
||||
/*
|
||||
*********************************************************************
|
||||
** Messaging Unit (MU) of Type E processor(LSI)
|
||||
*********************************************************************
|
||||
*/
|
||||
struct MessageUnit_E{
|
||||
uint32_t iobound_doorbell; /*0000 0003*/
|
||||
uint32_t write_sequence_3xxx; /*0004 0007*/
|
||||
uint32_t host_diagnostic_3xxx; /*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 reply_post_producer_index; /*0068 006B*/
|
||||
uint32_t reply_post_consumer_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*/
|
||||
};
|
||||
|
||||
typedef struct deliver_completeQ {
|
||||
uint16_t cmdFlag;
|
||||
uint16_t cmdSMID;
|
||||
uint16_t cmdLMID; // reserved (0)
|
||||
uint16_t cmdFlag2; // reserved (0)
|
||||
} DeliverQ, CompletionQ, *pDeliver_Q, *pCompletion_Q;
|
||||
/*
|
||||
*******************************************************************************
|
||||
** Adapter Control Block
|
||||
*******************************************************************************
|
||||
@ -625,6 +736,7 @@ struct AdapterControlBlock
|
||||
#define ACB_ADAPTER_TYPE_B 0x00000001 /* hbb M IOP */
|
||||
#define ACB_ADAPTER_TYPE_C 0x00000002 /* hbc L IOP */
|
||||
#define ACB_ADAPTER_TYPE_D 0x00000003 /* hbd M IOP */
|
||||
#define ACB_ADAPTER_TYPE_E 0x00000004 /* hba L IOP */
|
||||
u32 roundup_ccbsize;
|
||||
struct pci_dev * pdev;
|
||||
struct Scsi_Host * host;
|
||||
@ -644,6 +756,7 @@ struct AdapterControlBlock
|
||||
struct MessageUnit_B *pmuB;
|
||||
struct MessageUnit_C __iomem *pmuC;
|
||||
struct MessageUnit_D *pmuD;
|
||||
struct MessageUnit_E __iomem *pmuE;
|
||||
};
|
||||
/* message unit ATU inbound base address0 */
|
||||
void __iomem *mem_base0;
|
||||
@ -723,6 +836,12 @@ struct AdapterControlBlock
|
||||
atomic_t ante_token_value;
|
||||
uint32_t maxOutstanding;
|
||||
int vector_count;
|
||||
uint32_t doneq_index;
|
||||
uint32_t ccbsize;
|
||||
uint32_t in_doorbell;
|
||||
uint32_t out_doorbell;
|
||||
uint32_t completionQ_entry;
|
||||
pCompletion_Q pCompletionQ;
|
||||
};/* HW_DEVICE_EXTENSION */
|
||||
/*
|
||||
*******************************************************************************
|
||||
@ -748,12 +867,13 @@ struct CommandControlBlock{
|
||||
#define ARCMSR_CCB_START 0x55AA
|
||||
#define ARCMSR_CCB_ABORTED 0xAA55
|
||||
#define ARCMSR_CCB_ILLEGAL 0xFFFF
|
||||
uint32_t smid;
|
||||
#if BITS_PER_LONG == 64
|
||||
/* ======================512+64 bytes======================== */
|
||||
uint32_t reserved[5]; /*24 byte*/
|
||||
uint32_t reserved[4]; /*16 byte*/
|
||||
#else
|
||||
/* ======================512+32 bytes======================== */
|
||||
uint32_t reserved; /*8 byte*/
|
||||
// uint32_t reserved; /*4 byte*/
|
||||
#endif
|
||||
/* ======================================================= */
|
||||
struct ARCMSR_CDB arcmsr_cdb;
|
||||
|
@ -110,6 +110,8 @@ static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb);
|
||||
static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb);
|
||||
static void arcmsr_hbaC_message_isr(struct AdapterControlBlock *pACB);
|
||||
static void arcmsr_hbaD_message_isr(struct AdapterControlBlock *acb);
|
||||
static void arcmsr_hbaE_message_isr(struct AdapterControlBlock *acb);
|
||||
static void arcmsr_hbaE_postqueue_isr(struct AdapterControlBlock *acb);
|
||||
static void arcmsr_hardware_reset(struct AdapterControlBlock *acb);
|
||||
static const char *arcmsr_info(struct Scsi_Host *);
|
||||
static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb);
|
||||
@ -184,6 +186,8 @@ static struct pci_device_id arcmsr_device_id_table[] = {
|
||||
.driver_data = ACB_ADAPTER_TYPE_A},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1880),
|
||||
.driver_data = ACB_ADAPTER_TYPE_C},
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1884),
|
||||
.driver_data = ACB_ADAPTER_TYPE_E},
|
||||
{0, 0}, /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, arcmsr_device_id_table);
|
||||
@ -206,7 +210,8 @@ static void arcmsr_free_mu(struct AdapterControlBlock *acb)
|
||||
{
|
||||
switch (acb->adapter_type) {
|
||||
case ACB_ADAPTER_TYPE_B:
|
||||
case ACB_ADAPTER_TYPE_D: {
|
||||
case ACB_ADAPTER_TYPE_D:
|
||||
case ACB_ADAPTER_TYPE_E: {
|
||||
dma_free_coherent(&acb->pdev->dev, acb->roundup_ccbsize,
|
||||
acb->dma_coherent2, acb->dma_coherent_handle2);
|
||||
break;
|
||||
@ -271,6 +276,20 @@ static bool arcmsr_remap_pciregion(struct AdapterControlBlock *acb)
|
||||
acb->mem_base0 = mem_base0;
|
||||
break;
|
||||
}
|
||||
case ACB_ADAPTER_TYPE_E: {
|
||||
acb->pmuE = ioremap(pci_resource_start(pdev, 1),
|
||||
pci_resource_len(pdev, 1));
|
||||
if (!acb->pmuE) {
|
||||
pr_notice("arcmsr%d: memory mapping region fail \n",
|
||||
acb->host->host_no);
|
||||
return false;
|
||||
}
|
||||
writel(0, &acb->pmuE->host_int_status); /*clear interrupt*/
|
||||
writel(ARCMSR_HBEMU_DOORBELL_SYNC, &acb->pmuE->iobound_doorbell); /* synchronize doorbell to 0 */
|
||||
acb->in_doorbell = 0;
|
||||
acb->out_doorbell = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -295,6 +314,9 @@ static void arcmsr_unmap_pciregion(struct AdapterControlBlock *acb)
|
||||
case ACB_ADAPTER_TYPE_D:
|
||||
iounmap(acb->mem_base0);
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E:
|
||||
iounmap(acb->pmuE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,6 +430,24 @@ static bool arcmsr_hbaD_wait_msgint_ready(struct AdapterControlBlock *pACB)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool arcmsr_hbaE_wait_msgint_ready(struct AdapterControlBlock *pACB)
|
||||
{
|
||||
int i;
|
||||
uint32_t read_doorbell;
|
||||
struct MessageUnit_E __iomem *phbcmu = pACB->pmuE;
|
||||
|
||||
for (i = 0; i < 2000; i++) {
|
||||
read_doorbell = readl(&phbcmu->iobound_doorbell);
|
||||
if ((read_doorbell ^ pACB->in_doorbell) & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
|
||||
writel(0, &phbcmu->host_int_status); /*clear interrupt*/
|
||||
pACB->in_doorbell = read_doorbell;
|
||||
return true;
|
||||
}
|
||||
msleep(10);
|
||||
} /* max 20 seconds */
|
||||
return false;
|
||||
}
|
||||
|
||||
static void arcmsr_hbaA_flush_cache(struct AdapterControlBlock *acb)
|
||||
{
|
||||
struct MessageUnit_A __iomem *reg = acb->pmuA;
|
||||
@ -475,6 +515,24 @@ static void arcmsr_hbaD_flush_cache(struct AdapterControlBlock *pACB)
|
||||
} while (retry_count != 0);
|
||||
}
|
||||
|
||||
static void arcmsr_hbaE_flush_cache(struct AdapterControlBlock *pACB)
|
||||
{
|
||||
int retry_count = 30;
|
||||
struct MessageUnit_E __iomem *reg = pACB->pmuE;
|
||||
|
||||
writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0);
|
||||
pACB->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
|
||||
writel(pACB->out_doorbell, ®->iobound_doorbell);
|
||||
do {
|
||||
if (arcmsr_hbaE_wait_msgint_ready(pACB))
|
||||
break;
|
||||
retry_count--;
|
||||
pr_notice("arcmsr%d: wait 'flush adapter "
|
||||
"cache' timeout, retry count down = %d\n",
|
||||
pACB->host->host_no, retry_count);
|
||||
} while (retry_count != 0);
|
||||
}
|
||||
|
||||
static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
|
||||
{
|
||||
switch (acb->adapter_type) {
|
||||
@ -495,6 +553,9 @@ static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
|
||||
case ACB_ADAPTER_TYPE_D:
|
||||
arcmsr_hbaD_flush_cache(acb);
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E:
|
||||
arcmsr_hbaE_flush_cache(acb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -577,6 +638,23 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb)
|
||||
reg->msgcode_rwbuffer = MEM_BASE0(ARCMSR_ARC1214_MESSAGE_RWBUFFER);
|
||||
}
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E: {
|
||||
uint32_t completeQ_size;
|
||||
completeQ_size = sizeof(struct deliver_completeQ) * ARCMSR_MAX_HBE_DONEQUEUE + 128;
|
||||
acb->roundup_ccbsize = roundup(completeQ_size, 32);
|
||||
dma_coherent = dma_zalloc_coherent(&pdev->dev, acb->roundup_ccbsize,
|
||||
&dma_coherent_handle, GFP_KERNEL);
|
||||
if (!dma_coherent){
|
||||
pr_notice("arcmsr%d: DMA allocation failed\n", acb->host->host_no);
|
||||
return false;
|
||||
}
|
||||
acb->dma_coherent_handle2 = dma_coherent_handle;
|
||||
acb->dma_coherent2 = dma_coherent;
|
||||
acb->pCompletionQ = dma_coherent;
|
||||
acb->completionQ_entry = acb->roundup_ccbsize / sizeof(struct deliver_completeQ);
|
||||
acb->doneq_index = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -619,6 +697,7 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
|
||||
acb->dma_coherent = dma_coherent;
|
||||
acb->dma_coherent_handle = dma_coherent_handle;
|
||||
memset(dma_coherent, 0, acb->uncache_size);
|
||||
acb->ccbsize = roundup_ccbsize;
|
||||
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++){
|
||||
@ -630,11 +709,13 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_C:
|
||||
case ACB_ADAPTER_TYPE_D:
|
||||
case ACB_ADAPTER_TYPE_E:
|
||||
ccb_tmp->cdb_phyaddr = cdb_phyaddr;
|
||||
break;
|
||||
}
|
||||
acb->pccb_pool[i] = ccb_tmp;
|
||||
ccb_tmp->acb = acb;
|
||||
ccb_tmp->smid = (u32)i << 16;
|
||||
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);
|
||||
@ -683,6 +764,13 @@ static void arcmsr_message_isr_bh_fn(struct work_struct *work)
|
||||
devicemap = (char __iomem *)(®->msgcode_rwbuffer[21]);
|
||||
break;
|
||||
}
|
||||
case ACB_ADAPTER_TYPE_E: {
|
||||
struct MessageUnit_E __iomem *reg = acb->pmuE;
|
||||
|
||||
signature = (uint32_t __iomem *)(®->msgcode_rwbuffer[0]);
|
||||
devicemap = (char __iomem *)(®->msgcode_rwbuffer[21]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
atomic_inc(&acb->rq_map_token);
|
||||
if (readl(signature) != ARCMSR_SIGNATURE_GET_CONFIG)
|
||||
@ -998,6 +1086,21 @@ static uint8_t arcmsr_hbaD_abort_allcmd(struct AdapterControlBlock *pACB)
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t arcmsr_hbaE_abort_allcmd(struct AdapterControlBlock *pACB)
|
||||
{
|
||||
struct MessageUnit_E __iomem *reg = pACB->pmuE;
|
||||
|
||||
writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0);
|
||||
pACB->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
|
||||
writel(pACB->out_doorbell, ®->iobound_doorbell);
|
||||
if (!arcmsr_hbaE_wait_msgint_ready(pACB)) {
|
||||
pr_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;
|
||||
@ -1020,6 +1123,9 @@ static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
|
||||
case ACB_ADAPTER_TYPE_D:
|
||||
rtnval = arcmsr_hbaD_abort_allcmd(acb);
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E:
|
||||
rtnval = arcmsr_hbaE_abort_allcmd(acb);
|
||||
break;
|
||||
}
|
||||
return rtnval;
|
||||
}
|
||||
@ -1092,6 +1198,13 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb)
|
||||
writel(ARCMSR_ARC1214_ALL_INT_DISABLE, reg->pcief0_int_enable);
|
||||
}
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E: {
|
||||
struct MessageUnit_E __iomem *reg = acb->pmuE;
|
||||
orig_mask = readl(®->host_int_mask);
|
||||
writel(orig_mask | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR | ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR, ®->host_int_mask);
|
||||
readl(®->host_int_mask); /* Dummy readl to force pci flush */
|
||||
}
|
||||
break;
|
||||
}
|
||||
return orig_mask;
|
||||
}
|
||||
@ -1280,6 +1393,9 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
|
||||
pmu->doneq_index = 0x40FF;
|
||||
}
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E:
|
||||
arcmsr_hbaE_postqueue_isr(acb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1396,6 +1512,13 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb,
|
||||
writel(intmask_org | mask, reg->pcief0_int_enable);
|
||||
break;
|
||||
}
|
||||
case ACB_ADAPTER_TYPE_E: {
|
||||
struct MessageUnit_E __iomem *reg = acb->pmuE;
|
||||
|
||||
mask = ~(ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR | ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR);
|
||||
writel(intmask_org & mask, ®->host_int_mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1527,6 +1650,16 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr
|
||||
spin_unlock_irqrestore(&acb->postq_lock, flags);
|
||||
break;
|
||||
}
|
||||
case ACB_ADAPTER_TYPE_E: {
|
||||
struct MessageUnit_E __iomem *pmu = acb->pmuE;
|
||||
u32 ccb_post_stamp, arc_cdb_size;
|
||||
|
||||
arc_cdb_size = (ccb->arc_cdb_size > 0x300) ? 0x300 : ccb->arc_cdb_size;
|
||||
ccb_post_stamp = (ccb->smid | ((arc_cdb_size - 1) >> 6));
|
||||
writel(0, &pmu->inbound_queueport_high);
|
||||
writel(ccb_post_stamp, &pmu->inbound_queueport_low);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1580,6 +1713,20 @@ static void arcmsr_hbaD_stop_bgrb(struct AdapterControlBlock *pACB)
|
||||
"timeout\n", pACB->host->host_no);
|
||||
}
|
||||
|
||||
static void arcmsr_hbaE_stop_bgrb(struct AdapterControlBlock *pACB)
|
||||
{
|
||||
struct MessageUnit_E __iomem *reg = pACB->pmuE;
|
||||
|
||||
pACB->acb_flags &= ~ACB_F_MSG_START_BGRB;
|
||||
writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0);
|
||||
pACB->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
|
||||
writel(pACB->out_doorbell, ®->iobound_doorbell);
|
||||
if (!arcmsr_hbaE_wait_msgint_ready(pACB)) {
|
||||
pr_notice("arcmsr%d: wait 'stop adapter background rebulid' "
|
||||
"timeout\n", pACB->host->host_no);
|
||||
}
|
||||
}
|
||||
|
||||
static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
|
||||
{
|
||||
switch (acb->adapter_type) {
|
||||
@ -1599,6 +1746,9 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
|
||||
case ACB_ADAPTER_TYPE_D:
|
||||
arcmsr_hbaD_stop_bgrb(acb);
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E:
|
||||
arcmsr_hbaE_stop_bgrb(acb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1633,6 +1783,12 @@ static void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
|
||||
reg->inbound_doorbell);
|
||||
}
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E: {
|
||||
struct MessageUnit_E __iomem *reg = acb->pmuE;
|
||||
acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK;
|
||||
writel(acb->out_doorbell, ®->iobound_doorbell);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1673,6 +1829,12 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
|
||||
reg->inbound_doorbell);
|
||||
}
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E: {
|
||||
struct MessageUnit_E __iomem *reg = acb->pmuE;
|
||||
acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_WRITE_OK;
|
||||
writel(acb->out_doorbell, ®->iobound_doorbell);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1702,6 +1864,11 @@ struct QBUFFER __iomem *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb)
|
||||
qbuffer = (struct QBUFFER __iomem *)reg->message_rbuffer;
|
||||
}
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E: {
|
||||
struct MessageUnit_E __iomem *reg = acb->pmuE;
|
||||
qbuffer = (struct QBUFFER __iomem *)®->message_rbuffer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return qbuffer;
|
||||
}
|
||||
@ -1732,6 +1899,11 @@ static struct QBUFFER __iomem *arcmsr_get_iop_wqbuffer(struct AdapterControlBloc
|
||||
pqbuffer = (struct QBUFFER __iomem *)reg->message_wbuffer;
|
||||
}
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E: {
|
||||
struct MessageUnit_E __iomem *reg = acb->pmuE;
|
||||
pqbuffer = (struct QBUFFER __iomem *)®->message_wbuffer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return pqbuffer;
|
||||
}
|
||||
@ -1968,6 +2140,33 @@ static void arcmsr_hbaD_doorbell_isr(struct AdapterControlBlock *pACB)
|
||||
| ARCMSR_ARC1214_IOP2DRV_MESSAGE_CMD_DONE));
|
||||
}
|
||||
|
||||
static void arcmsr_hbaE_doorbell_isr(struct AdapterControlBlock *pACB)
|
||||
{
|
||||
uint32_t outbound_doorbell, in_doorbell, tmp;
|
||||
struct MessageUnit_E __iomem *reg = pACB->pmuE;
|
||||
|
||||
in_doorbell = readl(®->iobound_doorbell);
|
||||
outbound_doorbell = in_doorbell ^ pACB->in_doorbell;
|
||||
do {
|
||||
writel(0, ®->host_int_status); /* clear interrupt */
|
||||
if (outbound_doorbell & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) {
|
||||
arcmsr_iop2drv_data_wrote_handle(pACB);
|
||||
}
|
||||
if (outbound_doorbell & ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK) {
|
||||
arcmsr_iop2drv_data_read_handle(pACB);
|
||||
}
|
||||
if (outbound_doorbell & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
|
||||
arcmsr_hbaE_message_isr(pACB);
|
||||
}
|
||||
tmp = in_doorbell;
|
||||
in_doorbell = readl(®->iobound_doorbell);
|
||||
outbound_doorbell = tmp ^ in_doorbell;
|
||||
} while (outbound_doorbell & (ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK
|
||||
| ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK
|
||||
| ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE));
|
||||
pACB->in_doorbell = in_doorbell;
|
||||
}
|
||||
|
||||
static void arcmsr_hbaA_postqueue_isr(struct AdapterControlBlock *acb)
|
||||
{
|
||||
uint32_t flag_ccb;
|
||||
@ -2077,6 +2276,33 @@ static void arcmsr_hbaD_postqueue_isr(struct AdapterControlBlock *acb)
|
||||
spin_unlock_irqrestore(&acb->doneq_lock, flags);
|
||||
}
|
||||
|
||||
static void arcmsr_hbaE_postqueue_isr(struct AdapterControlBlock *acb)
|
||||
{
|
||||
uint32_t doneq_index;
|
||||
uint16_t cmdSMID;
|
||||
int error;
|
||||
struct MessageUnit_E __iomem *pmu;
|
||||
struct CommandControlBlock *ccb;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&acb->doneq_lock, flags);
|
||||
doneq_index = acb->doneq_index;
|
||||
pmu = acb->pmuE;
|
||||
while ((readl(&pmu->reply_post_producer_index) & 0xFFFF) != doneq_index) {
|
||||
cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
|
||||
ccb = acb->pccb_pool[cmdSMID];
|
||||
error = (acb->pCompletionQ[doneq_index].cmdFlag
|
||||
& ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? true : false;
|
||||
arcmsr_drain_donequeue(acb, ccb, error);
|
||||
doneq_index++;
|
||||
if (doneq_index >= acb->completionQ_entry)
|
||||
doneq_index = 0;
|
||||
}
|
||||
acb->doneq_index = doneq_index;
|
||||
writel(doneq_index, &pmu->reply_post_consumer_index);
|
||||
spin_unlock_irqrestore(&acb->doneq_lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************************
|
||||
** Handle a message interrupt
|
||||
@ -2126,6 +2352,14 @@ static void arcmsr_hbaD_message_isr(struct AdapterControlBlock *acb)
|
||||
schedule_work(&acb->arcmsr_do_message_isr_bh);
|
||||
}
|
||||
|
||||
static void arcmsr_hbaE_message_isr(struct AdapterControlBlock *acb)
|
||||
{
|
||||
struct MessageUnit_E __iomem *reg = acb->pmuE;
|
||||
|
||||
writel(0, ®->host_int_status);
|
||||
schedule_work(&acb->arcmsr_do_message_isr_bh);
|
||||
}
|
||||
|
||||
static int arcmsr_hbaA_handle_isr(struct AdapterControlBlock *acb)
|
||||
{
|
||||
uint32_t outbound_intstatus;
|
||||
@ -2229,6 +2463,31 @@ static irqreturn_t arcmsr_hbaD_handle_isr(struct AdapterControlBlock *pACB)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t arcmsr_hbaE_handle_isr(struct AdapterControlBlock *pACB)
|
||||
{
|
||||
uint32_t host_interrupt_status;
|
||||
struct MessageUnit_E __iomem *pmu = pACB->pmuE;
|
||||
|
||||
host_interrupt_status = readl(&pmu->host_int_status) &
|
||||
(ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR |
|
||||
ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR);
|
||||
if (!host_interrupt_status)
|
||||
return IRQ_NONE;
|
||||
do {
|
||||
/* MU ioctl transfer doorbell interrupts*/
|
||||
if (host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) {
|
||||
arcmsr_hbaE_doorbell_isr(pACB);
|
||||
}
|
||||
/* MU post queue interrupts*/
|
||||
if (host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) {
|
||||
arcmsr_hbaE_postqueue_isr(pACB);
|
||||
}
|
||||
host_interrupt_status = readl(&pmu->host_int_status);
|
||||
} while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR |
|
||||
ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR));
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb)
|
||||
{
|
||||
switch (acb->adapter_type) {
|
||||
@ -2242,6 +2501,8 @@ static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb)
|
||||
return arcmsr_hbaC_handle_isr(acb);
|
||||
case ACB_ADAPTER_TYPE_D:
|
||||
return arcmsr_hbaD_handle_isr(acb);
|
||||
case ACB_ADAPTER_TYPE_E:
|
||||
return arcmsr_hbaE_handle_isr(acb);
|
||||
default:
|
||||
return IRQ_NONE;
|
||||
}
|
||||
@ -2885,6 +3146,71 @@ static bool arcmsr_hbaD_get_config(struct AdapterControlBlock *acb)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool arcmsr_hbaE_get_config(struct AdapterControlBlock *pACB)
|
||||
{
|
||||
char *acb_firm_model = pACB->firm_model;
|
||||
char *acb_firm_version = pACB->firm_version;
|
||||
struct MessageUnit_E __iomem *reg = pACB->pmuE;
|
||||
char __iomem *iop_firm_model = (char __iomem *)(®->msgcode_rwbuffer[15]);
|
||||
char __iomem *iop_firm_version = (char __iomem *)(®->msgcode_rwbuffer[17]);
|
||||
uint32_t intmask_org, Index, firmware_state = 0, read_doorbell;
|
||||
int count;
|
||||
|
||||
/* disable all outbound interrupt */
|
||||
intmask_org = readl(®->host_int_mask); /* disable outbound message0 int */
|
||||
writel(intmask_org | ARCMSR_HBEMU_ALL_INTMASKENABLE, ®->host_int_mask);
|
||||
/* wait firmware ready */
|
||||
do {
|
||||
firmware_state = readl(®->outbound_msgaddr1);
|
||||
} while ((firmware_state & ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK) == 0);
|
||||
mdelay(20);
|
||||
/* post "get config" instruction */
|
||||
writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0);
|
||||
|
||||
pACB->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
|
||||
writel(pACB->out_doorbell, ®->iobound_doorbell);
|
||||
/* wait message ready */
|
||||
for (Index = 0; Index < 2000; Index++) {
|
||||
read_doorbell = readl(®->iobound_doorbell);
|
||||
if ((read_doorbell ^ pACB->in_doorbell) & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
|
||||
writel(0, ®->host_int_status);
|
||||
pACB->in_doorbell = read_doorbell;
|
||||
break;
|
||||
}
|
||||
mdelay(1);
|
||||
} /*max 1 seconds*/
|
||||
|
||||
if (Index >= 2000) {
|
||||
pr_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--;
|
||||
}
|
||||
pACB->firm_request_len = readl(®->msgcode_rwbuffer[1]);
|
||||
pACB->firm_numbers_queue = readl(®->msgcode_rwbuffer[2]);
|
||||
pACB->firm_sdram_size = readl(®->msgcode_rwbuffer[3]);
|
||||
pACB->firm_hd_channels = readl(®->msgcode_rwbuffer[4]);
|
||||
pACB->firm_cfg_version = readl(®->msgcode_rwbuffer[25]);
|
||||
pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n",
|
||||
pACB->host->host_no,
|
||||
pACB->firm_model,
|
||||
pACB->firm_version);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
|
||||
{
|
||||
bool rtn = false;
|
||||
@ -2902,6 +3228,9 @@ static bool arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
|
||||
case ACB_ADAPTER_TYPE_D:
|
||||
rtn = arcmsr_hbaD_get_config(acb);
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E:
|
||||
rtn = arcmsr_hbaE_get_config(acb);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -3166,6 +3495,75 @@ static int arcmsr_hbaD_polling_ccbdone(struct AdapterControlBlock *acb,
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static int arcmsr_hbaE_polling_ccbdone(struct AdapterControlBlock *acb,
|
||||
struct CommandControlBlock *poll_ccb)
|
||||
{
|
||||
bool error;
|
||||
uint32_t poll_ccb_done = 0, poll_count = 0, doneq_index;
|
||||
uint16_t cmdSMID;
|
||||
unsigned long flags;
|
||||
int rtn;
|
||||
struct CommandControlBlock *pCCB;
|
||||
struct MessageUnit_E __iomem *reg = acb->pmuE;
|
||||
|
||||
polling_hbaC_ccb_retry:
|
||||
poll_count++;
|
||||
while (1) {
|
||||
spin_lock_irqsave(&acb->doneq_lock, flags);
|
||||
doneq_index = acb->doneq_index;
|
||||
if ((readl(®->reply_post_producer_index) & 0xFFFF) ==
|
||||
doneq_index) {
|
||||
spin_unlock_irqrestore(&acb->doneq_lock, flags);
|
||||
if (poll_ccb_done) {
|
||||
rtn = SUCCESS;
|
||||
break;
|
||||
} else {
|
||||
msleep(25);
|
||||
if (poll_count > 40) {
|
||||
rtn = FAILED;
|
||||
break;
|
||||
}
|
||||
goto polling_hbaC_ccb_retry;
|
||||
}
|
||||
}
|
||||
cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
|
||||
doneq_index++;
|
||||
if (doneq_index >= acb->completionQ_entry)
|
||||
doneq_index = 0;
|
||||
acb->doneq_index = doneq_index;
|
||||
spin_unlock_irqrestore(&acb->doneq_lock, flags);
|
||||
pCCB = acb->pccb_pool[cmdSMID];
|
||||
poll_ccb_done |= (pCCB == poll_ccb) ? 1 : 0;
|
||||
/* check if command done with no error*/
|
||||
if ((pCCB->acb != acb) || (pCCB->startdone != ARCMSR_CCB_START)) {
|
||||
if (pCCB->startdone == ARCMSR_CCB_ABORTED) {
|
||||
pr_notice("arcmsr%d: scsi id = %d "
|
||||
"lun = %d ccb = '0x%p' poll command "
|
||||
"abort successfully\n"
|
||||
, acb->host->host_no
|
||||
, pCCB->pcmd->device->id
|
||||
, (u32)pCCB->pcmd->device->lun
|
||||
, pCCB);
|
||||
pCCB->pcmd->result = DID_ABORT << 16;
|
||||
arcmsr_ccb_complete(pCCB);
|
||||
continue;
|
||||
}
|
||||
pr_notice("arcmsr%d: polling an illegal "
|
||||
"ccb command done ccb = '0x%p' "
|
||||
"ccboutstandingcount = %d\n"
|
||||
, acb->host->host_no
|
||||
, pCCB
|
||||
, atomic_read(&acb->ccboutstandingcount));
|
||||
continue;
|
||||
}
|
||||
error = (acb->pCompletionQ[doneq_index].cmdFlag &
|
||||
ARCMSR_CCBREPLY_FLAG_ERROR_MODE1) ? true : false;
|
||||
arcmsr_report_ccb_state(acb, pCCB, error);
|
||||
}
|
||||
writel(doneq_index, ®->reply_post_consumer_index);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb,
|
||||
struct CommandControlBlock *poll_ccb)
|
||||
{
|
||||
@ -3188,6 +3586,9 @@ static int arcmsr_polling_ccbdone(struct AdapterControlBlock *acb,
|
||||
case ACB_ADAPTER_TYPE_D:
|
||||
rtn = arcmsr_hbaD_polling_ccbdone(acb, poll_ccb);
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E:
|
||||
rtn = arcmsr_hbaE_polling_ccbdone(acb, poll_ccb);
|
||||
break;
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
@ -3208,6 +3609,10 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb)
|
||||
case ACB_ADAPTER_TYPE_D:
|
||||
dma_coherent_handle = acb->dma_coherent_handle2;
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E:
|
||||
dma_coherent_handle = acb->dma_coherent_handle +
|
||||
offsetof(struct CommandControlBlock, arcmsr_cdb);
|
||||
break;
|
||||
default:
|
||||
dma_coherent_handle = acb->dma_coherent_handle;
|
||||
break;
|
||||
@ -3316,6 +3721,29 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E: {
|
||||
struct MessageUnit_E __iomem *reg = acb->pmuE;
|
||||
writel(ARCMSR_SIGNATURE_SET_CONFIG, ®->msgcode_rwbuffer[0]);
|
||||
writel(ARCMSR_SIGNATURE_1884, ®->msgcode_rwbuffer[1]);
|
||||
writel(cdb_phyaddr, ®->msgcode_rwbuffer[2]);
|
||||
writel(cdb_phyaddr_hi32, ®->msgcode_rwbuffer[3]);
|
||||
writel(acb->ccbsize, ®->msgcode_rwbuffer[4]);
|
||||
dma_coherent_handle = acb->dma_coherent_handle2;
|
||||
cdb_phyaddr = (uint32_t)(dma_coherent_handle & 0xffffffff);
|
||||
cdb_phyaddr_hi32 = (uint32_t)((dma_coherent_handle >> 16) >> 16);
|
||||
writel(cdb_phyaddr, ®->msgcode_rwbuffer[5]);
|
||||
writel(cdb_phyaddr_hi32, ®->msgcode_rwbuffer[6]);
|
||||
writel(acb->roundup_ccbsize, ®->msgcode_rwbuffer[7]);
|
||||
writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, ®->inbound_msgaddr0);
|
||||
acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
|
||||
writel(acb->out_doorbell, ®->iobound_doorbell);
|
||||
if (!arcmsr_hbaE_wait_msgint_ready(acb)) {
|
||||
pr_notice("arcmsr%d: 'set command Q window' timeout \n",
|
||||
acb->host->host_no);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -3356,6 +3784,13 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
|
||||
ARCMSR_ARC1214_MESSAGE_FIRMWARE_OK) == 0);
|
||||
}
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E: {
|
||||
struct MessageUnit_E __iomem *reg = acb->pmuE;
|
||||
do {
|
||||
firmware_state = readl(®->outbound_msgaddr1);
|
||||
} while ((firmware_state & ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK) == 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3455,6 +3890,36 @@ static void arcmsr_hbaD_request_device_map(struct AdapterControlBlock *acb)
|
||||
}
|
||||
}
|
||||
|
||||
static void arcmsr_hbaE_request_device_map(struct AdapterControlBlock *acb)
|
||||
{
|
||||
struct MessageUnit_E __iomem *reg = acb->pmuE;
|
||||
|
||||
if (unlikely(atomic_read(&acb->rq_map_token) == 0) ||
|
||||
((acb->acb_flags & ACB_F_BUS_RESET) != 0) ||
|
||||
((acb->acb_flags & ACB_F_ABORT) != 0)) {
|
||||
mod_timer(&acb->eternal_timer,
|
||||
jiffies + msecs_to_jiffies(6 * HZ));
|
||||
} 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)) {
|
||||
mod_timer(&acb->eternal_timer, jiffies +
|
||||
msecs_to_jiffies(6 * HZ));
|
||||
return;
|
||||
}
|
||||
writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0);
|
||||
acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
|
||||
writel(acb->out_doorbell, ®->iobound_doorbell);
|
||||
mod_timer(&acb->eternal_timer, jiffies +
|
||||
msecs_to_jiffies(6 * HZ));
|
||||
}
|
||||
}
|
||||
|
||||
static void arcmsr_request_device_map(struct timer_list *t)
|
||||
{
|
||||
struct AdapterControlBlock *acb = from_timer(acb, t, eternal_timer);
|
||||
@ -3474,6 +3939,9 @@ static void arcmsr_request_device_map(struct timer_list *t)
|
||||
case ACB_ADAPTER_TYPE_D:
|
||||
arcmsr_hbaD_request_device_map(acb);
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E:
|
||||
arcmsr_hbaE_request_device_map(acb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3524,6 +3992,20 @@ static void arcmsr_hbaD_start_bgrb(struct AdapterControlBlock *pACB)
|
||||
}
|
||||
}
|
||||
|
||||
static void arcmsr_hbaE_start_bgrb(struct AdapterControlBlock *pACB)
|
||||
{
|
||||
struct MessageUnit_E __iomem *pmu = pACB->pmuE;
|
||||
|
||||
pACB->acb_flags |= ACB_F_MSG_START_BGRB;
|
||||
writel(ARCMSR_INBOUND_MESG0_START_BGRB, &pmu->inbound_msgaddr0);
|
||||
pACB->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
|
||||
writel(pACB->out_doorbell, &pmu->iobound_doorbell);
|
||||
if (!arcmsr_hbaE_wait_msgint_ready(pACB)) {
|
||||
pr_notice("arcmsr%d: wait 'start adapter "
|
||||
"background rebulid' timeout \n", pACB->host->host_no);
|
||||
}
|
||||
}
|
||||
|
||||
static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
|
||||
{
|
||||
switch (acb->adapter_type) {
|
||||
@ -3539,6 +4021,9 @@ static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
|
||||
case ACB_ADAPTER_TYPE_D:
|
||||
arcmsr_hbaD_start_bgrb(acb);
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E:
|
||||
arcmsr_hbaE_start_bgrb(acb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3607,6 +4092,27 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E: {
|
||||
struct MessageUnit_E __iomem *reg = acb->pmuE;
|
||||
uint32_t i, tmp;
|
||||
|
||||
acb->in_doorbell = readl(®->iobound_doorbell);
|
||||
writel(0, ®->host_int_status); /*clear interrupt*/
|
||||
acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK;
|
||||
writel(acb->out_doorbell, ®->iobound_doorbell);
|
||||
for(i=0; i < 200; i++) {
|
||||
msleep(20);
|
||||
tmp = acb->in_doorbell;
|
||||
acb->in_doorbell = readl(®->iobound_doorbell);
|
||||
if((tmp ^ acb->in_doorbell) & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) {
|
||||
writel(0, ®->host_int_status); /*clear interrupt*/
|
||||
acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK;
|
||||
writel(acb->out_doorbell, ®->iobound_doorbell);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3658,6 +4164,19 @@ static void arcmsr_hardware_reset(struct AdapterControlBlock *acb)
|
||||
writel(0xD, &pmuC->write_sequence);
|
||||
} while (((readl(&pmuC->host_diagnostic) & ARCMSR_ARC1880_DiagWrite_ENABLE) == 0) && (count < 5));
|
||||
writel(ARCMSR_ARC1880_RESET_ADAPTER, &pmuC->host_diagnostic);
|
||||
} else if (acb->dev_id == 0x1884) {
|
||||
struct MessageUnit_E __iomem *pmuE = acb->pmuE;
|
||||
do {
|
||||
count++;
|
||||
writel(0x4, &pmuE->write_sequence_3xxx);
|
||||
writel(0xB, &pmuE->write_sequence_3xxx);
|
||||
writel(0x2, &pmuE->write_sequence_3xxx);
|
||||
writel(0x7, &pmuE->write_sequence_3xxx);
|
||||
writel(0xD, &pmuE->write_sequence_3xxx);
|
||||
mdelay(10);
|
||||
} while (((readl(&pmuE->host_diagnostic_3xxx) &
|
||||
ARCMSR_ARC1884_DiagWrite_ENABLE) == 0) && (count < 5));
|
||||
writel(ARCMSR_ARC188X_RESET_ADAPTER, &pmuE->host_diagnostic_3xxx);
|
||||
} else if ((acb->dev_id == 0x1214)) {
|
||||
writel(0x20, pmuD->reset_request);
|
||||
} else {
|
||||
@ -3700,6 +4219,12 @@ static bool arcmsr_reset_in_progress(struct AdapterControlBlock *acb)
|
||||
true : false;
|
||||
}
|
||||
break;
|
||||
case ACB_ADAPTER_TYPE_E:{
|
||||
struct MessageUnit_E __iomem *reg = acb->pmuE;
|
||||
rtn = (readl(®->host_diagnostic_3xxx) &
|
||||
ARCMSR_ARC188X_RESET_ADAPTER) ? true : false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
@ -3890,6 +4415,7 @@ static const char *arcmsr_info(struct Scsi_Host *host)
|
||||
case PCI_DEVICE_ID_ARECA_1680:
|
||||
case PCI_DEVICE_ID_ARECA_1681:
|
||||
case PCI_DEVICE_ID_ARECA_1880:
|
||||
case PCI_DEVICE_ID_ARECA_1884:
|
||||
type = "SAS/SATA";
|
||||
break;
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user