scsi: arcmsr: Support new RAID controller ARC-1688
Add support for new Areca RAID controller ARC-1688 Signed-off-by: ching Huang <ching2048@areca.com.tw> Link: https://lore.kernel.org/r/110bdc873497d3d5e090b908fb159b6155bb3a2b.camel@areca.com.tw Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
b85ea95d08
commit
14ef4b001a
@ -818,6 +818,23 @@ typedef struct deliver_completeQ {
|
||||
uint16_t cmdLMID; // reserved (0)
|
||||
uint16_t cmdFlag2; // reserved (0)
|
||||
} DeliverQ, CompletionQ, *pDeliver_Q, *pCompletion_Q;
|
||||
|
||||
#define ARCMSR_XOR_SEG_SIZE (1024 * 1024)
|
||||
struct HostRamBuf {
|
||||
uint32_t hrbSignature; // must be "HRBS"
|
||||
uint32_t hrbSize; // total sg size, be multiples of MB
|
||||
uint32_t hrbRes[2]; // reserved, must be set to 0
|
||||
};
|
||||
struct Xor_sg {
|
||||
dma_addr_t xorPhys;
|
||||
uint64_t xorBufLen;
|
||||
};
|
||||
struct XorHandle {
|
||||
dma_addr_t xorPhys;
|
||||
uint64_t xorBufLen;
|
||||
void *xorVirt;
|
||||
};
|
||||
|
||||
/*
|
||||
*******************************************************************************
|
||||
** Adapter Control Block
|
||||
@ -929,6 +946,7 @@ struct AdapterControlBlock
|
||||
char firm_model[12];
|
||||
char firm_version[20];
|
||||
char device_map[20]; /*21,84-99*/
|
||||
uint32_t firm_PicStatus;
|
||||
struct work_struct arcmsr_do_message_isr_bh;
|
||||
struct timer_list eternal_timer;
|
||||
unsigned short fw_flag;
|
||||
@ -937,6 +955,7 @@ struct AdapterControlBlock
|
||||
#define FW_DEADLOCK 0x0010
|
||||
uint32_t maxOutstanding;
|
||||
int vector_count;
|
||||
int xor_mega;
|
||||
uint32_t maxFreeCCB;
|
||||
struct timer_list refresh_timer;
|
||||
uint32_t doneq_index;
|
||||
@ -946,6 +965,10 @@ struct AdapterControlBlock
|
||||
uint32_t completionQ_entry;
|
||||
pCompletion_Q pCompletionQ;
|
||||
uint32_t completeQ_size;
|
||||
void *xorVirt;
|
||||
dma_addr_t xorPhys;
|
||||
unsigned int init2cfg_size;
|
||||
unsigned int xorVirtOffset;
|
||||
};/* HW_DEVICE_EXTENSION */
|
||||
/*
|
||||
*******************************************************************************
|
||||
|
@ -747,6 +747,57 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb)
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static int arcmsr_alloc_xor_buffer(struct AdapterControlBlock *acb)
|
||||
{
|
||||
int rc = 0;
|
||||
struct pci_dev *pdev = acb->pdev;
|
||||
void *dma_coherent;
|
||||
dma_addr_t dma_coherent_handle;
|
||||
int i, xor_ram;
|
||||
struct Xor_sg *pXorPhys;
|
||||
void **pXorVirt;
|
||||
struct HostRamBuf *pRamBuf;
|
||||
|
||||
// allocate 1 MB * N physically continuous memory for XOR engine.
|
||||
xor_ram = (acb->firm_PicStatus >> 24) & 0x0f;
|
||||
acb->xor_mega = (xor_ram - 1) * 32 + 128 + 3;
|
||||
acb->init2cfg_size = sizeof(struct HostRamBuf) +
|
||||
(sizeof(struct XorHandle) * acb->xor_mega);
|
||||
dma_coherent = dma_alloc_coherent(&pdev->dev, acb->init2cfg_size,
|
||||
&dma_coherent_handle, GFP_KERNEL);
|
||||
acb->xorVirt = dma_coherent;
|
||||
acb->xorPhys = dma_coherent_handle;
|
||||
pXorPhys = (struct Xor_sg *)((unsigned long)dma_coherent +
|
||||
sizeof(struct HostRamBuf));
|
||||
acb->xorVirtOffset = sizeof(struct HostRamBuf) +
|
||||
(sizeof(struct Xor_sg) * acb->xor_mega);
|
||||
pXorVirt = (void **)((unsigned long)dma_coherent +
|
||||
(unsigned long)acb->xorVirtOffset);
|
||||
for (i = 0; i < acb->xor_mega; i++) {
|
||||
dma_coherent = dma_alloc_coherent(&pdev->dev,
|
||||
ARCMSR_XOR_SEG_SIZE,
|
||||
&dma_coherent_handle, GFP_KERNEL);
|
||||
if (dma_coherent) {
|
||||
pXorPhys->xorPhys = dma_coherent_handle;
|
||||
pXorPhys->xorBufLen = ARCMSR_XOR_SEG_SIZE;
|
||||
*pXorVirt = dma_coherent;
|
||||
pXorPhys++;
|
||||
pXorVirt++;
|
||||
} else {
|
||||
pr_info("arcmsr%d: alloc max XOR buffer = 0x%x MB\n",
|
||||
acb->host->host_no, i);
|
||||
rc = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pRamBuf = (struct HostRamBuf *)acb->xorVirt;
|
||||
pRamBuf->hrbSignature = 0x53425248; //HRBS
|
||||
pRamBuf->hrbSize = i * ARCMSR_XOR_SEG_SIZE;
|
||||
pRamBuf->hrbRes[0] = 0;
|
||||
pRamBuf->hrbRes[1] = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
|
||||
{
|
||||
struct pci_dev *pdev = acb->pdev;
|
||||
@ -836,7 +887,11 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
|
||||
acb->completionQ_entry = acb->ioqueue_size / sizeof(struct deliver_completeQ);
|
||||
acb->doneq_index = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((acb->firm_PicStatus >> 24) & 0x0f) {
|
||||
if (arcmsr_alloc_xor_buffer(acb))
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2022,6 +2077,29 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
|
||||
|
||||
static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb)
|
||||
{
|
||||
if (acb->xor_mega) {
|
||||
struct Xor_sg *pXorPhys;
|
||||
void **pXorVirt;
|
||||
int i;
|
||||
|
||||
pXorPhys = (struct Xor_sg *)(acb->xorVirt +
|
||||
sizeof(struct HostRamBuf));
|
||||
pXorVirt = (void **)((unsigned long)acb->xorVirt +
|
||||
(unsigned long)acb->xorVirtOffset);
|
||||
for (i = 0; i < acb->xor_mega; i++) {
|
||||
if (pXorPhys->xorPhys) {
|
||||
dma_free_coherent(&acb->pdev->dev,
|
||||
ARCMSR_XOR_SEG_SIZE,
|
||||
*pXorVirt, pXorPhys->xorPhys);
|
||||
pXorPhys->xorPhys = 0;
|
||||
*pXorVirt = NULL;
|
||||
}
|
||||
pXorPhys++;
|
||||
pXorVirt++;
|
||||
}
|
||||
dma_free_coherent(&acb->pdev->dev, acb->init2cfg_size,
|
||||
acb->xorVirt, acb->xorPhys);
|
||||
}
|
||||
dma_free_coherent(&acb->pdev->dev, acb->uncache_size, acb->dma_coherent, acb->dma_coherent_handle);
|
||||
}
|
||||
|
||||
@ -3309,6 +3387,10 @@ static void arcmsr_get_adapter_config(struct AdapterControlBlock *pACB, uint32_t
|
||||
pACB->firm_sdram_size = readl(&rwbuffer[3]);
|
||||
pACB->firm_hd_channels = readl(&rwbuffer[4]);
|
||||
pACB->firm_cfg_version = readl(&rwbuffer[25]);
|
||||
if (pACB->adapter_type == ACB_ADAPTER_TYPE_F)
|
||||
pACB->firm_PicStatus = readl(&rwbuffer[30]);
|
||||
else
|
||||
pACB->firm_PicStatus = 0;
|
||||
pr_notice("Areca RAID Controller%d: Model %s, F/W %s\n",
|
||||
pACB->host->host_no,
|
||||
pACB->firm_model,
|
||||
@ -4096,6 +4178,12 @@ static int arcmsr_iop_confirm(struct AdapterControlBlock *acb)
|
||||
acb->msgcode_rwbuffer[5] = lower_32_bits(acb->dma_coherent_handle2);
|
||||
acb->msgcode_rwbuffer[6] = upper_32_bits(acb->dma_coherent_handle2);
|
||||
acb->msgcode_rwbuffer[7] = acb->completeQ_size;
|
||||
if (acb->xor_mega) {
|
||||
acb->msgcode_rwbuffer[8] = 0x455AA; //Linux init 2
|
||||
acb->msgcode_rwbuffer[9] = 0;
|
||||
acb->msgcode_rwbuffer[10] = lower_32_bits(acb->xorPhys);
|
||||
acb->msgcode_rwbuffer[11] = upper_32_bits(acb->xorPhys);
|
||||
}
|
||||
writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, ®->inbound_msgaddr0);
|
||||
acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
|
||||
writel(acb->out_doorbell, ®->iobound_doorbell);
|
||||
|
Loading…
x
Reference in New Issue
Block a user