diff options
Diffstat (limited to 'drivers/scsi/pm8001/pm8001_hwi.c')
-rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.c | 434 |
1 files changed, 320 insertions, 114 deletions
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index e12c4f632a63..3619f6eeeeda 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -338,26 +338,25 @@ update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha, int number) } /** - * bar4_shift - function is called to shift BAR base address - * @pm8001_ha : our hba card information + * pm8001_bar4_shift - function is called to shift BAR base address + * @pm8001_ha : our hba card infomation * @shiftValue : shifting value in memory bar. */ -static int bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue) +int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue) { u32 regVal; - u32 max_wait_count; + unsigned long start; /* program the inbound AXI translation Lower Address */ pm8001_cw32(pm8001_ha, 1, SPC_IBW_AXI_TRANSLATION_LOW, shiftValue); /* confirm the setting is written */ - max_wait_count = 1 * 1000 * 1000; /* 1 sec */ + start = jiffies + HZ; /* 1 sec */ do { - udelay(1); regVal = pm8001_cr32(pm8001_ha, 1, SPC_IBW_AXI_TRANSLATION_LOW); - } while ((regVal != shiftValue) && (--max_wait_count)); + } while ((regVal != shiftValue) && time_before(jiffies, start)); - if (!max_wait_count) { + if (regVal != shiftValue) { PM8001_INIT_DBG(pm8001_ha, pm8001_printk("TIMEOUT:SPC_IBW_AXI_TRANSLATION_LOW" " = 0x%x\n", regVal)); @@ -375,6 +374,7 @@ static void __devinit mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit) { u32 value, offset, i; + unsigned long flags; #define SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR 0x00030000 #define SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR 0x00040000 @@ -388,16 +388,23 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit) * Using shifted destination address 0x3_0000:0x1074 + 0x4000*N (N=0:3) * Using shifted destination address 0x4_0000:0x1074 + 0x4000*(N-4) (N=4:7) */ - if (-1 == bar4_shift(pm8001_ha, SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR)) + spin_lock_irqsave(&pm8001_ha->lock, flags); + if (-1 == pm8001_bar4_shift(pm8001_ha, + SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR)) { + spin_unlock_irqrestore(&pm8001_ha->lock, flags); return; + } for (i = 0; i < 4; i++) { offset = SAS2_SETTINGS_LOCAL_PHY_0_3_OFFSET + 0x4000 * i; pm8001_cw32(pm8001_ha, 2, offset, 0x80001501); } /* shift membase 3 for SAS2_SETTINGS_LOCAL_PHY 4 - 7 */ - if (-1 == bar4_shift(pm8001_ha, SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR)) + if (-1 == pm8001_bar4_shift(pm8001_ha, + SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR)) { + spin_unlock_irqrestore(&pm8001_ha->lock, flags); return; + } for (i = 4; i < 8; i++) { offset = SAS2_SETTINGS_LOCAL_PHY_4_7_OFFSET + 0x4000 * (i-4); pm8001_cw32(pm8001_ha, 2, offset, 0x80001501); @@ -421,7 +428,8 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit) pm8001_cw32(pm8001_ha, 2, 0xd8, 0x8000C016); /*set the shifted destination address to 0x0 to avoid error operation */ - bar4_shift(pm8001_ha, 0x0); + pm8001_bar4_shift(pm8001_ha, 0x0); + spin_unlock_irqrestore(&pm8001_ha->lock, flags); return; } @@ -437,6 +445,7 @@ mpi_set_open_retry_interval_reg(struct pm8001_hba_info *pm8001_ha, u32 offset; u32 value; u32 i; + unsigned long flags; #define OPEN_RETRY_INTERVAL_PHY_0_3_SHIFT_ADDR 0x00030000 #define OPEN_RETRY_INTERVAL_PHY_4_7_SHIFT_ADDR 0x00040000 @@ -445,24 +454,30 @@ mpi_set_open_retry_interval_reg(struct pm8001_hba_info *pm8001_ha, #define OPEN_RETRY_INTERVAL_REG_MASK 0x0000FFFF value = interval & OPEN_RETRY_INTERVAL_REG_MASK; + spin_lock_irqsave(&pm8001_ha->lock, flags); /* shift bar and set the OPEN_REJECT(RETRY) interval time of PHY 0 -3.*/ - if (-1 == bar4_shift(pm8001_ha, - OPEN_RETRY_INTERVAL_PHY_0_3_SHIFT_ADDR)) + if (-1 == pm8001_bar4_shift(pm8001_ha, + OPEN_RETRY_INTERVAL_PHY_0_3_SHIFT_ADDR)) { + spin_unlock_irqrestore(&pm8001_ha->lock, flags); return; + } for (i = 0; i < 4; i++) { offset = OPEN_RETRY_INTERVAL_PHY_0_3_OFFSET + 0x4000 * i; pm8001_cw32(pm8001_ha, 2, offset, value); } - if (-1 == bar4_shift(pm8001_ha, - OPEN_RETRY_INTERVAL_PHY_4_7_SHIFT_ADDR)) + if (-1 == pm8001_bar4_shift(pm8001_ha, + OPEN_RETRY_INTERVAL_PHY_4_7_SHIFT_ADDR)) { + spin_unlock_irqrestore(&pm8001_ha->lock, flags); return; + } for (i = 4; i < 8; i++) { offset = OPEN_RETRY_INTERVAL_PHY_4_7_OFFSET + 0x4000 * (i-4); pm8001_cw32(pm8001_ha, 2, offset, value); } /*set the shifted destination address to 0x0 to avoid error operation */ - bar4_shift(pm8001_ha, 0x0); + pm8001_bar4_shift(pm8001_ha, 0x0); + spin_unlock_irqrestore(&pm8001_ha->lock, flags); return; } @@ -607,7 +622,8 @@ static int __devinit pm8001_chip_init(struct pm8001_hba_info *pm8001_ha) update_inbnd_queue_table(pm8001_ha, 0); update_outbnd_queue_table(pm8001_ha, 0); mpi_set_phys_g3_with_ssc(pm8001_ha, 0); - mpi_set_open_retry_interval_reg(pm8001_ha, 7); + /* 7->130ms, 34->500ms, 119->1.5s */ + mpi_set_open_retry_interval_reg(pm8001_ha, 119); /* notify firmware update finished and check initialization status */ if (0 == mpi_init_check(pm8001_ha)) { PM8001_INIT_DBG(pm8001_ha, @@ -688,8 +704,11 @@ static u32 soft_reset_ready_check(struct pm8001_hba_info *pm8001_ha) PM8001_INIT_DBG(pm8001_ha, pm8001_printk("Firmware is ready for reset .\n")); } else { - /* Trigger NMI twice via RB6 */ - if (-1 == bar4_shift(pm8001_ha, RB6_ACCESS_REG)) { + unsigned long flags; + /* Trigger NMI twice via RB6 */ + spin_lock_irqsave(&pm8001_ha->lock, flags); + if (-1 == pm8001_bar4_shift(pm8001_ha, RB6_ACCESS_REG)) { + spin_unlock_irqrestore(&pm8001_ha->lock, flags); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Shift Bar4 to 0x%x failed\n", RB6_ACCESS_REG)); @@ -715,8 +734,10 @@ static u32 soft_reset_ready_check(struct pm8001_hba_info *pm8001_ha) PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("SCRATCH_PAD3 value = 0x%x\n", pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3))); + spin_unlock_irqrestore(&pm8001_ha->lock, flags); return -1; } + spin_unlock_irqrestore(&pm8001_ha->lock, flags); } return 0; } @@ -733,6 +754,7 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) u32 regVal, toggleVal; u32 max_wait_count; u32 regVal1, regVal2, regVal3; + unsigned long flags; /* step1: Check FW is ready for soft reset */ if (soft_reset_ready_check(pm8001_ha) != 0) { @@ -743,7 +765,9 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) /* step 2: clear NMI status register on AAP1 and IOP, write the same value to clear */ /* map 0x60000 to BAR4(0x20), BAR2(win) */ - if (-1 == bar4_shift(pm8001_ha, MBIC_AAP1_ADDR_BASE)) { + spin_lock_irqsave(&pm8001_ha->lock, flags); + if (-1 == pm8001_bar4_shift(pm8001_ha, MBIC_AAP1_ADDR_BASE)) { + spin_unlock_irqrestore(&pm8001_ha->lock, flags); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Shift Bar4 to 0x%x failed\n", MBIC_AAP1_ADDR_BASE)); @@ -754,7 +778,8 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) pm8001_printk("MBIC - NMI Enable VPE0 (IOP)= 0x%x\n", regVal)); pm8001_cw32(pm8001_ha, 2, MBIC_NMI_ENABLE_VPE0_IOP, 0x0); /* map 0x70000 to BAR4(0x20), BAR2(win) */ - if (-1 == bar4_shift(pm8001_ha, MBIC_IOP_ADDR_BASE)) { + if (-1 == pm8001_bar4_shift(pm8001_ha, MBIC_IOP_ADDR_BASE)) { + spin_unlock_irqrestore(&pm8001_ha->lock, flags); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Shift Bar4 to 0x%x failed\n", MBIC_IOP_ADDR_BASE)); @@ -796,7 +821,8 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) /* read required registers for confirmming */ /* map 0x0700000 to BAR4(0x20), BAR2(win) */ - if (-1 == bar4_shift(pm8001_ha, GSM_ADDR_BASE)) { + if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_ADDR_BASE)) { + spin_unlock_irqrestore(&pm8001_ha->lock, flags); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Shift Bar4 to 0x%x failed\n", GSM_ADDR_BASE)); @@ -862,7 +888,8 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) /* step 5: delay 10 usec */ udelay(10); /* step 5-b: set GPIO-0 output control to tristate anyway */ - if (-1 == bar4_shift(pm8001_ha, GPIO_ADDR_BASE)) { + if (-1 == pm8001_bar4_shift(pm8001_ha, GPIO_ADDR_BASE)) { + spin_unlock_irqrestore(&pm8001_ha->lock, flags); PM8001_INIT_DBG(pm8001_ha, pm8001_printk("Shift Bar4 to 0x%x failed\n", GPIO_ADDR_BASE)); @@ -878,7 +905,8 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) /* Step 6: Reset the IOP and AAP1 */ /* map 0x00000 to BAR4(0x20), BAR2(win) */ - if (-1 == bar4_shift(pm8001_ha, SPC_TOP_LEVEL_ADDR_BASE)) { + if (-1 == pm8001_bar4_shift(pm8001_ha, SPC_TOP_LEVEL_ADDR_BASE)) { + spin_unlock_irqrestore(&pm8001_ha->lock, flags); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("SPC Shift Bar4 to 0x%x failed\n", SPC_TOP_LEVEL_ADDR_BASE)); @@ -915,7 +943,8 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) /* step 11: reads and sets the GSM Configuration and Reset Register */ /* map 0x0700000 to BAR4(0x20), BAR2(win) */ - if (-1 == bar4_shift(pm8001_ha, GSM_ADDR_BASE)) { + if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_ADDR_BASE)) { + spin_unlock_irqrestore(&pm8001_ha->lock, flags); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("SPC Shift Bar4 to 0x%x failed\n", GSM_ADDR_BASE)); @@ -968,7 +997,8 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) /* step 13: bring the IOP and AAP1 out of reset */ /* map 0x00000 to BAR4(0x20), BAR2(win) */ - if (-1 == bar4_shift(pm8001_ha, SPC_TOP_LEVEL_ADDR_BASE)) { + if (-1 == pm8001_bar4_shift(pm8001_ha, SPC_TOP_LEVEL_ADDR_BASE)) { + spin_unlock_irqrestore(&pm8001_ha->lock, flags); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Shift Bar4 to 0x%x failed\n", SPC_TOP_LEVEL_ADDR_BASE)); @@ -1010,6 +1040,7 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) pm8001_printk("SCRATCH_PAD3 value = 0x%x\n", pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3))); + spin_unlock_irqrestore(&pm8001_ha->lock, flags); return -1; } @@ -1039,9 +1070,12 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) pm8001_printk("SCRATCH_PAD3 value = 0x%x\n", pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3))); + spin_unlock_irqrestore(&pm8001_ha->lock, flags); return -1; } } + pm8001_bar4_shift(pm8001_ha, 0); + spin_unlock_irqrestore(&pm8001_ha->lock, flags); PM8001_INIT_DBG(pm8001_ha, pm8001_printk("SPC soft reset Complete\n")); @@ -1157,8 +1191,8 @@ pm8001_chip_msix_interrupt_disable(struct pm8001_hba_info *pm8001_ha, msi_index = int_vec_idx * MSIX_TABLE_ELEMENT_SIZE; msi_index += MSIX_TABLE_BASE; pm8001_cw32(pm8001_ha, 0, msi_index, MSIX_INTERRUPT_DISABLE); - } + /** * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt * @pm8001_ha: our hba card information @@ -1212,7 +1246,7 @@ static int mpi_msg_free_get(struct inbound_queue_table *circularQ, consumer_index = pm8001_read_32(circularQ->ci_virt); circularQ->consumer_index = cpu_to_le32(consumer_index); if (((circularQ->producer_idx + bcCount) % 256) == - circularQ->consumer_index) { + le32_to_cpu(circularQ->consumer_index)) { *messagePtr = NULL; return -1; } @@ -1321,7 +1355,8 @@ static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha, u32 header_tmp; do { /* If there are not-yet-delivered messages ... */ - if (circularQ->producer_index != circularQ->consumer_idx) { + if (le32_to_cpu(circularQ->producer_index) + != circularQ->consumer_idx) { /*Get the pointer to the circular queue buffer element*/ msgHeader = (struct mpi_msg_hdr *) (circularQ->base_virt + @@ -1329,14 +1364,14 @@ static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha, /* read header */ header_tmp = pm8001_read_32(msgHeader); msgHeader_tmp = cpu_to_le32(header_tmp); - if (0 != (msgHeader_tmp & 0x80000000)) { + if (0 != (le32_to_cpu(msgHeader_tmp) & 0x80000000)) { if (OPC_OUB_SKIP_ENTRY != - (msgHeader_tmp & 0xfff)) { + (le32_to_cpu(msgHeader_tmp) & 0xfff)) { *messagePtr1 = ((u8 *)msgHeader) + sizeof(struct mpi_msg_hdr); - *pBC = (u8)((msgHeader_tmp >> 24) & - 0x1f); + *pBC = (u8)((le32_to_cpu(msgHeader_tmp) + >> 24) & 0x1f); PM8001_IO_DBG(pm8001_ha, pm8001_printk(": CI=%d PI=%d " "msgHeader=%x\n", @@ -1347,8 +1382,8 @@ static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha, } else { circularQ->consumer_idx = (circularQ->consumer_idx + - ((msgHeader_tmp >> 24) & 0x1f)) - % 256; + ((le32_to_cpu(msgHeader_tmp) + >> 24) & 0x1f)) % 256; msgHeader_tmp = 0; pm8001_write_32(msgHeader, 0, 0); /* update the CI of outbound queue */ @@ -1360,7 +1395,8 @@ static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha, } else { circularQ->consumer_idx = (circularQ->consumer_idx + - ((msgHeader_tmp >> 24) & 0x1f)) % 256; + ((le32_to_cpu(msgHeader_tmp) >> 24) & + 0x1f)) % 256; msgHeader_tmp = 0; pm8001_write_32(msgHeader, 0, 0); /* update the CI of outbound queue */ @@ -1376,7 +1412,8 @@ static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha, producer_index = pm8001_read_32(pi_virt); circularQ->producer_index = cpu_to_le32(producer_index); } - } while (circularQ->producer_index != circularQ->consumer_idx); + } while (le32_to_cpu(circularQ->producer_index) != + circularQ->consumer_idx); /* while we don't have any more not-yet-delivered message */ /* report empty */ return MPI_IO_STATUS_BUSY; @@ -1388,24 +1425,191 @@ static void pm8001_work_fn(struct work_struct *work) struct pm8001_device *pm8001_dev; struct domain_device *dev; + /* + * So far, all users of this stash an associated structure here. + * If we get here, and this pointer is null, then the action + * was cancelled. This nullification happens when the device + * goes away. + */ + pm8001_dev = pw->data; /* Most stash device structure */ + if ((pm8001_dev == NULL) + || ((pw->handler != IO_XFER_ERROR_BREAK) + && (pm8001_dev->dev_type == NO_DEVICE))) { + kfree(pw); + return; + } + switch (pw->handler) { + case IO_XFER_ERROR_BREAK: + { /* This one stashes the sas_task instead */ + struct sas_task *t = (struct sas_task *)pm8001_dev; + u32 tag; + struct pm8001_ccb_info *ccb; + struct pm8001_hba_info *pm8001_ha = pw->pm8001_ha; + unsigned long flags, flags1; + struct task_status_struct *ts; + int i; + + if (pm8001_query_task(t) == TMF_RESP_FUNC_SUCC) + break; /* Task still on lu */ + spin_lock_irqsave(&pm8001_ha->lock, flags); + + spin_lock_irqsave(&t->task_state_lock, flags1); + if (unlikely((t->task_state_flags & SAS_TASK_STATE_DONE))) { + spin_unlock_irqrestore(&t->task_state_lock, flags1); + spin_unlock_irqrestore(&pm8001_ha->lock, flags); + break; /* Task got completed by another */ + } + spin_unlock_irqrestore(&t->task_state_lock, flags1); + + /* Search for a possible ccb that matches the task */ + for (i = 0; ccb = NULL, i < PM8001_MAX_CCB; i++) { + ccb = &pm8001_ha->ccb_info[i]; + tag = ccb->ccb_tag; + if ((tag != 0xFFFFFFFF) && (ccb->task == t)) + break; + } + if (!ccb) { + spin_unlock_irqrestore(&pm8001_ha->lock, flags); + break; /* Task got freed by another */ + } + ts = &t->task_status; + ts->resp = SAS_TASK_COMPLETE; + /* Force the midlayer to retry */ + ts->stat = SAS_QUEUE_FULL; + pm8001_dev = ccb->device; + if (pm8001_dev) + pm8001_dev->running_req--; + spin_lock_irqsave(&t->task_state_lock, flags1); + t->task_state_flags &= ~SAS_TASK_STATE_PENDING; + t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; + t->task_state_flags |= SAS_TASK_STATE_DONE; + if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { + spin_unlock_irqrestore(&t->task_state_lock, flags1); + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("task 0x%p" + " done with event 0x%x resp 0x%x stat 0x%x but" + " aborted by upper layer!\n", + t, pw->handler, ts->resp, ts->stat)); + pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); + spin_unlock_irqrestore(&pm8001_ha->lock, flags); + } else { + spin_unlock_irqrestore(&t->task_state_lock, flags1); + pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); + mb();/* in order to force CPU ordering */ + spin_unlock_irqrestore(&pm8001_ha->lock, flags); + t->task_done(t); + } + } break; + case IO_XFER_OPEN_RETRY_TIMEOUT: + { /* This one stashes the sas_task instead */ + struct sas_task *t = (struct sas_task *)pm8001_dev; + u32 tag; + struct pm8001_ccb_info *ccb; + struct pm8001_hba_info *pm8001_ha = pw->pm8001_ha; + unsigned long flags, flags1; + int i, ret = 0; + + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); + + ret = pm8001_query_task(t); + + PM8001_IO_DBG(pm8001_ha, + switch (ret) { + case TMF_RESP_FUNC_SUCC: + pm8001_printk("...Task on lu\n"); + break; + + case TMF_RESP_FUNC_COMPLETE: + pm8001_printk("...Task NOT on lu\n"); + break; + + default: + pm8001_printk("...query task failed!!!\n"); + break; + }); + + spin_lock_irqsave(&pm8001_ha->lock, flags); + + spin_lock_irqsave(&t->task_state_lock, flags1); + + if (unlikely((t->task_state_flags & SAS_TASK_STATE_DONE))) { + spin_unlock_irqrestore(&t->task_state_lock, flags1); + spin_unlock_irqrestore(&pm8001_ha->lock, flags); + if (ret == TMF_RESP_FUNC_SUCC) /* task on lu */ + (void)pm8001_abort_task(t); + break; /* Task got completed by another */ + } + + spin_unlock_irqrestore(&t->task_state_lock, flags1); + + /* Search for a possible ccb that matches the task */ + for (i = 0; ccb = NULL, i < PM8001_MAX_CCB; i++) { + ccb = &pm8001_ha->ccb_info[i]; + tag = ccb->ccb_tag; + if ((tag != 0xFFFFFFFF) && (ccb->task == t)) + break; + } + if (!ccb) { + spin_unlock_irqrestore(&pm8001_ha->lock, flags); + if (ret == TMF_RESP_FUNC_SUCC) /* task on lu */ + (void)pm8001_abort_task(t); + break; /* Task got freed by another */ + } + + pm8001_dev = ccb->device; + dev = pm8001_dev->sas_device; + + switch (ret) { + case TMF_RESP_FUNC_SUCC: /* task on lu */ + ccb->open_retry = 1; /* Snub completion */ + spin_unlock_irqrestore(&pm8001_ha->lock, flags); + ret = pm8001_abort_task(t); + ccb->open_retry = 0; + switch (ret) { + case TMF_RESP_FUNC_SUCC: + case TMF_RESP_FUNC_COMPLETE: + break; + default: /* device misbehavior */ + ret = TMF_RESP_FUNC_FAILED; + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("...Reset phy\n")); + pm8001_I_T_nexus_reset(dev); + break; + } + break; + + case TMF_RESP_FUNC_COMPLETE: /* task not on lu */ + spin_unlock_irqrestore(&pm8001_ha->lock, flags); + /* Do we need to abort the task locally? */ + break; + + default: /* device misbehavior */ + spin_unlock_irqrestore(&pm8001_ha->lock, flags); + ret = TMF_RESP_FUNC_FAILED; + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("...Reset phy\n")); + pm8001_I_T_nexus_reset(dev); + } + + if (ret == TMF_RESP_FUNC_FAILED) + t = NULL; + pm8001_open_reject_retry(pm8001_ha, t, pm8001_dev); + PM8001_IO_DBG(pm8001_ha, pm8001_printk("...Complete\n")); + } break; case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: - pm8001_dev = pw->data; dev = pm8001_dev->sas_device; pm8001_I_T_nexus_reset(dev); break; case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY: - pm8001_dev = pw->data; dev = pm8001_dev->sas_device; pm8001_I_T_nexus_reset(dev); break; case IO_DS_IN_ERROR: - pm8001_dev = pw->data; dev = pm8001_dev->sas_device; pm8001_I_T_nexus_reset(dev); break; case IO_DS_NON_OPERATIONAL: - pm8001_dev = pw->data; dev = pm8001_dev->sas_device; pm8001_I_T_nexus_reset(dev); break; @@ -1460,6 +1664,11 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) status = le32_to_cpu(psspPayload->status); tag = le32_to_cpu(psspPayload->tag); ccb = &pm8001_ha->ccb_info[tag]; + if ((status == IO_ABORTED) && ccb->open_retry) { + /* Being completed by another */ + ccb->open_retry = 0; + return; + } pm8001_dev = ccb->device; param = le32_to_cpu(psspPayload->param); @@ -1515,6 +1724,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) pm8001_printk("IO_XFER_ERROR_BREAK\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; + /* Force the midlayer to retry */ + ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_XFER_ERROR_PHY_NOT_READY: PM8001_IO_DBG(pm8001_ha, @@ -1719,9 +1930,8 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) case IO_XFER_ERROR_BREAK: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_BREAK\n")); - ts->resp = SAS_TASK_COMPLETE; - ts->stat = SAS_INTERRUPTED; - break; + pm8001_handle_event(pm8001_ha, t, IO_XFER_ERROR_BREAK); + return; case IO_XFER_ERROR_PHY_NOT_READY: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); @@ -1800,10 +2010,8 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) case IO_XFER_OPEN_RETRY_TIMEOUT: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); - ts->resp = SAS_TASK_COMPLETE; - ts->stat = SAS_OPEN_REJECT; - ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; - break; + pm8001_handle_event(pm8001_ha, t, IO_XFER_OPEN_RETRY_TIMEOUT); + return; case IO_XFER_ERROR_UNEXPECTED_PHASE: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_UNEXPECTED_PHASE\n")); @@ -1877,7 +2085,6 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) { struct sas_task *t; struct pm8001_ccb_info *ccb; - unsigned long flags = 0; u32 param; u32 status; u32 tag; @@ -2016,9 +2223,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->stat = SAS_QUEUE_FULL; pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/*in order to force CPU ordering*/ - spin_unlock_irqrestore(&pm8001_ha->lock, flags); + spin_unlock_irq(&pm8001_ha->lock); t->task_done(t); - spin_lock_irqsave(&pm8001_ha->lock, flags); + spin_lock_irq(&pm8001_ha->lock); return; } break; @@ -2036,9 +2243,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->stat = SAS_QUEUE_FULL; pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/*ditto*/ - spin_unlock_irqrestore(&pm8001_ha->lock, flags); + spin_unlock_irq(&pm8001_ha->lock); t->task_done(t); - spin_lock_irqsave(&pm8001_ha->lock, flags); + spin_lock_irq(&pm8001_ha->lock); return; } break; @@ -2064,9 +2271,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->stat = SAS_QUEUE_FULL; pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/* ditto*/ - spin_unlock_irqrestore(&pm8001_ha->lock, flags); + spin_unlock_irq(&pm8001_ha->lock); t->task_done(t); - spin_lock_irqsave(&pm8001_ha->lock, flags); + spin_lock_irq(&pm8001_ha->lock); return; } break; @@ -2131,9 +2338,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->stat = SAS_QUEUE_FULL; pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/*ditto*/ - spin_unlock_irqrestore(&pm8001_ha->lock, flags); + spin_unlock_irq(&pm8001_ha->lock); t->task_done(t); - spin_lock_irqsave(&pm8001_ha->lock, flags); + spin_lock_irq(&pm8001_ha->lock); return; } break; @@ -2155,9 +2362,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->stat = SAS_QUEUE_FULL; pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/*ditto*/ - spin_unlock_irqrestore(&pm8001_ha->lock, flags); + spin_unlock_irq(&pm8001_ha->lock); t->task_done(t); - spin_lock_irqsave(&pm8001_ha->lock, flags); + spin_lock_irq(&pm8001_ha->lock); return; } break; @@ -2175,31 +2382,31 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->stat = SAS_DEV_NO_RESPONSE; break; } - spin_lock_irqsave(&t->task_state_lock, flags); + spin_lock_irq(&t->task_state_lock); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { - spin_unlock_irqrestore(&t->task_state_lock, flags); + spin_unlock_irq(&t->task_state_lock); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("task 0x%p done with io_status 0x%x" " resp 0x%x stat 0x%x but aborted by upper layer!\n", t, status, ts->resp, ts->stat)); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); } else if (t->uldd_task) { - spin_unlock_irqrestore(&t->task_state_lock, flags); + spin_unlock_irq(&t->task_state_lock); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/* ditto */ - spin_unlock_irqrestore(&pm8001_ha->lock, flags); + spin_unlock_irq(&pm8001_ha->lock); t->task_done(t); - spin_lock_irqsave(&pm8001_ha->lock, flags); + spin_lock_irq(&pm8001_ha->lock); } else if (!t->uldd_task) { - spin_unlock_irqrestore(&t->task_state_lock, flags); + spin_unlock_irq(&t->task_state_lock); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/*ditto*/ - spin_unlock_irqrestore(&pm8001_ha->lock, flags); + spin_unlock_irq(&pm8001_ha->lock); t->task_done(t); - spin_lock_irqsave(&pm8001_ha->lock, flags); + spin_lock_irq(&pm8001_ha->lock); } } @@ -2207,7 +2414,6 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) { struct sas_task *t; - unsigned long flags = 0; struct task_status_struct *ts; struct pm8001_ccb_info *ccb; struct pm8001_device *pm8001_dev; @@ -2287,9 +2493,9 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->stat = SAS_QUEUE_FULL; pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/*ditto*/ - spin_unlock_irqrestore(&pm8001_ha->lock, flags); + spin_unlock_irq(&pm8001_ha->lock); t->task_done(t); - spin_lock_irqsave(&pm8001_ha->lock, flags); + spin_lock_irq(&pm8001_ha->lock); return; } break; @@ -2387,31 +2593,31 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->stat = SAS_OPEN_TO; break; } - spin_lock_irqsave(&t->task_state_lock, flags); + spin_lock_irq(&t->task_state_lock); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { - spin_unlock_irqrestore(&t->task_state_lock, flags); + spin_unlock_irq(&t->task_state_lock); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("task 0x%p done with io_status 0x%x" " resp 0x%x stat 0x%x but aborted by upper layer!\n", t, event, ts->resp, ts->stat)); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); } else if (t->uldd_task) { - spin_unlock_irqrestore(&t->task_state_lock, flags); + spin_unlock_irq(&t->task_state_lock); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/* ditto */ - spin_unlock_irqrestore(&pm8001_ha->lock, flags); + spin_unlock_irq(&pm8001_ha->lock); t->task_done(t); - spin_lock_irqsave(&pm8001_ha->lock, flags); + spin_lock_irq(&pm8001_ha->lock); } else if (!t->uldd_task) { - spin_unlock_irqrestore(&t->task_state_lock, flags); + spin_unlock_irq(&t->task_state_lock); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/*ditto*/ - spin_unlock_irqrestore(&pm8001_ha->lock, flags); + spin_unlock_irq(&pm8001_ha->lock); t->task_done(t); - spin_lock_irqsave(&pm8001_ha->lock, flags); + spin_lock_irq(&pm8001_ha->lock); } } @@ -2857,7 +3063,7 @@ static void pm8001_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha, memset((u8 *)&payload, 0, sizeof(payload)); circularQ = &pm8001_ha->inbnd_q_tbl[Qnum]; - payload.tag = 1; + payload.tag = cpu_to_le32(1); payload.sea_phyid_portid = cpu_to_le32(((SEA & 0xFFFF) << 8) | ((phyId & 0x0F) << 4) | (port_id & 0x0F)); payload.param0 = cpu_to_le32(param0); @@ -2929,9 +3135,9 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) phy->phy_type |= PORT_TYPE_SAS; phy->identify.device_type = deviceType; phy->phy_attached = 1; - if (phy->identify.device_type == SAS_END_DEV) + if (phy->identify.device_type == SAS_END_DEVICE) phy->identify.target_port_protocols = SAS_PROTOCOL_SSP; - else if (phy->identify.device_type != NO_DEVICE) + else if (phy->identify.device_type != SAS_PHY_UNUSED) phy->identify.target_port_protocols = SAS_PROTOCOL_SMP; phy->sas_phy.oob_mode = SAS_OOB_MODE; sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); @@ -3075,7 +3281,7 @@ static int mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) (struct dev_reg_resp *)(piomb + 4); htag = le32_to_cpu(registerRespPayload->tag); - ccb = &pm8001_ha->ccb_info[registerRespPayload->tag]; + ccb = &pm8001_ha->ccb_info[htag]; pm8001_dev = ccb->device; status = le32_to_cpu(registerRespPayload->status); device_id = le32_to_cpu(registerRespPayload->device_id); @@ -3149,7 +3355,7 @@ mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) struct fw_control_ex fw_control_context; struct fw_flash_Update_resp *ppayload = (struct fw_flash_Update_resp *)(piomb + 4); - u32 tag = le32_to_cpu(ppayload->tag); + u32 tag = ppayload->tag; struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[tag]; status = le32_to_cpu(ppayload->status); memcpy(&fw_control_context, @@ -3238,13 +3444,12 @@ mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) struct task_abort_resp *pPayload = (struct task_abort_resp *)(piomb + 4); - ccb = &pm8001_ha->ccb_info[pPayload->tag]; - t = ccb->task; - status = le32_to_cpu(pPayload->status); tag = le32_to_cpu(pPayload->tag); scp = le32_to_cpu(pPayload->scp); + ccb = &pm8001_ha->ccb_info[tag]; + t = ccb->task; PM8001_IO_DBG(pm8001_ha, pm8001_printk(" status = 0x%x\n", status)); if (t == NULL) @@ -3270,7 +3475,7 @@ mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; spin_unlock_irqrestore(&t->task_state_lock, flags); - pm8001_ccb_task_free(pm8001_ha, t, ccb, pPayload->tag); + pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb(); t->task_done(t); return 0; @@ -3497,7 +3702,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) { u32 pHeader = (u32)*(u32 *)piomb; - u8 opc = (u8)((le32_to_cpu(pHeader)) & 0xFFF); + u8 opc = (u8)(pHeader & 0xFFF); PM8001_MSG_DBG(pm8001_ha, pm8001_printk("process_one_iomb:")); @@ -3664,9 +3869,11 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha) { struct outbound_queue_table *circularQ; void *pMsg1 = NULL; - u8 bc = 0; + u8 uninitialized_var(bc); u32 ret = MPI_IO_STATUS_FAIL; + unsigned long flags; + spin_lock_irqsave(&pm8001_ha->lock, flags); circularQ = &pm8001_ha->outbnd_q_tbl[0]; do { ret = mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc); @@ -3677,16 +3884,16 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha) mpi_msg_free_set(pm8001_ha, pMsg1, circularQ, bc); } if (MPI_IO_STATUS_BUSY == ret) { - u32 producer_idx; /* Update the producer index from SPC */ - producer_idx = pm8001_read_32(circularQ->pi_virt); - circularQ->producer_index = cpu_to_le32(producer_idx); - if (circularQ->producer_index == + circularQ->producer_index = + cpu_to_le32(pm8001_read_32(circularQ->pi_virt)); + if (le32_to_cpu(circularQ->producer_index) == circularQ->consumer_idx) /* OQ is empty */ break; } } while (1); + spin_unlock_irqrestore(&pm8001_ha->lock, flags); return ret; } @@ -3712,9 +3919,9 @@ pm8001_chip_make_sg(struct scatterlist *scatter, int nr, void *prd) } } -static void build_smp_cmd(u32 deviceID, u32 hTag, struct smp_req *psmp_cmd) +static void build_smp_cmd(u32 deviceID, __le32 hTag, struct smp_req *psmp_cmd) { - psmp_cmd->tag = cpu_to_le32(hTag); + psmp_cmd->tag = hTag; psmp_cmd->device_id = cpu_to_le32(deviceID); psmp_cmd->len_ip_ir = cpu_to_le32(1|(1 << 1)); } @@ -3798,7 +4005,7 @@ static int pm8001_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, struct ssp_ini_io_start_req ssp_cmd; u32 tag = ccb->ccb_tag; int ret; - __le64 phys_addr; + u64 phys_addr; struct inbound_queue_table *circularQ; u32 opc = OPC_INB_SSPINIIOSTART; memset(&ssp_cmd, 0, sizeof(ssp_cmd)); @@ -3819,15 +4026,15 @@ static int pm8001_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, /* fill in PRD (scatter/gather) table, if any */ if (task->num_scatter > 1) { pm8001_chip_make_sg(task->scatter, ccb->n_elem, ccb->buf_prd); - phys_addr = cpu_to_le64(ccb->ccb_dma_handle + - offsetof(struct pm8001_ccb_info, buf_prd[0])); - ssp_cmd.addr_low = lower_32_bits(phys_addr); - ssp_cmd.addr_high = upper_32_bits(phys_addr); + phys_addr = ccb->ccb_dma_handle + + offsetof(struct pm8001_ccb_info, buf_prd[0]); + ssp_cmd.addr_low = cpu_to_le32(lower_32_bits(phys_addr)); + ssp_cmd.addr_high = cpu_to_le32(upper_32_bits(phys_addr)); ssp_cmd.esgl = cpu_to_le32(1<<31); } else if (task->num_scatter == 1) { - __le64 dma_addr = cpu_to_le64(sg_dma_address(task->scatter)); - ssp_cmd.addr_low = lower_32_bits(dma_addr); - ssp_cmd.addr_high = upper_32_bits(dma_addr); + u64 dma_addr = sg_dma_address(task->scatter); + ssp_cmd.addr_low = cpu_to_le32(lower_32_bits(dma_addr)); + ssp_cmd.addr_high = cpu_to_le32(upper_32_bits(dma_addr)); ssp_cmd.len = cpu_to_le32(task->total_xfer_len); ssp_cmd.esgl = 0; } else if (task->num_scatter == 0) { @@ -3850,7 +4057,7 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha, int ret; struct sata_start_req sata_cmd; u32 hdr_tag, ncg_tag = 0; - __le64 phys_addr; + u64 phys_addr; u32 ATAP = 0x0; u32 dir; struct inbound_queue_table *circularQ; @@ -3889,13 +4096,13 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha, /* fill in PRD (scatter/gather) table, if any */ if (task->num_scatter > 1) { pm8001_chip_make_sg(task->scatter, ccb->n_elem, ccb->buf_prd); - phys_addr = cpu_to_le64(ccb->ccb_dma_handle + - offsetof(struct pm8001_ccb_info, buf_prd[0])); + phys_addr = ccb->ccb_dma_handle + + offsetof(struct pm8001_ccb_info, buf_prd[0]); sata_cmd.addr_low = lower_32_bits(phys_addr); sata_cmd.addr_high = upper_32_bits(phys_addr); sata_cmd.esgl = cpu_to_le32(1 << 31); } else if (task->num_scatter == 1) { - __le64 dma_addr = cpu_to_le64(sg_dma_address(task->scatter)); + u64 dma_addr = sg_dma_address(task->scatter); sata_cmd.addr_low = lower_32_bits(dma_addr); sata_cmd.addr_high = upper_32_bits(dma_addr); sata_cmd.len = cpu_to_le32(task->total_xfer_len); @@ -4039,7 +4246,7 @@ static int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha, circularQ = &pm8001_ha->inbnd_q_tbl[0]; memset(&payload, 0, sizeof(payload)); - payload.tag = 1; + payload.tag = cpu_to_le32(1); payload.device_id = cpu_to_le32(device_id); PM8001_MSG_DBG(pm8001_ha, pm8001_printk("unregister device device_id = %d\n", device_id)); @@ -4063,7 +4270,7 @@ static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, u32 opc = OPC_INB_LOCAL_PHY_CONTROL; memset(&payload, 0, sizeof(payload)); circularQ = &pm8001_ha->inbnd_q_tbl[0]; - payload.tag = 1; + payload.tag = cpu_to_le32(1); payload.phyop_phyid = cpu_to_le32(((phy_op & 0xff) << 8) | (phyId & 0x0F)); ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload); @@ -4092,12 +4299,9 @@ static u32 pm8001_chip_is_our_interupt(struct pm8001_hba_info *pm8001_ha) static irqreturn_t pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha) { - unsigned long flags; - spin_lock_irqsave(&pm8001_ha->lock, flags); pm8001_chip_interrupt_disable(pm8001_ha); process_oq(pm8001_ha); pm8001_chip_interrupt_enable(pm8001_ha); - spin_unlock_irqrestore(&pm8001_ha->lock, flags); return IRQ_HANDLED; } @@ -4360,8 +4564,10 @@ pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha, payload.cur_image_offset = cpu_to_le32(info->cur_image_offset); payload.total_image_len = cpu_to_le32(info->total_image_len); payload.len = info->sgl.im_len.len ; - payload.sgl_addr_lo = lower_32_bits(info->sgl.addr); - payload.sgl_addr_hi = upper_32_bits(info->sgl.addr); + payload.sgl_addr_lo = + cpu_to_le32(lower_32_bits(le64_to_cpu(info->sgl.addr))); + payload.sgl_addr_hi = + cpu_to_le32(upper_32_bits(le64_to_cpu(info->sgl.addr))); ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload); return ret; } |