diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 394 |
1 files changed, 204 insertions, 190 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c88f59f0ce30..a246410ce9df 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -59,22 +59,26 @@ static char *dif_op_str[] = { }; static void lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb); +static void +lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb); static void -lpfc_debug_save_data(struct scsi_cmnd *cmnd) +lpfc_debug_save_data(struct lpfc_hba *phba, struct scsi_cmnd *cmnd) { void *src, *dst; struct scatterlist *sgde = scsi_sglist(cmnd); if (!_dump_buf_data) { - printk(KERN_ERR "BLKGRD ERROR %s _dump_buf_data is NULL\n", + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9050 BLKGRD: ERROR %s _dump_buf_data is NULL\n", __func__); return; } if (!sgde) { - printk(KERN_ERR "BLKGRD ERROR: data scatterlist is null\n"); + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9051 BLKGRD: ERROR: data scatterlist is null\n"); return; } @@ -88,19 +92,21 @@ lpfc_debug_save_data(struct scsi_cmnd *cmnd) } static void -lpfc_debug_save_dif(struct scsi_cmnd *cmnd) +lpfc_debug_save_dif(struct lpfc_hba *phba, struct scsi_cmnd *cmnd) { void *src, *dst; struct scatterlist *sgde = scsi_prot_sglist(cmnd); if (!_dump_buf_dif) { - printk(KERN_ERR "BLKGRD ERROR %s _dump_buf_data is NULL\n", + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9052 BLKGRD: ERROR %s _dump_buf_data is NULL\n", __func__); return; } if (!sgde) { - printk(KERN_ERR "BLKGRD ERROR: prot scatterlist is null\n"); + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9053 BLKGRD: ERROR: prot scatterlist is null\n"); return; } @@ -242,6 +248,36 @@ lpfc_send_sdev_queuedepth_change_event(struct lpfc_hba *phba, } /** + * lpfc_change_queue_depth - Alter scsi device queue depth + * @sdev: Pointer the scsi device on which to change the queue depth. + * @qdepth: New queue depth to set the sdev to. + * @reason: The reason for the queue depth change. + * + * This function is called by the midlayer and the LLD to alter the queue + * depth for a scsi device. This function sets the queue depth to the new + * value and sends an event out to log the queue depth change. + **/ +int +lpfc_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) +{ + struct lpfc_vport *vport = (struct lpfc_vport *) sdev->host->hostdata; + struct lpfc_hba *phba = vport->phba; + struct lpfc_rport_data *rdata; + unsigned long new_queue_depth, old_queue_depth; + + old_queue_depth = sdev->queue_depth; + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); + new_queue_depth = sdev->queue_depth; + rdata = sdev->hostdata; + if (rdata) + lpfc_send_sdev_queuedepth_change_event(phba, vport, + rdata->pnode, sdev->lun, + old_queue_depth, + new_queue_depth); + return sdev->queue_depth; +} + +/** * lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread * @phba: The Hba for which this call is being executed. * @@ -305,8 +341,10 @@ lpfc_rampup_queue_depth(struct lpfc_vport *vport, if (vport->cfg_lun_queue_depth <= queue_depth) return; spin_lock_irqsave(&phba->hbalock, flags); - if (((phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) > jiffies) || - ((phba->last_rsrc_error_time + QUEUE_RAMP_UP_INTERVAL ) > jiffies)) { + if (time_before(jiffies, + phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) || + time_before(jiffies, + phba->last_rsrc_error_time + QUEUE_RAMP_UP_INTERVAL)) { spin_unlock_irqrestore(&phba->hbalock, flags); return; } @@ -338,10 +376,9 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) struct lpfc_vport **vports; struct Scsi_Host *shost; struct scsi_device *sdev; - unsigned long new_queue_depth, old_queue_depth; + unsigned long new_queue_depth; unsigned long num_rsrc_err, num_cmd_success; int i; - struct lpfc_rport_data *rdata; num_rsrc_err = atomic_read(&phba->num_rsrc_err); num_cmd_success = atomic_read(&phba->num_cmd_success); @@ -359,22 +396,8 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) else new_queue_depth = sdev->queue_depth - new_queue_depth; - old_queue_depth = sdev->queue_depth; - if (sdev->ordered_tags) - scsi_adjust_queue_depth(sdev, - MSG_ORDERED_TAG, - new_queue_depth); - else - scsi_adjust_queue_depth(sdev, - MSG_SIMPLE_TAG, - new_queue_depth); - rdata = sdev->hostdata; - if (rdata) - lpfc_send_sdev_queuedepth_change_event( - phba, vports[i], - rdata->pnode, - sdev->lun, old_queue_depth, - new_queue_depth); + lpfc_change_queue_depth(sdev, new_queue_depth, + SCSI_QDEPTH_DEFAULT); } } lpfc_destroy_vport_work_array(phba, vports); @@ -398,7 +421,6 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba) struct Scsi_Host *shost; struct scsi_device *sdev; int i; - struct lpfc_rport_data *rdata; vports = lpfc_create_vport_work_array(phba); if (vports != NULL) @@ -408,22 +430,9 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba) if (vports[i]->cfg_lun_queue_depth <= sdev->queue_depth) continue; - if (sdev->ordered_tags) - scsi_adjust_queue_depth(sdev, - MSG_ORDERED_TAG, - sdev->queue_depth+1); - else - scsi_adjust_queue_depth(sdev, - MSG_SIMPLE_TAG, - sdev->queue_depth+1); - rdata = sdev->hostdata; - if (rdata) - lpfc_send_sdev_queuedepth_change_event( - phba, vports[i], - rdata->pnode, - sdev->lun, - sdev->queue_depth - 1, - sdev->queue_depth); + lpfc_change_queue_depth(sdev, + sdev->queue_depth+1, + SCSI_QDEPTH_RAMP_UP); } } lpfc_destroy_vport_work_array(phba, vports); @@ -589,7 +598,7 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc) iocb->ulpClass = CLASS3; psb->status = IOSTAT_SUCCESS; /* Put it back into the SCSI buffer list */ - lpfc_release_scsi_buf_s4(phba, psb); + lpfc_release_scsi_buf_s3(phba, psb); } @@ -1024,7 +1033,8 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) lpfc_cmd->seg_cnt = nseg; if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { - printk(KERN_ERR "%s: Too many sg segments from " + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9064 BLKGRD: %s: Too many sg segments from " "dma_map_sg. Config %d, seg_cnt %d\n", __func__, phba->cfg_sg_seg_cnt, lpfc_cmd->seg_cnt); @@ -1112,7 +1122,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) * with the cmd */ static int -lpfc_sc_to_sli_prof(struct scsi_cmnd *sc) +lpfc_sc_to_sli_prof(struct lpfc_hba *phba, struct scsi_cmnd *sc) { uint8_t guard_type = scsi_host_get_guard(sc->device->host); uint8_t ret_prof = LPFC_PROF_INVALID; @@ -1136,7 +1146,8 @@ lpfc_sc_to_sli_prof(struct scsi_cmnd *sc) case SCSI_PROT_NORMAL: default: - printk(KERN_ERR "Bad op/guard:%d/%d combination\n", + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9063 BLKGRD:Bad op/guard:%d/%d combination\n", scsi_get_prot_op(sc), guard_type); break; @@ -1157,7 +1168,8 @@ lpfc_sc_to_sli_prof(struct scsi_cmnd *sc) case SCSI_PROT_WRITE_STRIP: case SCSI_PROT_NORMAL: default: - printk(KERN_ERR "Bad op/guard:%d/%d combination\n", + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9075 BLKGRD: Bad op/guard:%d/%d combination\n", scsi_get_prot_op(sc), guard_type); break; } @@ -1259,7 +1271,7 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, uint16_t apptagmask, apptagval; pde1 = (struct lpfc_pde *) bpl; - prof = lpfc_sc_to_sli_prof(sc); + prof = lpfc_sc_to_sli_prof(phba, sc); if (prof == LPFC_PROF_INVALID) goto out; @@ -1359,7 +1371,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, return 0; } - prof = lpfc_sc_to_sli_prof(sc); + prof = lpfc_sc_to_sli_prof(phba, sc); if (prof == LPFC_PROF_INVALID) goto out; @@ -1408,7 +1420,8 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, subtotal = 0; /* total bytes processed for current prot grp */ while (!pgdone) { if (!sgde) { - printk(KERN_ERR "%s Invalid data segment\n", + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9065 BLKGRD:%s Invalid data segment\n", __func__); return 0; } @@ -1462,7 +1475,8 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, reftag += protgrp_blks; } else { /* if we're here, we have a bug */ - printk(KERN_ERR "BLKGRD: bug in %s\n", __func__); + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9054 BLKGRD: bug in %s\n", __func__); } } while (!alldone); @@ -1544,8 +1558,10 @@ lpfc_bg_scsi_prep_dma_buf(struct lpfc_hba *phba, lpfc_cmd->seg_cnt = datasegcnt; if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { - printk(KERN_ERR "%s: Too many sg segments from " - "dma_map_sg. Config %d, seg_cnt %d\n", + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9067 BLKGRD: %s: Too many sg segments" + " from dma_map_sg. Config %d, seg_cnt" + " %d\n", __func__, phba->cfg_sg_seg_cnt, lpfc_cmd->seg_cnt); scsi_dma_unmap(scsi_cmnd); @@ -1579,8 +1595,9 @@ lpfc_bg_scsi_prep_dma_buf(struct lpfc_hba *phba, lpfc_cmd->prot_seg_cnt = protsegcnt; if (lpfc_cmd->prot_seg_cnt > phba->cfg_prot_sg_seg_cnt) { - printk(KERN_ERR "%s: Too many prot sg segments " - "from dma_map_sg. Config %d," + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9068 BLKGRD: %s: Too many prot sg " + "segments from dma_map_sg. Config %d," "prot_seg_cnt %d\n", __func__, phba->cfg_prot_sg_seg_cnt, lpfc_cmd->prot_seg_cnt); @@ -1671,23 +1688,26 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, uint32_t bgstat = bgf->bgstat; uint64_t failing_sector = 0; - printk(KERN_ERR "BG ERROR in cmd 0x%x lba 0x%llx blk cnt 0x%x " + lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9069 BLKGRD: BG ERROR in cmd" + " 0x%x lba 0x%llx blk cnt 0x%x " "bgstat=0x%x bghm=0x%x\n", cmd->cmnd[0], (unsigned long long)scsi_get_lba(cmd), blk_rq_sectors(cmd->request), bgstat, bghm); spin_lock(&_dump_buf_lock); if (!_dump_buf_done) { - printk(KERN_ERR "Saving Data for %u blocks to debugfs\n", + lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9070 BLKGRD: Saving" + " Data for %u blocks to debugfs\n", (cmd->cmnd[7] << 8 | cmd->cmnd[8])); - lpfc_debug_save_data(cmd); + lpfc_debug_save_data(phba, cmd); /* If we have a prot sgl, save the DIF buffer */ if (lpfc_prot_group_type(phba, cmd) == LPFC_PG_TYPE_DIF_BUF) { - printk(KERN_ERR "Saving DIF for %u blocks to debugfs\n", - (cmd->cmnd[7] << 8 | cmd->cmnd[8])); - lpfc_debug_save_dif(cmd); + lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9071 BLKGRD: " + "Saving DIF for %u blocks to debugfs\n", + (cmd->cmnd[7] << 8 | cmd->cmnd[8])); + lpfc_debug_save_dif(phba, cmd); } _dump_buf_done = 1; @@ -1696,15 +1716,17 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, if (lpfc_bgs_get_invalid_prof(bgstat)) { cmd->result = ScsiResult(DID_ERROR, 0); - printk(KERN_ERR "Invalid BlockGuard profile. bgstat:0x%x\n", - bgstat); + lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9072 BLKGRD: Invalid" + " BlockGuard profile. bgstat:0x%x\n", + bgstat); ret = (-1); goto out; } if (lpfc_bgs_get_uninit_dif_block(bgstat)) { cmd->result = ScsiResult(DID_ERROR, 0); - printk(KERN_ERR "Invalid BlockGuard DIF Block. bgstat:0x%x\n", + lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9073 BLKGRD: " + "Invalid BlockGuard DIF Block. bgstat:0x%x\n", bgstat); ret = (-1); goto out; @@ -1718,7 +1740,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, cmd->result = DRIVER_SENSE << 24 | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); phba->bg_guard_err_cnt++; - printk(KERN_ERR "BLKGRD: guard_tag error\n"); + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9055 BLKGRD: guard_tag error\n"); } if (lpfc_bgs_get_reftag_err(bgstat)) { @@ -1730,7 +1753,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); phba->bg_reftag_err_cnt++; - printk(KERN_ERR "BLKGRD: ref_tag error\n"); + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9056 BLKGRD: ref_tag error\n"); } if (lpfc_bgs_get_apptag_err(bgstat)) { @@ -1742,7 +1766,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); phba->bg_apptag_err_cnt++; - printk(KERN_ERR "BLKGRD: app_tag error\n"); + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9061 BLKGRD: app_tag error\n"); } if (lpfc_bgs_get_hi_water_mark_present(bgstat)) { @@ -1763,7 +1788,8 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, if (!ret) { /* No error was reported - problem in FW? */ cmd->result = ScsiResult(DID_ERROR, 0); - printk(KERN_ERR "BLKGRD: no errors reported!\n"); + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9057 BLKGRD: no errors reported!\n"); } out: @@ -1822,9 +1848,10 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) lpfc_cmd->seg_cnt = nseg; if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { - printk(KERN_ERR "%s: Too many sg segments from " - "dma_map_sg. Config %d, seg_cnt %d\n", - __func__, phba->cfg_sg_seg_cnt, + lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9074 BLKGRD:" + " %s: Too many sg segments from " + "dma_map_sg. Config %d, seg_cnt %d\n", + __func__, phba->cfg_sg_seg_cnt, lpfc_cmd->seg_cnt); scsi_dma_unmap(scsi_cmnd); return 1; @@ -2050,6 +2077,21 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, goto out; } + if (resp_info & RSP_LEN_VALID) { + rsplen = be32_to_cpu(fcprsp->rspRspLen); + if ((rsplen != 0 && rsplen != 4 && rsplen != 8) || + (fcprsp->rspInfo3 != RSP_NO_FAILURE)) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + "2719 Invalid response length: " + "tgt x%x lun x%x cmnd x%x rsplen x%x\n", + cmnd->device->id, + cmnd->device->lun, cmnd->cmnd[0], + rsplen); + host_status = DID_ERROR; + goto out; + } + } + if ((resp_info & SNS_LEN_VALID) && fcprsp->rspSnsLen) { uint32_t snslen = be32_to_cpu(fcprsp->rspSnsLen); if (snslen > SCSI_SENSE_BUFFERSIZE) @@ -2074,15 +2116,6 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, be32_to_cpu(fcprsp->rspRspLen), fcprsp->rspInfo3); - if (resp_info & RSP_LEN_VALID) { - rsplen = be32_to_cpu(fcprsp->rspRspLen); - if ((rsplen != 0 && rsplen != 4 && rsplen != 8) || - (fcprsp->rspInfo3 != RSP_NO_FAILURE)) { - host_status = DID_ERROR; - goto out; - } - } - scsi_set_resid(cmnd, 0); if (resp_info & RESID_UNDER) { scsi_set_resid(cmnd, be32_to_cpu(fcprsp->rspResId)); @@ -2180,7 +2213,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, struct scsi_cmnd *cmd = lpfc_cmd->pCmd; int result; struct scsi_device *tmp_sdev; - int depth = 0; + int depth; unsigned long flags; struct lpfc_fast_path_event *fast_path_evt; struct Scsi_Host *shost = cmd->device->host; @@ -2264,7 +2297,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, "9031 non-zero BGSTAT " - "on unprotected cmd"); + "on unprotected cmd\n"); } } @@ -2347,67 +2380,29 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, return; } - if (!result) lpfc_rampup_queue_depth(vport, queue_depth); - if (!result && pnode && NLP_CHK_NODE_ACT(pnode) && - ((jiffies - pnode->last_ramp_up_time) > - LPFC_Q_RAMP_UP_INTERVAL * HZ) && - ((jiffies - pnode->last_q_full_time) > - LPFC_Q_RAMP_UP_INTERVAL * HZ) && - (vport->cfg_lun_queue_depth > queue_depth)) { - shost_for_each_device(tmp_sdev, shost) { - if (vport->cfg_lun_queue_depth > tmp_sdev->queue_depth){ - if (tmp_sdev->id != scsi_id) - continue; - if (tmp_sdev->ordered_tags) - scsi_adjust_queue_depth(tmp_sdev, - MSG_ORDERED_TAG, - tmp_sdev->queue_depth+1); - else - scsi_adjust_queue_depth(tmp_sdev, - MSG_SIMPLE_TAG, - tmp_sdev->queue_depth+1); - - pnode->last_ramp_up_time = jiffies; - } - } - lpfc_send_sdev_queuedepth_change_event(phba, vport, pnode, - 0xFFFFFFFF, - queue_depth , queue_depth + 1); - } - /* * Check for queue full. If the lun is reporting queue full, then * back off the lun queue depth to prevent target overloads. */ if (result == SAM_STAT_TASK_SET_FULL && pnode && NLP_CHK_NODE_ACT(pnode)) { - pnode->last_q_full_time = jiffies; - shost_for_each_device(tmp_sdev, shost) { if (tmp_sdev->id != scsi_id) continue; depth = scsi_track_queue_full(tmp_sdev, - tmp_sdev->queue_depth - 1); - } - /* - * The queue depth cannot be lowered any more. - * Modify the returned error code to store - * the final depth value set by - * scsi_track_queue_full. - */ - if (depth == -1) - depth = shost->cmd_per_lun; - - if (depth) { + tmp_sdev->queue_depth-1); + if (depth <= 0) + continue; lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "0711 detected queue full - lun queue " "depth adjusted to %d.\n", depth); lpfc_send_sdev_queuedepth_change_event(phba, vport, - pnode, 0xFFFFFFFF, - depth+1, depth); + pnode, + tmp_sdev->lun, + depth+1, depth); } } @@ -2745,7 +2740,9 @@ void lpfc_poll_timeout(unsigned long ptr) struct lpfc_hba *phba = (struct lpfc_hba *) ptr; if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { - lpfc_sli_poll_fcp_ring (phba); + lpfc_sli_handle_fast_ring_event(phba, + &phba->sli.ring[LPFC_FCP_RING], HA_R0RE_REQ); + if (phba->cfg_poll & DISABLE_FCP_RING_INT) lpfc_poll_rearm_timer(phba); } @@ -2771,7 +2768,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_hba *phba = vport->phba; struct lpfc_rport_data *rdata = cmnd->device->hostdata; - struct lpfc_nodelist *ndlp = rdata->pnode; + struct lpfc_nodelist *ndlp; struct lpfc_scsi_buf *lpfc_cmd; struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); int err; @@ -2781,13 +2778,15 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) cmnd->result = err; goto out_fail_command; } + ndlp = rdata->pnode; if (!(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) { - printk(KERN_ERR "BLKGRD ERROR: rcvd protected cmd:%02x op:%02x " - "str=%s without registering for BlockGuard - " - "Rejecting command\n", + lpfc_printf_log(phba, KERN_ERR, LOG_BG, + "9058 BLKGRD: ERROR: rcvd protected cmd:%02x" + " op:%02x str=%s without registering for" + " BlockGuard - Rejecting command\n", cmnd->cmnd[0], scsi_get_prot_op(cmnd), dif_op_str[scsi_get_prot_op(cmnd)]); goto out_fail_command; @@ -2827,61 +2826,66 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) cmnd->scsi_done = done; if (scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) { - lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, + if (vport->phba->cfg_enable_bg) { + lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, "9033 BLKGRD: rcvd protected cmd:%02x op:%02x " "str=%s\n", cmnd->cmnd[0], scsi_get_prot_op(cmnd), dif_op_str[scsi_get_prot_op(cmnd)]); - lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, + lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, "9034 BLKGRD: CDB: %02x %02x %02x %02x %02x " "%02x %02x %02x %02x %02x\n", cmnd->cmnd[0], cmnd->cmnd[1], cmnd->cmnd[2], cmnd->cmnd[3], cmnd->cmnd[4], cmnd->cmnd[5], cmnd->cmnd[6], cmnd->cmnd[7], cmnd->cmnd[8], cmnd->cmnd[9]); - if (cmnd->cmnd[0] == READ_10) - lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, + if (cmnd->cmnd[0] == READ_10) + lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, "9035 BLKGRD: READ @ sector %llu, " "count %u\n", (unsigned long long)scsi_get_lba(cmnd), blk_rq_sectors(cmnd->request)); - else if (cmnd->cmnd[0] == WRITE_10) - lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, + else if (cmnd->cmnd[0] == WRITE_10) + lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, "9036 BLKGRD: WRITE @ sector %llu, " "count %u cmd=%p\n", (unsigned long long)scsi_get_lba(cmnd), blk_rq_sectors(cmnd->request), cmnd); + } err = lpfc_bg_scsi_prep_dma_buf(phba, lpfc_cmd); } else { - lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, - "9038 BLKGRD: rcvd unprotected cmd:%02x op:%02x" - " str=%s\n", - cmnd->cmnd[0], scsi_get_prot_op(cmnd), - dif_op_str[scsi_get_prot_op(cmnd)]); - lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, - "9039 BLKGRD: CDB: %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x\n", - cmnd->cmnd[0], cmnd->cmnd[1], cmnd->cmnd[2], - cmnd->cmnd[3], cmnd->cmnd[4], cmnd->cmnd[5], - cmnd->cmnd[6], cmnd->cmnd[7], cmnd->cmnd[8], - cmnd->cmnd[9]); - if (cmnd->cmnd[0] == READ_10) + if (vport->phba->cfg_enable_bg) { lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, - "9040 dbg: READ @ sector %llu, " - "count %u\n", - (unsigned long long)scsi_get_lba(cmnd), + "9038 BLKGRD: rcvd unprotected cmd:" + "%02x op:%02x str=%s\n", + cmnd->cmnd[0], scsi_get_prot_op(cmnd), + dif_op_str[scsi_get_prot_op(cmnd)]); + lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, + "9039 BLKGRD: CDB: %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x\n", + cmnd->cmnd[0], cmnd->cmnd[1], + cmnd->cmnd[2], cmnd->cmnd[3], + cmnd->cmnd[4], cmnd->cmnd[5], + cmnd->cmnd[6], cmnd->cmnd[7], + cmnd->cmnd[8], cmnd->cmnd[9]); + if (cmnd->cmnd[0] == READ_10) + lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, + "9040 dbg: READ @ sector %llu, " + "count %u\n", + (unsigned long long)scsi_get_lba(cmnd), blk_rq_sectors(cmnd->request)); - else if (cmnd->cmnd[0] == WRITE_10) - lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, + else if (cmnd->cmnd[0] == WRITE_10) + lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, "9041 dbg: WRITE @ sector %llu, " "count %u cmd=%p\n", (unsigned long long)scsi_get_lba(cmnd), blk_rq_sectors(cmnd->request), cmnd); - else - lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, + else + lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, "9042 dbg: parser not implemented\n"); + } err = lpfc_scsi_prep_dma_buf(phba, lpfc_cmd); } @@ -2898,7 +2902,11 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) goto out_host_busy_free_buf; } if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { - lpfc_sli_poll_fcp_ring(phba); + spin_unlock(shost->host_lock); + lpfc_sli_handle_fast_ring_event(phba, + &phba->sli.ring[LPFC_FCP_RING], HA_R0RE_REQ); + + spin_lock(shost->host_lock); if (phba->cfg_poll & DISABLE_FCP_RING_INT) lpfc_poll_rearm_timer(phba); } @@ -2917,28 +2925,6 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) } /** - * lpfc_block_error_handler - Routine to block error handler - * @cmnd: Pointer to scsi_cmnd data structure. - * - * This routine blocks execution till fc_rport state is not FC_PORSTAT_BLCOEKD. - **/ -static void -lpfc_block_error_handler(struct scsi_cmnd *cmnd) -{ - struct Scsi_Host *shost = cmnd->device->host; - struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); - - spin_lock_irq(shost->host_lock); - while (rport->port_state == FC_PORTSTATE_BLOCKED) { - spin_unlock_irq(shost->host_lock); - msleep(1000); - spin_lock_irq(shost->host_lock); - } - spin_unlock_irq(shost->host_lock); - return; -} - -/** * lpfc_abort_handler - scsi_host_template eh_abort_handler entry point * @cmnd: Pointer to scsi_cmnd data structure. * @@ -2961,7 +2947,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) int ret = SUCCESS; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq); - lpfc_block_error_handler(cmnd); + fc_block_scsi_eh(cmnd); lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble; BUG_ON(!lpfc_cmd); @@ -3001,6 +2987,10 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) icmd->ulpLe = 1; icmd->ulpClass = cmd->ulpClass; + + /* ABTS WQE must go to the same WQ as the WQE to be aborted */ + abtsiocb->fcp_wqidx = iocb->fcp_wqidx; + if (lpfc_is_link_up(phba)) icmd->ulpCommand = CMD_ABORT_XRI_CN; else @@ -3016,7 +3006,8 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) } if (phba->cfg_poll & DISABLE_FCP_RING_INT) - lpfc_sli_poll_fcp_ring (phba); + lpfc_sli_handle_fast_ring_event(phba, + &phba->sli.ring[LPFC_FCP_RING], HA_R0RE_REQ); lpfc_cmd->waitq = &waitq; /* Wait for abort to complete */ @@ -3166,9 +3157,15 @@ static int lpfc_chk_tgt_mapped(struct lpfc_vport *vport, struct scsi_cmnd *cmnd) { struct lpfc_rport_data *rdata = cmnd->device->hostdata; - struct lpfc_nodelist *pnode = rdata->pnode; + struct lpfc_nodelist *pnode; unsigned long later; + if (!rdata) { + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, + "0797 Tgt Map rport failure: rdata x%p\n", rdata); + return FAILED; + } + pnode = rdata->pnode; /* * If target is not in a MAPPED state, delay until * target is rediscovered or devloss timeout expires. @@ -3253,13 +3250,19 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) struct Scsi_Host *shost = cmnd->device->host; struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_rport_data *rdata = cmnd->device->hostdata; - struct lpfc_nodelist *pnode = rdata->pnode; + struct lpfc_nodelist *pnode; unsigned tgt_id = cmnd->device->id; unsigned int lun_id = cmnd->device->lun; struct lpfc_scsi_event_header scsi_event; int status; - lpfc_block_error_handler(cmnd); + if (!rdata) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + "0798 Device Reset rport failure: rdata x%p\n", rdata); + return FAILED; + } + pnode = rdata->pnode; + fc_block_scsi_eh(cmnd); status = lpfc_chk_tgt_mapped(vport, cmnd); if (status == FAILED) { @@ -3312,13 +3315,19 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) struct Scsi_Host *shost = cmnd->device->host; struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_rport_data *rdata = cmnd->device->hostdata; - struct lpfc_nodelist *pnode = rdata->pnode; + struct lpfc_nodelist *pnode; unsigned tgt_id = cmnd->device->id; unsigned int lun_id = cmnd->device->lun; struct lpfc_scsi_event_header scsi_event; int status; - lpfc_block_error_handler(cmnd); + if (!rdata) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, + "0799 Target Reset rport failure: rdata x%p\n", rdata); + return FAILED; + } + pnode = rdata->pnode; + fc_block_scsi_eh(cmnd); status = lpfc_chk_tgt_mapped(vport, cmnd); if (status == FAILED) { @@ -3384,7 +3393,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) fc_host_post_vendor_event(shost, fc_get_event_number(), sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID); - lpfc_block_error_handler(cmnd); + fc_block_scsi_eh(cmnd); /* * Since the driver manages a single bus device, reset all @@ -3498,6 +3507,8 @@ lpfc_slave_alloc(struct scsi_device *sdev) "Allocated %d buffers.\n", num_to_alloc, num_allocated); } + if (num_allocated > 0) + phba->total_scsi_bufs += num_allocated; return 0; } @@ -3534,7 +3545,8 @@ lpfc_slave_configure(struct scsi_device *sdev) rport->dev_loss_tmo = vport->cfg_devloss_tmo; if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { - lpfc_sli_poll_fcp_ring(phba); + lpfc_sli_handle_fast_ring_event(phba, + &phba->sli.ring[LPFC_FCP_RING], HA_R0RE_REQ); if (phba->cfg_poll & DISABLE_FCP_RING_INT) lpfc_poll_rearm_timer(phba); } @@ -3576,6 +3588,7 @@ struct scsi_host_template lpfc_template = { .shost_attrs = lpfc_hba_attrs, .max_sectors = 0xFFFF, .vendor_id = LPFC_NL_VENDOR_ID, + .change_queue_depth = lpfc_change_queue_depth, }; struct scsi_host_template lpfc_vport_template = { @@ -3597,4 +3610,5 @@ struct scsi_host_template lpfc_vport_template = { .use_clustering = ENABLE_CLUSTERING, .shost_attrs = lpfc_vport_attrs, .max_sectors = 0xFFFF, + .change_queue_depth = lpfc_change_queue_depth, }; |