diff options
Diffstat (limited to 'drivers/scsi/pm8001')
-rw-r--r-- | drivers/scsi/pm8001/pm8001_ctl.c | 20 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.c | 131 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_init.c | 36 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.c | 70 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.h | 24 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm80xx_hwi.c | 451 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm80xx_hwi.h | 3 |
7 files changed, 551 insertions, 184 deletions
diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index 6b85016b4db3..7c6be2ec110d 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c @@ -70,6 +70,25 @@ static DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL); /** + * controller_fatal_error_show - check controller is under fatal err + * @cdev: pointer to embedded class device + * @buf: the buffer returned + * + * A sysfs 'read only' shost attribute. + */ +static ssize_t controller_fatal_error_show(struct device *cdev, + struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(cdev); + struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); + struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; + + return snprintf(buf, PAGE_SIZE, "%d\n", + pm8001_ha->controller_fatal_error); +} +static DEVICE_ATTR_RO(controller_fatal_error); + +/** * pm8001_ctl_fw_version_show - firmware version * @cdev: pointer to embedded class device * @buf: the buffer returned @@ -804,6 +823,7 @@ static DEVICE_ATTR(update_fw, S_IRUGO|S_IWUSR|S_IWGRP, pm8001_show_update_fw, pm8001_store_update_fw); struct device_attribute *pm8001_host_attrs[] = { &dev_attr_interface_rev, + &dev_attr_controller_fatal_error, &dev_attr_fw_version, &dev_attr_update_fw, &dev_attr_aap_log, diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 68a8217032d0..1cbcade747fe 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -1336,10 +1336,13 @@ int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ, * @circularQ: the inbound queue we want to transfer to HBA. * @opCode: the operation code represents commands which LLDD and fw recognized. * @payload: the command payload of each operation command. + * @nb: size in bytes of the command payload + * @responseQueue: queue to interrupt on w/ command response (if any) */ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, struct inbound_queue_table *circularQ, - u32 opCode, void *payload, u32 responseQueue) + u32 opCode, void *payload, size_t nb, + u32 responseQueue) { u32 Header = 0, hpriority = 0, bc = 1, category = 0x02; void *pMessage; @@ -1350,10 +1353,13 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, pm8001_printk("No free mpi buffer\n")); return -ENOMEM; } - BUG_ON(!payload); - /*Copy to the payload*/ - memcpy(pMessage, payload, (pm8001_ha->iomb_size - - sizeof(struct mpi_msg_hdr))); + + if (nb > (pm8001_ha->iomb_size - sizeof(struct mpi_msg_hdr))) + nb = pm8001_ha->iomb_size - sizeof(struct mpi_msg_hdr); + memcpy(pMessage, payload, nb); + if (nb + sizeof(struct mpi_msg_hdr) < pm8001_ha->iomb_size) + memset(pMessage + nb, 0, pm8001_ha->iomb_size - + (nb + sizeof(struct mpi_msg_hdr))); /*Build the header*/ Header = ((1 << 31) | (hpriority << 30) | ((bc & 0x1f) << 24) @@ -1364,7 +1370,7 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, /*Update the PI to the firmware*/ pm8001_cw32(pm8001_ha, circularQ->pi_pci_bar, circularQ->pi_offset, circularQ->producer_idx); - PM8001_IO_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n", responseQueue, opCode, circularQ->producer_idx, circularQ->consumer_index)); @@ -1436,6 +1442,10 @@ u32 pm8001_mpi_msg_consume(struct pm8001_hba_info *pm8001_ha, /* read header */ header_tmp = pm8001_read_32(msgHeader); msgHeader_tmp = cpu_to_le32(header_tmp); + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( + "outbound opcode msgheader:%x ci=%d pi=%d\n", + msgHeader_tmp, circularQ->consumer_idx, + circularQ->producer_index)); if (0 != (le32_to_cpu(msgHeader_tmp) & 0x80000000)) { if (OPC_OUB_SKIP_ENTRY != (le32_to_cpu(msgHeader_tmp) & 0xfff)) { @@ -1604,7 +1614,8 @@ void pm8001_work_fn(struct work_struct *work) break; default: - pm8001_printk("...query task failed!!!\n"); + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( + "...query task failed!!!\n")); break; }); @@ -1758,7 +1769,8 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha, task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id); task_abort.tag = cpu_to_le32(ccb_tag); - ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, + sizeof(task_abort), 0); if (ret) pm8001_tag_free(pm8001_ha, ccb_tag); @@ -1831,7 +1843,8 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha, sata_cmd.ncqtag_atap_dir_m |= ((0x1 << 7) | (0x5 << 9)); memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis)); - res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0); + res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, + sizeof(sata_cmd), 0); if (res) { sas_free_task(task); pm8001_tag_free(pm8001_ha, ccb_tag); @@ -1890,6 +1903,11 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) pm8001_printk("SAS Address of IO Failure Drive:" "%016llx", SAS_ADDR(t->dev->sas_addr))); + if (status) + PM8001_IOERR_DBG(pm8001_ha, pm8001_printk( + "status:0x%x, tag:0x%x, task:0x%p\n", + status, tag, t)); + switch (status) { case IO_SUCCESS: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS" @@ -2072,7 +2090,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; default: - PM8001_IO_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("Unknown status 0x%x\n", status)); /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; @@ -2125,7 +2143,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) if (unlikely(!t || !t->lldd_task || !t->dev)) return; ts = &t->task_status; - PM8001_IO_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("port_id = %x,device_id = %x\n", port_id, dev_id)); switch (event) { @@ -2263,7 +2281,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) pm8001_printk(" IO_XFER_CMD_FRAME_ISSUED\n")); return; default: - PM8001_IO_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("Unknown status 0x%x\n", event)); /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; @@ -2352,6 +2370,12 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk("ts null\n")); return; } + + if (status) + PM8001_IOERR_DBG(pm8001_ha, pm8001_printk( + "status:0x%x, tag:0x%x, task::0x%p\n", + status, tag, t)); + /* Print sas address of IO failed device */ if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && (status != IO_UNDERFLOW)) { @@ -2652,7 +2676,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; default: - PM8001_IO_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("Unknown status 0x%x\n", status)); /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; @@ -2723,7 +2747,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) if (unlikely(!t || !t->lldd_task || !t->dev)) return; ts = &t->task_status; - PM8001_IO_DBG(pm8001_ha, pm8001_printk( + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( "port_id:0x%x, device_id:0x%x, tag:0x%x, event:0x%x\n", port_id, dev_id, tag, event)); switch (event) { @@ -2872,7 +2896,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->stat = SAS_OPEN_TO; break; default: - PM8001_IO_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("Unknown status 0x%x\n", event)); /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; @@ -2917,9 +2941,13 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) t = ccb->task; ts = &t->task_status; pm8001_dev = ccb->device; - if (status) + if (status) { PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("smp IO status 0x%x\n", status)); + PM8001_IOERR_DBG(pm8001_ha, + pm8001_printk("status:0x%x, tag:0x%x, task:0x%p\n", + status, tag, t)); + } if (unlikely(!t || !t->lldd_task || !t->dev)) return; @@ -3070,7 +3098,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; default: - PM8001_IO_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("Unknown status 0x%x\n", status)); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; @@ -3355,7 +3383,8 @@ static void pm8001_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha, ((phyId & 0x0F) << 4) | (port_id & 0x0F)); payload.param0 = cpu_to_le32(param0); payload.param1 = cpu_to_le32(param1); - pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); } static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, @@ -3416,7 +3445,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_get_lrate_mode(phy, link_rate); break; default: - PM8001_MSG_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("unknown device type(%x)\n", deviceType)); break; } @@ -3463,7 +3492,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) struct sas_ha_struct *sas_ha = pm8001_ha->sas; struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; unsigned long flags; - PM8001_MSG_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("HW_EVENT_SATA_PHY_UP port id = %d," " phy id = %d\n", port_id, phy_id)); port->port_state = portstate; @@ -3541,7 +3570,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) break; default: port->port_attached = 0; - PM8001_MSG_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(" phy Down and(default) = %x\n", portstate)); break; @@ -3689,7 +3718,7 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, pm8001_printk(": FLASH_UPDATE_DISABLED\n")); break; default: - PM8001_MSG_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("No matched status = %d\n", status)); break; } @@ -3805,8 +3834,9 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) struct sas_ha_struct *sas_ha = pm8001_ha->sas; struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("outbound queue HW event & event type : ")); + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( + "SPC HW event for portid:%d, phyid:%d, event:%x, status:%x\n", + port_id, phy_id, eventType, status)); switch (eventType) { case HW_EVENT_PHY_START_STATUS: PM8001_MSG_DBG(pm8001_ha, @@ -3990,7 +4020,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) pm8001_printk("EVENT_BROADCAST_ASYNCH_EVENT\n")); break; default: - PM8001_MSG_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("Unknown event type = %x\n", eventType)); break; } @@ -4161,7 +4191,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk("OPC_OUB_SAS_RE_INITIALIZE\n")); break; default: - PM8001_MSG_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("Unknown outbound Queue IOMB OPC = %x\n", opc)); break; @@ -4284,7 +4314,7 @@ static int pm8001_chip_smp_req(struct pm8001_hba_info *pm8001_ha, cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_resp)-4); build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, - (u32 *)&smp_cmd, 0); + &smp_cmd, sizeof(smp_cmd), 0); if (rc) goto err_out_2; @@ -4352,7 +4382,8 @@ static int pm8001_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, ssp_cmd.len = cpu_to_le32(task->total_xfer_len); ssp_cmd.esgl = 0; } - ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, + sizeof(ssp_cmd), 0); return ret; } @@ -4461,7 +4492,8 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha, } } - ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, + sizeof(sata_cmd), 0); return ret; } @@ -4496,7 +4528,8 @@ pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) memcpy(payload.sas_identify.sas_addr, pm8001_ha->sas_addr, SAS_ADDR_SIZE); payload.sas_identify.phy_id = phy_id; - ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, + sizeof(payload), 0); return ret; } @@ -4518,7 +4551,8 @@ static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha, memset(&payload, 0, sizeof(payload)); payload.tag = cpu_to_le32(tag); payload.phy_id = cpu_to_le32(phy_id); - ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, + sizeof(payload), 0); return ret; } @@ -4577,7 +4611,8 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, cpu_to_le32(ITNT | (firstBurstSize * 0x10000)); memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr, SAS_ADDR_SIZE); - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); return rc; } @@ -4598,7 +4633,8 @@ int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha, payload.device_id = cpu_to_le32(device_id); PM8001_MSG_DBG(pm8001_ha, pm8001_printk("unregister device device_id = %d\n", device_id)); - ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); return ret; } @@ -4621,7 +4657,8 @@ static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, payload.tag = cpu_to_le32(1); payload.phyop_phyid = cpu_to_le32(((phy_op & 0xff) << 8) | (phyId & 0x0F)); - ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); return ret; } @@ -4649,6 +4686,9 @@ static irqreturn_t pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec) { pm8001_chip_interrupt_disable(pm8001_ha, vec); + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( + "irq vec %d, ODMR:0x%x\n", + vec, pm8001_cr32(pm8001_ha, 0, 0x30))); process_oq(pm8001_ha, vec); pm8001_chip_interrupt_enable(pm8001_ha, vec); return IRQ_HANDLED; @@ -4672,7 +4712,8 @@ static int send_task_abort(struct pm8001_hba_info *pm8001_ha, u32 opc, task_abort.device_id = cpu_to_le32(dev_id); task_abort.tag = cpu_to_le32(cmd_tag); } - ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, + sizeof(task_abort), 0); return ret; } @@ -4729,7 +4770,8 @@ int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha, if (pm8001_ha->chip_id != chip_8001) sspTMCmd.ds_ads_m = 0x08; circularQ = &pm8001_ha->inbnd_q_tbl[0]; - ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd, + sizeof(sspTMCmd), 0); return ret; } @@ -4819,7 +4861,8 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, default: break; } - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, + sizeof(nvmd_req), 0); if (rc) { kfree(fw_control_context); pm8001_tag_free(pm8001_ha, tag); @@ -4903,7 +4946,8 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, default: break; } - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, + sizeof(nvmd_req), 0); if (rc) { kfree(fw_control_context); pm8001_tag_free(pm8001_ha, tag); @@ -4938,7 +4982,8 @@ pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha, 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 = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); return ret; } @@ -4960,6 +5005,8 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, if (!fw_control_context) return -ENOMEM; fw_control = (struct fw_control_info *)&ioctl_payload->func_specific; + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( + "dma fw_control context input length :%x\n", fw_control->len)); memcpy(buffer, fw_control->buffer, fw_control->len); flash_update_info.sgl.addr = cpu_to_le64(phys_addr); flash_update_info.sgl.im_len.len = cpu_to_le32(fw_control->len); @@ -5083,7 +5130,8 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha, payload.tag = cpu_to_le32(tag); payload.device_id = cpu_to_le32(pm8001_dev->device_id); payload.nds = cpu_to_le32(state); - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); return rc; } @@ -5108,7 +5156,8 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha) payload.SSAHOLT = cpu_to_le32(0xd << 25); payload.sata_hol_tmo = cpu_to_le32(80); payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff); - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); if (rc) pm8001_tag_free(pm8001_ha, tag); return rc; diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 3374f553c617..c6d9da7b546e 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -41,6 +41,19 @@ #include <linux/slab.h> #include "pm8001_sas.h" #include "pm8001_chips.h" +#include "pm80xx_hwi.h" + +static ulong logging_level = PM8001_FAIL_LOGGING | PM8001_IOERR_LOGGING; +module_param(logging_level, ulong, 0644); +MODULE_PARM_DESC(logging_level, " bits for enabling logging info."); + +static ulong link_rate = LINKRATE_15 | LINKRATE_30 | LINKRATE_60 | LINKRATE_120; +module_param(link_rate, ulong, 0644); +MODULE_PARM_DESC(link_rate, "Enable link rate.\n" + " 1: Link rate 1.5G\n" + " 2: Link rate 3.0G\n" + " 4: Link rate 6.0G\n" + " 8: Link rate 12.0G\n"); static struct scsi_transport_template *pm8001_stt; @@ -432,7 +445,7 @@ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha) } else { pm8001_ha->io_mem[logicalBar].membase = 0; pm8001_ha->io_mem[logicalBar].memsize = 0; - pm8001_ha->io_mem[logicalBar].memvirtaddr = 0; + pm8001_ha->io_mem[logicalBar].memvirtaddr = NULL; } logicalBar++; } @@ -466,7 +479,15 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev, pm8001_ha->sas = sha; pm8001_ha->shost = shost; pm8001_ha->id = pm8001_id++; - pm8001_ha->logging_level = 0x01; + pm8001_ha->logging_level = logging_level; + if (link_rate >= 1 && link_rate <= 15) + pm8001_ha->link_rate = (link_rate << 8); + else { + pm8001_ha->link_rate = LINKRATE_15 | LINKRATE_30 | + LINKRATE_60 | LINKRATE_120; + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( + "Setting link rate to default value\n")); + } sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id); /* IOMB size is 128 for 8088/89 controllers */ if (pm8001_ha->chip_id != chip_8001) @@ -873,7 +894,6 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) u32 number_of_intr; int flag = 0; int rc; - static char intr_drvname[PM8001_MAX_MSIX_VEC][sizeof(DRV_NAME)+3]; /* SPCv controllers supports 64 msi-x */ if (pm8001_ha->chip_id == chip_8001) { @@ -894,14 +914,16 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) rc, pm8001_ha->number_of_intr)); for (i = 0; i < number_of_intr; i++) { - snprintf(intr_drvname[i], sizeof(intr_drvname[0]), - DRV_NAME"%d", i); + snprintf(pm8001_ha->intr_drvname[i], + sizeof(pm8001_ha->intr_drvname[0]), + "%s-%d", pm8001_ha->name, i); pm8001_ha->irq_vector[i].irq_id = i; pm8001_ha->irq_vector[i].drv_inst = pm8001_ha; rc = request_irq(pci_irq_vector(pm8001_ha->pdev, i), pm8001_interrupt_handler_msix, flag, - intr_drvname[i], &(pm8001_ha->irq_vector[i])); + pm8001_ha->intr_drvname[i], + &(pm8001_ha->irq_vector[i])); if (rc) { for (j = 0; j < i; j++) { free_irq(pci_irq_vector(pm8001_ha->pdev, i), @@ -942,7 +964,7 @@ intx: pm8001_ha->irq_vector[0].irq_id = 0; pm8001_ha->irq_vector[0].drv_inst = pm8001_ha; rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED, - DRV_NAME, SHOST_TO_SAS_HA(pm8001_ha->shost)); + pm8001_ha->name, SHOST_TO_SAS_HA(pm8001_ha->shost)); return rc; } diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 7e48154e11c3..b7cbc312843e 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -119,7 +119,7 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr, mem_virt_alloc = dma_alloc_coherent(&pdev->dev, mem_size + align, &mem_dma_handle, GFP_KERNEL); if (!mem_virt_alloc) { - pm8001_printk("memory allocation error\n"); + pr_err("pm80xx: memory allocation error\n"); return -1; } *pphys_addr = mem_dma_handle; @@ -249,6 +249,8 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, spin_unlock_irqrestore(&pm8001_ha->lock, flags); return 0; default: + PM8001_DEVIO_DBG(pm8001_ha, + pm8001_printk("func 0x%x\n", func)); rc = -EOPNOTSUPP; } msleep(300); @@ -384,8 +386,9 @@ static int pm8001_task_exec(struct sas_task *task, struct pm8001_port *port = NULL; struct sas_task *t = task; struct pm8001_ccb_info *ccb; - u32 tag = 0xdeadbeef, rc, n_elem = 0; + u32 tag = 0xdeadbeef, rc = 0, n_elem = 0; unsigned long flags = 0; + enum sas_protocol task_proto = t->task_proto; if (!dev->port) { struct task_status_struct *tsm = &t->task_status; @@ -410,7 +413,7 @@ static int pm8001_task_exec(struct sas_task *task, pm8001_dev = dev->lldd_dev; port = &pm8001_ha->port[sas_find_local_port_id(dev)]; if (DEV_IS_GONE(pm8001_dev) || !port->port_attached) { - if (sas_protocol_ata(t->task_proto)) { + if (sas_protocol_ata(task_proto)) { struct task_status_struct *ts = &t->task_status; ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_PHY_DOWN; @@ -432,7 +435,7 @@ static int pm8001_task_exec(struct sas_task *task, goto err_out; ccb = &pm8001_ha->ccb_info[tag]; - if (!sas_protocol_ata(t->task_proto)) { + if (!sas_protocol_ata(task_proto)) { if (t->num_scatter) { n_elem = dma_map_sg(pm8001_ha->dev, t->scatter, @@ -452,7 +455,7 @@ static int pm8001_task_exec(struct sas_task *task, ccb->ccb_tag = tag; ccb->task = t; ccb->device = pm8001_dev; - switch (t->task_proto) { + switch (task_proto) { case SAS_PROTOCOL_SMP: rc = pm8001_task_prep_smp(pm8001_ha, ccb); break; @@ -469,8 +472,7 @@ static int pm8001_task_exec(struct sas_task *task, break; default: dev_printk(KERN_ERR, pm8001_ha->dev, - "unknown sas_task proto: 0x%x\n", - t->task_proto); + "unknown sas_task proto: 0x%x\n", task_proto); rc = -EINVAL; break; } @@ -493,7 +495,7 @@ err_out_tag: pm8001_tag_free(pm8001_ha, tag); err_out: dev_printk(KERN_ERR, pm8001_ha->dev, "pm8001 exec failed[%d]!\n", rc); - if (!sas_protocol_ata(t->task_proto)) + if (!sas_protocol_ata(task_proto)) if (n_elem) dma_unmap_sg(pm8001_ha->dev, t->scatter, t->num_scatter, t->data_dir); @@ -1179,7 +1181,7 @@ int pm8001_query_task(struct sas_task *task) break; } } - pm8001_printk(":rc= %d\n", rc); + pr_err("pm80xx: rc= %d\n", rc); return rc; } @@ -1202,8 +1204,8 @@ int pm8001_abort_task(struct sas_task *task) pm8001_dev = dev->lldd_dev; pm8001_ha = pm8001_find_ha_by_dev(dev); phy_id = pm8001_dev->attached_phy; - rc = pm8001_find_tag(task, &tag); - if (rc == 0) { + ret = pm8001_find_tag(task, &tag); + if (ret == 0) { pm8001_printk("no tag for task:%p\n", task); return TMF_RESP_FUNC_FAILED; } @@ -1241,26 +1243,50 @@ int pm8001_abort_task(struct sas_task *task) /* 2. Send Phy Control Hard Reset */ reinit_completion(&completion); + phy->port_reset_status = PORT_RESET_TMO; phy->reset_success = false; phy->enable_completion = &completion; phy->reset_completion = &completion_reset; ret = PM8001_CHIP_DISP->phy_ctl_req(pm8001_ha, phy_id, PHY_HARD_RESET); - if (ret) - goto out; - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("Waiting for local phy ctl\n")); - wait_for_completion(&completion); - if (!phy->reset_success) + if (ret) { + phy->enable_completion = NULL; + phy->reset_completion = NULL; goto out; + } - /* 3. Wait for Port Reset complete / Port reset TMO */ + /* In the case of the reset timeout/fail we still + * abort the command at the firmware. The assumption + * here is that the drive is off doing something so + * that it's not processing requests, and we want to + * avoid getting a completion for this and either + * leaking the task in libsas or losing the race and + * getting a double free. + */ PM8001_MSG_DBG(pm8001_ha, + pm8001_printk("Waiting for local phy ctl\n")); + ret = wait_for_completion_timeout(&completion, + PM8001_TASK_TIMEOUT * HZ); + if (!ret || !phy->reset_success) { + phy->enable_completion = NULL; + phy->reset_completion = NULL; + } else { + /* 3. Wait for Port Reset complete or + * Port reset TMO + */ + PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Waiting for Port reset\n")); - wait_for_completion(&completion_reset); - if (phy->port_reset_status) { - pm8001_dev_gone_notify(dev); - goto out; + ret = wait_for_completion_timeout( + &completion_reset, + PM8001_TASK_TIMEOUT * HZ); + if (!ret) + phy->reset_completion = NULL; + WARN_ON(phy->port_reset_status == + PORT_RESET_TMO); + if (phy->port_reset_status == PORT_RESET_TMO) { + pm8001_dev_gone_notify(dev); + goto out; + } } /* diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index ff17c6aff63d..93438c8f67da 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -66,8 +66,11 @@ #define PM8001_EH_LOGGING 0x10 /* libsas EH function logging*/ #define PM8001_IOCTL_LOGGING 0x20 /* IOCTL message logging */ #define PM8001_MSG_LOGGING 0x40 /* misc message logging */ -#define pm8001_printk(format, arg...) printk(KERN_INFO "pm80xx %s %d:" \ - format, __func__, __LINE__, ## arg) +#define PM8001_DEV_LOGGING 0x80 /* development message logging */ +#define PM8001_DEVIO_LOGGING 0x100 /* development io message logging */ +#define PM8001_IOERR_LOGGING 0x200 /* development io err message logging */ +#define pm8001_printk(format, arg...) pr_info("%s:: %s %d:" \ + format, pm8001_ha->name, __func__, __LINE__, ## arg) #define PM8001_CHECK_LOGGING(HBA, LEVEL, CMD) \ do { \ if (unlikely(HBA->logging_level & LEVEL)) \ @@ -97,6 +100,14 @@ do { \ #define PM8001_MSG_DBG(HBA, CMD) \ PM8001_CHECK_LOGGING(HBA, PM8001_MSG_LOGGING, CMD) +#define PM8001_DEV_DBG(HBA, CMD) \ + PM8001_CHECK_LOGGING(HBA, PM8001_DEV_LOGGING, CMD) + +#define PM8001_DEVIO_DBG(HBA, CMD) \ + PM8001_CHECK_LOGGING(HBA, PM8001_DEVIO_LOGGING, CMD) + +#define PM8001_IOERR_DBG(HBA, CMD) \ + PM8001_CHECK_LOGGING(HBA, PM8001_IOERR_LOGGING, CMD) #define PM8001_USE_TASKLET #define PM8001_USE_MSIX @@ -141,6 +152,8 @@ struct pm8001_ioctl_payload { #define MPI_FATAL_EDUMP_TABLE_HANDSHAKE 0x0C /* FDDHSHK */ #define MPI_FATAL_EDUMP_TABLE_STATUS 0x10 /* FDDTSTAT */ #define MPI_FATAL_EDUMP_TABLE_ACCUM_LEN 0x14 /* ACCDDLEN */ +#define MPI_FATAL_EDUMP_TABLE_TOTAL_LEN 0x18 /* TOTALLEN */ +#define MPI_FATAL_EDUMP_TABLE_SIGNATURE 0x1C /* SIGNITURE */ #define MPI_FATAL_EDUMP_HANDSHAKE_RDY 0x1 #define MPI_FATAL_EDUMP_HANDSHAKE_BUSY 0x0 #define MPI_FATAL_EDUMP_TABLE_STAT_RSVD 0x0 @@ -496,6 +509,7 @@ struct pm8001_hba_info { u32 forensic_last_offset; u32 fatal_forensic_shift_offset; u32 forensic_fatal_step; + u32 forensic_preserved_accumulated_transfer; u32 evtlog_ib_offset; u32 evtlog_ob_offset; void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/ @@ -530,11 +544,14 @@ struct pm8001_hba_info { struct pm8001_ccb_info *ccb_info; #ifdef PM8001_USE_MSIX int number_of_intr;/*will be used in remove()*/ + char intr_drvname[PM8001_MAX_MSIX_VEC] + [PM8001_NAME_LENGTH+1+3+1]; #endif #ifdef PM8001_USE_TASKLET struct tasklet_struct tasklet[PM8001_MAX_MSIX_VEC]; #endif u32 logging_level; + u32 link_rate; u32 fw_status; u32 smp_exp_mode; bool controller_fatal_error; @@ -663,7 +680,8 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr, void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha); int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, struct inbound_queue_table *circularQ, - u32 opCode, void *payload, u32 responseQueue); + u32 opCode, void *payload, size_t nb, + u32 responseQueue); int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ, u16 messageSize, void **messagePtr); u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg, diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 73261902d75d..19601138e889 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -37,6 +37,7 @@ * POSSIBILITY OF SUCH DAMAGES. * */ + #include <linux/version.h> #include <linux/slab.h> #include "pm8001_sas.h" #include "pm80xx_hwi.h" @@ -75,7 +76,7 @@ void pm80xx_pci_mem_copy(struct pm8001_hba_info *pm8001_ha, u32 soffset, destination1 = (u32 *)destination; for (index = 0; index < dw_count; index += 4, destination1++) { - offset = (soffset + index / 4); + offset = (soffset + index); if (offset < (64 * 1024)) { value = pm8001_cr32(pm8001_ha, bus_base_number, offset); *destination1 = cpu_to_le32(value); @@ -92,9 +93,12 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev, struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; void __iomem *fatal_table_address = pm8001_ha->fatal_tbl_addr; u32 accum_len , reg_val, index, *temp; + u32 status = 1; unsigned long start; u8 *direct_data; char *fatal_error_data = buf; + u32 length_to_read; + u32 offset; pm8001_ha->forensic_info.data_buf.direct_data = buf; if (pm8001_ha->chip_id == chip_8001) { @@ -104,16 +108,35 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev, return (char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf; } + /* initialize variables for very first call from host application */ if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) { PM8001_IO_DBG(pm8001_ha, pm8001_printk("forensic_info TYPE_NON_FATAL..............\n")); direct_data = (u8 *)fatal_error_data; pm8001_ha->forensic_info.data_type = TYPE_NON_FATAL; pm8001_ha->forensic_info.data_buf.direct_len = SYSFS_OFFSET; + pm8001_ha->forensic_info.data_buf.direct_offset = 0; pm8001_ha->forensic_info.data_buf.read_len = 0; + pm8001_ha->forensic_preserved_accumulated_transfer = 0; - pm8001_ha->forensic_info.data_buf.direct_data = direct_data; + /* Write signature to fatal dump table */ + pm8001_mw32(fatal_table_address, + MPI_FATAL_EDUMP_TABLE_SIGNATURE, 0x1234abcd); + pm8001_ha->forensic_info.data_buf.direct_data = direct_data; + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("ossaHwCB: status1 %d\n", status)); + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("ossaHwCB: read_len 0x%x\n", + pm8001_ha->forensic_info.data_buf.read_len)); + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("ossaHwCB: direct_len 0x%x\n", + pm8001_ha->forensic_info.data_buf.direct_len)); + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("ossaHwCB: direct_offset 0x%x\n", + pm8001_ha->forensic_info.data_buf.direct_offset)); + } + if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) { /* start to get data */ /* Program the MEMBASE II Shifting Register with 0x00.*/ pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, @@ -126,30 +149,66 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev, /* Read until accum_len is retrived */ accum_len = pm8001_mr32(fatal_table_address, MPI_FATAL_EDUMP_TABLE_ACCUM_LEN); - PM8001_IO_DBG(pm8001_ha, pm8001_printk("accum_len 0x%x\n", - accum_len)); + /* Determine length of data between previously stored transfer length + * and current accumulated transfer length + */ + length_to_read = + accum_len - pm8001_ha->forensic_preserved_accumulated_transfer; + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("get_fatal_spcv: accum_len 0x%x\n", accum_len)); + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("get_fatal_spcv: length_to_read 0x%x\n", + length_to_read)); + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("get_fatal_spcv: last_offset 0x%x\n", + pm8001_ha->forensic_last_offset)); + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("get_fatal_spcv: read_len 0x%x\n", + pm8001_ha->forensic_info.data_buf.read_len)); + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("get_fatal_spcv:: direct_len 0x%x\n", + pm8001_ha->forensic_info.data_buf.direct_len)); + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("get_fatal_spcv:: direct_offset 0x%x\n", + pm8001_ha->forensic_info.data_buf.direct_offset)); + + /* If accumulated length failed to read correctly fail the attempt.*/ if (accum_len == 0xFFFFFFFF) { PM8001_IO_DBG(pm8001_ha, pm8001_printk("Possible PCI issue 0x%x not expected\n", - accum_len)); - return -EIO; + accum_len)); + return status; } - if (accum_len == 0 || accum_len >= 0x100000) { + /* If accumulated length is zero fail the attempt */ + if (accum_len == 0) { pm8001_ha->forensic_info.data_buf.direct_data += sprintf(pm8001_ha->forensic_info.data_buf.direct_data, - "%08x ", 0xFFFFFFFF); + "%08x ", 0xFFFFFFFF); return (char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf; } + /* Accumulated length is good so start capturing the first data */ temp = (u32 *)pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr; if (pm8001_ha->forensic_fatal_step == 0) { moreData: + /* If data to read is less than SYSFS_OFFSET then reduce the + * length of dataLen + */ + if (pm8001_ha->forensic_last_offset + SYSFS_OFFSET + > length_to_read) { + pm8001_ha->forensic_info.data_buf.direct_len = + length_to_read - + pm8001_ha->forensic_last_offset; + } else { + pm8001_ha->forensic_info.data_buf.direct_len = + SYSFS_OFFSET; + } if (pm8001_ha->forensic_info.data_buf.direct_data) { /* Data is in bar, copy to host memory */ - pm80xx_pci_mem_copy(pm8001_ha, pm8001_ha->fatal_bar_loc, - pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr, - pm8001_ha->forensic_info.data_buf.direct_len , - 1); + pm80xx_pci_mem_copy(pm8001_ha, + pm8001_ha->fatal_bar_loc, + pm8001_ha->memoryMap.region[FORENSIC_MEM].virt_ptr, + pm8001_ha->forensic_info.data_buf.direct_len, 1); } pm8001_ha->fatal_bar_loc += pm8001_ha->forensic_info.data_buf.direct_len; @@ -160,21 +219,29 @@ moreData: pm8001_ha->forensic_info.data_buf.read_len = pm8001_ha->forensic_info.data_buf.direct_len; - if (pm8001_ha->forensic_last_offset >= accum_len) { + if (pm8001_ha->forensic_last_offset >= length_to_read) { pm8001_ha->forensic_info.data_buf.direct_data += sprintf(pm8001_ha->forensic_info.data_buf.direct_data, "%08x ", 3); - for (index = 0; index < (SYSFS_OFFSET / 4); index++) { + for (index = 0; index < + (pm8001_ha->forensic_info.data_buf.direct_len + / 4); index++) { pm8001_ha->forensic_info.data_buf.direct_data += - sprintf(pm8001_ha-> - forensic_info.data_buf.direct_data, - "%08x ", *(temp + index)); + sprintf( + pm8001_ha->forensic_info.data_buf.direct_data, + "%08x ", *(temp + index)); } pm8001_ha->fatal_bar_loc = 0; pm8001_ha->forensic_fatal_step = 1; pm8001_ha->fatal_forensic_shift_offset = 0; pm8001_ha->forensic_last_offset = 0; + status = 0; + offset = (int) + ((char *)pm8001_ha->forensic_info.data_buf.direct_data + - (char *)buf); + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("get_fatal_spcv:return1 0x%x\n", offset)); return (char *)pm8001_ha-> forensic_info.data_buf.direct_data - (char *)buf; @@ -184,12 +251,20 @@ moreData: sprintf(pm8001_ha-> forensic_info.data_buf.direct_data, "%08x ", 2); - for (index = 0; index < (SYSFS_OFFSET / 4); index++) { - pm8001_ha->forensic_info.data_buf.direct_data += - sprintf(pm8001_ha-> + for (index = 0; index < + (pm8001_ha->forensic_info.data_buf.direct_len + / 4); index++) { + pm8001_ha->forensic_info.data_buf.direct_data + += sprintf(pm8001_ha-> forensic_info.data_buf.direct_data, "%08x ", *(temp + index)); } + status = 0; + offset = (int) + ((char *)pm8001_ha->forensic_info.data_buf.direct_data + - (char *)buf); + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("get_fatal_spcv:return2 0x%x\n", offset)); return (char *)pm8001_ha-> forensic_info.data_buf.direct_data - (char *)buf; @@ -199,63 +274,122 @@ moreData: pm8001_ha->forensic_info.data_buf.direct_data += sprintf(pm8001_ha->forensic_info.data_buf.direct_data, "%08x ", 2); - for (index = 0; index < 256; index++) { + for (index = 0; index < + (pm8001_ha->forensic_info.data_buf.direct_len + / 4) ; index++) { pm8001_ha->forensic_info.data_buf.direct_data += sprintf(pm8001_ha-> - forensic_info.data_buf.direct_data, - "%08x ", *(temp + index)); + forensic_info.data_buf.direct_data, + "%08x ", *(temp + index)); } pm8001_ha->fatal_forensic_shift_offset += 0x100; pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, pm8001_ha->fatal_forensic_shift_offset); pm8001_ha->fatal_bar_loc = 0; + status = 0; + offset = (int) + ((char *)pm8001_ha->forensic_info.data_buf.direct_data + - (char *)buf); + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("get_fatal_spcv: return3 0x%x\n", offset)); return (char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf; } if (pm8001_ha->forensic_fatal_step == 1) { - pm8001_ha->fatal_forensic_shift_offset = 0; - /* Read 64K of the debug data. */ - pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER, - pm8001_ha->fatal_forensic_shift_offset); - pm8001_mw32(fatal_table_address, - MPI_FATAL_EDUMP_TABLE_HANDSHAKE, + /* store previous accumulated length before triggering next + * accumulated length update + */ + pm8001_ha->forensic_preserved_accumulated_transfer = + pm8001_mr32(fatal_table_address, + MPI_FATAL_EDUMP_TABLE_ACCUM_LEN); + + /* continue capturing the fatal log until Dump status is 0x3 */ + if (pm8001_mr32(fatal_table_address, + MPI_FATAL_EDUMP_TABLE_STATUS) < + MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) { + + /* reset fddstat bit by writing to zero*/ + pm8001_mw32(fatal_table_address, + MPI_FATAL_EDUMP_TABLE_STATUS, 0x0); + + /* set dump control value to '1' so that new data will + * be transferred to shared memory + */ + pm8001_mw32(fatal_table_address, + MPI_FATAL_EDUMP_TABLE_HANDSHAKE, MPI_FATAL_EDUMP_HANDSHAKE_RDY); - /* Poll FDDHSHK until clear */ - start = jiffies + (2 * HZ); /* 2 sec */ + /*Poll FDDHSHK until clear */ + start = jiffies + (2 * HZ); /* 2 sec */ - do { - reg_val = pm8001_mr32(fatal_table_address, + do { + reg_val = pm8001_mr32(fatal_table_address, MPI_FATAL_EDUMP_TABLE_HANDSHAKE); - } while ((reg_val) && time_before(jiffies, start)); + } while ((reg_val) && time_before(jiffies, start)); - if (reg_val != 0) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER" - " = 0x%x\n", reg_val)); - return -EIO; - } - - /* Read the next 64K of the debug data. */ - pm8001_ha->forensic_fatal_step = 0; - if (pm8001_mr32(fatal_table_address, - MPI_FATAL_EDUMP_TABLE_STATUS) != - MPI_FATAL_EDUMP_TABLE_STAT_NF_SUCCESS_DONE) { - pm8001_mw32(fatal_table_address, - MPI_FATAL_EDUMP_TABLE_HANDSHAKE, 0); - goto moreData; - } else { - pm8001_ha->forensic_info.data_buf.direct_data += - sprintf(pm8001_ha-> - forensic_info.data_buf.direct_data, - "%08x ", 4); - pm8001_ha->forensic_info.data_buf.read_len = 0xFFFFFFFF; - pm8001_ha->forensic_info.data_buf.direct_len = 0; - pm8001_ha->forensic_info.data_buf.direct_offset = 0; - pm8001_ha->forensic_info.data_buf.read_len = 0; + if (reg_val != 0) { + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( + "TIMEOUT:MPI_FATAL_EDUMP_TABLE_HDSHAKE 0x%x\n", + reg_val)); + /* Fail the dump if a timeout occurs */ + pm8001_ha->forensic_info.data_buf.direct_data += + sprintf( + pm8001_ha->forensic_info.data_buf.direct_data, + "%08x ", 0xFFFFFFFF); + return((char *) + pm8001_ha->forensic_info.data_buf.direct_data + - (char *)buf); + } + /* Poll status register until set to 2 or + * 3 for up to 2 seconds + */ + start = jiffies + (2 * HZ); /* 2 sec */ + + do { + reg_val = pm8001_mr32(fatal_table_address, + MPI_FATAL_EDUMP_TABLE_STATUS); + } while (((reg_val != 2) || (reg_val != 3)) && + time_before(jiffies, start)); + + if (reg_val < 2) { + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( + "TIMEOUT:MPI_FATAL_EDUMP_TABLE_STATUS = 0x%x\n", + reg_val)); + /* Fail the dump if a timeout occurs */ + pm8001_ha->forensic_info.data_buf.direct_data += + sprintf( + pm8001_ha->forensic_info.data_buf.direct_data, + "%08x ", 0xFFFFFFFF); + pm8001_cw32(pm8001_ha, 0, + MEMBASE_II_SHIFT_REGISTER, + pm8001_ha->fatal_forensic_shift_offset); + } + /* Read the next block of the debug data.*/ + length_to_read = pm8001_mr32(fatal_table_address, + MPI_FATAL_EDUMP_TABLE_ACCUM_LEN) - + pm8001_ha->forensic_preserved_accumulated_transfer; + if (length_to_read != 0x0) { + pm8001_ha->forensic_fatal_step = 0; + goto moreData; + } else { + pm8001_ha->forensic_info.data_buf.direct_data += + sprintf( + pm8001_ha->forensic_info.data_buf.direct_data, + "%08x ", 4); + pm8001_ha->forensic_info.data_buf.read_len + = 0xFFFFFFFF; + pm8001_ha->forensic_info.data_buf.direct_len + = 0; + pm8001_ha->forensic_info.data_buf.direct_offset + = 0; + pm8001_ha->forensic_info.data_buf.read_len = 0; + } } } - + offset = (int)((char *)pm8001_ha->forensic_info.data_buf.direct_data + - (char *)buf); + PM8001_IO_DBG(pm8001_ha, + pm8001_printk("get_fatal_spcv: return4 0x%x\n", offset)); return (char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf; } @@ -317,6 +451,25 @@ static void read_main_config_table(struct pm8001_hba_info *pm8001_ha) pm8001_mr32(address, MAIN_MPI_ILA_RELEASE_TYPE); pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version = pm8001_mr32(address, MAIN_MPI_INACTIVE_FW_VERSION); + + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "Main cfg table: sign:%x interface rev:%x fw_rev:%x\n", + pm8001_ha->main_cfg_tbl.pm80xx_tbl.signature, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev)); + + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "table offset: gst:%x iq:%x oq:%x int vec:%x phy attr:%x\n", + pm8001_ha->main_cfg_tbl.pm80xx_tbl.gst_offset, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_queue_offset, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.outbound_queue_offset, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.int_vec_table_offset, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.phy_attr_table_offset)); + + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "Main cfg table; ila rev:%x Inactive fw rev:%x\n", + pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version)); } /** @@ -521,6 +674,11 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) pm8001_mr32(addressib, (offsetib + 0x18)); pm8001_ha->inbnd_q_tbl[i].producer_idx = 0; pm8001_ha->inbnd_q_tbl[i].consumer_index = 0; + + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "IQ %d pi_bar 0x%x pi_offset 0x%x\n", i, + pm8001_ha->inbnd_q_tbl[i].pi_pci_bar, + pm8001_ha->inbnd_q_tbl[i].pi_offset)); } for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) { pm8001_ha->outbnd_q_tbl[i].element_size_cnt = @@ -549,6 +707,11 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) pm8001_mr32(addressob, (offsetob + 0x18)); pm8001_ha->outbnd_q_tbl[i].consumer_idx = 0; pm8001_ha->outbnd_q_tbl[i].producer_index = 0; + + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "OQ %d ci_bar 0x%x ci_offset 0x%x\n", i, + pm8001_ha->outbnd_q_tbl[i].ci_pci_bar, + pm8001_ha->outbnd_q_tbl[i].ci_offset)); } } @@ -582,6 +745,10 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha) ((pm8001_ha->number_of_intr - 1) << 8); pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT, pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt); + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "Updated Fatal error interrupt vector 0x%x\n", + pm8001_mr32(address, MAIN_FATAL_ERROR_INTERRUPT))); + pm8001_mw32(address, MAIN_EVENT_CRC_CHECK, pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump); @@ -591,6 +758,9 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha) pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping |= 0x20000000; pm8001_mw32(address, MAIN_GPIO_LED_FLAGS_OFFSET, pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping); + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "Programming DW 0x21 in main cfg table with 0x%x\n", + pm8001_mr32(address, MAIN_GPIO_LED_FLAGS_OFFSET))); pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER, pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer); @@ -629,6 +799,21 @@ static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha, pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr); pm8001_mw32(address, offset + IB_CI_BASE_ADDR_LO_OFFSET, pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr); + + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "IQ %d: Element pri size 0x%x\n", + number, + pm8001_ha->inbnd_q_tbl[number].element_pri_size_cnt)); + + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "IQ upr base addr 0x%x IQ lwr base addr 0x%x\n", + pm8001_ha->inbnd_q_tbl[number].upper_base_addr, + pm8001_ha->inbnd_q_tbl[number].lower_base_addr)); + + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "CI upper base addr 0x%x CI lower base addr 0x%x\n", + pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr, + pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr)); } /** @@ -652,6 +837,21 @@ static void update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha, pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr); pm8001_mw32(address, offset + OB_INTERRUPT_COALES_OFFSET, pm8001_ha->outbnd_q_tbl[number].interrup_vec_cnt_delay); + + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "OQ %d: Element pri size 0x%x\n", + number, + pm8001_ha->outbnd_q_tbl[number].element_size_cnt)); + + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "OQ upr base addr 0x%x OQ lwr base addr 0x%x\n", + pm8001_ha->outbnd_q_tbl[number].upper_base_addr, + pm8001_ha->outbnd_q_tbl[number].lower_base_addr)); + + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "PI upper base addr 0x%x PI lower base addr 0x%x\n", + pm8001_ha->outbnd_q_tbl[number].pi_upper_base_addr, + pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr)); } /** @@ -669,9 +869,9 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha) pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_UPDATE); /* wait until Inbound DoorBell Clear Register toggled */ if (IS_SPCV_12G(pm8001_ha->pdev)) { - max_wait_count = 4 * 1000 * 1000;/* 4 sec */ + max_wait_count = SPCV_DOORBELL_CLEAR_TIMEOUT; } else { - max_wait_count = 2 * 1000 * 1000;/* 2 sec */ + max_wait_count = SPC_DOORBELL_CLEAR_TIMEOUT; } do { udelay(1); @@ -797,7 +997,7 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha) value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0); offset = value & 0x03FFFFFF; /* scratch pad 0 TBL address */ - PM8001_INIT_DBG(pm8001_ha, + PM8001_DEV_DBG(pm8001_ha, pm8001_printk("Scratchpad 0 Offset: 0x%x value 0x%x\n", offset, value)); pcilogic = (value & 0xFC000000) >> 26; @@ -885,7 +1085,12 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha) (THERMAL_ENABLE << 8) | page_code; payload.cfg_pg[1] = (LTEMPHIL << 24) | (RTEMPHIL << 8); - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "Setting up thermal config. cfg_pg 0 0x%x cfg_pg 1 0x%x\n", + payload.cfg_pg[0], payload.cfg_pg[1])); + + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); if (rc) pm8001_tag_free(pm8001_ha, tag); return rc; @@ -967,7 +1172,8 @@ pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha) memcpy(&payload.cfg_pg, &SASConfigPage, sizeof(SASProtocolTimerConfig_t)); - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); if (rc) pm8001_tag_free(pm8001_ha, tag); @@ -1090,7 +1296,12 @@ static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha) payload.new_curidx_ksop = ((1 << 24) | (1 << 16) | (1 << 8) | KEK_MGMT_SUBOP_KEYCARDUPDATE); - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "Saving Encryption info to flash. payload 0x%x\n", + payload.new_curidx_ksop)); + + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); if (rc) pm8001_tag_free(pm8001_ha, tag); @@ -1241,7 +1452,7 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) pm8001_printk("reset register before write : 0x%x\n", regval)); pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, SPCv_NORMAL_RESET_VALUE); - mdelay(500); + msleep(500); regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET); PM8001_INIT_DBG(pm8001_ha, @@ -1443,7 +1654,10 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha, task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id); task_abort.tag = cpu_to_le32(ccb_tag); - ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, + sizeof(task_abort), 0); + PM8001_FAIL_DBG(pm8001_ha, + pm8001_printk("Executing abort task end\n")); if (ret) { sas_free_task(task); pm8001_tag_free(pm8001_ha, ccb_tag); @@ -1519,7 +1733,9 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, sata_cmd.ncqtag_atap_dir_m_dad |= ((0x1 << 7) | (0x5 << 9)); memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis)); - res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0); + res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, + sizeof(sata_cmd), 0); + PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Executing read log end\n")); if (res) { sas_free_task(task); pm8001_tag_free(pm8001_ha, ccb_tag); @@ -1570,6 +1786,10 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) if (unlikely(!t || !t->lldd_task || !t->dev)) return; ts = &t->task_status; + + PM8001_DEV_DBG(pm8001_ha, pm8001_printk( + "tag::0x%x, status::0x%x task::0x%p\n", tag, status, t)); + /* Print sas address of IO failed device */ if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && (status != IO_UNDERFLOW)) @@ -1772,7 +1992,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; default: - PM8001_IO_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("Unknown status 0x%x\n", status)); /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; @@ -1826,7 +2046,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) if (unlikely(!t || !t->lldd_task || !t->dev)) return; ts = &t->task_status; - PM8001_IO_DBG(pm8001_ha, + PM8001_IOERR_DBG(pm8001_ha, pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n", port_id, tag, event)); switch (event) { @@ -1963,7 +2183,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->stat = SAS_DATA_OVERRUN; break; case IO_XFER_ERROR_INTERNAL_CRC_ERROR: - PM8001_IO_DBG(pm8001_ha, + PM8001_IOERR_DBG(pm8001_ha, pm8001_printk("IO_XFR_ERROR_INTERNAL_CRC_ERROR\n")); /* TBC: used default set values */ ts->resp = SAS_TASK_COMPLETE; @@ -1974,7 +2194,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n")); return; default: - PM8001_IO_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("Unknown status 0x%x\n", event)); /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; @@ -2062,6 +2282,12 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk("ts null\n")); return; } + + if (unlikely(status)) + PM8001_IOERR_DBG(pm8001_ha, pm8001_printk( + "status:0x%x, tag:0x%x, task::0x%p\n", + status, tag, t)); + /* Print sas address of IO failed device */ if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && (status != IO_UNDERFLOW)) { @@ -2365,7 +2591,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; default: - PM8001_IO_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("Unknown status 0x%x\n", status)); /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; @@ -2382,6 +2608,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) 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)); + if (t->slow_task) + complete(&t->slow_task->completion); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); } else { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -2435,7 +2663,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) } ts = &t->task_status; - PM8001_IO_DBG(pm8001_ha, + PM8001_IOERR_DBG(pm8001_ha, pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n", port_id, tag, event)); switch (event) { @@ -2655,6 +2883,9 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) if (unlikely(!t || !t->lldd_task || !t->dev)) return; + PM8001_DEV_DBG(pm8001_ha, + pm8001_printk("tag::0x%x status::0x%x\n", tag, status)); + switch (status) { case IO_SUCCESS: @@ -2822,7 +3053,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; default: - PM8001_IO_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("Unknown status 0x%x\n", status)); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; @@ -2873,7 +3104,8 @@ static void pm80xx_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha, ((phyId & 0xFF) << 24) | (port_id & 0xFF)); payload.param0 = cpu_to_le32(param0); payload.param1 = cpu_to_le32(param1); - pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); } static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, @@ -2964,7 +3196,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_get_lrate_mode(phy, link_rate); break; default: - PM8001_MSG_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("unknown device type(%x)\n", deviceType)); break; } @@ -2984,7 +3216,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr); spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags); if (pm8001_ha->flags == PM8001F_RUN_TIME) - mdelay(200);/*delay a moment to wait disk to spinup*/ + msleep(200);/*delay a moment to wait disk to spinup*/ pm8001_bytes_dmaed(pm8001_ha, phy_id); } @@ -3013,7 +3245,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) struct sas_ha_struct *sas_ha = pm8001_ha->sas; struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; unsigned long flags; - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( "port id %d, phy id %d link_rate %d portstate 0x%x\n", port_id, phy_id, link_rate, portstate)); @@ -3101,7 +3333,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) break; default: port->port_attached = 0; - PM8001_MSG_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk(" Phy Down and(default) = 0x%x\n", portstate)); break; @@ -3130,8 +3362,10 @@ static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) if (status == 0) { phy->phy_state = PHY_LINK_DOWN; if (pm8001_ha->flags == PM8001F_RUN_TIME && - phy->enable_completion != NULL) + phy->enable_completion != NULL) { complete(phy->enable_completion); + phy->enable_completion = NULL; + } } return 0; @@ -3191,7 +3425,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; struct pm8001_port *port = &pm8001_ha->port[port_id]; struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; - PM8001_MSG_DBG(pm8001_ha, + PM8001_DEV_DBG(pm8001_ha, pm8001_printk("portid:%d phyid:%d event:0x%x status:0x%x\n", port_id, phy_id, eventType, status)); @@ -3376,7 +3610,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk("EVENT_BROADCAST_ASYNCH_EVENT\n")); break; default: - PM8001_MSG_DBG(pm8001_ha, + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk("Unknown event type 0x%x\n", eventType)); break; } @@ -3758,7 +3992,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) ssp_coalesced_comp_resp(pm8001_ha, piomb); break; default: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( "Unknown outbound Queue IOMB OPC = 0x%x\n", opc)); break; } @@ -3991,8 +4225,8 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd, pm8001_ha->smp_exp_mode, length); - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, - (u32 *)&smp_cmd, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &smp_cmd, + sizeof(smp_cmd), 0); if (rc) goto err_out_2; return 0; @@ -4200,7 +4434,7 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, } q_index = (u32) (pm8001_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM; ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, - &ssp_cmd, q_index); + &ssp_cmd, sizeof(ssp_cmd), q_index); return ret; } @@ -4441,7 +4675,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, } q_index = (u32) (pm8001_ha_dev->id & 0x00ffffff) % PM8001_MAX_OUTB_NUM; ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, - &sata_cmd, q_index); + &sata_cmd, sizeof(sata_cmd), q_index); return ret; } @@ -4465,23 +4699,9 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) PM8001_INIT_DBG(pm8001_ha, pm8001_printk("PHY START REQ for phy_id %d\n", phy_id)); - /* - ** [0:7] PHY Identifier - ** [8:11] link rate 1.5G, 3G, 6G - ** [12:13] link mode 01b SAS mode; 10b SATA mode; 11b Auto mode - ** [14] 0b disable spin up hold; 1b enable spin up hold - ** [15] ob no change in current PHY analig setup 1b enable using SPAST - */ - if (!IS_SPCV_12G(pm8001_ha->pdev)) - payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | - LINKMODE_AUTO | LINKRATE_15 | - LINKRATE_30 | LINKRATE_60 | phy_id); - else - payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | - LINKMODE_AUTO | LINKRATE_15 | - LINKRATE_30 | LINKRATE_60 | LINKRATE_120 | - phy_id); + payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | + LINKMODE_AUTO | pm8001_ha->link_rate | phy_id); /* SSC Disable and SAS Analog ST configuration */ /** payload.ase_sh_lm_slr_phyid = @@ -4494,9 +4714,10 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) payload.sas_identify.dev_type = SAS_END_DEVICE; payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL; memcpy(payload.sas_identify.sas_addr, - &pm8001_ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE); + &pm8001_ha->sas_addr, SAS_ADDR_SIZE); payload.sas_identify.phy_id = phy_id; - ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, + sizeof(payload), 0); return ret; } @@ -4518,7 +4739,8 @@ static int pm80xx_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha, memset(&payload, 0, sizeof(payload)); payload.tag = cpu_to_le32(tag); payload.phy_id = cpu_to_le32(phy_id); - ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0); + ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, + sizeof(payload), 0); return ret; } @@ -4584,7 +4806,8 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr, SAS_ADDR_SIZE); - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); if (rc) pm8001_tag_free(pm8001_ha, tag); @@ -4614,7 +4837,8 @@ static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, payload.tag = cpu_to_le32(tag); payload.phyop_phyid = cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF)); - return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); } static u32 pm80xx_chip_is_our_interrupt(struct pm8001_hba_info *pm8001_ha) @@ -4641,6 +4865,9 @@ static irqreturn_t pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec) { pm80xx_chip_interrupt_disable(pm8001_ha, vec); + PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( + "irq vec %d, ODMR:0x%x\n", + vec, pm8001_cr32(pm8001_ha, 0, 0x30))); process_oq(pm8001_ha, vec); pm80xx_chip_interrupt_enable(pm8001_ha, vec); return IRQ_HANDLED; @@ -4669,7 +4896,8 @@ void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha, payload.reserved[j] = cpu_to_le32(*((u32 *)buf + i)); j++; } - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); if (rc) pm8001_tag_free(pm8001_ha, tag); } @@ -4711,7 +4939,8 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha, for (i = 0; i < length; i++) payload.reserved[i] = cpu_to_le32(*(buf + i)); - rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, + sizeof(payload), 0); if (rc) pm8001_tag_free(pm8001_ha, tag); diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h index dc9ab7689060..701951a0f715 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.h +++ b/drivers/scsi/pm8001/pm80xx_hwi.h @@ -220,6 +220,9 @@ #define SAS_DOPNRJT_RTRY_TMO 128 #define SAS_COPNRJT_RTRY_TMO 128 +#define SPCV_DOORBELL_CLEAR_TIMEOUT (30 * 1000 * 1000) /* 30 sec */ +#define SPC_DOORBELL_CLEAR_TIMEOUT (15 * 1000 * 1000) /* 15 sec */ + /* Making ORR bigger than IT NEXUS LOSS which is 2000000us = 2 second. Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128 |