diff options
Diffstat (limited to 'drivers/scsi/qla2xxx')
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 2 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 6 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 20 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 192 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 11 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 4 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 7 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_nx.c | 2 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_nx2.c | 13 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 19 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_sup.c | 2 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_target.c | 827 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/qla_target.h | 73 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/tcm_qla2xxx.c | 256 | ||||
| -rw-r--r-- | drivers/scsi/qla2xxx/tcm_qla2xxx.h | 6 |
15 files changed, 1016 insertions, 424 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 82b92c414a9c..437254e1c4de 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
| @@ -738,7 +738,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, | |||
| 738 | ql_log(ql_log_info, vha, 0x706f, | 738 | ql_log(ql_log_info, vha, 0x706f, |
| 739 | "Issuing MPI reset.\n"); | 739 | "Issuing MPI reset.\n"); |
| 740 | 740 | ||
| 741 | if (IS_QLA83XX(ha)) { | 741 | if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { |
| 742 | uint32_t idc_control; | 742 | uint32_t idc_control; |
| 743 | 743 | ||
| 744 | qla83xx_idc_lock(vha, 0); | 744 | qla83xx_idc_lock(vha, 0); |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 0e6ee3ca30e6..8b011aef12bd 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c | |||
| @@ -67,10 +67,10 @@ | |||
| 67 | * | | | 0xd031-0xd0ff | | 67 | * | | | 0xd031-0xd0ff | |
| 68 | * | | | 0xd101-0xd1fe | | 68 | * | | | 0xd101-0xd1fe | |
| 69 | * | | | 0xd214-0xd2fe | | 69 | * | | | 0xd214-0xd2fe | |
| 70 | * | Target Mode | 0xe079 | | | 70 | * | Target Mode | 0xe080 | | |
| 71 | * | Target Mode Management | 0xf072 | 0xf002 | | 71 | * | Target Mode Management | 0xf096 | 0xf002 | |
| 72 | * | | | 0xf046-0xf049 | | 72 | * | | | 0xf046-0xf049 | |
| 73 | * | Target Mode Task Management | 0x1000b | | | 73 | * | Target Mode Task Management | 0x1000d | | |
| 74 | * ---------------------------------------------------------------------- | 74 | * ---------------------------------------------------------------------- |
| 75 | */ | 75 | */ |
| 76 | 76 | ||
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index e86201d3b8c6..9ad819edcd67 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
| @@ -274,6 +274,7 @@ | |||
| 274 | #define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/ | 274 | #define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/ |
| 275 | 275 | ||
| 276 | struct req_que; | 276 | struct req_que; |
| 277 | struct qla_tgt_sess; | ||
| 277 | 278 | ||
| 278 | /* | 279 | /* |
| 279 | * (sd.h is not exported, hence local inclusion) | 280 | * (sd.h is not exported, hence local inclusion) |
| @@ -2026,6 +2027,7 @@ typedef struct fc_port { | |||
| 2026 | uint16_t port_id; | 2027 | uint16_t port_id; |
| 2027 | 2028 | ||
| 2028 | unsigned long retry_delay_timestamp; | 2029 | unsigned long retry_delay_timestamp; |
| 2030 | struct qla_tgt_sess *tgt_session; | ||
| 2029 | } fc_port_t; | 2031 | } fc_port_t; |
| 2030 | 2032 | ||
| 2031 | #include "qla_mr.h" | 2033 | #include "qla_mr.h" |
| @@ -3154,13 +3156,13 @@ struct qla_hw_data { | |||
| 3154 | /* Bit 21 of fw_attributes decides the MCTP capabilities */ | 3156 | /* Bit 21 of fw_attributes decides the MCTP capabilities */ |
| 3155 | #define IS_MCTP_CAPABLE(ha) (IS_QLA2031(ha) && \ | 3157 | #define IS_MCTP_CAPABLE(ha) (IS_QLA2031(ha) && \ |
| 3156 | ((ha)->fw_attributes_ext[0] & BIT_0)) | 3158 | ((ha)->fw_attributes_ext[0] & BIT_0)) |
| 3157 | #define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha)) | 3159 | #define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) |
| 3158 | #define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha)) | 3160 | #define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) |
| 3159 | #define IS_PI_DIFB_DIX0_CAPABLE(ha) (0) | 3161 | #define IS_PI_DIFB_DIX0_CAPABLE(ha) (0) |
| 3160 | #define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha)) | 3162 | #define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) |
| 3161 | #define IS_PI_SPLIT_DET_CAPABLE(ha) (IS_PI_SPLIT_DET_CAPABLE_HBA(ha) && \ | 3163 | #define IS_PI_SPLIT_DET_CAPABLE(ha) (IS_PI_SPLIT_DET_CAPABLE_HBA(ha) && \ |
| 3162 | (((ha)->fw_attributes_h << 16 | (ha)->fw_attributes) & BIT_22)) | 3164 | (((ha)->fw_attributes_h << 16 | (ha)->fw_attributes) & BIT_22)) |
| 3163 | #define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha)) | 3165 | #define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) |
| 3164 | #define IS_TGT_MODE_CAPABLE(ha) (ha->tgt.atio_q_length) | 3166 | #define IS_TGT_MODE_CAPABLE(ha) (ha->tgt.atio_q_length) |
| 3165 | #define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha)) | 3167 | #define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha)) |
| 3166 | #define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) | 3168 | #define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) |
| @@ -3579,6 +3581,16 @@ typedef struct scsi_qla_host { | |||
| 3579 | uint16_t fcoe_fcf_idx; | 3581 | uint16_t fcoe_fcf_idx; |
| 3580 | uint8_t fcoe_vn_port_mac[6]; | 3582 | uint8_t fcoe_vn_port_mac[6]; |
| 3581 | 3583 | ||
| 3584 | /* list of commands waiting on workqueue */ | ||
| 3585 | struct list_head qla_cmd_list; | ||
| 3586 | struct list_head qla_sess_op_cmd_list; | ||
| 3587 | spinlock_t cmd_list_lock; | ||
| 3588 | |||
| 3589 | /* Counter to detect races between ELS and RSCN events */ | ||
| 3590 | atomic_t generation_tick; | ||
| 3591 | /* Time when global fcport update has been scheduled */ | ||
| 3592 | int total_fcport_update_gen; | ||
| 3593 | |||
| 3582 | uint32_t vp_abort_cnt; | 3594 | uint32_t vp_abort_cnt; |
| 3583 | 3595 | ||
| 3584 | struct fc_vport *fc_vport; /* holds fc_vport * for each vport */ | 3596 | struct fc_vport *fc_vport; /* holds fc_vport * for each vport */ |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 285cb204f300..11f2f3279eab 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
| @@ -115,6 +115,8 @@ qla2x00_async_iocb_timeout(void *data) | |||
| 115 | QLA_LOGIO_LOGIN_RETRIED : 0; | 115 | QLA_LOGIO_LOGIN_RETRIED : 0; |
| 116 | qla2x00_post_async_login_done_work(fcport->vha, fcport, | 116 | qla2x00_post_async_login_done_work(fcport->vha, fcport, |
| 117 | lio->u.logio.data); | 117 | lio->u.logio.data); |
| 118 | } else if (sp->type == SRB_LOGOUT_CMD) { | ||
| 119 | qlt_logo_completion_handler(fcport, QLA_FUNCTION_TIMEOUT); | ||
| 118 | } | 120 | } |
| 119 | } | 121 | } |
| 120 | 122 | ||
| @@ -497,7 +499,10 @@ void | |||
| 497 | qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport, | 499 | qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport, |
| 498 | uint16_t *data) | 500 | uint16_t *data) |
| 499 | { | 501 | { |
| 500 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | 502 | /* Don't re-login in target mode */ |
| 503 | if (!fcport->tgt_session) | ||
| 504 | qla2x00_mark_device_lost(vha, fcport, 1, 0); | ||
| 505 | qlt_logo_completion_handler(fcport, data[0]); | ||
| 501 | return; | 506 | return; |
| 502 | } | 507 | } |
| 503 | 508 | ||
| @@ -708,7 +713,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha) | |||
| 708 | if (rval != QLA_SUCCESS) { | 713 | if (rval != QLA_SUCCESS) { |
| 709 | ql_log(ql_log_warn, vha, 0x00d4, | 714 | ql_log(ql_log_warn, vha, 0x00d4, |
| 710 | "Unable to initialize ISP84XX.\n"); | 715 | "Unable to initialize ISP84XX.\n"); |
| 711 | qla84xx_put_chip(vha); | 716 | qla84xx_put_chip(vha); |
| 712 | } | 717 | } |
| 713 | } | 718 | } |
| 714 | 719 | ||
| @@ -1538,7 +1543,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) | |||
| 1538 | mem_size = (ha->fw_memory_size - 0x11000 + 1) * | 1543 | mem_size = (ha->fw_memory_size - 0x11000 + 1) * |
| 1539 | sizeof(uint16_t); | 1544 | sizeof(uint16_t); |
| 1540 | } else if (IS_FWI2_CAPABLE(ha)) { | 1545 | } else if (IS_FWI2_CAPABLE(ha)) { |
| 1541 | if (IS_QLA83XX(ha)) | 1546 | if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) |
| 1542 | fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem); | 1547 | fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem); |
| 1543 | else if (IS_QLA81XX(ha)) | 1548 | else if (IS_QLA81XX(ha)) |
| 1544 | fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem); | 1549 | fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem); |
| @@ -1550,7 +1555,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha) | |||
| 1550 | mem_size = (ha->fw_memory_size - 0x100000 + 1) * | 1555 | mem_size = (ha->fw_memory_size - 0x100000 + 1) * |
| 1551 | sizeof(uint32_t); | 1556 | sizeof(uint32_t); |
| 1552 | if (ha->mqenable) { | 1557 | if (ha->mqenable) { |
| 1553 | if (!IS_QLA83XX(ha)) | 1558 | if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) |
| 1554 | mq_size = sizeof(struct qla2xxx_mq_chain); | 1559 | mq_size = sizeof(struct qla2xxx_mq_chain); |
| 1555 | /* | 1560 | /* |
| 1556 | * Allocate maximum buffer size for all queues. | 1561 | * Allocate maximum buffer size for all queues. |
| @@ -2922,21 +2927,14 @@ qla2x00_rport_del(void *data) | |||
| 2922 | { | 2927 | { |
| 2923 | fc_port_t *fcport = data; | 2928 | fc_port_t *fcport = data; |
| 2924 | struct fc_rport *rport; | 2929 | struct fc_rport *rport; |
| 2925 | scsi_qla_host_t *vha = fcport->vha; | ||
| 2926 | unsigned long flags; | 2930 | unsigned long flags; |
| 2927 | 2931 | ||
| 2928 | spin_lock_irqsave(fcport->vha->host->host_lock, flags); | 2932 | spin_lock_irqsave(fcport->vha->host->host_lock, flags); |
| 2929 | rport = fcport->drport ? fcport->drport: fcport->rport; | 2933 | rport = fcport->drport ? fcport->drport: fcport->rport; |
| 2930 | fcport->drport = NULL; | 2934 | fcport->drport = NULL; |
| 2931 | spin_unlock_irqrestore(fcport->vha->host->host_lock, flags); | 2935 | spin_unlock_irqrestore(fcport->vha->host->host_lock, flags); |
| 2932 | if (rport) { | 2936 | if (rport) |
| 2933 | fc_remote_port_delete(rport); | 2937 | fc_remote_port_delete(rport); |
| 2934 | /* | ||
| 2935 | * Release the target mode FC NEXUS in qla_target.c code | ||
| 2936 | * if target mod is enabled. | ||
| 2937 | */ | ||
| 2938 | qlt_fc_port_deleted(vha, fcport); | ||
| 2939 | } | ||
| 2940 | } | 2938 | } |
| 2941 | 2939 | ||
| 2942 | /** | 2940 | /** |
| @@ -3303,6 +3301,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport) | |||
| 3303 | * Create target mode FC NEXUS in qla_target.c if target mode is | 3301 | * Create target mode FC NEXUS in qla_target.c if target mode is |
| 3304 | * enabled.. | 3302 | * enabled.. |
| 3305 | */ | 3303 | */ |
| 3304 | |||
| 3306 | qlt_fc_port_added(vha, fcport); | 3305 | qlt_fc_port_added(vha, fcport); |
| 3307 | 3306 | ||
| 3308 | spin_lock_irqsave(fcport->vha->host->host_lock, flags); | 3307 | spin_lock_irqsave(fcport->vha->host->host_lock, flags); |
| @@ -3341,8 +3340,7 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) | |||
| 3341 | 3340 | ||
| 3342 | if (IS_QLAFX00(vha->hw)) { | 3341 | if (IS_QLAFX00(vha->hw)) { |
| 3343 | qla2x00_set_fcport_state(fcport, FCS_ONLINE); | 3342 | qla2x00_set_fcport_state(fcport, FCS_ONLINE); |
| 3344 | qla2x00_reg_remote_port(vha, fcport); | 3343 | goto reg_port; |
| 3345 | return; | ||
| 3346 | } | 3344 | } |
| 3347 | fcport->login_retry = 0; | 3345 | fcport->login_retry = 0; |
| 3348 | fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT); | 3346 | fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT); |
| @@ -3350,7 +3348,16 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) | |||
| 3350 | qla2x00_set_fcport_state(fcport, FCS_ONLINE); | 3348 | qla2x00_set_fcport_state(fcport, FCS_ONLINE); |
| 3351 | qla2x00_iidma_fcport(vha, fcport); | 3349 | qla2x00_iidma_fcport(vha, fcport); |
| 3352 | qla24xx_update_fcport_fcp_prio(vha, fcport); | 3350 | qla24xx_update_fcport_fcp_prio(vha, fcport); |
| 3353 | qla2x00_reg_remote_port(vha, fcport); | 3351 | |
| 3352 | reg_port: | ||
| 3353 | if (qla_ini_mode_enabled(vha)) | ||
| 3354 | qla2x00_reg_remote_port(vha, fcport); | ||
| 3355 | else { | ||
| 3356 | /* | ||
| 3357 | * Create target mode FC NEXUS in qla_target.c | ||
| 3358 | */ | ||
| 3359 | qlt_fc_port_added(vha, fcport); | ||
| 3360 | } | ||
| 3354 | } | 3361 | } |
| 3355 | 3362 | ||
| 3356 | /* | 3363 | /* |
| @@ -3375,6 +3382,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) | |||
| 3375 | LIST_HEAD(new_fcports); | 3382 | LIST_HEAD(new_fcports); |
| 3376 | struct qla_hw_data *ha = vha->hw; | 3383 | struct qla_hw_data *ha = vha->hw; |
| 3377 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); | 3384 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); |
| 3385 | int discovery_gen; | ||
| 3378 | 3386 | ||
| 3379 | /* If FL port exists, then SNS is present */ | 3387 | /* If FL port exists, then SNS is present */ |
| 3380 | if (IS_FWI2_CAPABLE(ha)) | 3388 | if (IS_FWI2_CAPABLE(ha)) |
| @@ -3445,6 +3453,14 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) | |||
| 3445 | fcport->scan_state = QLA_FCPORT_SCAN; | 3453 | fcport->scan_state = QLA_FCPORT_SCAN; |
| 3446 | } | 3454 | } |
| 3447 | 3455 | ||
| 3456 | /* Mark the time right before querying FW for connected ports. | ||
| 3457 | * This process is long, asynchronous and by the time it's done, | ||
| 3458 | * collected information might not be accurate anymore. E.g. | ||
| 3459 | * disconnected port might have re-connected and a brand new | ||
| 3460 | * session has been created. In this case session's generation | ||
| 3461 | * will be newer than discovery_gen. */ | ||
| 3462 | qlt_do_generation_tick(vha, &discovery_gen); | ||
| 3463 | |||
| 3448 | rval = qla2x00_find_all_fabric_devs(vha, &new_fcports); | 3464 | rval = qla2x00_find_all_fabric_devs(vha, &new_fcports); |
| 3449 | if (rval != QLA_SUCCESS) | 3465 | if (rval != QLA_SUCCESS) |
| 3450 | break; | 3466 | break; |
| @@ -3460,20 +3476,44 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) | |||
| 3460 | if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) | 3476 | if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) |
| 3461 | continue; | 3477 | continue; |
| 3462 | 3478 | ||
| 3463 | if (fcport->scan_state == QLA_FCPORT_SCAN && | 3479 | if (fcport->scan_state == QLA_FCPORT_SCAN) { |
| 3464 | atomic_read(&fcport->state) == FCS_ONLINE) { | 3480 | if (qla_ini_mode_enabled(base_vha) && |
| 3465 | qla2x00_mark_device_lost(vha, fcport, | 3481 | atomic_read(&fcport->state) == FCS_ONLINE) { |
| 3466 | ql2xplogiabsentdevice, 0); | 3482 | qla2x00_mark_device_lost(vha, fcport, |
| 3467 | if (fcport->loop_id != FC_NO_LOOP_ID && | 3483 | ql2xplogiabsentdevice, 0); |
| 3468 | (fcport->flags & FCF_FCP2_DEVICE) == 0 && | 3484 | if (fcport->loop_id != FC_NO_LOOP_ID && |
| 3469 | fcport->port_type != FCT_INITIATOR && | 3485 | (fcport->flags & FCF_FCP2_DEVICE) == 0 && |
| 3470 | fcport->port_type != FCT_BROADCAST) { | 3486 | fcport->port_type != FCT_INITIATOR && |
| 3471 | ha->isp_ops->fabric_logout(vha, | 3487 | fcport->port_type != FCT_BROADCAST) { |
| 3472 | fcport->loop_id, | 3488 | ha->isp_ops->fabric_logout(vha, |
| 3473 | fcport->d_id.b.domain, | 3489 | fcport->loop_id, |
| 3474 | fcport->d_id.b.area, | 3490 | fcport->d_id.b.domain, |
| 3475 | fcport->d_id.b.al_pa); | 3491 | fcport->d_id.b.area, |
| 3476 | qla2x00_clear_loop_id(fcport); | 3492 | fcport->d_id.b.al_pa); |
| 3493 | qla2x00_clear_loop_id(fcport); | ||
| 3494 | } | ||
| 3495 | } else if (!qla_ini_mode_enabled(base_vha)) { | ||
| 3496 | /* | ||
| 3497 | * In target mode, explicitly kill | ||
| 3498 | * sessions and log out of devices | ||
| 3499 | * that are gone, so that we don't | ||
| 3500 | * end up with an initiator using the | ||
| 3501 | * wrong ACL (if the fabric recycles | ||
| 3502 | * an FC address and we have a stale | ||
| 3503 | * session around) and so that we don't | ||
| 3504 | * report initiators that are no longer | ||
| 3505 | * on the fabric. | ||
| 3506 | */ | ||
| 3507 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf077, | ||
| 3508 | "port gone, logging out/killing session: " | ||
| 3509 | "%8phC state 0x%x flags 0x%x fc4_type 0x%x " | ||
| 3510 | "scan_state %d\n", | ||
| 3511 | fcport->port_name, | ||
| 3512 | atomic_read(&fcport->state), | ||
| 3513 | fcport->flags, fcport->fc4_type, | ||
| 3514 | fcport->scan_state); | ||
| 3515 | qlt_fc_port_deleted(vha, fcport, | ||
| 3516 | discovery_gen); | ||
| 3477 | } | 3517 | } |
| 3478 | } | 3518 | } |
| 3479 | } | 3519 | } |
| @@ -3494,6 +3534,28 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) | |||
| 3494 | (fcport->flags & FCF_LOGIN_NEEDED) == 0) | 3534 | (fcport->flags & FCF_LOGIN_NEEDED) == 0) |
| 3495 | continue; | 3535 | continue; |
| 3496 | 3536 | ||
| 3537 | /* | ||
| 3538 | * If we're not an initiator, skip looking for devices | ||
| 3539 | * and logging in. There's no reason for us to do it, | ||
| 3540 | * and it seems to actively cause problems in target | ||
| 3541 | * mode if we race with the initiator logging into us | ||
| 3542 | * (we might get the "port ID used" status back from | ||
| 3543 | * our login command and log out the initiator, which | ||
| 3544 | * seems to cause havoc). | ||
| 3545 | */ | ||
| 3546 | if (!qla_ini_mode_enabled(base_vha)) { | ||
| 3547 | if (fcport->scan_state == QLA_FCPORT_FOUND) { | ||
| 3548 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf078, | ||
| 3549 | "port %8phC state 0x%x flags 0x%x fc4_type 0x%x " | ||
| 3550 | "scan_state %d (initiator mode disabled; skipping " | ||
| 3551 | "login)\n", fcport->port_name, | ||
| 3552 | atomic_read(&fcport->state), | ||
| 3553 | fcport->flags, fcport->fc4_type, | ||
| 3554 | fcport->scan_state); | ||
| 3555 | } | ||
| 3556 | continue; | ||
| 3557 | } | ||
| 3558 | |||
| 3497 | if (fcport->loop_id == FC_NO_LOOP_ID) { | 3559 | if (fcport->loop_id == FC_NO_LOOP_ID) { |
| 3498 | fcport->loop_id = next_loopid; | 3560 | fcport->loop_id = next_loopid; |
| 3499 | rval = qla2x00_find_new_loop_id( | 3561 | rval = qla2x00_find_new_loop_id( |
| @@ -3520,16 +3582,38 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha) | |||
| 3520 | test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) | 3582 | test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) |
| 3521 | break; | 3583 | break; |
| 3522 | 3584 | ||
| 3523 | /* Find a new loop ID to use. */ | 3585 | /* |
| 3524 | fcport->loop_id = next_loopid; | 3586 | * If we're not an initiator, skip looking for devices |
| 3525 | rval = qla2x00_find_new_loop_id(base_vha, fcport); | 3587 | * and logging in. There's no reason for us to do it, |
| 3526 | if (rval != QLA_SUCCESS) { | 3588 | * and it seems to actively cause problems in target |
| 3527 | /* Ran out of IDs to use */ | 3589 | * mode if we race with the initiator logging into us |
| 3528 | break; | 3590 | * (we might get the "port ID used" status back from |
| 3529 | } | 3591 | * our login command and log out the initiator, which |
| 3592 | * seems to cause havoc). | ||
| 3593 | */ | ||
| 3594 | if (qla_ini_mode_enabled(base_vha)) { | ||
| 3595 | /* Find a new loop ID to use. */ | ||
| 3596 | fcport->loop_id = next_loopid; | ||
| 3597 | rval = qla2x00_find_new_loop_id(base_vha, | ||
| 3598 | fcport); | ||
| 3599 | if (rval != QLA_SUCCESS) { | ||
| 3600 | /* Ran out of IDs to use */ | ||
| 3601 | break; | ||
| 3602 | } | ||
| 3530 | 3603 | ||
| 3531 | /* Login and update database */ | 3604 | /* Login and update database */ |
| 3532 | qla2x00_fabric_dev_login(vha, fcport, &next_loopid); | 3605 | qla2x00_fabric_dev_login(vha, fcport, |
| 3606 | &next_loopid); | ||
| 3607 | } else { | ||
| 3608 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf079, | ||
| 3609 | "new port %8phC state 0x%x flags 0x%x fc4_type " | ||
| 3610 | "0x%x scan_state %d (initiator mode disabled; " | ||
| 3611 | "skipping login)\n", | ||
| 3612 | fcport->port_name, | ||
| 3613 | atomic_read(&fcport->state), | ||
| 3614 | fcport->flags, fcport->fc4_type, | ||
| 3615 | fcport->scan_state); | ||
| 3616 | } | ||
| 3533 | 3617 | ||
| 3534 | list_move_tail(&fcport->list, &vha->vp_fcports); | 3618 | list_move_tail(&fcport->list, &vha->vp_fcports); |
| 3535 | } | 3619 | } |
| @@ -3725,11 +3809,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, | |||
| 3725 | fcport->fp_speed = new_fcport->fp_speed; | 3809 | fcport->fp_speed = new_fcport->fp_speed; |
| 3726 | 3810 | ||
| 3727 | /* | 3811 | /* |
| 3728 | * If address the same and state FCS_ONLINE, nothing | 3812 | * If address the same and state FCS_ONLINE |
| 3729 | * changed. | 3813 | * (or in target mode), nothing changed. |
| 3730 | */ | 3814 | */ |
| 3731 | if (fcport->d_id.b24 == new_fcport->d_id.b24 && | 3815 | if (fcport->d_id.b24 == new_fcport->d_id.b24 && |
| 3732 | atomic_read(&fcport->state) == FCS_ONLINE) { | 3816 | (atomic_read(&fcport->state) == FCS_ONLINE || |
| 3817 | !qla_ini_mode_enabled(base_vha))) { | ||
| 3733 | break; | 3818 | break; |
| 3734 | } | 3819 | } |
| 3735 | 3820 | ||
| @@ -3749,6 +3834,22 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, | |||
| 3749 | * Log it out if still logged in and mark it for | 3834 | * Log it out if still logged in and mark it for |
| 3750 | * relogin later. | 3835 | * relogin later. |
| 3751 | */ | 3836 | */ |
| 3837 | if (!qla_ini_mode_enabled(base_vha)) { | ||
| 3838 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf080, | ||
| 3839 | "port changed FC ID, %8phC" | ||
| 3840 | " old %x:%x:%x (loop_id 0x%04x)-> new %x:%x:%x\n", | ||
| 3841 | fcport->port_name, | ||
| 3842 | fcport->d_id.b.domain, | ||
| 3843 | fcport->d_id.b.area, | ||
| 3844 | fcport->d_id.b.al_pa, | ||
| 3845 | fcport->loop_id, | ||
| 3846 | new_fcport->d_id.b.domain, | ||
| 3847 | new_fcport->d_id.b.area, | ||
| 3848 | new_fcport->d_id.b.al_pa); | ||
| 3849 | fcport->d_id.b24 = new_fcport->d_id.b24; | ||
| 3850 | break; | ||
| 3851 | } | ||
| 3852 | |||
| 3752 | fcport->d_id.b24 = new_fcport->d_id.b24; | 3853 | fcport->d_id.b24 = new_fcport->d_id.b24; |
| 3753 | fcport->flags |= FCF_LOGIN_NEEDED; | 3854 | fcport->flags |= FCF_LOGIN_NEEDED; |
| 3754 | if (fcport->loop_id != FC_NO_LOOP_ID && | 3855 | if (fcport->loop_id != FC_NO_LOOP_ID && |
| @@ -3768,6 +3869,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, | |||
| 3768 | if (found) | 3869 | if (found) |
| 3769 | continue; | 3870 | continue; |
| 3770 | /* If device was not in our fcports list, then add it. */ | 3871 | /* If device was not in our fcports list, then add it. */ |
| 3872 | new_fcport->scan_state = QLA_FCPORT_FOUND; | ||
| 3771 | list_add_tail(&new_fcport->list, new_fcports); | 3873 | list_add_tail(&new_fcport->list, new_fcports); |
| 3772 | 3874 | ||
| 3773 | /* Allocate a new replacement fcport. */ | 3875 | /* Allocate a new replacement fcport. */ |
| @@ -4188,6 +4290,14 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha) | |||
| 4188 | atomic_read(&fcport->state) != FCS_UNCONFIGURED) { | 4290 | atomic_read(&fcport->state) != FCS_UNCONFIGURED) { |
| 4189 | spin_unlock_irqrestore(&ha->vport_slock, flags); | 4291 | spin_unlock_irqrestore(&ha->vport_slock, flags); |
| 4190 | qla2x00_rport_del(fcport); | 4292 | qla2x00_rport_del(fcport); |
| 4293 | |||
| 4294 | /* | ||
| 4295 | * Release the target mode FC NEXUS in | ||
| 4296 | * qla_target.c, if target mod is enabled. | ||
| 4297 | */ | ||
| 4298 | qlt_fc_port_deleted(vha, fcport, | ||
| 4299 | base_vha->total_fcport_update_gen); | ||
| 4300 | |||
| 4191 | spin_lock_irqsave(&ha->vport_slock, flags); | 4301 | spin_lock_irqsave(&ha->vport_slock, flags); |
| 4192 | } | 4302 | } |
| 4193 | } | 4303 | } |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index a1ab25fca874..6f02b26a35cf 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
| @@ -1943,6 +1943,9 @@ qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio) | |||
| 1943 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; | 1943 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; |
| 1944 | logio->control_flags = | 1944 | logio->control_flags = |
| 1945 | cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO); | 1945 | cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO); |
| 1946 | if (!sp->fcport->tgt_session || | ||
| 1947 | !sp->fcport->tgt_session->keep_nport_handle) | ||
| 1948 | logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT); | ||
| 1946 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); | 1949 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); |
| 1947 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; | 1950 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; |
| 1948 | logio->port_id[1] = sp->fcport->d_id.b.area; | 1951 | logio->port_id[1] = sp->fcport->d_id.b.area; |
| @@ -2797,10 +2800,10 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds) | |||
| 2797 | handle = req->current_outstanding_cmd; | 2800 | handle = req->current_outstanding_cmd; |
| 2798 | for (index = 1; index < req->num_outstanding_cmds; index++) { | 2801 | for (index = 1; index < req->num_outstanding_cmds; index++) { |
| 2799 | handle++; | 2802 | handle++; |
| 2800 | if (handle == req->num_outstanding_cmds) | 2803 | if (handle == req->num_outstanding_cmds) |
| 2801 | handle = 1; | 2804 | handle = 1; |
| 2802 | if (!req->outstanding_cmds[handle]) | 2805 | if (!req->outstanding_cmds[handle]) |
| 2803 | break; | 2806 | break; |
| 2804 | } | 2807 | } |
| 2805 | 2808 | ||
| 2806 | if (index == req->num_outstanding_cmds) { | 2809 | if (index == req->num_outstanding_cmds) { |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 6dc14cd782b2..5559d5e75bbf 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
| @@ -1580,7 +1580,7 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) | |||
| 1580 | ql_log(ql_log_warn, fcport->vha, 0x503c, | 1580 | ql_log(ql_log_warn, fcport->vha, 0x503c, |
| 1581 | "Async-%s error - hdl=%x response(%x).\n", | 1581 | "Async-%s error - hdl=%x response(%x).\n", |
| 1582 | type, sp->handle, sts->data[3]); | 1582 | type, sp->handle, sts->data[3]); |
| 1583 | iocb->u.tmf.data = QLA_FUNCTION_FAILED; | 1583 | iocb->u.tmf.data = QLA_FUNCTION_FAILED; |
| 1584 | } | 1584 | } |
| 1585 | } | 1585 | } |
| 1586 | 1586 | ||
| @@ -1979,7 +1979,7 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, | |||
| 1979 | rval = EXT_STATUS_ERR; | 1979 | rval = EXT_STATUS_ERR; |
| 1980 | break; | 1980 | break; |
| 1981 | } | 1981 | } |
| 1982 | bsg_job->reply->reply_payload_rcv_len = 0; | 1982 | bsg_job->reply->reply_payload_rcv_len = 0; |
| 1983 | 1983 | ||
| 1984 | done: | 1984 | done: |
| 1985 | /* Return the vendor specific reply to API */ | 1985 | /* Return the vendor specific reply to API */ |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 02b1c1c5355b..b2f713ad9034 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
| @@ -2415,7 +2415,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt, | |||
| 2415 | *orig_iocb_cnt = mcp->mb[10]; | 2415 | *orig_iocb_cnt = mcp->mb[10]; |
| 2416 | if (vha->hw->flags.npiv_supported && max_npiv_vports) | 2416 | if (vha->hw->flags.npiv_supported && max_npiv_vports) |
| 2417 | *max_npiv_vports = mcp->mb[11]; | 2417 | *max_npiv_vports = mcp->mb[11]; |
| 2418 | if ((IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw)) && max_fcfs) | 2418 | if ((IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw) || |
| 2419 | IS_QLA27XX(vha->hw)) && max_fcfs) | ||
| 2419 | *max_fcfs = mcp->mb[12]; | 2420 | *max_fcfs = mcp->mb[12]; |
| 2420 | } | 2421 | } |
| 2421 | 2422 | ||
| @@ -3898,7 +3899,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp) | |||
| 3898 | spin_lock_irqsave(&ha->hardware_lock, flags); | 3899 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| 3899 | if (!(rsp->options & BIT_0)) { | 3900 | if (!(rsp->options & BIT_0)) { |
| 3900 | WRT_REG_DWORD(rsp->rsp_q_out, 0); | 3901 | WRT_REG_DWORD(rsp->rsp_q_out, 0); |
| 3901 | if (!IS_QLA83XX(ha)) | 3902 | if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) |
| 3902 | WRT_REG_DWORD(rsp->rsp_q_in, 0); | 3903 | WRT_REG_DWORD(rsp->rsp_q_in, 0); |
| 3903 | } | 3904 | } |
| 3904 | 3905 | ||
| @@ -5345,7 +5346,7 @@ qla83xx_restart_nic_firmware(scsi_qla_host_t *vha) | |||
| 5345 | mbx_cmd_t *mcp = &mc; | 5346 | mbx_cmd_t *mcp = &mc; |
| 5346 | struct qla_hw_data *ha = vha->hw; | 5347 | struct qla_hw_data *ha = vha->hw; |
| 5347 | 5348 | ||
| 5348 | if (!IS_QLA83XX(ha)) | 5349 | if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) |
| 5349 | return QLA_FUNCTION_FAILED; | 5350 | return QLA_FUNCTION_FAILED; |
| 5350 | 5351 | ||
| 5351 | ql_dbg(ql_dbg_mbx, vha, 0x1143, "Entered %s.\n", __func__); | 5352 | ql_dbg(ql_dbg_mbx, vha, 0x1143, "Entered %s.\n", __func__); |
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 7d2b18f2675c..1620b0ec977b 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c | |||
| @@ -1843,7 +1843,7 @@ qla82xx_set_product_offset(struct qla_hw_data *ha) | |||
| 1843 | 1843 | ||
| 1844 | ptab_desc = qla82xx_get_table_desc(unirom, | 1844 | ptab_desc = qla82xx_get_table_desc(unirom, |
| 1845 | QLA82XX_URI_DIR_SECT_PRODUCT_TBL); | 1845 | QLA82XX_URI_DIR_SECT_PRODUCT_TBL); |
| 1846 | if (!ptab_desc) | 1846 | if (!ptab_desc) |
| 1847 | return -1; | 1847 | return -1; |
| 1848 | 1848 | ||
| 1849 | entries = cpu_to_le32(ptab_desc->num_entries); | 1849 | entries = cpu_to_le32(ptab_desc->num_entries); |
diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c index ed4d6b6b53e3..000c57e4d033 100644 --- a/drivers/scsi/qla2xxx/qla_nx2.c +++ b/drivers/scsi/qla2xxx/qla_nx2.c | |||
| @@ -397,11 +397,11 @@ qla8044_idc_lock(struct qla_hw_data *ha) | |||
| 397 | * has the lock, wait for 2secs | 397 | * has the lock, wait for 2secs |
| 398 | * and retry | 398 | * and retry |
| 399 | */ | 399 | */ |
| 400 | ql_dbg(ql_dbg_p3p, vha, 0xb08a, | 400 | ql_dbg(ql_dbg_p3p, vha, 0xb08a, |
| 401 | "%s: IDC lock Recovery by %d " | 401 | "%s: IDC lock Recovery by %d " |
| 402 | "failed, Retrying timeout\n", __func__, | 402 | "failed, Retrying timeout\n", __func__, |
| 403 | ha->portnum); | 403 | ha->portnum); |
| 404 | timeout = 0; | 404 | timeout = 0; |
| 405 | } | 405 | } |
| 406 | } | 406 | } |
| 407 | msleep(QLA8044_DRV_LOCK_MSLEEP); | 407 | msleep(QLA8044_DRV_LOCK_MSLEEP); |
| @@ -3141,8 +3141,7 @@ qla8044_minidump_process_rdmdio(struct scsi_qla_host *vha, | |||
| 3141 | goto error; | 3141 | goto error; |
| 3142 | 3142 | ||
| 3143 | addr7 = addr2 - (4 * stride1); | 3143 | addr7 = addr2 - (4 * stride1); |
| 3144 | data = qla8044_ipmdio_rd_reg(vha, addr1, addr3, | 3144 | data = qla8044_ipmdio_rd_reg(vha, addr1, addr3, mask, addr7); |
| 3145 | mask, addr7); | ||
| 3146 | if (data == -1) | 3145 | if (data == -1) |
| 3147 | goto error; | 3146 | goto error; |
| 3148 | 3147 | ||
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 7462dd70b150..8a5cac8448c7 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
| @@ -2504,6 +2504,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 2504 | ha->mbx_count = MAILBOX_REGISTER_COUNT; | 2504 | ha->mbx_count = MAILBOX_REGISTER_COUNT; |
| 2505 | req_length = REQUEST_ENTRY_CNT_24XX; | 2505 | req_length = REQUEST_ENTRY_CNT_24XX; |
| 2506 | rsp_length = RESPONSE_ENTRY_CNT_2300; | 2506 | rsp_length = RESPONSE_ENTRY_CNT_2300; |
| 2507 | ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; | ||
| 2507 | ha->max_loop_id = SNS_LAST_LOOP_ID_2300; | 2508 | ha->max_loop_id = SNS_LAST_LOOP_ID_2300; |
| 2508 | ha->init_cb_size = sizeof(struct mid_init_cb_81xx); | 2509 | ha->init_cb_size = sizeof(struct mid_init_cb_81xx); |
| 2509 | ha->gid_list_info_size = 8; | 2510 | ha->gid_list_info_size = 8; |
| @@ -3229,11 +3230,15 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport, | |||
| 3229 | spin_lock_irqsave(vha->host->host_lock, flags); | 3230 | spin_lock_irqsave(vha->host->host_lock, flags); |
| 3230 | fcport->drport = rport; | 3231 | fcport->drport = rport; |
| 3231 | spin_unlock_irqrestore(vha->host->host_lock, flags); | 3232 | spin_unlock_irqrestore(vha->host->host_lock, flags); |
| 3233 | qlt_do_generation_tick(vha, &base_vha->total_fcport_update_gen); | ||
| 3232 | set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); | 3234 | set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); |
| 3233 | qla2xxx_wake_dpc(base_vha); | 3235 | qla2xxx_wake_dpc(base_vha); |
| 3234 | } else { | 3236 | } else { |
| 3235 | fc_remote_port_delete(rport); | 3237 | int now; |
| 3236 | qlt_fc_port_deleted(vha, fcport); | 3238 | if (rport) |
| 3239 | fc_remote_port_delete(rport); | ||
| 3240 | qlt_do_generation_tick(vha, &now); | ||
| 3241 | qlt_fc_port_deleted(vha, fcport, now); | ||
| 3237 | } | 3242 | } |
| 3238 | } | 3243 | } |
| 3239 | 3244 | ||
| @@ -3763,8 +3768,11 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht, | |||
| 3763 | INIT_LIST_HEAD(&vha->vp_fcports); | 3768 | INIT_LIST_HEAD(&vha->vp_fcports); |
| 3764 | INIT_LIST_HEAD(&vha->work_list); | 3769 | INIT_LIST_HEAD(&vha->work_list); |
| 3765 | INIT_LIST_HEAD(&vha->list); | 3770 | INIT_LIST_HEAD(&vha->list); |
| 3771 | INIT_LIST_HEAD(&vha->qla_cmd_list); | ||
| 3772 | INIT_LIST_HEAD(&vha->qla_sess_op_cmd_list); | ||
| 3766 | 3773 | ||
| 3767 | spin_lock_init(&vha->work_lock); | 3774 | spin_lock_init(&vha->work_lock); |
| 3775 | spin_lock_init(&vha->cmd_list_lock); | ||
| 3768 | 3776 | ||
| 3769 | sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no); | 3777 | sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no); |
| 3770 | ql_dbg(ql_dbg_init, vha, 0x0041, | 3778 | ql_dbg(ql_dbg_init, vha, 0x0041, |
| @@ -4418,7 +4426,10 @@ retry_lock2: | |||
| 4418 | void | 4426 | void |
| 4419 | qla83xx_idc_unlock(scsi_qla_host_t *base_vha, uint16_t requester_id) | 4427 | qla83xx_idc_unlock(scsi_qla_host_t *base_vha, uint16_t requester_id) |
| 4420 | { | 4428 | { |
| 4421 | uint16_t options = (requester_id << 15) | BIT_7, retry; | 4429 | #if 0 |
| 4430 | uint16_t options = (requester_id << 15) | BIT_7; | ||
| 4431 | #endif | ||
| 4432 | uint16_t retry; | ||
| 4422 | uint32_t data; | 4433 | uint32_t data; |
| 4423 | struct qla_hw_data *ha = base_vha->hw; | 4434 | struct qla_hw_data *ha = base_vha->hw; |
| 4424 | 4435 | ||
| @@ -4454,6 +4465,7 @@ retry_unlock: | |||
| 4454 | 4465 | ||
| 4455 | return; | 4466 | return; |
| 4456 | 4467 | ||
| 4468 | #if 0 | ||
| 4457 | /* XXX: IDC-unlock implementation using access-control mbx */ | 4469 | /* XXX: IDC-unlock implementation using access-control mbx */ |
| 4458 | retry = 0; | 4470 | retry = 0; |
| 4459 | retry_unlock2: | 4471 | retry_unlock2: |
| @@ -4469,6 +4481,7 @@ retry_unlock2: | |||
| 4469 | } | 4481 | } |
| 4470 | 4482 | ||
| 4471 | return; | 4483 | return; |
| 4484 | #endif | ||
| 4472 | } | 4485 | } |
| 4473 | 4486 | ||
| 4474 | int | 4487 | int |
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 028e8c8a7de9..2feb5f38edcd 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
| @@ -1697,7 +1697,7 @@ qla83xx_select_led_port(struct qla_hw_data *ha) | |||
| 1697 | { | 1697 | { |
| 1698 | uint32_t led_select_value = 0; | 1698 | uint32_t led_select_value = 0; |
| 1699 | 1699 | ||
| 1700 | if (!IS_QLA83XX(ha)) | 1700 | if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) |
| 1701 | goto out; | 1701 | goto out; |
| 1702 | 1702 | ||
| 1703 | if (ha->port_no == 0) | 1703 | if (ha->port_no == 0) |
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index fe8a8d157e22..58651ecbd88c 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c | |||
| @@ -113,6 +113,11 @@ static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, | |||
| 113 | static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, | 113 | static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, |
| 114 | struct atio_from_isp *atio, uint16_t status, int qfull); | 114 | struct atio_from_isp *atio, uint16_t status, int qfull); |
| 115 | static void qlt_disable_vha(struct scsi_qla_host *vha); | 115 | static void qlt_disable_vha(struct scsi_qla_host *vha); |
| 116 | static void qlt_clear_tgt_db(struct qla_tgt *tgt); | ||
| 117 | static void qlt_send_notify_ack(struct scsi_qla_host *vha, | ||
| 118 | struct imm_ntfy_from_isp *ntfy, | ||
| 119 | uint32_t add_flags, uint16_t resp_code, int resp_code_valid, | ||
| 120 | uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan); | ||
| 116 | /* | 121 | /* |
| 117 | * Global Variables | 122 | * Global Variables |
| 118 | */ | 123 | */ |
| @@ -122,6 +127,16 @@ static struct workqueue_struct *qla_tgt_wq; | |||
| 122 | static DEFINE_MUTEX(qla_tgt_mutex); | 127 | static DEFINE_MUTEX(qla_tgt_mutex); |
| 123 | static LIST_HEAD(qla_tgt_glist); | 128 | static LIST_HEAD(qla_tgt_glist); |
| 124 | 129 | ||
| 130 | /* This API intentionally takes dest as a parameter, rather than returning | ||
| 131 | * int value to avoid caller forgetting to issue wmb() after the store */ | ||
| 132 | void qlt_do_generation_tick(struct scsi_qla_host *vha, int *dest) | ||
| 133 | { | ||
| 134 | scsi_qla_host_t *base_vha = pci_get_drvdata(vha->hw->pdev); | ||
| 135 | *dest = atomic_inc_return(&base_vha->generation_tick); | ||
| 136 | /* memory barrier */ | ||
| 137 | wmb(); | ||
| 138 | } | ||
| 139 | |||
| 125 | /* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */ | 140 | /* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */ |
| 126 | static struct qla_tgt_sess *qlt_find_sess_by_port_name( | 141 | static struct qla_tgt_sess *qlt_find_sess_by_port_name( |
| 127 | struct qla_tgt *tgt, | 142 | struct qla_tgt *tgt, |
| @@ -381,14 +396,73 @@ static void qlt_free_session_done(struct work_struct *work) | |||
| 381 | struct qla_tgt *tgt = sess->tgt; | 396 | struct qla_tgt *tgt = sess->tgt; |
| 382 | struct scsi_qla_host *vha = sess->vha; | 397 | struct scsi_qla_host *vha = sess->vha; |
| 383 | struct qla_hw_data *ha = vha->hw; | 398 | struct qla_hw_data *ha = vha->hw; |
| 399 | unsigned long flags; | ||
| 400 | bool logout_started = false; | ||
| 401 | fc_port_t fcport; | ||
| 402 | |||
| 403 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf084, | ||
| 404 | "%s: se_sess %p / sess %p from port %8phC loop_id %#04x" | ||
| 405 | " s_id %02x:%02x:%02x logout %d keep %d plogi %d\n", | ||
| 406 | __func__, sess->se_sess, sess, sess->port_name, sess->loop_id, | ||
| 407 | sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa, | ||
| 408 | sess->logout_on_delete, sess->keep_nport_handle, | ||
| 409 | sess->plogi_ack_needed); | ||
| 384 | 410 | ||
| 385 | BUG_ON(!tgt); | 411 | BUG_ON(!tgt); |
| 412 | |||
| 413 | if (sess->logout_on_delete) { | ||
| 414 | int rc; | ||
| 415 | |||
| 416 | memset(&fcport, 0, sizeof(fcport)); | ||
| 417 | fcport.loop_id = sess->loop_id; | ||
| 418 | fcport.d_id = sess->s_id; | ||
| 419 | memcpy(fcport.port_name, sess->port_name, WWN_SIZE); | ||
| 420 | fcport.vha = vha; | ||
| 421 | fcport.tgt_session = sess; | ||
| 422 | |||
| 423 | rc = qla2x00_post_async_logout_work(vha, &fcport, NULL); | ||
| 424 | if (rc != QLA_SUCCESS) | ||
| 425 | ql_log(ql_log_warn, vha, 0xf085, | ||
| 426 | "Schedule logo failed sess %p rc %d\n", | ||
| 427 | sess, rc); | ||
| 428 | else | ||
| 429 | logout_started = true; | ||
| 430 | } | ||
| 431 | |||
| 386 | /* | 432 | /* |
| 387 | * Release the target session for FC Nexus from fabric module code. | 433 | * Release the target session for FC Nexus from fabric module code. |
| 388 | */ | 434 | */ |
| 389 | if (sess->se_sess != NULL) | 435 | if (sess->se_sess != NULL) |
| 390 | ha->tgt.tgt_ops->free_session(sess); | 436 | ha->tgt.tgt_ops->free_session(sess); |
| 391 | 437 | ||
| 438 | if (logout_started) { | ||
| 439 | bool traced = false; | ||
| 440 | |||
| 441 | while (!ACCESS_ONCE(sess->logout_completed)) { | ||
| 442 | if (!traced) { | ||
| 443 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf086, | ||
| 444 | "%s: waiting for sess %p logout\n", | ||
| 445 | __func__, sess); | ||
| 446 | traced = true; | ||
| 447 | } | ||
| 448 | msleep(100); | ||
| 449 | } | ||
| 450 | |||
| 451 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf087, | ||
| 452 | "%s: sess %p logout completed\n", | ||
| 453 | __func__, sess); | ||
| 454 | } | ||
| 455 | |||
| 456 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
| 457 | |||
| 458 | if (sess->plogi_ack_needed) | ||
| 459 | qlt_send_notify_ack(vha, &sess->tm_iocb, | ||
| 460 | 0, 0, 0, 0, 0, 0); | ||
| 461 | |||
| 462 | list_del(&sess->sess_list_entry); | ||
| 463 | |||
| 464 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
| 465 | |||
| 392 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf001, | 466 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf001, |
| 393 | "Unregistration of sess %p finished\n", sess); | 467 | "Unregistration of sess %p finished\n", sess); |
| 394 | 468 | ||
| @@ -409,9 +483,9 @@ void qlt_unreg_sess(struct qla_tgt_sess *sess) | |||
| 409 | 483 | ||
| 410 | vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess); | 484 | vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess); |
| 411 | 485 | ||
| 412 | list_del(&sess->sess_list_entry); | 486 | if (!list_empty(&sess->del_list_entry)) |
| 413 | if (sess->deleted) | 487 | list_del_init(&sess->del_list_entry); |
| 414 | list_del(&sess->del_list_entry); | 488 | sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; |
| 415 | 489 | ||
| 416 | INIT_WORK(&sess->free_work, qlt_free_session_done); | 490 | INIT_WORK(&sess->free_work, qlt_free_session_done); |
| 417 | schedule_work(&sess->free_work); | 491 | schedule_work(&sess->free_work); |
| @@ -431,10 +505,10 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd) | |||
| 431 | 505 | ||
| 432 | loop_id = le16_to_cpu(n->u.isp24.nport_handle); | 506 | loop_id = le16_to_cpu(n->u.isp24.nport_handle); |
| 433 | if (loop_id == 0xFFFF) { | 507 | if (loop_id == 0xFFFF) { |
| 434 | #if 0 /* FIXME: Re-enable Global event handling.. */ | ||
| 435 | /* Global event */ | 508 | /* Global event */ |
| 436 | atomic_inc(&ha->tgt.qla_tgt->tgt_global_resets_count); | 509 | atomic_inc(&vha->vha_tgt.qla_tgt->tgt_global_resets_count); |
| 437 | qlt_clear_tgt_db(ha->tgt.qla_tgt); | 510 | qlt_clear_tgt_db(vha->vha_tgt.qla_tgt); |
| 511 | #if 0 /* FIXME: do we need to choose a session here? */ | ||
| 438 | if (!list_empty(&ha->tgt.qla_tgt->sess_list)) { | 512 | if (!list_empty(&ha->tgt.qla_tgt->sess_list)) { |
| 439 | sess = list_entry(ha->tgt.qla_tgt->sess_list.next, | 513 | sess = list_entry(ha->tgt.qla_tgt->sess_list.next, |
| 440 | typeof(*sess), sess_list_entry); | 514 | typeof(*sess), sess_list_entry); |
| @@ -489,27 +563,38 @@ static void qlt_schedule_sess_for_deletion(struct qla_tgt_sess *sess, | |||
| 489 | struct qla_tgt *tgt = sess->tgt; | 563 | struct qla_tgt *tgt = sess->tgt; |
| 490 | uint32_t dev_loss_tmo = tgt->ha->port_down_retry_count + 5; | 564 | uint32_t dev_loss_tmo = tgt->ha->port_down_retry_count + 5; |
| 491 | 565 | ||
| 492 | if (sess->deleted) | 566 | if (sess->deleted) { |
| 493 | return; | 567 | /* Upgrade to unconditional deletion in case it was temporary */ |
| 568 | if (immediate && sess->deleted == QLA_SESS_DELETION_PENDING) | ||
| 569 | list_del(&sess->del_list_entry); | ||
| 570 | else | ||
| 571 | return; | ||
| 572 | } | ||
| 494 | 573 | ||
| 495 | ql_dbg(ql_dbg_tgt, sess->vha, 0xe001, | 574 | ql_dbg(ql_dbg_tgt, sess->vha, 0xe001, |
| 496 | "Scheduling sess %p for deletion\n", sess); | 575 | "Scheduling sess %p for deletion\n", sess); |
| 497 | list_add_tail(&sess->del_list_entry, &tgt->del_sess_list); | ||
| 498 | sess->deleted = 1; | ||
| 499 | 576 | ||
| 500 | if (immediate) | 577 | if (immediate) { |
| 501 | dev_loss_tmo = 0; | 578 | dev_loss_tmo = 0; |
| 579 | sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; | ||
| 580 | list_add(&sess->del_list_entry, &tgt->del_sess_list); | ||
| 581 | } else { | ||
| 582 | sess->deleted = QLA_SESS_DELETION_PENDING; | ||
| 583 | list_add_tail(&sess->del_list_entry, &tgt->del_sess_list); | ||
| 584 | } | ||
| 502 | 585 | ||
| 503 | sess->expires = jiffies + dev_loss_tmo * HZ; | 586 | sess->expires = jiffies + dev_loss_tmo * HZ; |
| 504 | 587 | ||
| 505 | ql_dbg(ql_dbg_tgt, sess->vha, 0xe048, | 588 | ql_dbg(ql_dbg_tgt, sess->vha, 0xe048, |
| 506 | "qla_target(%d): session for port %8phC (loop ID %d) scheduled for " | 589 | "qla_target(%d): session for port %8phC (loop ID %d s_id %02x:%02x:%02x)" |
| 507 | "deletion in %u secs (expires: %lu) immed: %d\n", | 590 | " scheduled for deletion in %u secs (expires: %lu) immed: %d, logout: %d, gen: %#x\n", |
| 508 | sess->vha->vp_idx, sess->port_name, sess->loop_id, dev_loss_tmo, | 591 | sess->vha->vp_idx, sess->port_name, sess->loop_id, |
| 509 | sess->expires, immediate); | 592 | sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa, |
| 593 | dev_loss_tmo, sess->expires, immediate, sess->logout_on_delete, | ||
| 594 | sess->generation); | ||
| 510 | 595 | ||
| 511 | if (immediate) | 596 | if (immediate) |
| 512 | schedule_delayed_work(&tgt->sess_del_work, 0); | 597 | mod_delayed_work(system_wq, &tgt->sess_del_work, 0); |
| 513 | else | 598 | else |
| 514 | schedule_delayed_work(&tgt->sess_del_work, | 599 | schedule_delayed_work(&tgt->sess_del_work, |
| 515 | sess->expires - jiffies); | 600 | sess->expires - jiffies); |
| @@ -578,9 +663,9 @@ out_free_id_list: | |||
| 578 | /* ha->hardware_lock supposed to be held on entry */ | 663 | /* ha->hardware_lock supposed to be held on entry */ |
| 579 | static void qlt_undelete_sess(struct qla_tgt_sess *sess) | 664 | static void qlt_undelete_sess(struct qla_tgt_sess *sess) |
| 580 | { | 665 | { |
| 581 | BUG_ON(!sess->deleted); | 666 | BUG_ON(sess->deleted != QLA_SESS_DELETION_PENDING); |
| 582 | 667 | ||
| 583 | list_del(&sess->del_list_entry); | 668 | list_del_init(&sess->del_list_entry); |
| 584 | sess->deleted = 0; | 669 | sess->deleted = 0; |
| 585 | } | 670 | } |
| 586 | 671 | ||
| @@ -599,7 +684,9 @@ static void qlt_del_sess_work_fn(struct delayed_work *work) | |||
| 599 | del_list_entry); | 684 | del_list_entry); |
| 600 | elapsed = jiffies; | 685 | elapsed = jiffies; |
| 601 | if (time_after_eq(elapsed, sess->expires)) { | 686 | if (time_after_eq(elapsed, sess->expires)) { |
| 602 | qlt_undelete_sess(sess); | 687 | /* No turning back */ |
| 688 | list_del_init(&sess->del_list_entry); | ||
| 689 | sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; | ||
| 603 | 690 | ||
| 604 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004, | 691 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004, |
| 605 | "Timeout: sess %p about to be deleted\n", | 692 | "Timeout: sess %p about to be deleted\n", |
| @@ -643,6 +730,13 @@ static struct qla_tgt_sess *qlt_create_sess( | |||
| 643 | fcport->d_id.b.al_pa, fcport->d_id.b.area, | 730 | fcport->d_id.b.al_pa, fcport->d_id.b.area, |
| 644 | fcport->loop_id); | 731 | fcport->loop_id); |
| 645 | 732 | ||
| 733 | /* Cannot undelete at this point */ | ||
| 734 | if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { | ||
| 735 | spin_unlock_irqrestore(&ha->hardware_lock, | ||
| 736 | flags); | ||
| 737 | return NULL; | ||
| 738 | } | ||
| 739 | |||
| 646 | if (sess->deleted) | 740 | if (sess->deleted) |
| 647 | qlt_undelete_sess(sess); | 741 | qlt_undelete_sess(sess); |
| 648 | 742 | ||
| @@ -652,6 +746,9 @@ static struct qla_tgt_sess *qlt_create_sess( | |||
| 652 | 746 | ||
| 653 | if (sess->local && !local) | 747 | if (sess->local && !local) |
| 654 | sess->local = 0; | 748 | sess->local = 0; |
| 749 | |||
| 750 | qlt_do_generation_tick(vha, &sess->generation); | ||
| 751 | |||
| 655 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 752 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| 656 | 753 | ||
| 657 | return sess; | 754 | return sess; |
| @@ -673,6 +770,14 @@ static struct qla_tgt_sess *qlt_create_sess( | |||
| 673 | sess->s_id = fcport->d_id; | 770 | sess->s_id = fcport->d_id; |
| 674 | sess->loop_id = fcport->loop_id; | 771 | sess->loop_id = fcport->loop_id; |
| 675 | sess->local = local; | 772 | sess->local = local; |
| 773 | INIT_LIST_HEAD(&sess->del_list_entry); | ||
| 774 | |||
| 775 | /* Under normal circumstances we want to logout from firmware when | ||
| 776 | * session eventually ends and release corresponding nport handle. | ||
| 777 | * In the exception cases (e.g. when new PLOGI is waiting) corresponding | ||
| 778 | * code will adjust these flags as necessary. */ | ||
| 779 | sess->logout_on_delete = 1; | ||
| 780 | sess->keep_nport_handle = 0; | ||
| 676 | 781 | ||
| 677 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf006, | 782 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf006, |
| 678 | "Adding sess %p to tgt %p via ->check_initiator_node_acl()\n", | 783 | "Adding sess %p to tgt %p via ->check_initiator_node_acl()\n", |
| @@ -705,6 +810,7 @@ static struct qla_tgt_sess *qlt_create_sess( | |||
| 705 | spin_lock_irqsave(&ha->hardware_lock, flags); | 810 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| 706 | list_add_tail(&sess->sess_list_entry, &vha->vha_tgt.qla_tgt->sess_list); | 811 | list_add_tail(&sess->sess_list_entry, &vha->vha_tgt.qla_tgt->sess_list); |
| 707 | vha->vha_tgt.qla_tgt->sess_count++; | 812 | vha->vha_tgt.qla_tgt->sess_count++; |
| 813 | qlt_do_generation_tick(vha, &sess->generation); | ||
| 708 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 814 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| 709 | 815 | ||
| 710 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b, | 816 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b, |
| @@ -718,7 +824,7 @@ static struct qla_tgt_sess *qlt_create_sess( | |||
| 718 | } | 824 | } |
| 719 | 825 | ||
| 720 | /* | 826 | /* |
| 721 | * Called from drivers/scsi/qla2xxx/qla_init.c:qla2x00_reg_remote_port() | 827 | * Called from qla2x00_reg_remote_port() |
| 722 | */ | 828 | */ |
| 723 | void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) | 829 | void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) |
| 724 | { | 830 | { |
| @@ -750,6 +856,10 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) | |||
| 750 | mutex_unlock(&vha->vha_tgt.tgt_mutex); | 856 | mutex_unlock(&vha->vha_tgt.tgt_mutex); |
| 751 | 857 | ||
| 752 | spin_lock_irqsave(&ha->hardware_lock, flags); | 858 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| 859 | } else if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { | ||
| 860 | /* Point of no return */ | ||
| 861 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
| 862 | return; | ||
| 753 | } else { | 863 | } else { |
| 754 | kref_get(&sess->se_sess->sess_kref); | 864 | kref_get(&sess->se_sess->sess_kref); |
| 755 | 865 | ||
| @@ -780,27 +890,36 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) | |||
| 780 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 890 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
| 781 | } | 891 | } |
| 782 | 892 | ||
| 783 | void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport) | 893 | /* |
| 894 | * max_gen - specifies maximum session generation | ||
| 895 | * at which this deletion requestion is still valid | ||
| 896 | */ | ||
| 897 | void | ||
| 898 | qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen) | ||
| 784 | { | 899 | { |
| 785 | struct qla_hw_data *ha = vha->hw; | ||
| 786 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; | 900 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
| 787 | struct qla_tgt_sess *sess; | 901 | struct qla_tgt_sess *sess; |
| 788 | unsigned long flags; | ||
| 789 | 902 | ||
| 790 | if (!vha->hw->tgt.tgt_ops) | 903 | if (!vha->hw->tgt.tgt_ops) |
| 791 | return; | 904 | return; |
| 792 | 905 | ||
| 793 | if (!tgt || (fcport->port_type != FCT_INITIATOR)) | 906 | if (!tgt) |
| 794 | return; | 907 | return; |
| 795 | 908 | ||
| 796 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
| 797 | if (tgt->tgt_stop) { | 909 | if (tgt->tgt_stop) { |
| 798 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
| 799 | return; | 910 | return; |
| 800 | } | 911 | } |
| 801 | sess = qlt_find_sess_by_port_name(tgt, fcport->port_name); | 912 | sess = qlt_find_sess_by_port_name(tgt, fcport->port_name); |
| 802 | if (!sess) { | 913 | if (!sess) { |
| 803 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 914 | return; |
| 915 | } | ||
| 916 | |||
| 917 | if (max_gen - sess->generation < 0) { | ||
| 918 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf092, | ||
| 919 | "Ignoring stale deletion request for se_sess %p / sess %p" | ||
| 920 | " for port %8phC, req_gen %d, sess_gen %d\n", | ||
| 921 | sess->se_sess, sess, sess->port_name, max_gen, | ||
| 922 | sess->generation); | ||
| 804 | return; | 923 | return; |
| 805 | } | 924 | } |
| 806 | 925 | ||
| @@ -808,7 +927,6 @@ void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport) | |||
| 808 | 927 | ||
| 809 | sess->local = 1; | 928 | sess->local = 1; |
| 810 | qlt_schedule_sess_for_deletion(sess, false); | 929 | qlt_schedule_sess_for_deletion(sess, false); |
| 811 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
| 812 | } | 930 | } |
| 813 | 931 | ||
| 814 | static inline int test_tgt_sess_count(struct qla_tgt *tgt) | 932 | static inline int test_tgt_sess_count(struct qla_tgt *tgt) |
| @@ -1175,6 +1293,70 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha, | |||
| 1175 | FCP_TMF_CMPL, true); | 1293 | FCP_TMF_CMPL, true); |
| 1176 | } | 1294 | } |
| 1177 | 1295 | ||
| 1296 | static int abort_cmd_for_tag(struct scsi_qla_host *vha, uint32_t tag) | ||
| 1297 | { | ||
| 1298 | struct qla_tgt_sess_op *op; | ||
| 1299 | struct qla_tgt_cmd *cmd; | ||
| 1300 | |||
| 1301 | spin_lock(&vha->cmd_list_lock); | ||
| 1302 | |||
| 1303 | list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) { | ||
| 1304 | if (tag == op->atio.u.isp24.exchange_addr) { | ||
| 1305 | op->aborted = true; | ||
| 1306 | spin_unlock(&vha->cmd_list_lock); | ||
| 1307 | return 1; | ||
| 1308 | } | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) { | ||
| 1312 | if (tag == cmd->atio.u.isp24.exchange_addr) { | ||
| 1313 | cmd->state = QLA_TGT_STATE_ABORTED; | ||
| 1314 | spin_unlock(&vha->cmd_list_lock); | ||
| 1315 | return 1; | ||
| 1316 | } | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | spin_unlock(&vha->cmd_list_lock); | ||
| 1320 | return 0; | ||
| 1321 | } | ||
| 1322 | |||
| 1323 | /* drop cmds for the given lun | ||
| 1324 | * XXX only looks for cmds on the port through which lun reset was recieved | ||
| 1325 | * XXX does not go through the list of other port (which may have cmds | ||
| 1326 | * for the same lun) | ||
| 1327 | */ | ||
| 1328 | static void abort_cmds_for_lun(struct scsi_qla_host *vha, | ||
| 1329 | uint32_t lun, uint8_t *s_id) | ||
| 1330 | { | ||
| 1331 | struct qla_tgt_sess_op *op; | ||
| 1332 | struct qla_tgt_cmd *cmd; | ||
| 1333 | uint32_t key; | ||
| 1334 | |||
| 1335 | key = sid_to_key(s_id); | ||
| 1336 | spin_lock(&vha->cmd_list_lock); | ||
| 1337 | list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) { | ||
| 1338 | uint32_t op_key; | ||
| 1339 | uint32_t op_lun; | ||
| 1340 | |||
| 1341 | op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id); | ||
| 1342 | op_lun = scsilun_to_int( | ||
| 1343 | (struct scsi_lun *)&op->atio.u.isp24.fcp_cmnd.lun); | ||
| 1344 | if (op_key == key && op_lun == lun) | ||
| 1345 | op->aborted = true; | ||
| 1346 | } | ||
| 1347 | list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) { | ||
| 1348 | uint32_t cmd_key; | ||
| 1349 | uint32_t cmd_lun; | ||
| 1350 | |||
| 1351 | cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id); | ||
| 1352 | cmd_lun = scsilun_to_int( | ||
| 1353 | (struct scsi_lun *)&cmd->atio.u.isp24.fcp_cmnd.lun); | ||
| 1354 | if (cmd_key == key && cmd_lun == lun) | ||
| 1355 | cmd->state = QLA_TGT_STATE_ABORTED; | ||
| 1356 | } | ||
| 1357 | spin_unlock(&vha->cmd_list_lock); | ||
| 1358 | } | ||
| 1359 | |||
| 1178 | /* ha->hardware_lock supposed to be held on entry */ | 1360 | /* ha->hardware_lock supposed to be held on entry */ |
| 1179 | static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, | 1361 | static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, |
| 1180 | struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess) | 1362 | struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess) |
| @@ -1191,7 +1373,7 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, | |||
| 1191 | list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) { | 1373 | list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) { |
| 1192 | struct qla_tgt_cmd *cmd = | 1374 | struct qla_tgt_cmd *cmd = |
| 1193 | container_of(se_cmd, struct qla_tgt_cmd, se_cmd); | 1375 | container_of(se_cmd, struct qla_tgt_cmd, se_cmd); |
| 1194 | if (cmd->tag == abts->exchange_addr_to_abort) { | 1376 | if (se_cmd->tag == abts->exchange_addr_to_abort) { |
| 1195 | lun = cmd->unpacked_lun; | 1377 | lun = cmd->unpacked_lun; |
| 1196 | found_lun = true; | 1378 | found_lun = true; |
| 1197 | break; | 1379 | break; |
| @@ -1199,8 +1381,19 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, | |||
| 1199 | } | 1381 | } |
| 1200 | spin_unlock(&se_sess->sess_cmd_lock); | 1382 | spin_unlock(&se_sess->sess_cmd_lock); |
| 1201 | 1383 | ||
| 1202 | if (!found_lun) | 1384 | /* cmd not in LIO lists, look in qla list */ |
| 1203 | return -ENOENT; | 1385 | if (!found_lun) { |
| 1386 | if (abort_cmd_for_tag(vha, abts->exchange_addr_to_abort)) { | ||
| 1387 | /* send TASK_ABORT response immediately */ | ||
| 1388 | qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_CMPL, false); | ||
| 1389 | return 0; | ||
| 1390 | } else { | ||
| 1391 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf081, | ||
| 1392 | "unable to find cmd in driver or LIO for tag 0x%x\n", | ||
| 1393 | abts->exchange_addr_to_abort); | ||
| 1394 | return -ENOENT; | ||
| 1395 | } | ||
| 1396 | } | ||
| 1204 | 1397 | ||
| 1205 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f, | 1398 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f, |
| 1206 | "qla_target(%d): task abort (tag=%d)\n", | 1399 | "qla_target(%d): task abort (tag=%d)\n", |
| @@ -1284,6 +1477,11 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha, | |||
| 1284 | return; | 1477 | return; |
| 1285 | } | 1478 | } |
| 1286 | 1479 | ||
| 1480 | if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { | ||
| 1481 | qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false); | ||
| 1482 | return; | ||
| 1483 | } | ||
| 1484 | |||
| 1287 | rc = __qlt_24xx_handle_abts(vha, abts, sess); | 1485 | rc = __qlt_24xx_handle_abts(vha, abts, sess); |
| 1288 | if (rc != 0) { | 1486 | if (rc != 0) { |
| 1289 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf054, | 1487 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf054, |
| @@ -1726,21 +1924,6 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd, | |||
| 1726 | struct qla_hw_data *ha = vha->hw; | 1924 | struct qla_hw_data *ha = vha->hw; |
| 1727 | struct se_cmd *se_cmd = &cmd->se_cmd; | 1925 | struct se_cmd *se_cmd = &cmd->se_cmd; |
| 1728 | 1926 | ||
| 1729 | if (unlikely(cmd->aborted)) { | ||
| 1730 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014, | ||
| 1731 | "qla_target(%d): terminating exchange " | ||
| 1732 | "for aborted cmd=%p (se_cmd=%p, tag=%d)", vha->vp_idx, cmd, | ||
| 1733 | se_cmd, cmd->tag); | ||
| 1734 | |||
| 1735 | cmd->state = QLA_TGT_STATE_ABORTED; | ||
| 1736 | cmd->cmd_flags |= BIT_6; | ||
| 1737 | |||
| 1738 | qlt_send_term_exchange(vha, cmd, &cmd->atio, 0); | ||
| 1739 | |||
| 1740 | /* !! At this point cmd could be already freed !! */ | ||
| 1741 | return QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED; | ||
| 1742 | } | ||
| 1743 | |||
| 1744 | prm->cmd = cmd; | 1927 | prm->cmd = cmd; |
| 1745 | prm->tgt = tgt; | 1928 | prm->tgt = tgt; |
| 1746 | prm->rq_result = scsi_status; | 1929 | prm->rq_result = scsi_status; |
| @@ -1765,18 +1948,17 @@ static int qlt_pre_xmit_response(struct qla_tgt_cmd *cmd, | |||
| 1765 | if (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { | 1948 | if (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { |
| 1766 | prm->residual = se_cmd->residual_count; | 1949 | prm->residual = se_cmd->residual_count; |
| 1767 | ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x305c, | 1950 | ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x305c, |
| 1768 | "Residual underflow: %d (tag %d, " | 1951 | "Residual underflow: %d (tag %lld, op %x, bufflen %d, rq_result %x)\n", |
| 1769 | "op %x, bufflen %d, rq_result %x)\n", prm->residual, | 1952 | prm->residual, se_cmd->tag, |
| 1770 | cmd->tag, se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0, | 1953 | se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0, |
| 1771 | cmd->bufflen, prm->rq_result); | 1954 | cmd->bufflen, prm->rq_result); |
| 1772 | prm->rq_result |= SS_RESIDUAL_UNDER; | 1955 | prm->rq_result |= SS_RESIDUAL_UNDER; |
| 1773 | } else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { | 1956 | } else if (se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) { |
| 1774 | prm->residual = se_cmd->residual_count; | 1957 | prm->residual = se_cmd->residual_count; |
| 1775 | ql_dbg(ql_dbg_io, vha, 0x305d, | 1958 | ql_dbg(ql_dbg_io, vha, 0x305d, |
| 1776 | "Residual overflow: %d (tag %d, " | 1959 | "Residual overflow: %d (tag %lld, op %x, bufflen %d, rq_result %x)\n", |
| 1777 | "op %x, bufflen %d, rq_result %x)\n", prm->residual, | 1960 | prm->residual, se_cmd->tag, se_cmd->t_task_cdb ? |
| 1778 | cmd->tag, se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0, | 1961 | se_cmd->t_task_cdb[0] : 0, cmd->bufflen, prm->rq_result); |
| 1779 | cmd->bufflen, prm->rq_result); | ||
| 1780 | prm->rq_result |= SS_RESIDUAL_OVER; | 1962 | prm->rq_result |= SS_RESIDUAL_OVER; |
| 1781 | } | 1963 | } |
| 1782 | 1964 | ||
| @@ -1849,7 +2031,7 @@ static void qlt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type) | |||
| 1849 | == 50) { | 2031 | == 50) { |
| 1850 | *xmit_type &= ~QLA_TGT_XMIT_STATUS; | 2032 | *xmit_type &= ~QLA_TGT_XMIT_STATUS; |
| 1851 | ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf015, | 2033 | ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf015, |
| 1852 | "Dropping cmd %p (tag %d) status", cmd, cmd->tag); | 2034 | "Dropping cmd %p (tag %d) status", cmd, se_cmd->tag); |
| 1853 | } | 2035 | } |
| 1854 | #endif | 2036 | #endif |
| 1855 | /* | 2037 | /* |
| @@ -1873,7 +2055,7 @@ static void qlt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type) | |||
| 1873 | ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf016, | 2055 | ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf016, |
| 1874 | "Cutting cmd %p (tag %d) buffer" | 2056 | "Cutting cmd %p (tag %d) buffer" |
| 1875 | " tail to len %d, sg_cnt %d (cmd->bufflen %d," | 2057 | " tail to len %d, sg_cnt %d (cmd->bufflen %d," |
| 1876 | " cmd->sg_cnt %d)", cmd, cmd->tag, tot_len, leave, | 2058 | " cmd->sg_cnt %d)", cmd, se_cmd->tag, tot_len, leave, |
| 1877 | cmd->bufflen, cmd->sg_cnt); | 2059 | cmd->bufflen, cmd->sg_cnt); |
| 1878 | 2060 | ||
| 1879 | cmd->bufflen = tot_len; | 2061 | cmd->bufflen = tot_len; |
| @@ -1885,13 +2067,13 @@ static void qlt_check_srr_debug(struct qla_tgt_cmd *cmd, int *xmit_type) | |||
| 1885 | 2067 | ||
| 1886 | ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf017, | 2068 | ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf017, |
| 1887 | "Cutting cmd %p (tag %d) buffer head " | 2069 | "Cutting cmd %p (tag %d) buffer head " |
| 1888 | "to offset %d (cmd->bufflen %d)", cmd, cmd->tag, offset, | 2070 | "to offset %d (cmd->bufflen %d)", cmd, se_cmd->tag, offset, |
| 1889 | cmd->bufflen); | 2071 | cmd->bufflen); |
| 1890 | if (offset == 0) | 2072 | if (offset == 0) |
| 1891 | *xmit_type &= ~QLA_TGT_XMIT_DATA; | 2073 | *xmit_type &= ~QLA_TGT_XMIT_DATA; |
| 1892 | else if (qlt_set_data_offset(cmd, offset)) { | 2074 | else if (qlt_set_data_offset(cmd, offset)) { |
| 1893 | ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf018, | 2075 | ql_dbg(ql_dbg_tgt_mgt, cmd->vha, 0xf018, |
| 1894 | "qlt_set_data_offset() failed (tag %d)", cmd->tag); | 2076 | "qlt_set_data_offset() failed (tag %d)", se_cmd->tag); |
| 1895 | } | 2077 | } |
| 1896 | } | 2078 | } |
| 1897 | } | 2079 | } |
| @@ -2303,6 +2485,19 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, | |||
| 2303 | unsigned long flags = 0; | 2485 | unsigned long flags = 0; |
| 2304 | int res; | 2486 | int res; |
| 2305 | 2487 | ||
| 2488 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
| 2489 | if (cmd->sess && cmd->sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { | ||
| 2490 | cmd->state = QLA_TGT_STATE_PROCESSED; | ||
| 2491 | if (cmd->sess->logout_completed) | ||
| 2492 | /* no need to terminate. FW already freed exchange. */ | ||
| 2493 | qlt_abort_cmd_on_host_reset(cmd->vha, cmd); | ||
| 2494 | else | ||
| 2495 | qlt_send_term_exchange(vha, cmd, &cmd->atio, 1); | ||
| 2496 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
| 2497 | return 0; | ||
| 2498 | } | ||
| 2499 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
| 2500 | |||
| 2306 | memset(&prm, 0, sizeof(prm)); | 2501 | memset(&prm, 0, sizeof(prm)); |
| 2307 | qlt_check_srr_debug(cmd, &xmit_type); | 2502 | qlt_check_srr_debug(cmd, &xmit_type); |
| 2308 | 2503 | ||
| @@ -2315,9 +2510,6 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, | |||
| 2315 | res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status, | 2510 | res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status, |
| 2316 | &full_req_cnt); | 2511 | &full_req_cnt); |
| 2317 | if (unlikely(res != 0)) { | 2512 | if (unlikely(res != 0)) { |
| 2318 | if (res == QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED) | ||
| 2319 | return 0; | ||
| 2320 | |||
| 2321 | return res; | 2513 | return res; |
| 2322 | } | 2514 | } |
| 2323 | 2515 | ||
| @@ -2347,9 +2539,10 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, | |||
| 2347 | res = qlt_build_ctio_crc2_pkt(&prm, vha); | 2539 | res = qlt_build_ctio_crc2_pkt(&prm, vha); |
| 2348 | else | 2540 | else |
| 2349 | res = qlt_24xx_build_ctio_pkt(&prm, vha); | 2541 | res = qlt_24xx_build_ctio_pkt(&prm, vha); |
| 2350 | if (unlikely(res != 0)) | 2542 | if (unlikely(res != 0)) { |
| 2543 | vha->req->cnt += full_req_cnt; | ||
| 2351 | goto out_unmap_unlock; | 2544 | goto out_unmap_unlock; |
| 2352 | 2545 | } | |
| 2353 | 2546 | ||
| 2354 | pkt = (struct ctio7_to_24xx *)prm.pkt; | 2547 | pkt = (struct ctio7_to_24xx *)prm.pkt; |
| 2355 | 2548 | ||
| @@ -2463,7 +2656,8 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) | |||
| 2463 | 2656 | ||
| 2464 | spin_lock_irqsave(&ha->hardware_lock, flags); | 2657 | spin_lock_irqsave(&ha->hardware_lock, flags); |
| 2465 | 2658 | ||
| 2466 | if (qla2x00_reset_active(vha) || cmd->reset_count != ha->chip_reset) { | 2659 | if (qla2x00_reset_active(vha) || (cmd->reset_count != ha->chip_reset) || |
| 2660 | (cmd->sess && cmd->sess->deleted == QLA_SESS_DELETION_IN_PROGRESS)) { | ||
| 2467 | /* | 2661 | /* |
| 2468 | * Either a chip reset is active or this request was from | 2662 | * Either a chip reset is active or this request was from |
| 2469 | * previous life, just abort the processing. | 2663 | * previous life, just abort the processing. |
| @@ -2487,8 +2681,11 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd) | |||
| 2487 | else | 2681 | else |
| 2488 | res = qlt_24xx_build_ctio_pkt(&prm, vha); | 2682 | res = qlt_24xx_build_ctio_pkt(&prm, vha); |
| 2489 | 2683 | ||
| 2490 | if (unlikely(res != 0)) | 2684 | if (unlikely(res != 0)) { |
| 2685 | vha->req->cnt += prm.req_cnt; | ||
| 2491 | goto out_unlock_free_unmap; | 2686 | goto out_unlock_free_unmap; |
| 2687 | } | ||
| 2688 | |||
| 2492 | pkt = (struct ctio7_to_24xx *)prm.pkt; | 2689 | pkt = (struct ctio7_to_24xx *)prm.pkt; |
| 2493 | pkt->u.status0.flags |= __constant_cpu_to_le16(CTIO7_FLAGS_DATA_OUT | | 2690 | pkt->u.status0.flags |= __constant_cpu_to_le16(CTIO7_FLAGS_DATA_OUT | |
| 2494 | CTIO7_FLAGS_STATUS_MODE_0); | 2691 | CTIO7_FLAGS_STATUS_MODE_0); |
| @@ -2653,6 +2850,89 @@ out: | |||
| 2653 | 2850 | ||
| 2654 | /* If hardware_lock held on entry, might drop it, then reaquire */ | 2851 | /* If hardware_lock held on entry, might drop it, then reaquire */ |
| 2655 | /* This function sends the appropriate CTIO to ISP 2xxx or 24xx */ | 2852 | /* This function sends the appropriate CTIO to ISP 2xxx or 24xx */ |
| 2853 | static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha, | ||
| 2854 | struct imm_ntfy_from_isp *ntfy) | ||
| 2855 | { | ||
| 2856 | struct nack_to_isp *nack; | ||
| 2857 | struct qla_hw_data *ha = vha->hw; | ||
| 2858 | request_t *pkt; | ||
| 2859 | int ret = 0; | ||
| 2860 | |||
| 2861 | ql_dbg(ql_dbg_tgt_tmr, vha, 0xe01c, | ||
| 2862 | "Sending TERM ELS CTIO (ha=%p)\n", ha); | ||
| 2863 | |||
| 2864 | pkt = (request_t *)qla2x00_alloc_iocbs_ready(vha, NULL); | ||
| 2865 | if (pkt == NULL) { | ||
| 2866 | ql_dbg(ql_dbg_tgt, vha, 0xe080, | ||
| 2867 | "qla_target(%d): %s failed: unable to allocate " | ||
| 2868 | "request packet\n", vha->vp_idx, __func__); | ||
| 2869 | return -ENOMEM; | ||
| 2870 | } | ||
| 2871 | |||
| 2872 | pkt->entry_type = NOTIFY_ACK_TYPE; | ||
| 2873 | pkt->entry_count = 1; | ||
| 2874 | pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; | ||
| 2875 | |||
| 2876 | nack = (struct nack_to_isp *)pkt; | ||
| 2877 | nack->ox_id = ntfy->ox_id; | ||
| 2878 | |||
| 2879 | nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle; | ||
| 2880 | if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) { | ||
| 2881 | nack->u.isp24.flags = ntfy->u.isp24.flags & | ||
| 2882 | __constant_cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB); | ||
| 2883 | } | ||
| 2884 | |||
| 2885 | /* terminate */ | ||
| 2886 | nack->u.isp24.flags |= | ||
| 2887 | __constant_cpu_to_le16(NOTIFY_ACK_FLAGS_TERMINATE); | ||
| 2888 | |||
| 2889 | nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id; | ||
| 2890 | nack->u.isp24.status = ntfy->u.isp24.status; | ||
| 2891 | nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode; | ||
| 2892 | nack->u.isp24.fw_handle = ntfy->u.isp24.fw_handle; | ||
| 2893 | nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address; | ||
| 2894 | nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs; | ||
| 2895 | nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui; | ||
| 2896 | nack->u.isp24.vp_index = ntfy->u.isp24.vp_index; | ||
| 2897 | |||
| 2898 | qla2x00_start_iocbs(vha, vha->req); | ||
| 2899 | return ret; | ||
| 2900 | } | ||
| 2901 | |||
| 2902 | static void qlt_send_term_imm_notif(struct scsi_qla_host *vha, | ||
| 2903 | struct imm_ntfy_from_isp *imm, int ha_locked) | ||
| 2904 | { | ||
| 2905 | unsigned long flags = 0; | ||
| 2906 | int rc; | ||
| 2907 | |||
| 2908 | if (qlt_issue_marker(vha, ha_locked) < 0) | ||
| 2909 | return; | ||
| 2910 | |||
| 2911 | if (ha_locked) { | ||
| 2912 | rc = __qlt_send_term_imm_notif(vha, imm); | ||
| 2913 | |||
| 2914 | #if 0 /* Todo */ | ||
| 2915 | if (rc == -ENOMEM) | ||
| 2916 | qlt_alloc_qfull_cmd(vha, imm, 0, 0); | ||
| 2917 | #endif | ||
| 2918 | goto done; | ||
| 2919 | } | ||
| 2920 | |||
| 2921 | spin_lock_irqsave(&vha->hw->hardware_lock, flags); | ||
| 2922 | rc = __qlt_send_term_imm_notif(vha, imm); | ||
| 2923 | |||
| 2924 | #if 0 /* Todo */ | ||
| 2925 | if (rc == -ENOMEM) | ||
| 2926 | qlt_alloc_qfull_cmd(vha, imm, 0, 0); | ||
| 2927 | #endif | ||
| 2928 | |||
| 2929 | done: | ||
| 2930 | if (!ha_locked) | ||
| 2931 | spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); | ||
| 2932 | } | ||
| 2933 | |||
| 2934 | /* If hardware_lock held on entry, might drop it, then reaquire */ | ||
| 2935 | /* This function sends the appropriate CTIO to ISP 2xxx or 24xx */ | ||
| 2656 | static int __qlt_send_term_exchange(struct scsi_qla_host *vha, | 2936 | static int __qlt_send_term_exchange(struct scsi_qla_host *vha, |
| 2657 | struct qla_tgt_cmd *cmd, | 2937 | struct qla_tgt_cmd *cmd, |
| 2658 | struct atio_from_isp *atio) | 2938 | struct atio_from_isp *atio) |
| @@ -2717,7 +2997,7 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha, | |||
| 2717 | static void qlt_send_term_exchange(struct scsi_qla_host *vha, | 2997 | static void qlt_send_term_exchange(struct scsi_qla_host *vha, |
| 2718 | struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked) | 2998 | struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked) |
| 2719 | { | 2999 | { |
| 2720 | unsigned long flags; | 3000 | unsigned long flags = 0; |
| 2721 | int rc; | 3001 | int rc; |
| 2722 | 3002 | ||
| 2723 | if (qlt_issue_marker(vha, ha_locked) < 0) | 3003 | if (qlt_issue_marker(vha, ha_locked) < 0) |
| @@ -2733,17 +3013,18 @@ static void qlt_send_term_exchange(struct scsi_qla_host *vha, | |||
| 2733 | rc = __qlt_send_term_exchange(vha, cmd, atio); | 3013 | rc = __qlt_send_term_exchange(vha, cmd, atio); |
| 2734 | if (rc == -ENOMEM) | 3014 | if (rc == -ENOMEM) |
| 2735 | qlt_alloc_qfull_cmd(vha, atio, 0, 0); | 3015 | qlt_alloc_qfull_cmd(vha, atio, 0, 0); |
| 2736 | spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); | ||
| 2737 | 3016 | ||
| 2738 | done: | 3017 | done: |
| 2739 | if (cmd && ((cmd->state != QLA_TGT_STATE_ABORTED) || | 3018 | if (cmd && ((cmd->state != QLA_TGT_STATE_ABORTED) || |
| 2740 | !cmd->cmd_sent_to_fw)) { | 3019 | !cmd->cmd_sent_to_fw)) { |
| 2741 | if (!ha_locked && !in_interrupt()) | 3020 | if (cmd->sg_mapped) |
| 2742 | msleep(250); /* just in case */ | 3021 | qlt_unmap_sg(vha, cmd); |
| 2743 | |||
| 2744 | qlt_unmap_sg(vha, cmd); | ||
| 2745 | vha->hw->tgt.tgt_ops->free_cmd(cmd); | 3022 | vha->hw->tgt.tgt_ops->free_cmd(cmd); |
| 2746 | } | 3023 | } |
| 3024 | |||
| 3025 | if (!ha_locked) | ||
| 3026 | spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); | ||
| 3027 | |||
| 2747 | return; | 3028 | return; |
| 2748 | } | 3029 | } |
| 2749 | 3030 | ||
| @@ -2794,6 +3075,24 @@ static void qlt_chk_exch_leak_thresh_hold(struct scsi_qla_host *vha) | |||
| 2794 | 3075 | ||
| 2795 | } | 3076 | } |
| 2796 | 3077 | ||
| 3078 | void qlt_abort_cmd(struct qla_tgt_cmd *cmd) | ||
| 3079 | { | ||
| 3080 | struct qla_tgt *tgt = cmd->tgt; | ||
| 3081 | struct scsi_qla_host *vha = tgt->vha; | ||
| 3082 | struct se_cmd *se_cmd = &cmd->se_cmd; | ||
| 3083 | |||
| 3084 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014, | ||
| 3085 | "qla_target(%d): terminating exchange for aborted cmd=%p " | ||
| 3086 | "(se_cmd=%p, tag=%llu)", vha->vp_idx, cmd, &cmd->se_cmd, | ||
| 3087 | se_cmd->tag); | ||
| 3088 | |||
| 3089 | cmd->state = QLA_TGT_STATE_ABORTED; | ||
| 3090 | cmd->cmd_flags |= BIT_6; | ||
| 3091 | |||
| 3092 | qlt_send_term_exchange(vha, cmd, &cmd->atio, 0); | ||
| 3093 | } | ||
| 3094 | EXPORT_SYMBOL(qlt_abort_cmd); | ||
| 3095 | |||
| 2797 | void qlt_free_cmd(struct qla_tgt_cmd *cmd) | 3096 | void qlt_free_cmd(struct qla_tgt_cmd *cmd) |
| 2798 | { | 3097 | { |
| 2799 | struct qla_tgt_sess *sess = cmd->sess; | 3098 | struct qla_tgt_sess *sess = cmd->sess; |
| @@ -3017,7 +3316,7 @@ qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd) | |||
| 3017 | dump_stack(); | 3316 | dump_stack(); |
| 3018 | } | 3317 | } |
| 3019 | 3318 | ||
| 3020 | cmd->cmd_flags |= BIT_12; | 3319 | cmd->cmd_flags |= BIT_17; |
| 3021 | ha->tgt.tgt_ops->free_cmd(cmd); | 3320 | ha->tgt.tgt_ops->free_cmd(cmd); |
| 3022 | } | 3321 | } |
| 3023 | 3322 | ||
| @@ -3179,7 +3478,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle, | |||
| 3179 | skip_term: | 3478 | skip_term: |
| 3180 | 3479 | ||
| 3181 | if (cmd->state == QLA_TGT_STATE_PROCESSED) { | 3480 | if (cmd->state == QLA_TGT_STATE_PROCESSED) { |
| 3182 | ; | 3481 | cmd->cmd_flags |= BIT_12; |
| 3183 | } else if (cmd->state == QLA_TGT_STATE_NEED_DATA) { | 3482 | } else if (cmd->state == QLA_TGT_STATE_NEED_DATA) { |
| 3184 | int rx_status = 0; | 3483 | int rx_status = 0; |
| 3185 | 3484 | ||
| @@ -3193,9 +3492,11 @@ skip_term: | |||
| 3193 | ha->tgt.tgt_ops->handle_data(cmd); | 3492 | ha->tgt.tgt_ops->handle_data(cmd); |
| 3194 | return; | 3493 | return; |
| 3195 | } else if (cmd->state == QLA_TGT_STATE_ABORTED) { | 3494 | } else if (cmd->state == QLA_TGT_STATE_ABORTED) { |
| 3495 | cmd->cmd_flags |= BIT_18; | ||
| 3196 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01e, | 3496 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01e, |
| 3197 | "Aborted command %p (tag %d) finished\n", cmd, cmd->tag); | 3497 | "Aborted command %p (tag %lld) finished\n", cmd, se_cmd->tag); |
| 3198 | } else { | 3498 | } else { |
| 3499 | cmd->cmd_flags |= BIT_19; | ||
| 3199 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05c, | 3500 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05c, |
| 3200 | "qla_target(%d): A command in state (%d) should " | 3501 | "qla_target(%d): A command in state (%d) should " |
| 3201 | "not return a CTIO complete\n", vha->vp_idx, cmd->state); | 3502 | "not return a CTIO complete\n", vha->vp_idx, cmd->state); |
| @@ -3207,7 +3508,6 @@ skip_term: | |||
| 3207 | dump_stack(); | 3508 | dump_stack(); |
| 3208 | } | 3509 | } |
| 3209 | 3510 | ||
| 3210 | |||
| 3211 | ha->tgt.tgt_ops->free_cmd(cmd); | 3511 | ha->tgt.tgt_ops->free_cmd(cmd); |
| 3212 | } | 3512 | } |
| 3213 | 3513 | ||
| @@ -3265,8 +3565,15 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) | |||
| 3265 | if (tgt->tgt_stop) | 3565 | if (tgt->tgt_stop) |
| 3266 | goto out_term; | 3566 | goto out_term; |
| 3267 | 3567 | ||
| 3568 | if (cmd->state == QLA_TGT_STATE_ABORTED) { | ||
| 3569 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf082, | ||
| 3570 | "cmd with tag %u is aborted\n", | ||
| 3571 | cmd->atio.u.isp24.exchange_addr); | ||
| 3572 | goto out_term; | ||
| 3573 | } | ||
| 3574 | |||
| 3268 | cdb = &atio->u.isp24.fcp_cmnd.cdb[0]; | 3575 | cdb = &atio->u.isp24.fcp_cmnd.cdb[0]; |
| 3269 | cmd->tag = atio->u.isp24.exchange_addr; | 3576 | cmd->se_cmd.tag = atio->u.isp24.exchange_addr; |
| 3270 | cmd->unpacked_lun = scsilun_to_int( | 3577 | cmd->unpacked_lun = scsilun_to_int( |
| 3271 | (struct scsi_lun *)&atio->u.isp24.fcp_cmnd.lun); | 3578 | (struct scsi_lun *)&atio->u.isp24.fcp_cmnd.lun); |
| 3272 | 3579 | ||
| @@ -3318,6 +3625,12 @@ out_term: | |||
| 3318 | static void qlt_do_work(struct work_struct *work) | 3625 | static void qlt_do_work(struct work_struct *work) |
| 3319 | { | 3626 | { |
| 3320 | struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); | 3627 | struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); |
| 3628 | scsi_qla_host_t *vha = cmd->vha; | ||
| 3629 | unsigned long flags; | ||
| 3630 | |||
| 3631 | spin_lock_irqsave(&vha->cmd_list_lock, flags); | ||
| 3632 | list_del(&cmd->cmd_list); | ||
| 3633 | spin_unlock_irqrestore(&vha->cmd_list_lock, flags); | ||
| 3321 | 3634 | ||
| 3322 | __qlt_do_work(cmd); | 3635 | __qlt_do_work(cmd); |
| 3323 | } | 3636 | } |
| @@ -3347,6 +3660,11 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha, | |||
| 3347 | cmd->loop_id = sess->loop_id; | 3660 | cmd->loop_id = sess->loop_id; |
| 3348 | cmd->conf_compl_supported = sess->conf_compl_supported; | 3661 | cmd->conf_compl_supported = sess->conf_compl_supported; |
| 3349 | 3662 | ||
| 3663 | cmd->cmd_flags = 0; | ||
| 3664 | cmd->jiffies_at_alloc = get_jiffies_64(); | ||
| 3665 | |||
| 3666 | cmd->reset_count = vha->hw->chip_reset; | ||
| 3667 | |||
| 3350 | return cmd; | 3668 | return cmd; |
| 3351 | } | 3669 | } |
| 3352 | 3670 | ||
| @@ -3364,14 +3682,25 @@ static void qlt_create_sess_from_atio(struct work_struct *work) | |||
| 3364 | unsigned long flags; | 3682 | unsigned long flags; |
| 3365 | uint8_t *s_id = op->atio.u.isp24.fcp_hdr.s_id; | 3683 | uint8_t *s_id = op->atio.u.isp24.fcp_hdr.s_id; |
| 3366 | 3684 | ||
| 3685 | spin_lock_irqsave(&vha->cmd_list_lock, flags); | ||
| 3686 | list_del(&op->cmd_list); | ||
| 3687 | spin_unlock_irqrestore(&vha->cmd_list_lock, flags); | ||
| 3688 | |||
| 3689 | if (op->aborted) { | ||
| 3690 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf083, | ||
| 3691 | "sess_op with tag %u is aborted\n", | ||
| 3692 | op->atio.u.isp24.exchange_addr); | ||
| 3693 | goto out_term; | ||
| 3694 | } | ||
| 3695 | |||
| 3367 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022, | 3696 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022, |
| 3368 | "qla_target(%d): Unable to find wwn login" | 3697 | "qla_target(%d): Unable to find wwn login" |
| 3369 | " (s_id %x:%x:%x), trying to create it manually\n", | 3698 | " (s_id %x:%x:%x), trying to create it manually\n", |
| 3370 | vha->vp_idx, s_id[0], s_id[1], s_id[2]); | 3699 | vha->vp_idx, s_id[0], s_id[1], s_id[2]); |
| 3371 | 3700 | ||
| 3372 | if (op->atio.u.raw.entry_count > 1) { | 3701 | if (op->atio.u.raw.entry_count > 1) { |
| 3373 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023, | 3702 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023, |
| 3374 | "Dropping multy entry atio %p\n", &op->atio); | 3703 | "Dropping multy entry atio %p\n", &op->atio); |
| 3375 | goto out_term; | 3704 | goto out_term; |
| 3376 | } | 3705 | } |
| 3377 | 3706 | ||
| @@ -3436,10 +3765,25 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, | |||
| 3436 | 3765 | ||
| 3437 | memcpy(&op->atio, atio, sizeof(*atio)); | 3766 | memcpy(&op->atio, atio, sizeof(*atio)); |
| 3438 | op->vha = vha; | 3767 | op->vha = vha; |
| 3768 | |||
| 3769 | spin_lock(&vha->cmd_list_lock); | ||
| 3770 | list_add_tail(&op->cmd_list, &vha->qla_sess_op_cmd_list); | ||
| 3771 | spin_unlock(&vha->cmd_list_lock); | ||
| 3772 | |||
| 3439 | INIT_WORK(&op->work, qlt_create_sess_from_atio); | 3773 | INIT_WORK(&op->work, qlt_create_sess_from_atio); |
| 3440 | queue_work(qla_tgt_wq, &op->work); | 3774 | queue_work(qla_tgt_wq, &op->work); |
| 3441 | return 0; | 3775 | return 0; |
| 3442 | } | 3776 | } |
| 3777 | |||
| 3778 | /* Another WWN used to have our s_id. Our PLOGI scheduled its | ||
| 3779 | * session deletion, but it's still in sess_del_work wq */ | ||
| 3780 | if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { | ||
| 3781 | ql_dbg(ql_dbg_io, vha, 0x3061, | ||
| 3782 | "New command while old session %p is being deleted\n", | ||
| 3783 | sess); | ||
| 3784 | return -EFAULT; | ||
| 3785 | } | ||
| 3786 | |||
| 3443 | /* | 3787 | /* |
| 3444 | * Do kref_get() before returning + dropping qla_hw_data->hardware_lock. | 3788 | * Do kref_get() before returning + dropping qla_hw_data->hardware_lock. |
| 3445 | */ | 3789 | */ |
| @@ -3453,13 +3797,13 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, | |||
| 3453 | return -ENOMEM; | 3797 | return -ENOMEM; |
| 3454 | } | 3798 | } |
| 3455 | 3799 | ||
| 3456 | cmd->cmd_flags = 0; | ||
| 3457 | cmd->jiffies_at_alloc = get_jiffies_64(); | ||
| 3458 | |||
| 3459 | cmd->reset_count = vha->hw->chip_reset; | ||
| 3460 | |||
| 3461 | cmd->cmd_in_wq = 1; | 3800 | cmd->cmd_in_wq = 1; |
| 3462 | cmd->cmd_flags |= BIT_0; | 3801 | cmd->cmd_flags |= BIT_0; |
| 3802 | |||
| 3803 | spin_lock(&vha->cmd_list_lock); | ||
| 3804 | list_add_tail(&cmd->cmd_list, &vha->qla_cmd_list); | ||
| 3805 | spin_unlock(&vha->cmd_list_lock); | ||
| 3806 | |||
| 3463 | INIT_WORK(&cmd->work, qlt_do_work); | 3807 | INIT_WORK(&cmd->work, qlt_do_work); |
| 3464 | queue_work(qla_tgt_wq, &cmd->work); | 3808 | queue_work(qla_tgt_wq, &cmd->work); |
| 3465 | return 0; | 3809 | return 0; |
| @@ -3473,6 +3817,7 @@ static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun, | |||
| 3473 | struct scsi_qla_host *vha = sess->vha; | 3817 | struct scsi_qla_host *vha = sess->vha; |
| 3474 | struct qla_hw_data *ha = vha->hw; | 3818 | struct qla_hw_data *ha = vha->hw; |
| 3475 | struct qla_tgt_mgmt_cmd *mcmd; | 3819 | struct qla_tgt_mgmt_cmd *mcmd; |
| 3820 | struct atio_from_isp *a = (struct atio_from_isp *)iocb; | ||
| 3476 | int res; | 3821 | int res; |
| 3477 | uint8_t tmr_func; | 3822 | uint8_t tmr_func; |
| 3478 | 3823 | ||
| @@ -3513,6 +3858,7 @@ static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun, | |||
| 3513 | ql_dbg(ql_dbg_tgt_tmr, vha, 0x10002, | 3858 | ql_dbg(ql_dbg_tgt_tmr, vha, 0x10002, |
| 3514 | "qla_target(%d): LUN_RESET received\n", sess->vha->vp_idx); | 3859 | "qla_target(%d): LUN_RESET received\n", sess->vha->vp_idx); |
| 3515 | tmr_func = TMR_LUN_RESET; | 3860 | tmr_func = TMR_LUN_RESET; |
| 3861 | abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id); | ||
| 3516 | break; | 3862 | break; |
| 3517 | 3863 | ||
| 3518 | case QLA_TGT_CLEAR_TS: | 3864 | case QLA_TGT_CLEAR_TS: |
| @@ -3601,6 +3947,9 @@ static int qlt_handle_task_mgmt(struct scsi_qla_host *vha, void *iocb) | |||
| 3601 | sizeof(struct atio_from_isp)); | 3947 | sizeof(struct atio_from_isp)); |
| 3602 | } | 3948 | } |
| 3603 | 3949 | ||
| 3950 | if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) | ||
| 3951 | return -EFAULT; | ||
| 3952 | |||
| 3604 | return qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0); | 3953 | return qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0); |
| 3605 | } | 3954 | } |
| 3606 | 3955 | ||
| @@ -3666,22 +4015,280 @@ static int qlt_abort_task(struct scsi_qla_host *vha, | |||
| 3666 | return __qlt_abort_task(vha, iocb, sess); | 4015 | return __qlt_abort_task(vha, iocb, sess); |
| 3667 | } | 4016 | } |
| 3668 | 4017 | ||
| 4018 | void qlt_logo_completion_handler(fc_port_t *fcport, int rc) | ||
| 4019 | { | ||
| 4020 | if (fcport->tgt_session) { | ||
| 4021 | if (rc != MBS_COMMAND_COMPLETE) { | ||
| 4022 | ql_dbg(ql_dbg_tgt_mgt, fcport->vha, 0xf093, | ||
| 4023 | "%s: se_sess %p / sess %p from" | ||
| 4024 | " port %8phC loop_id %#04x s_id %02x:%02x:%02x" | ||
| 4025 | " LOGO failed: %#x\n", | ||
| 4026 | __func__, | ||
| 4027 | fcport->tgt_session->se_sess, | ||
| 4028 | fcport->tgt_session, | ||
| 4029 | fcport->port_name, fcport->loop_id, | ||
| 4030 | fcport->d_id.b.domain, fcport->d_id.b.area, | ||
| 4031 | fcport->d_id.b.al_pa, rc); | ||
| 4032 | } | ||
| 4033 | |||
| 4034 | fcport->tgt_session->logout_completed = 1; | ||
| 4035 | } | ||
| 4036 | } | ||
| 4037 | |||
| 4038 | static void qlt_swap_imm_ntfy_iocb(struct imm_ntfy_from_isp *a, | ||
| 4039 | struct imm_ntfy_from_isp *b) | ||
| 4040 | { | ||
| 4041 | struct imm_ntfy_from_isp tmp; | ||
| 4042 | memcpy(&tmp, a, sizeof(struct imm_ntfy_from_isp)); | ||
| 4043 | memcpy(a, b, sizeof(struct imm_ntfy_from_isp)); | ||
| 4044 | memcpy(b, &tmp, sizeof(struct imm_ntfy_from_isp)); | ||
| 4045 | } | ||
| 4046 | |||
| 4047 | /* | ||
| 4048 | * ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) | ||
| 4049 | * | ||
| 4050 | * Schedules sessions with matching port_id/loop_id but different wwn for | ||
| 4051 | * deletion. Returns existing session with matching wwn if present. | ||
| 4052 | * Null otherwise. | ||
| 4053 | */ | ||
| 4054 | static struct qla_tgt_sess * | ||
| 4055 | qlt_find_sess_invalidate_other(struct qla_tgt *tgt, uint64_t wwn, | ||
| 4056 | port_id_t port_id, uint16_t loop_id) | ||
| 4057 | { | ||
| 4058 | struct qla_tgt_sess *sess = NULL, *other_sess; | ||
| 4059 | uint64_t other_wwn; | ||
| 4060 | |||
| 4061 | list_for_each_entry(other_sess, &tgt->sess_list, sess_list_entry) { | ||
| 4062 | |||
| 4063 | other_wwn = wwn_to_u64(other_sess->port_name); | ||
| 4064 | |||
| 4065 | if (wwn == other_wwn) { | ||
| 4066 | WARN_ON(sess); | ||
| 4067 | sess = other_sess; | ||
| 4068 | continue; | ||
| 4069 | } | ||
| 4070 | |||
| 4071 | /* find other sess with nport_id collision */ | ||
| 4072 | if (port_id.b24 == other_sess->s_id.b24) { | ||
| 4073 | if (loop_id != other_sess->loop_id) { | ||
| 4074 | ql_dbg(ql_dbg_tgt_tmr, tgt->vha, 0x1000c, | ||
| 4075 | "Invalidating sess %p loop_id %d wwn %llx.\n", | ||
| 4076 | other_sess, other_sess->loop_id, other_wwn); | ||
| 4077 | |||
| 4078 | /* | ||
| 4079 | * logout_on_delete is set by default, but another | ||
| 4080 | * session that has the same s_id/loop_id combo | ||
| 4081 | * might have cleared it when requested this session | ||
| 4082 | * deletion, so don't touch it | ||
| 4083 | */ | ||
| 4084 | qlt_schedule_sess_for_deletion(other_sess, true); | ||
| 4085 | } else { | ||
| 4086 | /* | ||
| 4087 | * Another wwn used to have our s_id/loop_id | ||
| 4088 | * combo - kill the session, but don't log out | ||
| 4089 | */ | ||
| 4090 | sess->logout_on_delete = 0; | ||
| 4091 | qlt_schedule_sess_for_deletion(other_sess, | ||
| 4092 | true); | ||
| 4093 | } | ||
| 4094 | continue; | ||
| 4095 | } | ||
| 4096 | |||
| 4097 | /* find other sess with nport handle collision */ | ||
| 4098 | if (loop_id == other_sess->loop_id) { | ||
| 4099 | ql_dbg(ql_dbg_tgt_tmr, tgt->vha, 0x1000d, | ||
| 4100 | "Invalidating sess %p loop_id %d wwn %llx.\n", | ||
| 4101 | other_sess, other_sess->loop_id, other_wwn); | ||
| 4102 | |||
| 4103 | /* Same loop_id but different s_id | ||
| 4104 | * Ok to kill and logout */ | ||
| 4105 | qlt_schedule_sess_for_deletion(other_sess, true); | ||
| 4106 | } | ||
| 4107 | } | ||
| 4108 | |||
| 4109 | return sess; | ||
| 4110 | } | ||
| 4111 | |||
| 4112 | /* Abort any commands for this s_id waiting on qla_tgt_wq workqueue */ | ||
| 4113 | static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id) | ||
| 4114 | { | ||
| 4115 | struct qla_tgt_sess_op *op; | ||
| 4116 | struct qla_tgt_cmd *cmd; | ||
| 4117 | uint32_t key; | ||
| 4118 | int count = 0; | ||
| 4119 | |||
| 4120 | key = (((u32)s_id->b.domain << 16) | | ||
| 4121 | ((u32)s_id->b.area << 8) | | ||
| 4122 | ((u32)s_id->b.al_pa)); | ||
| 4123 | |||
| 4124 | spin_lock(&vha->cmd_list_lock); | ||
| 4125 | list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) { | ||
| 4126 | uint32_t op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id); | ||
| 4127 | if (op_key == key) { | ||
| 4128 | op->aborted = true; | ||
| 4129 | count++; | ||
| 4130 | } | ||
| 4131 | } | ||
| 4132 | list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) { | ||
| 4133 | uint32_t cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id); | ||
| 4134 | if (cmd_key == key) { | ||
| 4135 | cmd->state = QLA_TGT_STATE_ABORTED; | ||
| 4136 | count++; | ||
| 4137 | } | ||
| 4138 | } | ||
| 4139 | spin_unlock(&vha->cmd_list_lock); | ||
| 4140 | |||
| 4141 | return count; | ||
| 4142 | } | ||
| 4143 | |||
| 3669 | /* | 4144 | /* |
| 3670 | * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire | 4145 | * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire |
| 3671 | */ | 4146 | */ |
| 3672 | static int qlt_24xx_handle_els(struct scsi_qla_host *vha, | 4147 | static int qlt_24xx_handle_els(struct scsi_qla_host *vha, |
| 3673 | struct imm_ntfy_from_isp *iocb) | 4148 | struct imm_ntfy_from_isp *iocb) |
| 3674 | { | 4149 | { |
| 4150 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; | ||
| 4151 | struct qla_hw_data *ha = vha->hw; | ||
| 4152 | struct qla_tgt_sess *sess = NULL; | ||
| 4153 | uint64_t wwn; | ||
| 4154 | port_id_t port_id; | ||
| 4155 | uint16_t loop_id; | ||
| 4156 | uint16_t wd3_lo; | ||
| 3675 | int res = 0; | 4157 | int res = 0; |
| 3676 | 4158 | ||
| 4159 | wwn = wwn_to_u64(iocb->u.isp24.port_name); | ||
| 4160 | |||
| 4161 | port_id.b.domain = iocb->u.isp24.port_id[2]; | ||
| 4162 | port_id.b.area = iocb->u.isp24.port_id[1]; | ||
| 4163 | port_id.b.al_pa = iocb->u.isp24.port_id[0]; | ||
| 4164 | port_id.b.rsvd_1 = 0; | ||
| 4165 | |||
| 4166 | loop_id = le16_to_cpu(iocb->u.isp24.nport_handle); | ||
| 4167 | |||
| 3677 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf026, | 4168 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf026, |
| 3678 | "qla_target(%d): Port ID: 0x%3phC ELS opcode: 0x%02x\n", | 4169 | "qla_target(%d): Port ID: 0x%3phC ELS opcode: 0x%02x\n", |
| 3679 | vha->vp_idx, iocb->u.isp24.port_id, iocb->u.isp24.status_subcode); | 4170 | vha->vp_idx, iocb->u.isp24.port_id, iocb->u.isp24.status_subcode); |
| 3680 | 4171 | ||
| 4172 | /* res = 1 means ack at the end of thread | ||
| 4173 | * res = 0 means ack async/later. | ||
| 4174 | */ | ||
| 3681 | switch (iocb->u.isp24.status_subcode) { | 4175 | switch (iocb->u.isp24.status_subcode) { |
| 3682 | case ELS_PLOGI: | 4176 | case ELS_PLOGI: |
| 3683 | case ELS_FLOGI: | 4177 | |
| 4178 | /* Mark all stale commands in qla_tgt_wq for deletion */ | ||
| 4179 | abort_cmds_for_s_id(vha, &port_id); | ||
| 4180 | |||
| 4181 | if (wwn) | ||
| 4182 | sess = qlt_find_sess_invalidate_other(tgt, wwn, | ||
| 4183 | port_id, loop_id); | ||
| 4184 | |||
| 4185 | if (!sess || IS_SW_RESV_ADDR(sess->s_id)) { | ||
| 4186 | res = 1; | ||
| 4187 | break; | ||
| 4188 | } | ||
| 4189 | |||
| 4190 | if (sess->plogi_ack_needed) { | ||
| 4191 | /* | ||
| 4192 | * Initiator sent another PLOGI before last PLOGI could | ||
| 4193 | * finish. Swap plogi iocbs and terminate old one | ||
| 4194 | * without acking, new one will get acked when session | ||
| 4195 | * deletion completes. | ||
| 4196 | */ | ||
| 4197 | ql_log(ql_log_warn, sess->vha, 0xf094, | ||
| 4198 | "sess %p received double plogi.\n", sess); | ||
| 4199 | |||
| 4200 | qlt_swap_imm_ntfy_iocb(iocb, &sess->tm_iocb); | ||
| 4201 | |||
| 4202 | qlt_send_term_imm_notif(vha, iocb, 1); | ||
| 4203 | |||
| 4204 | res = 0; | ||
| 4205 | break; | ||
| 4206 | } | ||
| 4207 | |||
| 4208 | res = 0; | ||
| 4209 | |||
| 4210 | /* | ||
| 4211 | * Save immediate Notif IOCB for Ack when sess is done | ||
| 4212 | * and being deleted. | ||
| 4213 | */ | ||
| 4214 | memcpy(&sess->tm_iocb, iocb, sizeof(sess->tm_iocb)); | ||
| 4215 | sess->plogi_ack_needed = 1; | ||
| 4216 | |||
| 4217 | /* | ||
| 4218 | * Under normal circumstances we want to release nport handle | ||
| 4219 | * during LOGO process to avoid nport handle leaks inside FW. | ||
| 4220 | * The exception is when LOGO is done while another PLOGI with | ||
| 4221 | * the same nport handle is waiting as might be the case here. | ||
| 4222 | * Note: there is always a possibily of a race where session | ||
| 4223 | * deletion has already started for other reasons (e.g. ACL | ||
| 4224 | * removal) and now PLOGI arrives: | ||
| 4225 | * 1. if PLOGI arrived in FW after nport handle has been freed, | ||
| 4226 | * FW must have assigned this PLOGI a new/same handle and we | ||
| 4227 | * can proceed ACK'ing it as usual when session deletion | ||
| 4228 | * completes. | ||
| 4229 | * 2. if PLOGI arrived in FW before LOGO with LCF_FREE_NPORT | ||
| 4230 | * bit reached it, the handle has now been released. We'll | ||
| 4231 | * get an error when we ACK this PLOGI. Nothing will be sent | ||
| 4232 | * back to initiator. Initiator should eventually retry | ||
| 4233 | * PLOGI and situation will correct itself. | ||
| 4234 | */ | ||
| 4235 | sess->keep_nport_handle = ((sess->loop_id == loop_id) && | ||
| 4236 | (sess->s_id.b24 == port_id.b24)); | ||
| 4237 | qlt_schedule_sess_for_deletion(sess, true); | ||
| 4238 | break; | ||
| 4239 | |||
| 3684 | case ELS_PRLI: | 4240 | case ELS_PRLI: |
| 4241 | wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo); | ||
| 4242 | |||
| 4243 | if (wwn) | ||
| 4244 | sess = qlt_find_sess_invalidate_other(tgt, wwn, port_id, | ||
| 4245 | loop_id); | ||
| 4246 | |||
| 4247 | if (sess != NULL) { | ||
| 4248 | if (sess->deleted) { | ||
| 4249 | /* | ||
| 4250 | * Impatient initiator sent PRLI before last | ||
| 4251 | * PLOGI could finish. Will force him to re-try, | ||
| 4252 | * while last one finishes. | ||
| 4253 | */ | ||
| 4254 | ql_log(ql_log_warn, sess->vha, 0xf095, | ||
| 4255 | "sess %p PRLI received, before plogi ack.\n", | ||
| 4256 | sess); | ||
| 4257 | qlt_send_term_imm_notif(vha, iocb, 1); | ||
| 4258 | res = 0; | ||
| 4259 | break; | ||
| 4260 | } | ||
| 4261 | |||
| 4262 | /* | ||
| 4263 | * This shouldn't happen under normal circumstances, | ||
| 4264 | * since we have deleted the old session during PLOGI | ||
| 4265 | */ | ||
| 4266 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf096, | ||
| 4267 | "PRLI (loop_id %#04x) for existing sess %p (loop_id %#04x)\n", | ||
| 4268 | sess->loop_id, sess, iocb->u.isp24.nport_handle); | ||
| 4269 | |||
| 4270 | sess->local = 0; | ||
| 4271 | sess->loop_id = loop_id; | ||
| 4272 | sess->s_id = port_id; | ||
| 4273 | |||
| 4274 | if (wd3_lo & BIT_7) | ||
| 4275 | sess->conf_compl_supported = 1; | ||
| 4276 | |||
| 4277 | } | ||
| 4278 | res = 1; /* send notify ack */ | ||
| 4279 | |||
| 4280 | /* Make session global (not used in fabric mode) */ | ||
| 4281 | if (ha->current_topology != ISP_CFG_F) { | ||
| 4282 | set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); | ||
| 4283 | set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); | ||
| 4284 | qla2xxx_wake_dpc(vha); | ||
| 4285 | } else { | ||
| 4286 | /* todo: else - create sess here. */ | ||
| 4287 | res = 1; /* send notify ack */ | ||
| 4288 | } | ||
| 4289 | |||
| 4290 | break; | ||
| 4291 | |||
| 3685 | case ELS_LOGO: | 4292 | case ELS_LOGO: |
| 3686 | case ELS_PRLO: | 4293 | case ELS_PRLO: |
| 3687 | res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS); | 4294 | res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS); |
| @@ -3699,6 +4306,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, | |||
| 3699 | break; | 4306 | break; |
| 3700 | } | 4307 | } |
| 3701 | 4308 | ||
| 4309 | case ELS_FLOGI: /* should never happen */ | ||
| 3702 | default: | 4310 | default: |
| 3703 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf061, | 4311 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf061, |
| 3704 | "qla_target(%d): Unsupported ELS command %x " | 4312 | "qla_target(%d): Unsupported ELS command %x " |
| @@ -3712,6 +4320,14 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, | |||
| 3712 | 4320 | ||
| 3713 | static int qlt_set_data_offset(struct qla_tgt_cmd *cmd, uint32_t offset) | 4321 | static int qlt_set_data_offset(struct qla_tgt_cmd *cmd, uint32_t offset) |
| 3714 | { | 4322 | { |
| 4323 | #if 1 | ||
| 4324 | /* | ||
| 4325 | * FIXME: Reject non zero SRR relative offset until we can test | ||
| 4326 | * this code properly. | ||
| 4327 | */ | ||
| 4328 | pr_debug("Rejecting non zero SRR rel_offs: %u\n", offset); | ||
| 4329 | return -1; | ||
| 4330 | #else | ||
| 3715 | struct scatterlist *sg, *sgp, *sg_srr, *sg_srr_start = NULL; | 4331 | struct scatterlist *sg, *sgp, *sg_srr, *sg_srr_start = NULL; |
| 3716 | size_t first_offset = 0, rem_offset = offset, tmp = 0; | 4332 | size_t first_offset = 0, rem_offset = offset, tmp = 0; |
| 3717 | int i, sg_srr_cnt, bufflen = 0; | 4333 | int i, sg_srr_cnt, bufflen = 0; |
| @@ -3721,13 +4337,6 @@ static int qlt_set_data_offset(struct qla_tgt_cmd *cmd, uint32_t offset) | |||
| 3721 | "cmd->sg_cnt: %u, direction: %d\n", | 4337 | "cmd->sg_cnt: %u, direction: %d\n", |
| 3722 | cmd, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction); | 4338 | cmd, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction); |
| 3723 | 4339 | ||
| 3724 | /* | ||
| 3725 | * FIXME: Reject non zero SRR relative offset until we can test | ||
| 3726 | * this code properly. | ||
| 3727 | */ | ||
| 3728 | pr_debug("Rejecting non zero SRR rel_offs: %u\n", offset); | ||
| 3729 | return -1; | ||
| 3730 | |||
| 3731 | if (!cmd->sg || !cmd->sg_cnt) { | 4340 | if (!cmd->sg || !cmd->sg_cnt) { |
| 3732 | ql_dbg(ql_dbg_tgt, cmd->vha, 0xe055, | 4341 | ql_dbg(ql_dbg_tgt, cmd->vha, 0xe055, |
| 3733 | "Missing cmd->sg or zero cmd->sg_cnt in" | 4342 | "Missing cmd->sg or zero cmd->sg_cnt in" |
| @@ -3810,6 +4419,7 @@ static int qlt_set_data_offset(struct qla_tgt_cmd *cmd, uint32_t offset) | |||
| 3810 | BUG(); | 4419 | BUG(); |
| 3811 | 4420 | ||
| 3812 | return 0; | 4421 | return 0; |
| 4422 | #endif | ||
| 3813 | } | 4423 | } |
| 3814 | 4424 | ||
| 3815 | static inline int qlt_srr_adjust_data(struct qla_tgt_cmd *cmd, | 4425 | static inline int qlt_srr_adjust_data(struct qla_tgt_cmd *cmd, |
| @@ -3891,9 +4501,8 @@ static void qlt_handle_srr(struct scsi_qla_host *vha, | |||
| 3891 | resp = 1; | 4501 | resp = 1; |
| 3892 | } else { | 4502 | } else { |
| 3893 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf064, | 4503 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf064, |
| 3894 | "qla_target(%d): SRR for in data for cmd " | 4504 | "qla_target(%d): SRR for in data for cmd without them (tag %lld, SCSI status %d), reject", |
| 3895 | "without them (tag %d, SCSI status %d), " | 4505 | vha->vp_idx, se_cmd->tag, |
| 3896 | "reject", vha->vp_idx, cmd->tag, | ||
| 3897 | cmd->se_cmd.scsi_status); | 4506 | cmd->se_cmd.scsi_status); |
| 3898 | goto out_reject; | 4507 | goto out_reject; |
| 3899 | } | 4508 | } |
| @@ -3927,10 +4536,8 @@ static void qlt_handle_srr(struct scsi_qla_host *vha, | |||
| 3927 | } | 4536 | } |
| 3928 | } else { | 4537 | } else { |
| 3929 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf066, | 4538 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf066, |
| 3930 | "qla_target(%d): SRR for out data for cmd " | 4539 | "qla_target(%d): SRR for out data for cmd without them (tag %lld, SCSI status %d), reject", |
| 3931 | "without them (tag %d, SCSI status %d), " | 4540 | vha->vp_idx, se_cmd->tag, cmd->se_cmd.scsi_status); |
| 3932 | "reject", vha->vp_idx, cmd->tag, | ||
| 3933 | cmd->se_cmd.scsi_status); | ||
| 3934 | goto out_reject; | 4541 | goto out_reject; |
| 3935 | } | 4542 | } |
| 3936 | break; | 4543 | break; |
| @@ -4051,10 +4658,9 @@ restart: | |||
| 4051 | cmd->sg = se_cmd->t_data_sg; | 4658 | cmd->sg = se_cmd->t_data_sg; |
| 4052 | 4659 | ||
| 4053 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02c, | 4660 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf02c, |
| 4054 | "SRR cmd %p (se_cmd %p, tag %d, op %x), " | 4661 | "SRR cmd %p (se_cmd %p, tag %lld, op %x), sg_cnt=%d, offset=%d", |
| 4055 | "sg_cnt=%d, offset=%d", cmd, &cmd->se_cmd, cmd->tag, | 4662 | cmd, &cmd->se_cmd, se_cmd->tag, se_cmd->t_task_cdb ? |
| 4056 | se_cmd->t_task_cdb ? se_cmd->t_task_cdb[0] : 0, | 4663 | se_cmd->t_task_cdb[0] : 0, cmd->sg_cnt, cmd->offset); |
| 4057 | cmd->sg_cnt, cmd->offset); | ||
| 4058 | 4664 | ||
| 4059 | qlt_handle_srr(vha, sctio, imm); | 4665 | qlt_handle_srr(vha, sctio, imm); |
| 4060 | 4666 | ||
| @@ -5016,6 +5622,11 @@ static void qlt_abort_work(struct qla_tgt *tgt, | |||
| 5016 | if (!sess) | 5622 | if (!sess) |
| 5017 | goto out_term; | 5623 | goto out_term; |
| 5018 | } else { | 5624 | } else { |
| 5625 | if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { | ||
| 5626 | sess = NULL; | ||
| 5627 | goto out_term; | ||
| 5628 | } | ||
| 5629 | |||
| 5019 | kref_get(&sess->se_sess->sess_kref); | 5630 | kref_get(&sess->se_sess->sess_kref); |
| 5020 | } | 5631 | } |
| 5021 | 5632 | ||
| @@ -5070,6 +5681,11 @@ static void qlt_tmr_work(struct qla_tgt *tgt, | |||
| 5070 | if (!sess) | 5681 | if (!sess) |
| 5071 | goto out_term; | 5682 | goto out_term; |
| 5072 | } else { | 5683 | } else { |
| 5684 | if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { | ||
| 5685 | sess = NULL; | ||
| 5686 | goto out_term; | ||
| 5687 | } | ||
| 5688 | |||
| 5073 | kref_get(&sess->se_sess->sess_kref); | 5689 | kref_get(&sess->se_sess->sess_kref); |
| 5074 | } | 5690 | } |
| 5075 | 5691 | ||
| @@ -5556,6 +6172,7 @@ qlt_24xx_process_atio_queue(struct scsi_qla_host *vha) | |||
| 5556 | 6172 | ||
| 5557 | /* Adjust ring index */ | 6173 | /* Adjust ring index */ |
| 5558 | WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), ha->tgt.atio_ring_index); | 6174 | WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), ha->tgt.atio_ring_index); |
| 6175 | RD_REG_DWORD_RELAXED(ISP_ATIO_Q_OUT(vha)); | ||
| 5559 | } | 6176 | } |
| 5560 | 6177 | ||
| 5561 | void | 6178 | void |
| @@ -5797,7 +6414,7 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha) | |||
| 5797 | if (!QLA_TGT_MODE_ENABLED()) | 6414 | if (!QLA_TGT_MODE_ENABLED()) |
| 5798 | return; | 6415 | return; |
| 5799 | 6416 | ||
| 5800 | if (ha->mqenable || IS_QLA83XX(ha)) { | 6417 | if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { |
| 5801 | ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in; | 6418 | ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in; |
| 5802 | ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out; | 6419 | ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out; |
| 5803 | } else { | 6420 | } else { |
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 332086776dfe..bca584ae45b7 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h | |||
| @@ -167,7 +167,24 @@ struct imm_ntfy_from_isp { | |||
| 167 | uint32_t srr_rel_offs; | 167 | uint32_t srr_rel_offs; |
| 168 | uint16_t srr_ui; | 168 | uint16_t srr_ui; |
| 169 | uint16_t srr_ox_id; | 169 | uint16_t srr_ox_id; |
| 170 | uint8_t reserved_4[19]; | 170 | union { |
| 171 | struct { | ||
| 172 | uint8_t node_name[8]; | ||
| 173 | } plogi; /* PLOGI/ADISC/PDISC */ | ||
| 174 | struct { | ||
| 175 | /* PRLI word 3 bit 0-15 */ | ||
| 176 | uint16_t wd3_lo; | ||
| 177 | uint8_t resv0[6]; | ||
| 178 | } prli; | ||
| 179 | struct { | ||
| 180 | uint8_t port_id[3]; | ||
| 181 | uint8_t resv1; | ||
| 182 | uint16_t nport_handle; | ||
| 183 | uint16_t resv2; | ||
| 184 | } req_els; | ||
| 185 | } u; | ||
| 186 | uint8_t port_name[8]; | ||
| 187 | uint8_t resv3[3]; | ||
| 171 | uint8_t vp_index; | 188 | uint8_t vp_index; |
| 172 | uint32_t reserved_5; | 189 | uint32_t reserved_5; |
| 173 | uint8_t port_id[3]; | 190 | uint8_t port_id[3]; |
| @@ -234,6 +251,7 @@ struct nack_to_isp { | |||
| 234 | uint8_t reserved[2]; | 251 | uint8_t reserved[2]; |
| 235 | uint16_t ox_id; | 252 | uint16_t ox_id; |
| 236 | } __packed; | 253 | } __packed; |
| 254 | #define NOTIFY_ACK_FLAGS_TERMINATE BIT_3 | ||
| 237 | #define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0 | 255 | #define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0 |
| 238 | #define NOTIFY_ACK_SRR_FLAGS_REJECT 1 | 256 | #define NOTIFY_ACK_SRR_FLAGS_REJECT 1 |
| 239 | 257 | ||
| @@ -790,13 +808,6 @@ int qla2x00_wait_for_hba_online(struct scsi_qla_host *); | |||
| 790 | #define FC_TM_REJECT 4 | 808 | #define FC_TM_REJECT 4 |
| 791 | #define FC_TM_FAILED 5 | 809 | #define FC_TM_FAILED 5 |
| 792 | 810 | ||
| 793 | /* | ||
| 794 | * Error code of qlt_pre_xmit_response() meaning that cmd's exchange was | ||
| 795 | * terminated, so no more actions is needed and success should be returned | ||
| 796 | * to target. | ||
| 797 | */ | ||
| 798 | #define QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED 0x1717 | ||
| 799 | |||
| 800 | #if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G) | 811 | #if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G) |
| 801 | #define pci_dma_lo32(a) (a & 0xffffffff) | 812 | #define pci_dma_lo32(a) (a & 0xffffffff) |
| 802 | #define pci_dma_hi32(a) ((((a) >> 16)>>16) & 0xffffffff) | 813 | #define pci_dma_hi32(a) ((((a) >> 16)>>16) & 0xffffffff) |
| @@ -874,6 +885,15 @@ struct qla_tgt_sess_op { | |||
| 874 | struct scsi_qla_host *vha; | 885 | struct scsi_qla_host *vha; |
| 875 | struct atio_from_isp atio; | 886 | struct atio_from_isp atio; |
| 876 | struct work_struct work; | 887 | struct work_struct work; |
| 888 | struct list_head cmd_list; | ||
| 889 | bool aborted; | ||
| 890 | }; | ||
| 891 | |||
| 892 | enum qla_sess_deletion { | ||
| 893 | QLA_SESS_DELETION_NONE = 0, | ||
| 894 | QLA_SESS_DELETION_PENDING = 1, /* hopefully we can get rid of | ||
| 895 | * this one */ | ||
| 896 | QLA_SESS_DELETION_IN_PROGRESS = 2, | ||
| 877 | }; | 897 | }; |
| 878 | 898 | ||
| 879 | /* | 899 | /* |
| @@ -884,8 +904,15 @@ struct qla_tgt_sess { | |||
| 884 | port_id_t s_id; | 904 | port_id_t s_id; |
| 885 | 905 | ||
| 886 | unsigned int conf_compl_supported:1; | 906 | unsigned int conf_compl_supported:1; |
| 887 | unsigned int deleted:1; | 907 | unsigned int deleted:2; |
| 888 | unsigned int local:1; | 908 | unsigned int local:1; |
| 909 | unsigned int logout_on_delete:1; | ||
| 910 | unsigned int plogi_ack_needed:1; | ||
| 911 | unsigned int keep_nport_handle:1; | ||
| 912 | |||
| 913 | unsigned char logout_completed; | ||
| 914 | |||
| 915 | int generation; | ||
| 889 | 916 | ||
| 890 | struct se_session *se_sess; | 917 | struct se_session *se_sess; |
| 891 | struct scsi_qla_host *vha; | 918 | struct scsi_qla_host *vha; |
| @@ -897,6 +924,10 @@ struct qla_tgt_sess { | |||
| 897 | 924 | ||
| 898 | uint8_t port_name[WWN_SIZE]; | 925 | uint8_t port_name[WWN_SIZE]; |
| 899 | struct work_struct free_work; | 926 | struct work_struct free_work; |
| 927 | |||
| 928 | union { | ||
| 929 | struct imm_ntfy_from_isp tm_iocb; | ||
| 930 | }; | ||
| 900 | }; | 931 | }; |
| 901 | 932 | ||
| 902 | struct qla_tgt_cmd { | 933 | struct qla_tgt_cmd { |
| @@ -912,7 +943,6 @@ struct qla_tgt_cmd { | |||
| 912 | unsigned int conf_compl_supported:1; | 943 | unsigned int conf_compl_supported:1; |
| 913 | unsigned int sg_mapped:1; | 944 | unsigned int sg_mapped:1; |
| 914 | unsigned int free_sg:1; | 945 | unsigned int free_sg:1; |
| 915 | unsigned int aborted:1; /* Needed in case of SRR */ | ||
| 916 | unsigned int write_data_transferred:1; | 946 | unsigned int write_data_transferred:1; |
| 917 | unsigned int ctx_dsd_alloced:1; | 947 | unsigned int ctx_dsd_alloced:1; |
| 918 | unsigned int q_full:1; | 948 | unsigned int q_full:1; |
| @@ -924,7 +954,6 @@ struct qla_tgt_cmd { | |||
| 924 | int sg_cnt; /* SG segments count */ | 954 | int sg_cnt; /* SG segments count */ |
| 925 | int bufflen; /* cmd buffer length */ | 955 | int bufflen; /* cmd buffer length */ |
| 926 | int offset; | 956 | int offset; |
| 927 | uint32_t tag; | ||
| 928 | uint32_t unpacked_lun; | 957 | uint32_t unpacked_lun; |
| 929 | enum dma_data_direction dma_data_direction; | 958 | enum dma_data_direction dma_data_direction; |
| 930 | uint32_t reset_count; | 959 | uint32_t reset_count; |
| @@ -962,6 +991,9 @@ struct qla_tgt_cmd { | |||
| 962 | * BIT_14 - Back end data received/sent. | 991 | * BIT_14 - Back end data received/sent. |
| 963 | * BIT_15 - SRR prepare ctio | 992 | * BIT_15 - SRR prepare ctio |
| 964 | * BIT_16 - complete free | 993 | * BIT_16 - complete free |
| 994 | * BIT_17 - flush - qlt_abort_cmd_on_host_reset | ||
| 995 | * BIT_18 - completion w/abort status | ||
| 996 | * BIT_19 - completion w/unknown status | ||
| 965 | */ | 997 | */ |
| 966 | uint32_t cmd_flags; | 998 | uint32_t cmd_flags; |
| 967 | }; | 999 | }; |
| @@ -1027,6 +1059,10 @@ struct qla_tgt_srr_ctio { | |||
| 1027 | struct qla_tgt_cmd *cmd; | 1059 | struct qla_tgt_cmd *cmd; |
| 1028 | }; | 1060 | }; |
| 1029 | 1061 | ||
| 1062 | /* Check for Switch reserved address */ | ||
| 1063 | #define IS_SW_RESV_ADDR(_s_id) \ | ||
| 1064 | ((_s_id.b.domain == 0xff) && (_s_id.b.area == 0xfc)) | ||
| 1065 | |||
| 1030 | #define QLA_TGT_XMIT_DATA 1 | 1066 | #define QLA_TGT_XMIT_DATA 1 |
| 1031 | #define QLA_TGT_XMIT_STATUS 2 | 1067 | #define QLA_TGT_XMIT_STATUS 2 |
| 1032 | #define QLA_TGT_XMIT_ALL (QLA_TGT_XMIT_STATUS|QLA_TGT_XMIT_DATA) | 1068 | #define QLA_TGT_XMIT_ALL (QLA_TGT_XMIT_STATUS|QLA_TGT_XMIT_DATA) |
| @@ -1044,7 +1080,7 @@ extern int qlt_lport_register(void *, u64, u64, u64, | |||
| 1044 | extern void qlt_lport_deregister(struct scsi_qla_host *); | 1080 | extern void qlt_lport_deregister(struct scsi_qla_host *); |
| 1045 | extern void qlt_unreg_sess(struct qla_tgt_sess *); | 1081 | extern void qlt_unreg_sess(struct qla_tgt_sess *); |
| 1046 | extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *); | 1082 | extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *); |
| 1047 | extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *); | 1083 | extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *, int); |
| 1048 | extern int __init qlt_init(void); | 1084 | extern int __init qlt_init(void); |
| 1049 | extern void qlt_exit(void); | 1085 | extern void qlt_exit(void); |
| 1050 | extern void qlt_update_vp_map(struct scsi_qla_host *, int); | 1086 | extern void qlt_update_vp_map(struct scsi_qla_host *, int); |
| @@ -1074,12 +1110,23 @@ static inline void qla_reverse_ini_mode(struct scsi_qla_host *ha) | |||
| 1074 | ha->host->active_mode |= MODE_INITIATOR; | 1110 | ha->host->active_mode |= MODE_INITIATOR; |
| 1075 | } | 1111 | } |
| 1076 | 1112 | ||
| 1113 | static inline uint32_t sid_to_key(const uint8_t *s_id) | ||
| 1114 | { | ||
| 1115 | uint32_t key; | ||
| 1116 | |||
| 1117 | key = (((unsigned long)s_id[0] << 16) | | ||
| 1118 | ((unsigned long)s_id[1] << 8) | | ||
| 1119 | (unsigned long)s_id[2]); | ||
| 1120 | return key; | ||
| 1121 | } | ||
| 1122 | |||
| 1077 | /* | 1123 | /* |
| 1078 | * Exported symbols from qla_target.c LLD logic used by qla2xxx code.. | 1124 | * Exported symbols from qla_target.c LLD logic used by qla2xxx code.. |
| 1079 | */ | 1125 | */ |
| 1080 | extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *); | 1126 | extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *); |
| 1081 | extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *); | 1127 | extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *); |
| 1082 | extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t); | 1128 | extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t); |
| 1129 | extern void qlt_abort_cmd(struct qla_tgt_cmd *); | ||
| 1083 | extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *); | 1130 | extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *); |
| 1084 | extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *); | 1131 | extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *); |
| 1085 | extern void qlt_free_cmd(struct qla_tgt_cmd *cmd); | 1132 | extern void qlt_free_cmd(struct qla_tgt_cmd *cmd); |
| @@ -1110,5 +1157,7 @@ extern void qlt_stop_phase2(struct qla_tgt *); | |||
| 1110 | extern irqreturn_t qla83xx_msix_atio_q(int, void *); | 1157 | extern irqreturn_t qla83xx_msix_atio_q(int, void *); |
| 1111 | extern void qlt_83xx_iospace_config(struct qla_hw_data *); | 1158 | extern void qlt_83xx_iospace_config(struct qla_hw_data *); |
| 1112 | extern int qlt_free_qfull_cmds(struct scsi_qla_host *); | 1159 | extern int qlt_free_qfull_cmds(struct scsi_qla_host *); |
| 1160 | extern void qlt_logo_completion_handler(fc_port_t *, int); | ||
| 1161 | extern void qlt_do_generation_tick(struct scsi_qla_host *, int *); | ||
| 1113 | 1162 | ||
| 1114 | #endif /* __QLA_TARGET_H */ | 1163 | #endif /* __QLA_TARGET_H */ |
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 5c9e680aa375..9224a06646e6 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/moduleparam.h> | 27 | #include <linux/moduleparam.h> |
| 28 | #include <generated/utsrelease.h> | 28 | #include <generated/utsrelease.h> |
| 29 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
| 30 | #include <linux/vmalloc.h> | ||
| 30 | #include <linux/init.h> | 31 | #include <linux/init.h> |
| 31 | #include <linux/list.h> | 32 | #include <linux/list.h> |
| 32 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
| @@ -43,7 +44,6 @@ | |||
| 43 | #include <target/target_core_base.h> | 44 | #include <target/target_core_base.h> |
| 44 | #include <target/target_core_fabric.h> | 45 | #include <target/target_core_fabric.h> |
| 45 | #include <target/target_core_fabric_configfs.h> | 46 | #include <target/target_core_fabric_configfs.h> |
| 46 | #include <target/target_core_configfs.h> | ||
| 47 | #include <target/configfs_macros.h> | 47 | #include <target/configfs_macros.h> |
| 48 | 48 | ||
| 49 | #include "qla_def.h" | 49 | #include "qla_def.h" |
| @@ -53,9 +53,6 @@ | |||
| 53 | static struct workqueue_struct *tcm_qla2xxx_free_wq; | 53 | static struct workqueue_struct *tcm_qla2xxx_free_wq; |
| 54 | static struct workqueue_struct *tcm_qla2xxx_cmd_wq; | 54 | static struct workqueue_struct *tcm_qla2xxx_cmd_wq; |
| 55 | 55 | ||
| 56 | static const struct target_core_fabric_ops tcm_qla2xxx_ops; | ||
| 57 | static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops; | ||
| 58 | |||
| 59 | /* | 56 | /* |
| 60 | * Parse WWN. | 57 | * Parse WWN. |
| 61 | * If strict, we require lower-case hex and colon separators to be sure | 58 | * If strict, we require lower-case hex and colon separators to be sure |
| @@ -190,23 +187,6 @@ static char *tcm_qla2xxx_npiv_get_fabric_name(void) | |||
| 190 | return "qla2xxx_npiv"; | 187 | return "qla2xxx_npiv"; |
| 191 | } | 188 | } |
| 192 | 189 | ||
| 193 | static u8 tcm_qla2xxx_get_fabric_proto_ident(struct se_portal_group *se_tpg) | ||
| 194 | { | ||
| 195 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
| 196 | struct tcm_qla2xxx_tpg, se_tpg); | ||
| 197 | struct tcm_qla2xxx_lport *lport = tpg->lport; | ||
| 198 | u8 proto_id; | ||
| 199 | |||
| 200 | switch (lport->lport_proto_id) { | ||
| 201 | case SCSI_PROTOCOL_FCP: | ||
| 202 | default: | ||
| 203 | proto_id = fc_get_fabric_proto_ident(se_tpg); | ||
| 204 | break; | ||
| 205 | } | ||
| 206 | |||
| 207 | return proto_id; | ||
| 208 | } | ||
| 209 | |||
| 210 | static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg) | 190 | static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg) |
| 211 | { | 191 | { |
| 212 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | 192 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, |
| @@ -223,78 +203,6 @@ static u16 tcm_qla2xxx_get_tag(struct se_portal_group *se_tpg) | |||
| 223 | return tpg->lport_tpgt; | 203 | return tpg->lport_tpgt; |
| 224 | } | 204 | } |
| 225 | 205 | ||
| 226 | static u32 tcm_qla2xxx_get_default_depth(struct se_portal_group *se_tpg) | ||
| 227 | { | ||
| 228 | return 1; | ||
| 229 | } | ||
| 230 | |||
| 231 | static u32 tcm_qla2xxx_get_pr_transport_id( | ||
| 232 | struct se_portal_group *se_tpg, | ||
| 233 | struct se_node_acl *se_nacl, | ||
| 234 | struct t10_pr_registration *pr_reg, | ||
| 235 | int *format_code, | ||
| 236 | unsigned char *buf) | ||
| 237 | { | ||
| 238 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
| 239 | struct tcm_qla2xxx_tpg, se_tpg); | ||
| 240 | struct tcm_qla2xxx_lport *lport = tpg->lport; | ||
| 241 | int ret = 0; | ||
| 242 | |||
| 243 | switch (lport->lport_proto_id) { | ||
| 244 | case SCSI_PROTOCOL_FCP: | ||
| 245 | default: | ||
| 246 | ret = fc_get_pr_transport_id(se_tpg, se_nacl, pr_reg, | ||
| 247 | format_code, buf); | ||
| 248 | break; | ||
| 249 | } | ||
| 250 | |||
| 251 | return ret; | ||
| 252 | } | ||
| 253 | |||
| 254 | static u32 tcm_qla2xxx_get_pr_transport_id_len( | ||
| 255 | struct se_portal_group *se_tpg, | ||
| 256 | struct se_node_acl *se_nacl, | ||
| 257 | struct t10_pr_registration *pr_reg, | ||
| 258 | int *format_code) | ||
| 259 | { | ||
| 260 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
| 261 | struct tcm_qla2xxx_tpg, se_tpg); | ||
| 262 | struct tcm_qla2xxx_lport *lport = tpg->lport; | ||
| 263 | int ret = 0; | ||
| 264 | |||
| 265 | switch (lport->lport_proto_id) { | ||
| 266 | case SCSI_PROTOCOL_FCP: | ||
| 267 | default: | ||
| 268 | ret = fc_get_pr_transport_id_len(se_tpg, se_nacl, pr_reg, | ||
| 269 | format_code); | ||
| 270 | break; | ||
| 271 | } | ||
| 272 | |||
| 273 | return ret; | ||
| 274 | } | ||
| 275 | |||
| 276 | static char *tcm_qla2xxx_parse_pr_out_transport_id( | ||
| 277 | struct se_portal_group *se_tpg, | ||
| 278 | const char *buf, | ||
| 279 | u32 *out_tid_len, | ||
| 280 | char **port_nexus_ptr) | ||
| 281 | { | ||
| 282 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | ||
| 283 | struct tcm_qla2xxx_tpg, se_tpg); | ||
| 284 | struct tcm_qla2xxx_lport *lport = tpg->lport; | ||
| 285 | char *tid = NULL; | ||
| 286 | |||
| 287 | switch (lport->lport_proto_id) { | ||
| 288 | case SCSI_PROTOCOL_FCP: | ||
| 289 | default: | ||
| 290 | tid = fc_parse_pr_out_transport_id(se_tpg, buf, out_tid_len, | ||
| 291 | port_nexus_ptr); | ||
| 292 | break; | ||
| 293 | } | ||
| 294 | |||
| 295 | return tid; | ||
| 296 | } | ||
| 297 | |||
| 298 | static int tcm_qla2xxx_check_demo_mode(struct se_portal_group *se_tpg) | 206 | static int tcm_qla2xxx_check_demo_mode(struct se_portal_group *se_tpg) |
| 299 | { | 207 | { |
| 300 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | 208 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, |
| @@ -343,29 +251,6 @@ static int tcm_qla2xxx_check_prot_fabric_only(struct se_portal_group *se_tpg) | |||
| 343 | return tpg->tpg_attrib.fabric_prot_type; | 251 | return tpg->tpg_attrib.fabric_prot_type; |
| 344 | } | 252 | } |
| 345 | 253 | ||
| 346 | static struct se_node_acl *tcm_qla2xxx_alloc_fabric_acl( | ||
| 347 | struct se_portal_group *se_tpg) | ||
| 348 | { | ||
| 349 | struct tcm_qla2xxx_nacl *nacl; | ||
| 350 | |||
| 351 | nacl = kzalloc(sizeof(struct tcm_qla2xxx_nacl), GFP_KERNEL); | ||
| 352 | if (!nacl) { | ||
| 353 | pr_err("Unable to allocate struct tcm_qla2xxx_nacl\n"); | ||
| 354 | return NULL; | ||
| 355 | } | ||
| 356 | |||
| 357 | return &nacl->se_node_acl; | ||
| 358 | } | ||
| 359 | |||
| 360 | static void tcm_qla2xxx_release_fabric_acl( | ||
| 361 | struct se_portal_group *se_tpg, | ||
| 362 | struct se_node_acl *se_nacl) | ||
| 363 | { | ||
| 364 | struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, | ||
| 365 | struct tcm_qla2xxx_nacl, se_node_acl); | ||
| 366 | kfree(nacl); | ||
| 367 | } | ||
| 368 | |||
| 369 | static u32 tcm_qla2xxx_tpg_get_inst_index(struct se_portal_group *se_tpg) | 254 | static u32 tcm_qla2xxx_tpg_get_inst_index(struct se_portal_group *se_tpg) |
| 370 | { | 255 | { |
| 371 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, | 256 | struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, |
| @@ -429,7 +314,7 @@ static int tcm_qla2xxx_check_stop_free(struct se_cmd *se_cmd) | |||
| 429 | cmd->cmd_flags |= BIT_14; | 314 | cmd->cmd_flags |= BIT_14; |
| 430 | } | 315 | } |
| 431 | 316 | ||
| 432 | return target_put_sess_cmd(se_cmd->se_sess, se_cmd); | 317 | return target_put_sess_cmd(se_cmd); |
| 433 | } | 318 | } |
| 434 | 319 | ||
| 435 | /* tcm_qla2xxx_release_cmd - Callback from TCM Core to release underlying | 320 | /* tcm_qla2xxx_release_cmd - Callback from TCM Core to release underlying |
| @@ -489,7 +374,7 @@ static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd) | |||
| 489 | { | 374 | { |
| 490 | struct qla_tgt_cmd *cmd = container_of(se_cmd, | 375 | struct qla_tgt_cmd *cmd = container_of(se_cmd, |
| 491 | struct qla_tgt_cmd, se_cmd); | 376 | struct qla_tgt_cmd, se_cmd); |
| 492 | 377 | cmd->cmd_flags |= BIT_3; | |
| 493 | cmd->bufflen = se_cmd->data_length; | 378 | cmd->bufflen = se_cmd->data_length; |
| 494 | cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); | 379 | cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); |
| 495 | 380 | ||
| @@ -520,7 +405,7 @@ static int tcm_qla2xxx_write_pending_status(struct se_cmd *se_cmd) | |||
| 520 | se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) { | 405 | se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) { |
| 521 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); | 406 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); |
| 522 | wait_for_completion_timeout(&se_cmd->t_transport_stop_comp, | 407 | wait_for_completion_timeout(&se_cmd->t_transport_stop_comp, |
| 523 | 3000); | 408 | 3 * HZ); |
| 524 | return 0; | 409 | return 0; |
| 525 | } | 410 | } |
| 526 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); | 411 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); |
| @@ -533,19 +418,6 @@ static void tcm_qla2xxx_set_default_node_attrs(struct se_node_acl *nacl) | |||
| 533 | return; | 418 | return; |
| 534 | } | 419 | } |
| 535 | 420 | ||
| 536 | static u32 tcm_qla2xxx_get_task_tag(struct se_cmd *se_cmd) | ||
| 537 | { | ||
| 538 | struct qla_tgt_cmd *cmd; | ||
| 539 | |||
| 540 | /* check for task mgmt cmd */ | ||
| 541 | if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) | ||
| 542 | return 0xffffffff; | ||
| 543 | |||
| 544 | cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); | ||
| 545 | |||
| 546 | return cmd->tag; | ||
| 547 | } | ||
| 548 | |||
| 549 | static int tcm_qla2xxx_get_cmd_state(struct se_cmd *se_cmd) | 421 | static int tcm_qla2xxx_get_cmd_state(struct se_cmd *se_cmd) |
| 550 | { | 422 | { |
| 551 | return 0; | 423 | return 0; |
| @@ -669,12 +541,10 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd) | |||
| 669 | cmd->cmd_flags |= BIT_4; | 541 | cmd->cmd_flags |= BIT_4; |
| 670 | cmd->bufflen = se_cmd->data_length; | 542 | cmd->bufflen = se_cmd->data_length; |
| 671 | cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); | 543 | cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); |
| 672 | cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED); | ||
| 673 | 544 | ||
| 674 | cmd->sg_cnt = se_cmd->t_data_nents; | 545 | cmd->sg_cnt = se_cmd->t_data_nents; |
| 675 | cmd->sg = se_cmd->t_data_sg; | 546 | cmd->sg = se_cmd->t_data_sg; |
| 676 | cmd->offset = 0; | 547 | cmd->offset = 0; |
| 677 | cmd->cmd_flags |= BIT_3; | ||
| 678 | 548 | ||
| 679 | cmd->prot_sg_cnt = se_cmd->t_prot_nents; | 549 | cmd->prot_sg_cnt = se_cmd->t_prot_nents; |
| 680 | cmd->prot_sg = se_cmd->t_prot_sg; | 550 | cmd->prot_sg = se_cmd->t_prot_sg; |
| @@ -699,7 +569,6 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd) | |||
| 699 | cmd->sg_cnt = 0; | 569 | cmd->sg_cnt = 0; |
| 700 | cmd->offset = 0; | 570 | cmd->offset = 0; |
| 701 | cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); | 571 | cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); |
| 702 | cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED); | ||
| 703 | if (cmd->cmd_flags & BIT_5) { | 572 | if (cmd->cmd_flags & BIT_5) { |
| 704 | pr_crit("Bit_5 already set for cmd = %p.\n", cmd); | 573 | pr_crit("Bit_5 already set for cmd = %p.\n", cmd); |
| 705 | dump_stack(); | 574 | dump_stack(); |
| @@ -764,14 +633,7 @@ static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd) | |||
| 764 | { | 633 | { |
| 765 | struct qla_tgt_cmd *cmd = container_of(se_cmd, | 634 | struct qla_tgt_cmd *cmd = container_of(se_cmd, |
| 766 | struct qla_tgt_cmd, se_cmd); | 635 | struct qla_tgt_cmd, se_cmd); |
| 767 | struct scsi_qla_host *vha = cmd->vha; | 636 | qlt_abort_cmd(cmd); |
| 768 | struct qla_hw_data *ha = vha->hw; | ||
| 769 | |||
| 770 | if (!cmd->sg_mapped) | ||
| 771 | return; | ||
| 772 | |||
| 773 | pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction); | ||
| 774 | cmd->sg_mapped = 0; | ||
| 775 | } | 637 | } |
| 776 | 638 | ||
| 777 | static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *, | 639 | static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *, |
| @@ -826,17 +688,6 @@ static void tcm_qla2xxx_release_session(struct kref *kref) | |||
| 826 | qlt_unreg_sess(se_sess->fabric_sess_ptr); | 688 | qlt_unreg_sess(se_sess->fabric_sess_ptr); |
| 827 | } | 689 | } |
| 828 | 690 | ||
| 829 | static void tcm_qla2xxx_put_session(struct se_session *se_sess) | ||
| 830 | { | ||
| 831 | struct qla_tgt_sess *sess = se_sess->fabric_sess_ptr; | ||
| 832 | struct qla_hw_data *ha = sess->vha->hw; | ||
| 833 | unsigned long flags; | ||
| 834 | |||
| 835 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
| 836 | kref_put(&se_sess->sess_kref, tcm_qla2xxx_release_session); | ||
| 837 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
| 838 | } | ||
| 839 | |||
| 840 | static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess) | 691 | static void tcm_qla2xxx_put_sess(struct qla_tgt_sess *sess) |
| 841 | { | 692 | { |
| 842 | if (!sess) | 693 | if (!sess) |
| @@ -852,53 +703,20 @@ static void tcm_qla2xxx_shutdown_sess(struct qla_tgt_sess *sess) | |||
| 852 | target_sess_cmd_list_set_waiting(sess->se_sess); | 703 | target_sess_cmd_list_set_waiting(sess->se_sess); |
| 853 | } | 704 | } |
| 854 | 705 | ||
| 855 | static struct se_node_acl *tcm_qla2xxx_make_nodeacl( | 706 | static int tcm_qla2xxx_init_nodeacl(struct se_node_acl *se_nacl, |
| 856 | struct se_portal_group *se_tpg, | 707 | const char *name) |
| 857 | struct config_group *group, | ||
| 858 | const char *name) | ||
| 859 | { | 708 | { |
| 860 | struct se_node_acl *se_nacl, *se_nacl_new; | 709 | struct tcm_qla2xxx_nacl *nacl = |
| 861 | struct tcm_qla2xxx_nacl *nacl; | 710 | container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); |
| 862 | u64 wwnn; | 711 | u64 wwnn; |
| 863 | u32 qla2xxx_nexus_depth; | ||
| 864 | 712 | ||
| 865 | if (tcm_qla2xxx_parse_wwn(name, &wwnn, 1) < 0) | 713 | if (tcm_qla2xxx_parse_wwn(name, &wwnn, 1) < 0) |
| 866 | return ERR_PTR(-EINVAL); | 714 | return -EINVAL; |
| 867 | |||
| 868 | se_nacl_new = tcm_qla2xxx_alloc_fabric_acl(se_tpg); | ||
| 869 | if (!se_nacl_new) | ||
| 870 | return ERR_PTR(-ENOMEM); | ||
| 871 | /* #warning FIXME: Hardcoded qla2xxx_nexus depth in tcm_qla2xxx_make_nodeacl */ | ||
| 872 | qla2xxx_nexus_depth = 1; | ||
| 873 | 715 | ||
| 874 | /* | ||
| 875 | * se_nacl_new may be released by core_tpg_add_initiator_node_acl() | ||
| 876 | * when converting a NodeACL from demo mode -> explict | ||
| 877 | */ | ||
| 878 | se_nacl = core_tpg_add_initiator_node_acl(se_tpg, se_nacl_new, | ||
| 879 | name, qla2xxx_nexus_depth); | ||
| 880 | if (IS_ERR(se_nacl)) { | ||
| 881 | tcm_qla2xxx_release_fabric_acl(se_tpg, se_nacl_new); | ||
| 882 | return se_nacl; | ||
| 883 | } | ||
| 884 | /* | ||
| 885 | * Locate our struct tcm_qla2xxx_nacl and set the FC Nport WWPN | ||
| 886 | */ | ||
| 887 | nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); | ||
| 888 | nacl->nport_wwnn = wwnn; | 716 | nacl->nport_wwnn = wwnn; |
| 889 | tcm_qla2xxx_format_wwn(&nacl->nport_name[0], TCM_QLA2XXX_NAMELEN, wwnn); | 717 | tcm_qla2xxx_format_wwn(&nacl->nport_name[0], TCM_QLA2XXX_NAMELEN, wwnn); |
| 890 | 718 | ||
| 891 | return se_nacl; | 719 | return 0; |
| 892 | } | ||
| 893 | |||
| 894 | static void tcm_qla2xxx_drop_nodeacl(struct se_node_acl *se_acl) | ||
| 895 | { | ||
| 896 | struct se_portal_group *se_tpg = se_acl->se_tpg; | ||
| 897 | struct tcm_qla2xxx_nacl *nacl = container_of(se_acl, | ||
| 898 | struct tcm_qla2xxx_nacl, se_node_acl); | ||
| 899 | |||
| 900 | core_tpg_del_initiator_node_acl(se_tpg, se_acl, 1); | ||
| 901 | kfree(nacl); | ||
| 902 | } | 720 | } |
| 903 | 721 | ||
| 904 | /* Start items for tcm_qla2xxx_tpg_attrib_cit */ | 722 | /* Start items for tcm_qla2xxx_tpg_attrib_cit */ |
| @@ -1174,8 +992,7 @@ static struct se_portal_group *tcm_qla2xxx_make_tpg( | |||
| 1174 | tpg->tpg_attrib.cache_dynamic_acls = 1; | 992 | tpg->tpg_attrib.cache_dynamic_acls = 1; |
| 1175 | tpg->tpg_attrib.demo_mode_login_only = 1; | 993 | tpg->tpg_attrib.demo_mode_login_only = 1; |
| 1176 | 994 | ||
| 1177 | ret = core_tpg_register(&tcm_qla2xxx_ops, wwn, | 995 | ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_FCP); |
| 1178 | &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL); | ||
| 1179 | if (ret < 0) { | 996 | if (ret < 0) { |
| 1180 | kfree(tpg); | 997 | kfree(tpg); |
| 1181 | return NULL; | 998 | return NULL; |
| @@ -1294,8 +1111,7 @@ static struct se_portal_group *tcm_qla2xxx_npiv_make_tpg( | |||
| 1294 | tpg->tpg_attrib.cache_dynamic_acls = 1; | 1111 | tpg->tpg_attrib.cache_dynamic_acls = 1; |
| 1295 | tpg->tpg_attrib.demo_mode_login_only = 1; | 1112 | tpg->tpg_attrib.demo_mode_login_only = 1; |
| 1296 | 1113 | ||
| 1297 | ret = core_tpg_register(&tcm_qla2xxx_npiv_ops, wwn, | 1114 | ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_FCP); |
| 1298 | &tpg->se_tpg, tpg, TRANSPORT_TPG_TYPE_NORMAL); | ||
| 1299 | if (ret < 0) { | 1115 | if (ret < 0) { |
| 1300 | kfree(tpg); | 1116 | kfree(tpg); |
| 1301 | return NULL; | 1117 | return NULL; |
| @@ -1323,9 +1139,7 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id( | |||
| 1323 | return NULL; | 1139 | return NULL; |
| 1324 | } | 1140 | } |
| 1325 | 1141 | ||
| 1326 | key = (((unsigned long)s_id[0] << 16) | | 1142 | key = sid_to_key(s_id); |
| 1327 | ((unsigned long)s_id[1] << 8) | | ||
| 1328 | (unsigned long)s_id[2]); | ||
| 1329 | pr_debug("find_sess_by_s_id: 0x%06x\n", key); | 1143 | pr_debug("find_sess_by_s_id: 0x%06x\n", key); |
| 1330 | 1144 | ||
| 1331 | se_nacl = btree_lookup32(&lport->lport_fcport_map, key); | 1145 | se_nacl = btree_lookup32(&lport->lport_fcport_map, key); |
| @@ -1360,9 +1174,7 @@ static void tcm_qla2xxx_set_sess_by_s_id( | |||
| 1360 | void *slot; | 1174 | void *slot; |
| 1361 | int rc; | 1175 | int rc; |
| 1362 | 1176 | ||
| 1363 | key = (((unsigned long)s_id[0] << 16) | | 1177 | key = sid_to_key(s_id); |
| 1364 | ((unsigned long)s_id[1] << 8) | | ||
| 1365 | (unsigned long)s_id[2]); | ||
| 1366 | pr_debug("set_sess_by_s_id: %06x\n", key); | 1178 | pr_debug("set_sess_by_s_id: %06x\n", key); |
| 1367 | 1179 | ||
| 1368 | slot = btree_lookup32(&lport->lport_fcport_map, key); | 1180 | slot = btree_lookup32(&lport->lport_fcport_map, key); |
| @@ -1718,6 +1530,10 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id, | |||
| 1718 | } | 1530 | } |
| 1719 | 1531 | ||
| 1720 | sess->conf_compl_supported = conf_compl_supported; | 1532 | sess->conf_compl_supported = conf_compl_supported; |
| 1533 | |||
| 1534 | /* Reset logout parameters to default */ | ||
| 1535 | sess->logout_on_delete = 1; | ||
| 1536 | sess->keep_nport_handle = 0; | ||
| 1721 | } | 1537 | } |
| 1722 | 1538 | ||
| 1723 | /* | 1539 | /* |
| @@ -1987,14 +1803,10 @@ static struct configfs_attribute *tcm_qla2xxx_wwn_attrs[] = { | |||
| 1987 | static const struct target_core_fabric_ops tcm_qla2xxx_ops = { | 1803 | static const struct target_core_fabric_ops tcm_qla2xxx_ops = { |
| 1988 | .module = THIS_MODULE, | 1804 | .module = THIS_MODULE, |
| 1989 | .name = "qla2xxx", | 1805 | .name = "qla2xxx", |
| 1806 | .node_acl_size = sizeof(struct tcm_qla2xxx_nacl), | ||
| 1990 | .get_fabric_name = tcm_qla2xxx_get_fabric_name, | 1807 | .get_fabric_name = tcm_qla2xxx_get_fabric_name, |
| 1991 | .get_fabric_proto_ident = tcm_qla2xxx_get_fabric_proto_ident, | ||
| 1992 | .tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn, | 1808 | .tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn, |
| 1993 | .tpg_get_tag = tcm_qla2xxx_get_tag, | 1809 | .tpg_get_tag = tcm_qla2xxx_get_tag, |
| 1994 | .tpg_get_default_depth = tcm_qla2xxx_get_default_depth, | ||
| 1995 | .tpg_get_pr_transport_id = tcm_qla2xxx_get_pr_transport_id, | ||
| 1996 | .tpg_get_pr_transport_id_len = tcm_qla2xxx_get_pr_transport_id_len, | ||
| 1997 | .tpg_parse_pr_out_transport_id = tcm_qla2xxx_parse_pr_out_transport_id, | ||
| 1998 | .tpg_check_demo_mode = tcm_qla2xxx_check_demo_mode, | 1810 | .tpg_check_demo_mode = tcm_qla2xxx_check_demo_mode, |
| 1999 | .tpg_check_demo_mode_cache = tcm_qla2xxx_check_demo_mode_cache, | 1811 | .tpg_check_demo_mode_cache = tcm_qla2xxx_check_demo_mode_cache, |
| 2000 | .tpg_check_demo_mode_write_protect = | 1812 | .tpg_check_demo_mode_write_protect = |
| @@ -2003,12 +1815,9 @@ static const struct target_core_fabric_ops tcm_qla2xxx_ops = { | |||
| 2003 | tcm_qla2xxx_check_prod_write_protect, | 1815 | tcm_qla2xxx_check_prod_write_protect, |
| 2004 | .tpg_check_prot_fabric_only = tcm_qla2xxx_check_prot_fabric_only, | 1816 | .tpg_check_prot_fabric_only = tcm_qla2xxx_check_prot_fabric_only, |
| 2005 | .tpg_check_demo_mode_login_only = tcm_qla2xxx_check_demo_mode_login_only, | 1817 | .tpg_check_demo_mode_login_only = tcm_qla2xxx_check_demo_mode_login_only, |
| 2006 | .tpg_alloc_fabric_acl = tcm_qla2xxx_alloc_fabric_acl, | ||
| 2007 | .tpg_release_fabric_acl = tcm_qla2xxx_release_fabric_acl, | ||
| 2008 | .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, | 1818 | .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, |
| 2009 | .check_stop_free = tcm_qla2xxx_check_stop_free, | 1819 | .check_stop_free = tcm_qla2xxx_check_stop_free, |
| 2010 | .release_cmd = tcm_qla2xxx_release_cmd, | 1820 | .release_cmd = tcm_qla2xxx_release_cmd, |
| 2011 | .put_session = tcm_qla2xxx_put_session, | ||
| 2012 | .shutdown_session = tcm_qla2xxx_shutdown_session, | 1821 | .shutdown_session = tcm_qla2xxx_shutdown_session, |
| 2013 | .close_session = tcm_qla2xxx_close_session, | 1822 | .close_session = tcm_qla2xxx_close_session, |
| 2014 | .sess_get_index = tcm_qla2xxx_sess_get_index, | 1823 | .sess_get_index = tcm_qla2xxx_sess_get_index, |
| @@ -2016,7 +1825,6 @@ static const struct target_core_fabric_ops tcm_qla2xxx_ops = { | |||
| 2016 | .write_pending = tcm_qla2xxx_write_pending, | 1825 | .write_pending = tcm_qla2xxx_write_pending, |
| 2017 | .write_pending_status = tcm_qla2xxx_write_pending_status, | 1826 | .write_pending_status = tcm_qla2xxx_write_pending_status, |
| 2018 | .set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs, | 1827 | .set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs, |
| 2019 | .get_task_tag = tcm_qla2xxx_get_task_tag, | ||
| 2020 | .get_cmd_state = tcm_qla2xxx_get_cmd_state, | 1828 | .get_cmd_state = tcm_qla2xxx_get_cmd_state, |
| 2021 | .queue_data_in = tcm_qla2xxx_queue_data_in, | 1829 | .queue_data_in = tcm_qla2xxx_queue_data_in, |
| 2022 | .queue_status = tcm_qla2xxx_queue_status, | 1830 | .queue_status = tcm_qla2xxx_queue_status, |
| @@ -2030,12 +1838,7 @@ static const struct target_core_fabric_ops tcm_qla2xxx_ops = { | |||
| 2030 | .fabric_drop_wwn = tcm_qla2xxx_drop_lport, | 1838 | .fabric_drop_wwn = tcm_qla2xxx_drop_lport, |
| 2031 | .fabric_make_tpg = tcm_qla2xxx_make_tpg, | 1839 | .fabric_make_tpg = tcm_qla2xxx_make_tpg, |
| 2032 | .fabric_drop_tpg = tcm_qla2xxx_drop_tpg, | 1840 | .fabric_drop_tpg = tcm_qla2xxx_drop_tpg, |
| 2033 | .fabric_post_link = NULL, | 1841 | .fabric_init_nodeacl = tcm_qla2xxx_init_nodeacl, |
| 2034 | .fabric_pre_unlink = NULL, | ||
| 2035 | .fabric_make_np = NULL, | ||
| 2036 | .fabric_drop_np = NULL, | ||
| 2037 | .fabric_make_nodeacl = tcm_qla2xxx_make_nodeacl, | ||
| 2038 | .fabric_drop_nodeacl = tcm_qla2xxx_drop_nodeacl, | ||
| 2039 | 1842 | ||
| 2040 | .tfc_wwn_attrs = tcm_qla2xxx_wwn_attrs, | 1843 | .tfc_wwn_attrs = tcm_qla2xxx_wwn_attrs, |
| 2041 | .tfc_tpg_base_attrs = tcm_qla2xxx_tpg_attrs, | 1844 | .tfc_tpg_base_attrs = tcm_qla2xxx_tpg_attrs, |
| @@ -2045,26 +1848,19 @@ static const struct target_core_fabric_ops tcm_qla2xxx_ops = { | |||
| 2045 | static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = { | 1848 | static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = { |
| 2046 | .module = THIS_MODULE, | 1849 | .module = THIS_MODULE, |
| 2047 | .name = "qla2xxx_npiv", | 1850 | .name = "qla2xxx_npiv", |
| 1851 | .node_acl_size = sizeof(struct tcm_qla2xxx_nacl), | ||
| 2048 | .get_fabric_name = tcm_qla2xxx_npiv_get_fabric_name, | 1852 | .get_fabric_name = tcm_qla2xxx_npiv_get_fabric_name, |
| 2049 | .get_fabric_proto_ident = tcm_qla2xxx_get_fabric_proto_ident, | ||
| 2050 | .tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn, | 1853 | .tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn, |
| 2051 | .tpg_get_tag = tcm_qla2xxx_get_tag, | 1854 | .tpg_get_tag = tcm_qla2xxx_get_tag, |
| 2052 | .tpg_get_default_depth = tcm_qla2xxx_get_default_depth, | ||
| 2053 | .tpg_get_pr_transport_id = tcm_qla2xxx_get_pr_transport_id, | ||
| 2054 | .tpg_get_pr_transport_id_len = tcm_qla2xxx_get_pr_transport_id_len, | ||
| 2055 | .tpg_parse_pr_out_transport_id = tcm_qla2xxx_parse_pr_out_transport_id, | ||
| 2056 | .tpg_check_demo_mode = tcm_qla2xxx_check_demo_mode, | 1855 | .tpg_check_demo_mode = tcm_qla2xxx_check_demo_mode, |
| 2057 | .tpg_check_demo_mode_cache = tcm_qla2xxx_check_demo_mode_cache, | 1856 | .tpg_check_demo_mode_cache = tcm_qla2xxx_check_demo_mode_cache, |
| 2058 | .tpg_check_demo_mode_write_protect = tcm_qla2xxx_check_demo_mode, | 1857 | .tpg_check_demo_mode_write_protect = tcm_qla2xxx_check_demo_mode, |
| 2059 | .tpg_check_prod_mode_write_protect = | 1858 | .tpg_check_prod_mode_write_protect = |
| 2060 | tcm_qla2xxx_check_prod_write_protect, | 1859 | tcm_qla2xxx_check_prod_write_protect, |
| 2061 | .tpg_check_demo_mode_login_only = tcm_qla2xxx_check_demo_mode_login_only, | 1860 | .tpg_check_demo_mode_login_only = tcm_qla2xxx_check_demo_mode_login_only, |
| 2062 | .tpg_alloc_fabric_acl = tcm_qla2xxx_alloc_fabric_acl, | ||
| 2063 | .tpg_release_fabric_acl = tcm_qla2xxx_release_fabric_acl, | ||
| 2064 | .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, | 1861 | .tpg_get_inst_index = tcm_qla2xxx_tpg_get_inst_index, |
| 2065 | .check_stop_free = tcm_qla2xxx_check_stop_free, | 1862 | .check_stop_free = tcm_qla2xxx_check_stop_free, |
| 2066 | .release_cmd = tcm_qla2xxx_release_cmd, | 1863 | .release_cmd = tcm_qla2xxx_release_cmd, |
| 2067 | .put_session = tcm_qla2xxx_put_session, | ||
| 2068 | .shutdown_session = tcm_qla2xxx_shutdown_session, | 1864 | .shutdown_session = tcm_qla2xxx_shutdown_session, |
| 2069 | .close_session = tcm_qla2xxx_close_session, | 1865 | .close_session = tcm_qla2xxx_close_session, |
| 2070 | .sess_get_index = tcm_qla2xxx_sess_get_index, | 1866 | .sess_get_index = tcm_qla2xxx_sess_get_index, |
| @@ -2072,7 +1868,6 @@ static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = { | |||
| 2072 | .write_pending = tcm_qla2xxx_write_pending, | 1868 | .write_pending = tcm_qla2xxx_write_pending, |
| 2073 | .write_pending_status = tcm_qla2xxx_write_pending_status, | 1869 | .write_pending_status = tcm_qla2xxx_write_pending_status, |
| 2074 | .set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs, | 1870 | .set_default_node_attributes = tcm_qla2xxx_set_default_node_attrs, |
| 2075 | .get_task_tag = tcm_qla2xxx_get_task_tag, | ||
| 2076 | .get_cmd_state = tcm_qla2xxx_get_cmd_state, | 1871 | .get_cmd_state = tcm_qla2xxx_get_cmd_state, |
| 2077 | .queue_data_in = tcm_qla2xxx_queue_data_in, | 1872 | .queue_data_in = tcm_qla2xxx_queue_data_in, |
| 2078 | .queue_status = tcm_qla2xxx_queue_status, | 1873 | .queue_status = tcm_qla2xxx_queue_status, |
| @@ -2086,12 +1881,7 @@ static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = { | |||
| 2086 | .fabric_drop_wwn = tcm_qla2xxx_npiv_drop_lport, | 1881 | .fabric_drop_wwn = tcm_qla2xxx_npiv_drop_lport, |
| 2087 | .fabric_make_tpg = tcm_qla2xxx_npiv_make_tpg, | 1882 | .fabric_make_tpg = tcm_qla2xxx_npiv_make_tpg, |
| 2088 | .fabric_drop_tpg = tcm_qla2xxx_drop_tpg, | 1883 | .fabric_drop_tpg = tcm_qla2xxx_drop_tpg, |
| 2089 | .fabric_post_link = NULL, | 1884 | .fabric_init_nodeacl = tcm_qla2xxx_init_nodeacl, |
| 2090 | .fabric_pre_unlink = NULL, | ||
| 2091 | .fabric_make_np = NULL, | ||
| 2092 | .fabric_drop_np = NULL, | ||
| 2093 | .fabric_make_nodeacl = tcm_qla2xxx_make_nodeacl, | ||
| 2094 | .fabric_drop_nodeacl = tcm_qla2xxx_drop_nodeacl, | ||
| 2095 | 1885 | ||
| 2096 | .tfc_wwn_attrs = tcm_qla2xxx_wwn_attrs, | 1886 | .tfc_wwn_attrs = tcm_qla2xxx_wwn_attrs, |
| 2097 | .tfc_tpg_base_attrs = tcm_qla2xxx_npiv_tpg_attrs, | 1887 | .tfc_tpg_base_attrs = tcm_qla2xxx_npiv_tpg_attrs, |
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/drivers/scsi/qla2xxx/tcm_qla2xxx.h index 23295115c9fc..3bbf4cb6fd97 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.h +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.h | |||
| @@ -13,6 +13,8 @@ | |||
| 13 | #include "qla_target.h" | 13 | #include "qla_target.h" |
| 14 | 14 | ||
| 15 | struct tcm_qla2xxx_nacl { | 15 | struct tcm_qla2xxx_nacl { |
| 16 | struct se_node_acl se_node_acl; | ||
| 17 | |||
| 16 | /* From libfc struct fc_rport->port_id */ | 18 | /* From libfc struct fc_rport->port_id */ |
| 17 | u32 nport_id; | 19 | u32 nport_id; |
| 18 | /* Binary World Wide unique Node Name for remote FC Initiator Nport */ | 20 | /* Binary World Wide unique Node Name for remote FC Initiator Nport */ |
| @@ -23,8 +25,6 @@ struct tcm_qla2xxx_nacl { | |||
| 23 | struct qla_tgt_sess *qla_tgt_sess; | 25 | struct qla_tgt_sess *qla_tgt_sess; |
| 24 | /* Pointer to TCM FC nexus */ | 26 | /* Pointer to TCM FC nexus */ |
| 25 | struct se_session *nport_nexus; | 27 | struct se_session *nport_nexus; |
| 26 | /* Returned by tcm_qla2xxx_make_nodeacl() */ | ||
| 27 | struct se_node_acl se_node_acl; | ||
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | struct tcm_qla2xxx_tpg_attrib { | 30 | struct tcm_qla2xxx_tpg_attrib { |
| @@ -57,8 +57,6 @@ struct tcm_qla2xxx_fc_loopid { | |||
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | struct tcm_qla2xxx_lport { | 59 | struct tcm_qla2xxx_lport { |
| 60 | /* SCSI protocol the lport is providing */ | ||
| 61 | u8 lport_proto_id; | ||
| 62 | /* Binary World Wide unique Port Name for FC Target Lport */ | 60 | /* Binary World Wide unique Port Name for FC Target Lport */ |
| 63 | u64 lport_wwpn; | 61 | u64 lport_wwpn; |
| 64 | /* Binary World Wide unique Port Name for FC NPIV Target Lport */ | 62 | /* Binary World Wide unique Port Name for FC NPIV Target Lport */ |
