diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-15 01:15:35 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-15 01:15:35 +0300 |
commit | 55e0500eb5c0440a3d43074edbd8db3e95851b66 (patch) | |
tree | 874b9da7a764df298441242ce79b9fd89c2910df /drivers/scsi/ibmvscsi | |
parent | 4815519ed0af833884ce9c288183bf1ae3cb9caa (diff) | |
parent | 69f4ec1edb136d2d2511d1ef96f94ef0aeecefdf (diff) | |
download | linux-55e0500eb5c0440a3d43074edbd8db3e95851b66.tar.xz |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"The usual driver updates (ufs, qla2xxx, tcmu, ibmvfc, lpfc, smartpqi,
hisi_sas, qedi, qedf, mpt3sas) and minor bug fixes.
There are only three core changes: adding sense codes, cleaning up
noretry and adding an option for limitless retries"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (226 commits)
scsi: hisi_sas: Recover PHY state according to the status before reset
scsi: hisi_sas: Filter out new PHY up events during suspend
scsi: hisi_sas: Add device link between SCSI devices and hisi_hba
scsi: hisi_sas: Add check for methods _PS0 and _PR0
scsi: hisi_sas: Add controller runtime PM support for v3 hw
scsi: hisi_sas: Switch to new framework to support suspend and resume
scsi: hisi_sas: Use hisi_hba->cq_nvecs for calling calling synchronize_irq()
scsi: qedf: Remove redundant assignment to variable 'rc'
scsi: lpfc: Remove unneeded variable 'status' in lpfc_fcp_cpu_map_store()
scsi: snic: Convert to use DEFINE_SEQ_ATTRIBUTE macro
scsi: qla4xxx: Delete unneeded variable 'status' in qla4xxx_process_ddb_changed
scsi: sun_esp: Use module_platform_driver to simplify the code
scsi: sun3x_esp: Use module_platform_driver to simplify the code
scsi: sni_53c710: Use module_platform_driver to simplify the code
scsi: qlogicpti: Use module_platform_driver to simplify the code
scsi: mac_esp: Use module_platform_driver to simplify the code
scsi: jazz_esp: Use module_platform_driver to simplify the code
scsi: mvumi: Fix error return in mvumi_io_attach()
scsi: lpfc: Drop nodelist reference on error in lpfc_gen_req()
scsi: be2iscsi: Fix a theoretical leak in beiscsi_create_eqs()
...
Diffstat (limited to 'drivers/scsi/ibmvscsi')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvfc.c | 229 | ||||
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvfc.h | 160 |
2 files changed, 342 insertions, 47 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index ea7c8930592d..070cf516b98f 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -134,6 +134,7 @@ static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *); static void ibmvfc_tgt_query_target(struct ibmvfc_target *); static void ibmvfc_npiv_logout(struct ibmvfc_host *); static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *); +static void ibmvfc_tgt_move_login(struct ibmvfc_target *); static const char *unknown_error = "unknown error"; @@ -431,7 +432,20 @@ static int ibmvfc_set_tgt_action(struct ibmvfc_target *tgt, } break; case IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT: - if (action == IBMVFC_TGT_ACTION_DEL_RPORT) { + if (action == IBMVFC_TGT_ACTION_DEL_RPORT || + action == IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT) { + tgt->action = action; + rc = 0; + } + break; + case IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT: + if (action == IBMVFC_TGT_ACTION_LOGOUT_RPORT) { + tgt->action = action; + rc = 0; + } + break; + case IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT: + if (action == IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT) { tgt->action = action; rc = 0; } @@ -441,16 +455,18 @@ static int ibmvfc_set_tgt_action(struct ibmvfc_target *tgt, tgt->action = action; rc = 0; } + break; case IBMVFC_TGT_ACTION_DELETED_RPORT: break; default: - if (action >= IBMVFC_TGT_ACTION_LOGOUT_RPORT) - tgt->add_rport = 0; tgt->action = action; rc = 0; break; } + if (action >= IBMVFC_TGT_ACTION_LOGOUT_RPORT) + tgt->add_rport = 0; + return rc; } @@ -548,7 +564,8 @@ static void ibmvfc_set_host_action(struct ibmvfc_host *vhost, **/ static void ibmvfc_reinit_host(struct ibmvfc_host *vhost) { - if (vhost->action == IBMVFC_HOST_ACTION_NONE) { + if (vhost->action == IBMVFC_HOST_ACTION_NONE && + vhost->state == IBMVFC_ACTIVE) { if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) { scsi_block_requests(vhost->host); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY); @@ -2574,7 +2591,9 @@ static void ibmvfc_terminate_rport_io(struct fc_rport *rport) struct ibmvfc_host *vhost = shost_priv(shost); struct fc_rport *dev_rport; struct scsi_device *sdev; - unsigned long rc; + struct ibmvfc_target *tgt; + unsigned long rc, flags; + unsigned int found; ENTER; shost_for_each_device(sdev, shost) { @@ -2588,6 +2607,27 @@ static void ibmvfc_terminate_rport_io(struct fc_rport *rport) if (rc == FAILED) ibmvfc_issue_fc_host_lip(shost); + + spin_lock_irqsave(shost->host_lock, flags); + found = 0; + list_for_each_entry(tgt, &vhost->targets, queue) { + if (tgt->scsi_id == rport->port_id) { + found++; + break; + } + } + + if (found && tgt->action == IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT) { + /* + * If we get here, that means we previously attempted to send + * an implicit logout to the target but it failed, most likely + * due to I/O being pending, so we need to send it again + */ + ibmvfc_del_tgt(tgt); + ibmvfc_reinit_host(vhost); + } + + spin_unlock_irqrestore(shost->host_lock, flags); LEAVE; } @@ -3623,7 +3663,18 @@ static void ibmvfc_tgt_implicit_logout_and_del_done(struct ibmvfc_event *evt) vhost->discovery_threads--; ibmvfc_free_event(evt); - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + + /* + * If our state is IBMVFC_HOST_OFFLINE, we could be unloading the + * driver in which case we need to free up all the targets. If we are + * not unloading, we will still go through a hard reset to get out of + * offline state, so there is no need to track the old targets in that + * case. + */ + if (status == IBMVFC_MAD_SUCCESS || vhost->state == IBMVFC_HOST_OFFLINE) + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + else + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT); tgt_dbg(tgt, "Implicit Logout %s\n", (status == IBMVFC_MAD_SUCCESS) ? "succeeded" : "failed"); kref_put(&tgt->kref, ibmvfc_release_tgt); @@ -3662,6 +3713,94 @@ static void ibmvfc_tgt_implicit_logout_and_del(struct ibmvfc_target *tgt) } /** + * ibmvfc_tgt_move_login_done - Completion handler for Move Login + * @evt: ibmvfc event struct + * + **/ +static void ibmvfc_tgt_move_login_done(struct ibmvfc_event *evt) +{ + struct ibmvfc_target *tgt = evt->tgt; + struct ibmvfc_host *vhost = evt->vhost; + struct ibmvfc_move_login *rsp = &evt->xfer_iu->move_login; + u32 status = be16_to_cpu(rsp->common.status); + int level = IBMVFC_DEFAULT_LOG_LEVEL; + + vhost->discovery_threads--; + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE); + switch (status) { + case IBMVFC_MAD_SUCCESS: + tgt_dbg(tgt, "Move Login succeeded for old scsi_id: %llX\n", tgt->old_scsi_id); + tgt->ids.node_name = wwn_to_u64(rsp->service_parms.node_name); + tgt->ids.port_name = wwn_to_u64(rsp->service_parms.port_name); + tgt->ids.port_id = tgt->scsi_id; + memcpy(&tgt->service_parms, &rsp->service_parms, + sizeof(tgt->service_parms)); + memcpy(&tgt->service_parms_change, &rsp->service_parms_change, + sizeof(tgt->service_parms_change)); + ibmvfc_init_tgt(tgt, ibmvfc_tgt_send_prli); + break; + case IBMVFC_MAD_DRIVER_FAILED: + break; + case IBMVFC_MAD_CRQ_ERROR: + ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_move_login); + break; + case IBMVFC_MAD_FAILED: + default: + level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_move_login); + + tgt_log(tgt, level, + "Move Login failed: old scsi_id: %llX, flags:%x, vios_flags:%x, rc=0x%02X\n", + tgt->old_scsi_id, be32_to_cpu(rsp->flags), be16_to_cpu(rsp->vios_flags), + status); + break; + } + + kref_put(&tgt->kref, ibmvfc_release_tgt); + ibmvfc_free_event(evt); + wake_up(&vhost->work_wait_q); +} + + +/** + * ibmvfc_tgt_move_login - Initiate a move login for specified target + * @tgt: ibmvfc target struct + * + **/ +static void ibmvfc_tgt_move_login(struct ibmvfc_target *tgt) +{ + struct ibmvfc_host *vhost = tgt->vhost; + struct ibmvfc_move_login *move; + struct ibmvfc_event *evt; + + if (vhost->discovery_threads >= disc_threads) + return; + + kref_get(&tgt->kref); + evt = ibmvfc_get_event(vhost); + vhost->discovery_threads++; + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); + ibmvfc_init_event(evt, ibmvfc_tgt_move_login_done, IBMVFC_MAD_FORMAT); + evt->tgt = tgt; + move = &evt->iu.move_login; + memset(move, 0, sizeof(*move)); + move->common.version = cpu_to_be32(1); + move->common.opcode = cpu_to_be32(IBMVFC_MOVE_LOGIN); + move->common.length = cpu_to_be16(sizeof(*move)); + + move->old_scsi_id = cpu_to_be64(tgt->old_scsi_id); + move->new_scsi_id = cpu_to_be64(tgt->scsi_id); + move->wwpn = cpu_to_be64(tgt->wwpn); + move->node_name = cpu_to_be64(tgt->ids.node_name); + + if (ibmvfc_send_event(evt, vhost, default_timeout)) { + vhost->discovery_threads--; + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + kref_put(&tgt->kref, ibmvfc_release_tgt); + } else + tgt_dbg(tgt, "Sent Move Login for old scsi_id: %llX\n", tgt->old_scsi_id); +} + +/** * ibmvfc_adisc_needs_plogi - Does device need PLOGI? * @mad: ibmvfc passthru mad struct * @tgt: ibmvfc target struct @@ -3979,31 +4118,77 @@ static void ibmvfc_tgt_query_target(struct ibmvfc_target *tgt) * Returns: * 0 on success / other on failure **/ -static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, u64 scsi_id) +static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, + struct ibmvfc_discover_targets_entry *target) { + struct ibmvfc_target *stgt = NULL; + struct ibmvfc_target *wtgt = NULL; struct ibmvfc_target *tgt; unsigned long flags; + u64 scsi_id = be32_to_cpu(target->scsi_id) & IBMVFC_DISC_TGT_SCSI_ID_MASK; + u64 wwpn = be64_to_cpu(target->wwpn); + /* Look to see if we already have a target allocated for this SCSI ID or WWPN */ spin_lock_irqsave(vhost->host->host_lock, flags); list_for_each_entry(tgt, &vhost->targets, queue) { + if (tgt->wwpn == wwpn) { + wtgt = tgt; + break; + } + } + + list_for_each_entry(tgt, &vhost->targets, queue) { if (tgt->scsi_id == scsi_id) { - if (tgt->need_login) - ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout); + stgt = tgt; + break; + } + } + + if (wtgt && !stgt) { + /* + * A WWPN target has moved and we still are tracking the old + * SCSI ID. The only way we should be able to get here is if + * we attempted to send an implicit logout for the old SCSI ID + * and it failed for some reason, such as there being I/O + * pending to the target. In this case, we will have already + * deleted the rport from the FC transport so we do a move + * login, which works even with I/O pending, as it will cancel + * any active commands. + */ + if (wtgt->action == IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT) { + /* + * Do a move login here. The old target is no longer + * known to the transport layer We don't use the + * normal ibmvfc_set_tgt_action to set this, as we + * don't normally want to allow this state change. + */ + wtgt->old_scsi_id = wtgt->scsi_id; + wtgt->scsi_id = scsi_id; + wtgt->action = IBMVFC_TGT_ACTION_INIT; + ibmvfc_init_tgt(wtgt, ibmvfc_tgt_move_login); goto unlock_out; + } else { + tgt_err(wtgt, "Unexpected target state: %d, %p\n", + wtgt->action, wtgt->rport); } + } else if (stgt) { + if (tgt->need_login) + ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout); + goto unlock_out; } spin_unlock_irqrestore(vhost->host->host_lock, flags); tgt = mempool_alloc(vhost->tgt_pool, GFP_NOIO); memset(tgt, 0, sizeof(*tgt)); tgt->scsi_id = scsi_id; + tgt->wwpn = wwpn; tgt->vhost = vhost; tgt->need_login = 1; - tgt->cancel_key = vhost->task_set++; timer_setup(&tgt->timer, ibmvfc_adisc_timeout, 0); kref_init(&tgt->kref); ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout); spin_lock_irqsave(vhost->host->host_lock, flags); + tgt->cancel_key = vhost->task_set++; list_add_tail(&tgt->queue, &vhost->targets); unlock_out: @@ -4023,9 +4208,7 @@ static int ibmvfc_alloc_targets(struct ibmvfc_host *vhost) int i, rc; for (i = 0, rc = 0; !rc && i < vhost->num_targets; i++) - rc = ibmvfc_alloc_target(vhost, - be32_to_cpu(vhost->disc_buf->scsi_id[i]) & - IBMVFC_DISC_TGT_SCSI_ID_MASK); + rc = ibmvfc_alloc_target(vhost, &vhost->disc_buf[i]); return rc; } @@ -4085,6 +4268,7 @@ static void ibmvfc_discover_targets(struct ibmvfc_host *vhost) mad->bufflen = cpu_to_be32(vhost->disc_buf_sz); mad->buffer.va = cpu_to_be64(vhost->disc_buf_dma); mad->buffer.len = cpu_to_be32(vhost->disc_buf_sz); + mad->flags = cpu_to_be32(IBMVFC_DISC_TGT_PORT_ID_WWPN_LIST); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT); if (!ibmvfc_send_event(evt, vhost, default_timeout)) @@ -4420,6 +4604,13 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt) del_timer_sync(&tgt->timer); kref_put(&tgt->kref, ibmvfc_release_tgt); return; + } else if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT) { + tgt_dbg(tgt, "Deleting rport with outstanding I/O\n"); + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT); + tgt->rport = NULL; + spin_unlock_irqrestore(vhost->host->host_lock, flags); + fc_remote_port_delete(rport); + return; } else if (rport && tgt->action == IBMVFC_TGT_ACTION_DELETED_RPORT) { spin_unlock_irqrestore(vhost->host->host_lock, flags); return; @@ -4543,6 +4734,15 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) del_timer_sync(&tgt->timer); kref_put(&tgt->kref, ibmvfc_release_tgt); return; + } else if (tgt->action == IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT) { + tgt_dbg(tgt, "Deleting rport with I/O outstanding\n"); + rport = tgt->rport; + tgt->rport = NULL; + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT); + spin_unlock_irqrestore(vhost->host->host_lock, flags); + if (rport) + fc_remote_port_delete(rport); + return; } } @@ -4775,7 +4975,7 @@ static int ibmvfc_alloc_mem(struct ibmvfc_host *vhost) goto free_sg_pool; } - vhost->disc_buf_sz = sizeof(vhost->disc_buf->scsi_id[0]) * max_targets; + vhost->disc_buf_sz = sizeof(*vhost->disc_buf) * max_targets; vhost->disc_buf = dma_alloc_coherent(dev, vhost->disc_buf_sz, &vhost->disc_buf_dma, GFP_KERNEL); @@ -4928,6 +5128,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id) if (IS_ERR(vhost->work_thread)) { dev_err(dev, "Couldn't create kernel thread: %ld\n", PTR_ERR(vhost->work_thread)); + rc = PTR_ERR(vhost->work_thread); goto free_host_mem; } diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index 907889f1fa9d..34debccfb142 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -120,10 +120,14 @@ enum ibmvfc_mad_types { IBMVFC_PORT_LOGIN = 0x0004, IBMVFC_PROCESS_LOGIN = 0x0008, IBMVFC_QUERY_TARGET = 0x0010, + IBMVFC_MOVE_LOGIN = 0x0020, IBMVFC_IMPLICIT_LOGOUT = 0x0040, IBMVFC_PASSTHRU = 0x0200, IBMVFC_TMF_MAD = 0x0100, IBMVFC_NPIV_LOGOUT = 0x0800, + IBMVFC_CHANNEL_ENQUIRY = 0x1000, + IBMVFC_CHANNEL_SETUP = 0x2000, + IBMVFC_CONNECTION_INFO = 0x4000, }; struct ibmvfc_mad_common { @@ -133,16 +137,16 @@ struct ibmvfc_mad_common { __be16 status; __be16 length; __be64 tag; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); struct ibmvfc_npiv_login_mad { struct ibmvfc_mad_common common; struct srp_direct_buf buffer; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); struct ibmvfc_npiv_logout_mad { struct ibmvfc_mad_common common; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); #define IBMVFC_MAX_NAME 256 @@ -162,13 +166,15 @@ struct ibmvfc_npiv_login { __be32 max_cmds; __be64 capabilities; #define IBMVFC_CAN_MIGRATE 0x01 +#define IBMVFC_CAN_USE_CHANNELS 0x02 +#define IBMVFC_CAN_HANDLE_FPIN 0x04 __be64 node_name; struct srp_direct_buf async; u8 partition_name[IBMVFC_MAX_NAME]; u8 device_name[IBMVFC_MAX_NAME]; u8 drc_name[IBMVFC_MAX_NAME]; __be64 reserved2[2]; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); struct ibmvfc_common_svc_parms { __be16 fcph_version; @@ -177,7 +183,7 @@ struct ibmvfc_common_svc_parms { __be16 bb_rcv_sz; /* upper nibble is BB_SC_N */ __be32 ratov; __be32 edtov; -}__attribute__((packed, aligned (4))); +} __packed __aligned(4); struct ibmvfc_service_parms { struct ibmvfc_common_svc_parms common; @@ -192,7 +198,8 @@ struct ibmvfc_service_parms { __be32 ext_len; __be32 reserved[30]; __be32 clk_sync_qos[2]; -}__attribute__((packed, aligned (4))); + __be32 reserved2; +} __packed __aligned(4); struct ibmvfc_npiv_login_resp { __be32 version; @@ -204,6 +211,7 @@ struct ibmvfc_npiv_login_resp { __be64 capabilities; #define IBMVFC_CAN_FLUSH_ON_HALT 0x08 #define IBMVFC_CAN_SUPPRESS_ABTS 0x10 +#define IBMVFC_CAN_SUPPORT_CHANNELS 0x20 __be32 max_cmds; __be32 scsi_id_sz; __be64 max_dma_len; @@ -217,29 +225,32 @@ struct ibmvfc_npiv_login_resp { u8 drc_name[IBMVFC_MAX_NAME]; struct ibmvfc_service_parms service_parms; __be64 reserved2; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); union ibmvfc_npiv_login_data { struct ibmvfc_npiv_login login; struct ibmvfc_npiv_login_resp resp; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); -struct ibmvfc_discover_targets_buf { - __be32 scsi_id[1]; +struct ibmvfc_discover_targets_entry { + __be32 scsi_id; + __be32 pad; + __be64 wwpn; #define IBMVFC_DISC_TGT_SCSI_ID_MASK 0x00ffffff -}; +} __packed __aligned(8); struct ibmvfc_discover_targets { struct ibmvfc_mad_common common; struct srp_direct_buf buffer; __be32 flags; +#define IBMVFC_DISC_TGT_PORT_ID_WWPN_LIST 0x02 __be16 status; __be16 error; __be32 bufflen; __be32 num_avail; __be32 num_written; __be64 reserved[2]; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); enum ibmvfc_fc_reason { IBMVFC_INVALID_ELS_CMD_CODE = 0x01, @@ -283,7 +294,27 @@ struct ibmvfc_port_login { struct ibmvfc_service_parms service_parms; struct ibmvfc_service_parms service_parms_change; __be64 reserved3[2]; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); + +struct ibmvfc_move_login { + struct ibmvfc_mad_common common; + __be64 old_scsi_id; + __be64 new_scsi_id; + __be64 wwpn; + __be64 node_name; + __be32 flags; +#define IBMVFC_MOVE_LOGIN_IMPLICIT_OLD_FAILED 0x01 +#define IBMVFC_MOVE_LOGIN_IMPLICIT_NEW_FAILED 0x02 +#define IBMVFC_MOVE_LOGIN_PORT_LOGIN_FAILED 0x04 + __be32 reserved; + struct ibmvfc_service_parms service_parms; + struct ibmvfc_service_parms service_parms_change; + __be32 reserved2; + __be16 service_class; + __be16 vios_flags; +#define IBMVFC_MOVE_LOGIN_VF_NOT_SENT_ADAPTER 0x01 + __be64 reserved3; +} __packed __aligned(8); struct ibmvfc_prli_svc_parms { u8 type; @@ -303,7 +334,7 @@ struct ibmvfc_prli_svc_parms { #define IBMVFC_PRLI_TARGET_FUNC 0x00000010 #define IBMVFC_PRLI_READ_FCP_XFER_RDY_DISABLED 0x00000002 #define IBMVFC_PRLI_WR_FCP_XFER_RDY_DISABLED 0x00000001 -}__attribute__((packed, aligned (4))); +} __packed __aligned(4); struct ibmvfc_process_login { struct ibmvfc_mad_common common; @@ -314,7 +345,7 @@ struct ibmvfc_process_login { __be16 error; /* also fc_reason */ __be32 reserved2; __be64 reserved3[2]; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); struct ibmvfc_query_tgt { struct ibmvfc_mad_common common; @@ -325,13 +356,13 @@ struct ibmvfc_query_tgt { __be16 fc_explain; __be16 fc_type; __be64 reserved[2]; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); struct ibmvfc_implicit_logout { struct ibmvfc_mad_common common; __be64 old_scsi_id; __be64 reserved[2]; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); struct ibmvfc_tmf { struct ibmvfc_mad_common common; @@ -348,7 +379,7 @@ struct ibmvfc_tmf { __be32 my_cancel_key; __be32 pad; __be64 reserved[2]; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); enum ibmvfc_fcp_rsp_info_codes { RSP_NO_FAILURE = 0x00, @@ -361,7 +392,7 @@ struct ibmvfc_fcp_rsp_info { u8 reserved[3]; u8 rsp_code; u8 reserved2[4]; -}__attribute__((packed, aligned (2))); +} __packed __aligned(2); enum ibmvfc_fcp_rsp_flags { FCP_BIDI_RSP = 0x80, @@ -377,7 +408,7 @@ enum ibmvfc_fcp_rsp_flags { union ibmvfc_fcp_rsp_data { struct ibmvfc_fcp_rsp_info info; u8 sense[SCSI_SENSE_BUFFERSIZE + sizeof(struct ibmvfc_fcp_rsp_info)]; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); struct ibmvfc_fcp_rsp { __be64 reserved; @@ -388,7 +419,7 @@ struct ibmvfc_fcp_rsp { __be32 fcp_sense_len; __be32 fcp_rsp_len; union ibmvfc_fcp_rsp_data data; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); enum ibmvfc_cmd_flags { IBMVFC_SCATTERLIST = 0x0001, @@ -422,7 +453,7 @@ struct ibmvfc_fcp_cmd_iu { #define IBMVFC_WRDATA 0x01 u8 cdb[IBMVFC_MAX_CDB_LEN]; __be32 xfer_len; -}__attribute__((packed, aligned (4))); +} __packed __aligned(4); struct ibmvfc_cmd { __be64 task_tag; @@ -446,7 +477,7 @@ struct ibmvfc_cmd { __be64 reserved3[2]; struct ibmvfc_fcp_cmd_iu iu; struct ibmvfc_fcp_rsp rsp; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); struct ibmvfc_passthru_fc_iu { __be32 payload[7]; @@ -473,18 +504,64 @@ struct ibmvfc_passthru_iu { __be64 scsi_id; __be64 tag; __be64 reserved2[2]; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); struct ibmvfc_passthru_mad { struct ibmvfc_mad_common common; struct srp_direct_buf cmd_ioba; struct ibmvfc_passthru_iu iu; struct ibmvfc_passthru_fc_iu fc_iu; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); + +struct ibmvfc_channel_enquiry { + struct ibmvfc_mad_common common; + __be32 flags; +#define IBMVFC_NO_CHANNELS_TO_CRQ_SUPPORT 0x01 +#define IBMVFC_SUPPORT_VARIABLE_SUBQ_MSG 0x02 +#define IBMVFC_NO_N_TO_M_CHANNELS_SUPPORT 0x04 + __be32 num_scsi_subq_channels; + __be32 num_nvmeof_subq_channels; + __be32 num_scsi_vas_channels; + __be32 num_nvmeof_vas_channels; +} __packed __aligned(8); + +struct ibmvfc_channel_setup_mad { + struct ibmvfc_mad_common common; + struct srp_direct_buf buffer; +} __packed __aligned(8); + +#define IBMVFC_MAX_CHANNELS 502 + +struct ibmvfc_channel_setup { + __be32 flags; +#define IBMVFC_CANCEL_CHANNELS 0x01 +#define IBMVFC_USE_BUFFER 0x02 +#define IBMVFC_CHANNELS_CANCELED 0x04 + __be32 reserved; + __be32 num_scsi_subq_channels; + __be32 num_nvmeof_subq_channels; + __be32 num_scsi_vas_channels; + __be32 num_nvmeof_vas_channels; + struct srp_direct_buf buffer; + __be64 reserved2[5]; + __be64 channel_handles[IBMVFC_MAX_CHANNELS]; +} __packed __aligned(8); + +struct ibmvfc_connection_info { + struct ibmvfc_mad_common common; + __be64 information_bits; +#define IBMVFC_NO_FC_IO_CHANNEL 0x01 +#define IBMVFC_NO_PHYP_VAS 0x02 +#define IBMVFC_NO_PHYP_SUBQ 0x04 +#define IBMVFC_PHYP_DEPRECATED_SUBQ 0x08 +#define IBMVFC_PHYP_PRESERVED_SUBQ 0x10 +#define IBMVFC_PHYP_FULL_SUBQ 0x20 + __be64 reserved[16]; +} __packed __aligned(8); struct ibmvfc_trace_start_entry { u32 xfer_len; -}__attribute__((packed)); +} __packed; struct ibmvfc_trace_end_entry { u16 status; @@ -493,7 +570,7 @@ struct ibmvfc_trace_end_entry { u8 rsp_code; u8 scsi_status; u8 reserved; -}__attribute__((packed)); +} __packed; struct ibmvfc_trace_entry { struct ibmvfc_event *evt; @@ -510,7 +587,7 @@ struct ibmvfc_trace_entry { struct ibmvfc_trace_start_entry start; struct ibmvfc_trace_end_entry end; } u; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); enum ibmvfc_crq_formats { IBMVFC_CMD_FORMAT = 0x01, @@ -532,6 +609,7 @@ enum ibmvfc_async_event { IBMVFC_AE_HALT = 0x0400, IBMVFC_AE_RESUME = 0x0800, IBMVFC_AE_ADAPTER_FAILED = 0x1000, + IBMVFC_AE_FPIN = 0x2000, }; struct ibmvfc_async_desc { @@ -545,7 +623,7 @@ struct ibmvfc_crq { volatile u8 format; u8 reserved[6]; volatile __be64 ioba; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); struct ibmvfc_crq_queue { struct ibmvfc_crq *msgs; @@ -560,17 +638,25 @@ enum ibmvfc_ae_link_state { IBMVFC_AE_LS_LINK_DEAD = 0x08, }; +enum ibmvfc_ae_fpin_status { + IBMVFC_AE_FPIN_LINK_CONGESTED = 0x1, + IBMVFC_AE_FPIN_PORT_CONGESTED = 0x2, + IBMVFC_AE_FPIN_PORT_CLEARED = 0x3, + IBMVFC_AE_FPIN_PORT_DEGRADED = 0x4, +}; + struct ibmvfc_async_crq { volatile u8 valid; u8 link_state; - u8 pad[2]; + u8 fpin_status; + u8 pad; __be32 pad2; volatile __be64 event; volatile __be64 scsi_id; volatile __be64 wwpn; volatile __be64 node_name; __be64 reserved; -}__attribute__((packed, aligned (8))); +} __packed __aligned(8); struct ibmvfc_async_crq_queue { struct ibmvfc_async_crq *msgs; @@ -585,12 +671,16 @@ union ibmvfc_iu { struct ibmvfc_discover_targets discover_targets; struct ibmvfc_port_login plogi; struct ibmvfc_process_login prli; + struct ibmvfc_move_login move_login; struct ibmvfc_query_tgt query_tgt; struct ibmvfc_implicit_logout implicit_logout; struct ibmvfc_tmf tmf; struct ibmvfc_cmd cmd; struct ibmvfc_passthru_mad passthru; -}__attribute__((packed, aligned (8))); + struct ibmvfc_channel_enquiry channel_enquiry; + struct ibmvfc_channel_setup_mad channel_setup; + struct ibmvfc_connection_info connection_info; +} __packed __aligned(8); enum ibmvfc_target_action { IBMVFC_TGT_ACTION_NONE = 0, @@ -600,12 +690,16 @@ enum ibmvfc_target_action { IBMVFC_TGT_ACTION_LOGOUT_RPORT_WAIT, IBMVFC_TGT_ACTION_DEL_RPORT, IBMVFC_TGT_ACTION_DELETED_RPORT, + IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT, + IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT, }; struct ibmvfc_target { struct list_head queue; struct ibmvfc_host *vhost; u64 scsi_id; + u64 wwpn; + u64 old_scsi_id; struct fc_rport *rport; int target_id; enum ibmvfc_target_action action; @@ -701,7 +795,7 @@ struct ibmvfc_host { dma_addr_t login_buf_dma; int disc_buf_sz; int log_level; - struct ibmvfc_discover_targets_buf *disc_buf; + struct ibmvfc_discover_targets_entry *disc_buf; struct mutex passthru_mutex; int task_set; int init_retries; |