From: "nickcheng" <nick.cheng@areca.com.tw>
To: 'Andrew Morton' <akpm@linux-foundation.org>,
James.Bottomley@SteelEye.com
Cc: linux-scsi@vger.kernel.org, randy.dunlap@oracle.com
Subject: [PATCH] scsi: upstream arcmsr-1.20.00.15
Date: Thu, 10 Jan 2008 21:20:07 +0800 [thread overview]
Message-ID: <000001c8538b$84f88c20$8800a8c0@Nick> (raw)
In-Reply-To:
[-- Attachment #1: Type: text/plain, Size: 985 bytes --]
Subject: [PATCH] scsi: upstream arcmsr-1.20.00.15-71224
From: Nick Cheng <nick.cheng@areca.com.tw>
Description:
*** add arcmsr_enable_eoi_mode()and readl(reg->iop2drv_doorbell_reg) in
arcmsr_handle_hbb_isr() on adapter Type B in case of the doorbell interrupt
clearance is cached
*** add conditional declaration for arcmsr_pci_error_detected() and
arcmsr_pci_slot_reset
*** check if the sg list member number exceeds arcmsr default limit in
arcmsr_build_ccb()
*** change the returned value type of arcmsr_build_ccb()from "void" to "int"
returns FAILED in arcmsr_queue_command()
*** modify arcmsr_drain_donequeue() to ignore unknown command and let kernel
process command timeout. This could handle IO request violating maximum
segments, i.e. Linux XFS over DM-CRYPT. Thanks to Milan Broz's comments
<mbroz@redhat.com>
*** fix the release of dma memory for type B in arcmsr_free_ccb_pool()
*** fix the arcmsr_polling_hbb_ccbdone()
Signed-off-by: Nick Cheng <nick.cheng@areca.com.tw>
[-- Attachment #2: patch4arcmsr --]
[-- Type: application/octet-stream, Size: 15017 bytes --]
diff --git a/Documentation/scsi/ChangeLog.arcmsr b/Documentation/scsi/ChangeLog.arcmsr
index cd8403a..357b112 100644
--- a/Documentation/scsi/ChangeLog.arcmsr
+++ b/Documentation/scsi/ChangeLog.arcmsr
@@ -53,19 +53,60 @@
** for linux standard list
** enable usage of pci message signal interrupt
** follow Randy.Danlup kindness suggestion cleanup this code
-** 1.20.00.14 05/02/2007 Erich Chen & Nick Cheng
+** 1.20.00.14 05/02/2007 Erich Chen & Nick Cheng
** 1.implement PCI-Express error recovery function and AER capability
-** 2.implement the selection of ARCMSR_MAX_XFER_SECTORS_B=4096
-** if firmware version is newer than 1.42
-** 3.modify arcmsr_iop_reset to improve the ability
-** 4.modify the ISR, arcmsr_interrupt routine,to prevent the
-** inconsistency with sg_mod driver if application directly calls
-** the arcmsr driver w/o passing through scsi mid layer
+** 2.implement the selection of ARCMSR_MAX_XFER_SECTORS_B=4096
+** if firmware version is newer than 1.42
+** 3.modify arcmsr_iop_reset to improve the ability
+** 4.modify the ISR, arcmsr_interrupt routine,to prevent the
+** inconsistency with sg_mod driver if application directly calls
+** the arcmsr driver w/o passing through scsi mid layer
** specially thanks to Yanmin Zhang's openhanded help about AER
** 1.20.00.15 08/30/2007 Erich Chen & Nick Cheng
** 1. support ARC1200/1201/1202 SATA RAID adapter, which is named
-** ACB_ADAPTER_TYPE_B
+** ACB_ADAPTER_TYPE_B
** 2. modify the arcmsr_pci_slot_reset function
** 3. modify the arcmsr_pci_ers_disconnect_forepart function
** 4. modify the arcmsr_pci_ers_need_reset_forepart function
+** 1.20.00.15 09/27/2007 Erich Chen & Nick Cheng
+** 1. add arcmsr_enable_eoi_mode() on adapter Type B
+** 2. add readl(reg->iop2drv_doorbell_reg) in arcmsr_handle_hbb_isr()
+** in case of the doorbell interrupt clearance is cached
+** 1.20.00.15 10/01/2007 Erich Chen & Nick Cheng
+** 1. modify acb->devstate[i][j]
+** as ARECA_RAID_GOOD instead of
+** ARECA_RAID_GONE in arcmsr_alloc_ccb_pool
+** 1.20.00.15 11/06/2007 Erich Chen & Nick Cheng
+** 1. add conditional declaration for
+** arcmsr_pci_error_detected() and
+** arcmsr_pci_slot_reset
+** 1.20.00.15 11/23/2007 Erich Chen & Nick Cheng
+** 1.check if the sg list member number
+** exceeds arcmsr default limit in arcmsr_build_ccb()
+** 2.change the returned value type of arcmsr_build_ccb()
+** from "void" to "int"
+** 3.add the conditional check if arcmsr_build_ccb()
+** returns FAILED
+** 1.20.00.15 12/04/2007 Erich Chen & Nick Cheng
+** 1. modify arcmsr_drain_donequeue() to ignore unknown
+** command and let kernel process command timeout.
+** This could handle IO request violating max. segments
+** while Linux XFS over DM-CRYPT.
+** Thanks to Milan Broz's comments <mbroz@redhat.com>
+** 1.20.00.15 12/24/2007 Erich Chen & Nick Cheng
+** 1.fix the portability problems
+** 2.fix type B where we should _not_ iounmap() acb->pmu;
+** it's not ioremapped.
+** 3.add return -ENOMEM if ioremap() fails
+** 4.transfer IS_SG64_ADDR w/ cpu_to_le32()
+** in arcmsr_build_ccb
+** 5. modify acb->devstate[i][j] as ARECA_RAID_GONE instead of
+** ARECA_RAID_GOOD in arcmsr_alloc_ccb_pool()
+** 6.fix arcmsr_cdb->Context as (unsigned long)arcmsr_cdb
+** 7.add the checking state of
+** (outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT) == 0
+** in arcmsr_handle_hba_isr
+** 8.replace pci_alloc_consistent()/pci_free_consistent() with kmalloc()/kfree() in arcmsr_iop_message_xfer()
+** 9. fix the release of dma memory for type B in arcmsr_free_ccb_pool()
+** 10.fix the arcmsr_polling_hbb_ccbdone()
**************************************************************************
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h
index a67e29f..5778650 100644
--- a/drivers/scsi/arcmsr/arcmsr.h
+++ b/drivers/scsi/arcmsr/arcmsr.h
@@ -48,7 +48,7 @@ struct class_device_attribute;
/*The limit of outstanding scsi command that firmware can handle*/
#define ARCMSR_MAX_OUTSTANDING_CMD 256
#define ARCMSR_MAX_FREECCB_NUM 320
-#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2007/08/30"
+#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2007/12/24"
#define ARCMSR_SCSI_INITIATOR_ID 255
#define ARCMSR_MAX_XFER_SECTORS 512
#define ARCMSR_MAX_XFER_SECTORS_B 4096
@@ -248,6 +248,7 @@ struct FIRMWARE_INFO
#define ARCMSR_MESSAGE_START_BGRB 0x00060008
#define ARCMSR_MESSAGE_START_DRIVER_MODE 0x000E0008
#define ARCMSR_MESSAGE_SET_POST_WINDOW 0x000F0008
+#define ARCMSR_MESSAGE_ACTIVE_EOI_MODE 0x00100008
/* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */
#define ARCMSR_MESSAGE_FIRMWARE_OK 0x80000000
/* ioctl transfer */
@@ -256,6 +257,7 @@ struct FIRMWARE_INFO
#define ARCMSR_DRV2IOP_DATA_READ_OK 0x00000002
#define ARCMSR_DRV2IOP_CDB_POSTED 0x00000004
#define ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED 0x00000008
+#define ARCMSR_DRV2IOP_END_OF_INTERRUPT 0x00000010
/* data tunnel buffer between user space program and its firmware */
/* user space data to iop 128bytes */
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index d466a2d..3ca1fe7 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -316,9 +316,6 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
(0x20 - ((unsigned long)dma_coherent_handle & 0x1F));
}
- reg = (struct MessageUnit_B *)(dma_coherent +
- ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock));
-
dma_addr = dma_coherent_handle;
ccb_tmp = (struct CommandControlBlock *)dma_coherent;
for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
@@ -372,8 +369,8 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb)
out:
dma_free_coherent(&acb->pdev->dev,
- ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20,
- acb->dma_coherent, acb->dma_coherent_handle);
+ (ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 +
+ sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle);
return -ENOMEM;
}
@@ -510,6 +507,7 @@ static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
& ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN
, reg->iop2drv_doorbell_reg);
+ writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg);
return 0x00;
}
msleep(10);
@@ -749,6 +747,7 @@ static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, uint32_t fla
, ccb->startdone
, atomic_read(&acb->ccboutstandingcount));
}
+ else
arcmsr_report_ccb_state(acb, ccb, flag_ccb);
}
@@ -887,7 +886,7 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \
}
}
-static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
+static int arcmsr_build_ccb(struct AdapterControlBlock *acb,
struct CommandControlBlock *ccb, struct scsi_cmnd *pcmd)
{
struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb;
@@ -907,6 +906,8 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len);
nseg = scsi_dma_map(pcmd);
+ if (nseg > ARCMSR_MAX_SG_ENTRIES)
+ return FAILED;
BUG_ON(nseg < 0);
if (nseg) {
@@ -947,6 +948,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb,
arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
ccb->ccb_flags |= CCB_FLAG_WRITE;
}
+ return SUCCESS;
}
static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb)
@@ -1037,18 +1039,22 @@ static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb)
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
iounmap(acb->pmuA);
+ dma_free_coherent(&acb->pdev->dev,
+ ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20,
+ acb->dma_coherent,
+ acb->dma_coherent_handle);
break;
}
case ACB_ADAPTER_TYPE_B: {
struct MessageUnit_B *reg = acb->pmuB;
iounmap(reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL);
iounmap(reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER);
+ dma_free_coherent(&acb->pdev->dev,
+ (ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 +
+ sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle);
}
}
- dma_free_coherent(&acb->pdev->dev,
- ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20,
- acb->dma_coherent,
- acb->dma_coherent_handle);
+
}
void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
@@ -1274,7 +1280,9 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb)
return 1;
writel(~outbound_doorbell, reg->iop2drv_doorbell_reg);
-
+ /*in case the last action of doorbell interrupt clearance is cached, this action can push HW to write down the clear bit*/
+ readl(reg->iop2drv_doorbell_reg);
+ writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg);
if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) {
arcmsr_iop2drv_data_wrote_handle(acb);
}
@@ -1381,12 +1389,13 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
case ARCMSR_MESSAGE_READ_RQBUFFER: {
unsigned long *ver_addr;
- dma_addr_t buf_handle;
uint8_t *pQbuffer, *ptmpQbuffer;
int32_t allxfer_len = 0;
+ void *tmp;
- ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle);
- if (!ver_addr) {
+ tmp = kmalloc(1032, GFP_KERNEL|GFP_DMA);
+ ver_addr = (unsigned long *)tmp;
+ if (!tmp) {
retvalue = ARCMSR_MESSAGE_FAIL;
goto message_out;
}
@@ -1422,18 +1431,19 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
memcpy(pcmdmessagefld->messagedatabuffer, (uint8_t *)ver_addr, allxfer_len);
pcmdmessagefld->cmdmessage.Length = allxfer_len;
pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
- pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle);
+ kfree(tmp);
}
break;
case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
unsigned long *ver_addr;
- dma_addr_t buf_handle;
int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
uint8_t *pQbuffer, *ptmpuserbuffer;
-
- ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle);
- if (!ver_addr) {
+ void *tmp;
+
+ tmp = kmalloc(1032, GFP_KERNEL|GFP_DMA);
+ ver_addr = (unsigned long *)tmp;
+ if (!tmp) {
retvalue = ARCMSR_MESSAGE_FAIL;
goto message_out;
}
@@ -1483,7 +1493,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \
retvalue = ARCMSR_MESSAGE_FAIL;
}
}
- pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle);
+ kfree(tmp);
}
break;
@@ -1683,8 +1693,11 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd,
ccb = arcmsr_get_freeccb(acb);
if (!ccb)
return SCSI_MLQUEUE_HOST_BUSY;
-
- arcmsr_build_ccb(acb, ccb, cmd);
+ if ( arcmsr_build_ccb( acb, ccb, cmd ) == FAILED ) {
+ cmd->result = (DID_ERROR << 16) | (RESERVATION_CONFLICT << 1);
+ cmd->scsi_done(cmd);
+ return 0;
+ }
arcmsr_post_ccb(acb, ccb);
return 0;
}
@@ -1845,7 +1858,7 @@ static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb,
}
}
-static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \
+static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb,
struct CommandControlBlock *poll_ccb)
{
struct MessageUnit_B *reg = acb->pmuB;
@@ -1879,7 +1892,7 @@ static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \
(acb->vir2phy_offset + (flag_ccb << 5));/*frame must be 32 bytes aligned*/
poll_ccb_done = (ccb == poll_ccb) ? 1:0;
if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) {
- if (ccb->startdone == ARCMSR_CCB_ABORTED) {
+ if ((ccb->startdone == ARCMSR_CCB_ABORTED) || (ccb == poll_ccb)) {
printk(KERN_NOTICE "arcmsr%d: \
scsi id = %d lun = %d ccb = '0x%p' poll command abort successfully \n"
,acb->host->host_no
@@ -1902,7 +1915,7 @@ static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \
} /*drain reply FIFO*/
}
-static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, \
+static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb,
struct CommandControlBlock *poll_ccb)
{
switch (acb->adapter_type) {
@@ -2027,6 +2040,7 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb)
do {
firmware_state = readl(reg->iop2drv_doorbell_reg);
} while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0);
+ writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg);
}
break;
}
@@ -2091,19 +2105,39 @@ static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb)
}
}
+static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb)
+{
+ switch (acb->adapter_type) {
+ case ACB_ADAPTER_TYPE_A:
+ return;
+ case ACB_ADAPTER_TYPE_B:
+ {
+ struct MessageUnit_B *reg = acb->pmuB;
+ writel(ARCMSR_MESSAGE_ACTIVE_EOI_MODE, reg->drv2iop_doorbell_reg);
+ if(arcmsr_hbb_wait_msgint_ready(acb)) {
+ printk(KERN_NOTICE "ARCMSR IOP enables EOI_MODE TIMEOUT");
+ return;
+ }
+ }
+ break;
+ }
+ return;
+}
+
static void arcmsr_iop_init(struct AdapterControlBlock *acb)
{
uint32_t intmask_org;
- arcmsr_wait_firmware_ready(acb);
- arcmsr_iop_confirm(acb);
/* disable all outbound interrupt */
intmask_org = arcmsr_disable_outbound_ints(acb);
+ arcmsr_wait_firmware_ready(acb);
+ arcmsr_iop_confirm(acb);
arcmsr_get_firmware_spec(acb);
/*start background rebuild*/
arcmsr_start_adapter_bgrb(acb);
/* empty doorbell Qbuffer if door bell ringed */
arcmsr_clear_doorbell_queue_buffer(acb);
+ arcmsr_enable_eoi_mode(acb);
/* enable outbound Post Queue,outbound doorbell Interrupt */
arcmsr_enable_outbound_ints(acb, intmask_org);
acb->acb_flags |= ACB_F_IOP_INITED;
@@ -2276,6 +2310,7 @@ static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev)
arcmsr_start_adapter_bgrb(acb);
/* empty doorbell Qbuffer if door bell ringed */
arcmsr_clear_doorbell_queue_buffer(acb);
+ arcmsr_enable_eoi_mode(acb);
/* enable outbound Post Queue,outbound doorbell Interrupt */
arcmsr_enable_outbound_ints(acb, intmask_org);
acb->acb_flags |= ACB_F_IOP_INITED;
next reply other threads:[~2008-01-10 13:33 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-10 13:20 nickcheng [this message]
-- strict thread matches above, loose matches on Subject: below --
2008-01-10 13:21 [PATCH] scsi: upstream arcmsr-1.20.00.15 nickcheng
2007-09-13 9:26 nickcheng
2007-09-15 16:41 ` James Bottomley
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='000001c8538b$84f88c20$8800a8c0@Nick' \
--to=nick.cheng@areca.com.tw \
--cc=James.Bottomley@SteelEye.com \
--cc=akpm@linux-foundation.org \
--cc=linux-scsi@vger.kernel.org \
--cc=randy.dunlap@oracle.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.