diff options
Diffstat (limited to 'drivers/scsi/ipr.c')
-rw-r--r-- | drivers/scsi/ipr.c | 154 |
1 files changed, 137 insertions, 17 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index b62836ddbbee..536cd5a80422 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -6363,15 +6363,19 @@ static int ipr_queuecommand(struct Scsi_Host *shost, | |||
6363 | ipr_cmd->scsi_cmd = scsi_cmd; | 6363 | ipr_cmd->scsi_cmd = scsi_cmd; |
6364 | ipr_cmd->done = ipr_scsi_eh_done; | 6364 | ipr_cmd->done = ipr_scsi_eh_done; |
6365 | 6365 | ||
6366 | if (ipr_is_gscsi(res) || ipr_is_vset_device(res)) { | 6366 | if (ipr_is_gscsi(res)) { |
6367 | if (scsi_cmd->underflow == 0) | 6367 | if (scsi_cmd->underflow == 0) |
6368 | ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_ULEN_CHK; | 6368 | ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_ULEN_CHK; |
6369 | 6369 | ||
6370 | ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_LINK_DESC; | 6370 | if (res->reset_occurred) { |
6371 | if (ipr_is_gscsi(res) && res->reset_occurred) { | ||
6372 | res->reset_occurred = 0; | 6371 | res->reset_occurred = 0; |
6373 | ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_DELAY_AFTER_RST; | 6372 | ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_DELAY_AFTER_RST; |
6374 | } | 6373 | } |
6374 | } | ||
6375 | |||
6376 | if (ipr_is_gscsi(res) || ipr_is_vset_device(res)) { | ||
6377 | ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_LINK_DESC; | ||
6378 | |||
6375 | ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_ALIGNED_BFR; | 6379 | ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_ALIGNED_BFR; |
6376 | if (scsi_cmd->flags & SCMD_TAGGED) | 6380 | if (scsi_cmd->flags & SCMD_TAGGED) |
6377 | ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_SIMPLE_TASK; | 6381 | ioarcb->cmd_pkt.flags_lo |= IPR_FLAGS_LO_SIMPLE_TASK; |
@@ -6502,7 +6506,6 @@ static struct scsi_host_template driver_template = { | |||
6502 | .shost_attrs = ipr_ioa_attrs, | 6506 | .shost_attrs = ipr_ioa_attrs, |
6503 | .sdev_attrs = ipr_dev_attrs, | 6507 | .sdev_attrs = ipr_dev_attrs, |
6504 | .proc_name = IPR_NAME, | 6508 | .proc_name = IPR_NAME, |
6505 | .use_blk_tags = 1, | ||
6506 | }; | 6509 | }; |
6507 | 6510 | ||
6508 | /** | 6511 | /** |
@@ -7671,6 +7674,63 @@ static int ipr_ioafp_query_ioa_cfg(struct ipr_cmnd *ipr_cmd) | |||
7671 | return IPR_RC_JOB_RETURN; | 7674 | return IPR_RC_JOB_RETURN; |
7672 | } | 7675 | } |
7673 | 7676 | ||
7677 | static int ipr_ioa_service_action_failed(struct ipr_cmnd *ipr_cmd) | ||
7678 | { | ||
7679 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); | ||
7680 | |||
7681 | if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) | ||
7682 | return IPR_RC_JOB_CONTINUE; | ||
7683 | |||
7684 | return ipr_reset_cmd_failed(ipr_cmd); | ||
7685 | } | ||
7686 | |||
7687 | static void ipr_build_ioa_service_action(struct ipr_cmnd *ipr_cmd, | ||
7688 | __be32 res_handle, u8 sa_code) | ||
7689 | { | ||
7690 | struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; | ||
7691 | |||
7692 | ioarcb->res_handle = res_handle; | ||
7693 | ioarcb->cmd_pkt.cdb[0] = IPR_IOA_SERVICE_ACTION; | ||
7694 | ioarcb->cmd_pkt.cdb[1] = sa_code; | ||
7695 | ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD; | ||
7696 | } | ||
7697 | |||
7698 | /** | ||
7699 | * ipr_ioafp_set_caching_parameters - Issue Set Cache parameters service | ||
7700 | * action | ||
7701 | * | ||
7702 | * Return value: | ||
7703 | * none | ||
7704 | **/ | ||
7705 | static int ipr_ioafp_set_caching_parameters(struct ipr_cmnd *ipr_cmd) | ||
7706 | { | ||
7707 | struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; | ||
7708 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
7709 | struct ipr_inquiry_pageC4 *pageC4 = &ioa_cfg->vpd_cbs->pageC4_data; | ||
7710 | |||
7711 | ENTER; | ||
7712 | |||
7713 | ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg; | ||
7714 | |||
7715 | if (pageC4->cache_cap[0] & IPR_CAP_SYNC_CACHE) { | ||
7716 | ipr_build_ioa_service_action(ipr_cmd, | ||
7717 | cpu_to_be32(IPR_IOA_RES_HANDLE), | ||
7718 | IPR_IOA_SA_CHANGE_CACHE_PARAMS); | ||
7719 | |||
7720 | ioarcb->cmd_pkt.cdb[2] = 0x40; | ||
7721 | |||
7722 | ipr_cmd->job_step_failed = ipr_ioa_service_action_failed; | ||
7723 | ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, | ||
7724 | IPR_SET_SUP_DEVICE_TIMEOUT); | ||
7725 | |||
7726 | LEAVE; | ||
7727 | return IPR_RC_JOB_RETURN; | ||
7728 | } | ||
7729 | |||
7730 | LEAVE; | ||
7731 | return IPR_RC_JOB_CONTINUE; | ||
7732 | } | ||
7733 | |||
7674 | /** | 7734 | /** |
7675 | * ipr_ioafp_inquiry - Send an Inquiry to the adapter. | 7735 | * ipr_ioafp_inquiry - Send an Inquiry to the adapter. |
7676 | * @ipr_cmd: ipr command struct | 7736 | * @ipr_cmd: ipr command struct |
@@ -7722,6 +7782,39 @@ static int ipr_inquiry_page_supported(struct ipr_inquiry_page0 *page0, u8 page) | |||
7722 | } | 7782 | } |
7723 | 7783 | ||
7724 | /** | 7784 | /** |
7785 | * ipr_ioafp_pageC4_inquiry - Send a Page 0xC4 Inquiry to the adapter. | ||
7786 | * @ipr_cmd: ipr command struct | ||
7787 | * | ||
7788 | * This function sends a Page 0xC4 inquiry to the adapter | ||
7789 | * to retrieve software VPD information. | ||
7790 | * | ||
7791 | * Return value: | ||
7792 | * IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN | ||
7793 | **/ | ||
7794 | static int ipr_ioafp_pageC4_inquiry(struct ipr_cmnd *ipr_cmd) | ||
7795 | { | ||
7796 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
7797 | struct ipr_inquiry_page0 *page0 = &ioa_cfg->vpd_cbs->page0_data; | ||
7798 | struct ipr_inquiry_pageC4 *pageC4 = &ioa_cfg->vpd_cbs->pageC4_data; | ||
7799 | |||
7800 | ENTER; | ||
7801 | ipr_cmd->job_step = ipr_ioafp_set_caching_parameters; | ||
7802 | memset(pageC4, 0, sizeof(*pageC4)); | ||
7803 | |||
7804 | if (ipr_inquiry_page_supported(page0, 0xC4)) { | ||
7805 | ipr_ioafp_inquiry(ipr_cmd, 1, 0xC4, | ||
7806 | (ioa_cfg->vpd_cbs_dma | ||
7807 | + offsetof(struct ipr_misc_cbs, | ||
7808 | pageC4_data)), | ||
7809 | sizeof(struct ipr_inquiry_pageC4)); | ||
7810 | return IPR_RC_JOB_RETURN; | ||
7811 | } | ||
7812 | |||
7813 | LEAVE; | ||
7814 | return IPR_RC_JOB_CONTINUE; | ||
7815 | } | ||
7816 | |||
7817 | /** | ||
7725 | * ipr_ioafp_cap_inquiry - Send a Page 0xD0 Inquiry to the adapter. | 7818 | * ipr_ioafp_cap_inquiry - Send a Page 0xD0 Inquiry to the adapter. |
7726 | * @ipr_cmd: ipr command struct | 7819 | * @ipr_cmd: ipr command struct |
7727 | * | 7820 | * |
@@ -7738,7 +7831,7 @@ static int ipr_ioafp_cap_inquiry(struct ipr_cmnd *ipr_cmd) | |||
7738 | struct ipr_inquiry_cap *cap = &ioa_cfg->vpd_cbs->cap; | 7831 | struct ipr_inquiry_cap *cap = &ioa_cfg->vpd_cbs->cap; |
7739 | 7832 | ||
7740 | ENTER; | 7833 | ENTER; |
7741 | ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg; | 7834 | ipr_cmd->job_step = ipr_ioafp_pageC4_inquiry; |
7742 | memset(cap, 0, sizeof(*cap)); | 7835 | memset(cap, 0, sizeof(*cap)); |
7743 | 7836 | ||
7744 | if (ipr_inquiry_page_supported(page0, 0xD0)) { | 7837 | if (ipr_inquiry_page_supported(page0, 0xD0)) { |
@@ -8277,6 +8370,42 @@ static int ipr_reset_get_unit_check_job(struct ipr_cmnd *ipr_cmd) | |||
8277 | return IPR_RC_JOB_RETURN; | 8370 | return IPR_RC_JOB_RETURN; |
8278 | } | 8371 | } |
8279 | 8372 | ||
8373 | static int ipr_dump_mailbox_wait(struct ipr_cmnd *ipr_cmd) | ||
8374 | { | ||
8375 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
8376 | |||
8377 | ENTER; | ||
8378 | |||
8379 | if (ioa_cfg->sdt_state != GET_DUMP) | ||
8380 | return IPR_RC_JOB_RETURN; | ||
8381 | |||
8382 | if (!ioa_cfg->sis64 || !ipr_cmd->u.time_left || | ||
8383 | (readl(ioa_cfg->regs.sense_interrupt_reg) & | ||
8384 | IPR_PCII_MAILBOX_STABLE)) { | ||
8385 | |||
8386 | if (!ipr_cmd->u.time_left) | ||
8387 | dev_err(&ioa_cfg->pdev->dev, | ||
8388 | "Timed out waiting for Mailbox register.\n"); | ||
8389 | |||
8390 | ioa_cfg->sdt_state = READ_DUMP; | ||
8391 | ioa_cfg->dump_timeout = 0; | ||
8392 | if (ioa_cfg->sis64) | ||
8393 | ipr_reset_start_timer(ipr_cmd, IPR_SIS64_DUMP_TIMEOUT); | ||
8394 | else | ||
8395 | ipr_reset_start_timer(ipr_cmd, IPR_SIS32_DUMP_TIMEOUT); | ||
8396 | ipr_cmd->job_step = ipr_reset_wait_for_dump; | ||
8397 | schedule_work(&ioa_cfg->work_q); | ||
8398 | |||
8399 | } else { | ||
8400 | ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT; | ||
8401 | ipr_reset_start_timer(ipr_cmd, | ||
8402 | IPR_CHECK_FOR_RESET_TIMEOUT); | ||
8403 | } | ||
8404 | |||
8405 | LEAVE; | ||
8406 | return IPR_RC_JOB_RETURN; | ||
8407 | } | ||
8408 | |||
8280 | /** | 8409 | /** |
8281 | * ipr_reset_restore_cfg_space - Restore PCI config space. | 8410 | * ipr_reset_restore_cfg_space - Restore PCI config space. |
8282 | * @ipr_cmd: ipr command struct | 8411 | * @ipr_cmd: ipr command struct |
@@ -8326,20 +8455,11 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) | |||
8326 | 8455 | ||
8327 | if (ioa_cfg->in_ioa_bringdown) { | 8456 | if (ioa_cfg->in_ioa_bringdown) { |
8328 | ipr_cmd->job_step = ipr_ioa_bringdown_done; | 8457 | ipr_cmd->job_step = ipr_ioa_bringdown_done; |
8458 | } else if (ioa_cfg->sdt_state == GET_DUMP) { | ||
8459 | ipr_cmd->job_step = ipr_dump_mailbox_wait; | ||
8460 | ipr_cmd->u.time_left = IPR_WAIT_FOR_MAILBOX; | ||
8329 | } else { | 8461 | } else { |
8330 | ipr_cmd->job_step = ipr_reset_enable_ioa; | 8462 | ipr_cmd->job_step = ipr_reset_enable_ioa; |
8331 | |||
8332 | if (GET_DUMP == ioa_cfg->sdt_state) { | ||
8333 | ioa_cfg->sdt_state = READ_DUMP; | ||
8334 | ioa_cfg->dump_timeout = 0; | ||
8335 | if (ioa_cfg->sis64) | ||
8336 | ipr_reset_start_timer(ipr_cmd, IPR_SIS64_DUMP_TIMEOUT); | ||
8337 | else | ||
8338 | ipr_reset_start_timer(ipr_cmd, IPR_SIS32_DUMP_TIMEOUT); | ||
8339 | ipr_cmd->job_step = ipr_reset_wait_for_dump; | ||
8340 | schedule_work(&ioa_cfg->work_q); | ||
8341 | return IPR_RC_JOB_RETURN; | ||
8342 | } | ||
8343 | } | 8463 | } |
8344 | 8464 | ||
8345 | LEAVE; | 8465 | LEAVE; |