From 547aab51a914e1f18394d8238ef9fb4f76d5b491 Mon Sep 17 00:00:00 2001 From: Shyam Sundar Date: Wed, 21 Oct 2020 02:27:12 -0700 Subject: scsi: fc: Add FPIN statistics to fc_host and fc_rport objects Add a structure for holding FPIN statistics, for host & rport respectively, and add associated sysfs nodes: /sys/class/fc_host/hostXX/statistics/ /sys/class/fc_remote_ports/rport-XX\:Y-Z/statistics/ Link: https://lore.kernel.org/r/20201021092715.22669-3-njavali@marvell.com Reviewed-by: James Smart Reviewed-by: Himanshu Madhani Signed-off-by: Shyam Sundar Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_fc.c | 117 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 2ff7f06203da..501e165ae6f1 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "scsi_priv.h" static int fc_queue_work(struct Scsi_Host *, struct work_struct *); @@ -419,6 +420,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev, fc_host->fabric_name = -1; memset(fc_host->symbolic_name, 0, sizeof(fc_host->symbolic_name)); memset(fc_host->system_hostname, 0, sizeof(fc_host->system_hostname)); + memset(&fc_host->fpin_stats, 0, sizeof(fc_host->fpin_stats)); fc_host->tgtid_bind_type = FC_TGTID_BIND_BY_WWPN; @@ -991,6 +993,67 @@ store_fc_rport_fast_io_fail_tmo(struct device *dev, static FC_DEVICE_ATTR(rport, fast_io_fail_tmo, S_IRUGO | S_IWUSR, show_fc_rport_fast_io_fail_tmo, store_fc_rport_fast_io_fail_tmo); +#define fc_rport_fpin_statistic(name) \ +static ssize_t fc_rport_fpinstat_##name(struct device *cd, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct fc_rport *rport = transport_class_to_rport(cd); \ + \ + return snprintf(buf, 20, "0x%llx\n", rport->fpin_stats.name); \ +} \ +static FC_DEVICE_ATTR(rport, fpin_##name, 0444, fc_rport_fpinstat_##name, NULL) + +fc_rport_fpin_statistic(dn); +fc_rport_fpin_statistic(dn_unknown); +fc_rport_fpin_statistic(dn_timeout); +fc_rport_fpin_statistic(dn_unable_to_route); +fc_rport_fpin_statistic(dn_device_specific); +fc_rport_fpin_statistic(cn); +fc_rport_fpin_statistic(cn_clear); +fc_rport_fpin_statistic(cn_lost_credit); +fc_rport_fpin_statistic(cn_credit_stall); +fc_rport_fpin_statistic(cn_oversubscription); +fc_rport_fpin_statistic(cn_device_specific); +fc_rport_fpin_statistic(li); +fc_rport_fpin_statistic(li_failure_unknown); +fc_rport_fpin_statistic(li_link_failure_count); +fc_rport_fpin_statistic(li_loss_of_sync_count); +fc_rport_fpin_statistic(li_loss_of_signals_count); +fc_rport_fpin_statistic(li_prim_seq_err_count); +fc_rport_fpin_statistic(li_invalid_tx_word_count); +fc_rport_fpin_statistic(li_invalid_crc_count); +fc_rport_fpin_statistic(li_device_specific); + +static struct attribute *fc_rport_statistics_attrs[] = { + &device_attr_rport_fpin_dn.attr, + &device_attr_rport_fpin_dn_unknown.attr, + &device_attr_rport_fpin_dn_timeout.attr, + &device_attr_rport_fpin_dn_unable_to_route.attr, + &device_attr_rport_fpin_dn_device_specific.attr, + &device_attr_rport_fpin_li.attr, + &device_attr_rport_fpin_li_failure_unknown.attr, + &device_attr_rport_fpin_li_link_failure_count.attr, + &device_attr_rport_fpin_li_loss_of_sync_count.attr, + &device_attr_rport_fpin_li_loss_of_signals_count.attr, + &device_attr_rport_fpin_li_prim_seq_err_count.attr, + &device_attr_rport_fpin_li_invalid_tx_word_count.attr, + &device_attr_rport_fpin_li_invalid_crc_count.attr, + &device_attr_rport_fpin_li_device_specific.attr, + &device_attr_rport_fpin_cn.attr, + &device_attr_rport_fpin_cn_clear.attr, + &device_attr_rport_fpin_cn_lost_credit.attr, + &device_attr_rport_fpin_cn_credit_stall.attr, + &device_attr_rport_fpin_cn_oversubscription.attr, + &device_attr_rport_fpin_cn_device_specific.attr, + NULL +}; + +static struct attribute_group fc_rport_statistics_group = { + .name = "statistics", + .attrs = fc_rport_statistics_attrs, +}; + /* * FC SCSI Target Attribute Management @@ -1745,6 +1808,39 @@ fc_host_statistic(fc_xid_busy); fc_host_statistic(fc_seq_not_found); fc_host_statistic(fc_non_bls_resp); +#define fc_host_fpin_statistic(name) \ +static ssize_t fc_host_fpinstat_##name(struct device *cd, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct Scsi_Host *shost = transport_class_to_shost(cd); \ + struct fc_host_attrs *fc_host = shost_to_fc_host(shost); \ + \ + return snprintf(buf, 20, "0x%llx\n", fc_host->fpin_stats.name); \ +} \ +static FC_DEVICE_ATTR(host, fpin_##name, 0444, fc_host_fpinstat_##name, NULL) + +fc_host_fpin_statistic(dn); +fc_host_fpin_statistic(dn_unknown); +fc_host_fpin_statistic(dn_timeout); +fc_host_fpin_statistic(dn_unable_to_route); +fc_host_fpin_statistic(dn_device_specific); +fc_host_fpin_statistic(cn); +fc_host_fpin_statistic(cn_clear); +fc_host_fpin_statistic(cn_lost_credit); +fc_host_fpin_statistic(cn_credit_stall); +fc_host_fpin_statistic(cn_oversubscription); +fc_host_fpin_statistic(cn_device_specific); +fc_host_fpin_statistic(li); +fc_host_fpin_statistic(li_failure_unknown); +fc_host_fpin_statistic(li_link_failure_count); +fc_host_fpin_statistic(li_loss_of_sync_count); +fc_host_fpin_statistic(li_loss_of_signals_count); +fc_host_fpin_statistic(li_prim_seq_err_count); +fc_host_fpin_statistic(li_invalid_tx_word_count); +fc_host_fpin_statistic(li_invalid_crc_count); +fc_host_fpin_statistic(li_device_specific); + static ssize_t fc_reset_statistics(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1794,6 +1890,26 @@ static struct attribute *fc_statistics_attrs[] = { &device_attr_host_fc_seq_not_found.attr, &device_attr_host_fc_non_bls_resp.attr, &device_attr_host_reset_statistics.attr, + &device_attr_host_fpin_dn.attr, + &device_attr_host_fpin_dn_unknown.attr, + &device_attr_host_fpin_dn_timeout.attr, + &device_attr_host_fpin_dn_unable_to_route.attr, + &device_attr_host_fpin_dn_device_specific.attr, + &device_attr_host_fpin_li.attr, + &device_attr_host_fpin_li_failure_unknown.attr, + &device_attr_host_fpin_li_link_failure_count.attr, + &device_attr_host_fpin_li_loss_of_sync_count.attr, + &device_attr_host_fpin_li_loss_of_signals_count.attr, + &device_attr_host_fpin_li_prim_seq_err_count.attr, + &device_attr_host_fpin_li_invalid_tx_word_count.attr, + &device_attr_host_fpin_li_invalid_crc_count.attr, + &device_attr_host_fpin_li_device_specific.attr, + &device_attr_host_fpin_cn.attr, + &device_attr_host_fpin_cn_clear.attr, + &device_attr_host_fpin_cn_lost_credit.attr, + &device_attr_host_fpin_cn_credit_stall.attr, + &device_attr_host_fpin_cn_oversubscription.attr, + &device_attr_host_fpin_cn_device_specific.attr, NULL }; @@ -2177,6 +2293,7 @@ fc_attach_transport(struct fc_function_template *ft) i->rport_attr_cont.ac.attrs = &i->rport_attrs[0]; i->rport_attr_cont.ac.class = &fc_rport_class.class; i->rport_attr_cont.ac.match = fc_rport_match; + i->rport_attr_cont.statistics = &fc_rport_statistics_group; transport_container_register(&i->rport_attr_cont); i->vport_attr_cont.ac.attrs = &i->vport_attrs[0]; -- cgit v1.2.3 From 3dcfe0de5a9752e646a61f4ce513ac059960c7c3 Mon Sep 17 00:00:00 2001 From: Shyam Sundar Date: Wed, 21 Oct 2020 02:27:13 -0700 Subject: scsi: fc: Parse FPIN packets and update statistics Parse the incoming FPIN packets and update the host and rport FPIN statistics based on the FPINs. Link: https://lore.kernel.org/r/20201021092715.22669-4-njavali@marvell.com Reviewed-by: Himanshu Madhani Reviewed-by: James Smart Signed-off-by: Shyam Sundar Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_fc.c | 293 +++++++++++++++++++++++++++++++++++++++ include/scsi/scsi_transport_fc.h | 1 + 2 files changed, 294 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 501e165ae6f1..4dfa0e40d8e5 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -34,6 +34,11 @@ static int fc_bsg_hostadd(struct Scsi_Host *, struct fc_host_attrs *); static int fc_bsg_rportadd(struct Scsi_Host *, struct fc_rport *); static void fc_bsg_remove(struct request_queue *); static void fc_bsg_goose_queue(struct fc_rport *); +static void fc_li_stats_update(struct fc_fn_li_desc *li_desc, + struct fc_fpin_stats *stats); +static void fc_delivery_stats_update(u32 reason_code, + struct fc_fpin_stats *stats); +static void fc_cn_stats_update(u16 event_type, struct fc_fpin_stats *stats); /* * Module Parameters @@ -630,6 +635,262 @@ fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number, } EXPORT_SYMBOL(fc_host_post_vendor_event); +/** + * fc_find_rport_by_wwpn - find the fc_rport pointer for a given wwpn + * @shost: host the fc_rport is associated with + * @wwpn: wwpn of the fc_rport device + * + * Notes: + * This routine assumes no locks are held on entry. + */ +struct fc_rport * +fc_find_rport_by_wwpn(struct Scsi_Host *shost, u64 wwpn) +{ + struct fc_rport *rport; + unsigned long flags; + + spin_lock_irqsave(shost->host_lock, flags); + + list_for_each_entry(rport, &fc_host_rports(shost), peers) { + if (rport->port_state != FC_PORTSTATE_ONLINE) + continue; + + if (rport->port_name == wwpn) { + spin_unlock_irqrestore(shost->host_lock, flags); + return rport; + } + } + + spin_unlock_irqrestore(shost->host_lock, flags); + return NULL; +} +EXPORT_SYMBOL(fc_find_rport_by_wwpn); + +static void +fc_li_stats_update(struct fc_fn_li_desc *li_desc, + struct fc_fpin_stats *stats) +{ + stats->li += be32_to_cpu(li_desc->event_count); + switch (be16_to_cpu(li_desc->event_type)) { + case FPIN_LI_UNKNOWN: + stats->li_failure_unknown += + be32_to_cpu(li_desc->event_count); + break; + case FPIN_LI_LINK_FAILURE: + stats->li_link_failure_count += + be32_to_cpu(li_desc->event_count); + break; + case FPIN_LI_LOSS_OF_SYNC: + stats->li_loss_of_sync_count += + be32_to_cpu(li_desc->event_count); + break; + case FPIN_LI_LOSS_OF_SIG: + stats->li_loss_of_signals_count += + be32_to_cpu(li_desc->event_count); + break; + case FPIN_LI_PRIM_SEQ_ERR: + stats->li_prim_seq_err_count += + be32_to_cpu(li_desc->event_count); + break; + case FPIN_LI_INVALID_TX_WD: + stats->li_invalid_tx_word_count += + be32_to_cpu(li_desc->event_count); + break; + case FPIN_LI_INVALID_CRC: + stats->li_invalid_crc_count += + be32_to_cpu(li_desc->event_count); + break; + case FPIN_LI_DEVICE_SPEC: + stats->li_device_specific += + be32_to_cpu(li_desc->event_count); + break; + } +} + +static void +fc_delivery_stats_update(u32 reason_code, struct fc_fpin_stats *stats) +{ + stats->dn++; + switch (reason_code) { + case FPIN_DELI_UNKNOWN: + stats->dn_unknown++; + break; + case FPIN_DELI_TIMEOUT: + stats->dn_timeout++; + break; + case FPIN_DELI_UNABLE_TO_ROUTE: + stats->dn_unable_to_route++; + break; + case FPIN_DELI_DEVICE_SPEC: + stats->dn_device_specific++; + break; + } +} + +static void +fc_cn_stats_update(u16 event_type, struct fc_fpin_stats *stats) +{ + stats->cn++; + switch (event_type) { + case FPIN_CONGN_CLEAR: + stats->cn_clear++; + break; + case FPIN_CONGN_LOST_CREDIT: + stats->cn_lost_credit++; + break; + case FPIN_CONGN_CREDIT_STALL: + stats->cn_credit_stall++; + break; + case FPIN_CONGN_OVERSUBSCRIPTION: + stats->cn_oversubscription++; + break; + case FPIN_CONGN_DEVICE_SPEC: + stats->cn_device_specific++; + } +} + +/* + * fc_fpin_li_stats_update - routine to update Link Integrity + * event statistics. + * @shost: host the FPIN was received on + * @tlv: pointer to link integrity descriptor + * + */ +static void +fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv) +{ + u8 i; + struct fc_rport *rport = NULL; + struct fc_rport *attach_rport = NULL; + struct fc_host_attrs *fc_host = shost_to_fc_host(shost); + struct fc_fn_li_desc *li_desc = (struct fc_fn_li_desc *)tlv; + u64 wwpn; + + rport = fc_find_rport_by_wwpn(shost, + be64_to_cpu(li_desc->attached_wwpn)); + if (rport && + (rport->roles & FC_PORT_ROLE_FCP_TARGET || + rport->roles & FC_PORT_ROLE_NVME_TARGET)) { + attach_rport = rport; + fc_li_stats_update(li_desc, &attach_rport->fpin_stats); + } + + if (be32_to_cpu(li_desc->pname_count) > 0) { + for (i = 0; + i < be32_to_cpu(li_desc->pname_count); + i++) { + wwpn = be64_to_cpu(li_desc->pname_list[i]); + rport = fc_find_rport_by_wwpn(shost, wwpn); + if (rport && + (rport->roles & FC_PORT_ROLE_FCP_TARGET || + rport->roles & FC_PORT_ROLE_NVME_TARGET)) { + if (rport == attach_rport) + continue; + fc_li_stats_update(li_desc, + &rport->fpin_stats); + } + } + } + + if (fc_host->port_name == be64_to_cpu(li_desc->attached_wwpn)) + fc_li_stats_update(li_desc, &fc_host->fpin_stats); +} + +/* + * fc_fpin_delivery_stats_update - routine to update Delivery Notification + * event statistics. + * @shost: host the FPIN was received on + * @tlv: pointer to delivery descriptor + * + */ +static void +fc_fpin_delivery_stats_update(struct Scsi_Host *shost, + struct fc_tlv_desc *tlv) +{ + struct fc_rport *rport = NULL; + struct fc_rport *attach_rport = NULL; + struct fc_host_attrs *fc_host = shost_to_fc_host(shost); + struct fc_fn_deli_desc *dn_desc = (struct fc_fn_deli_desc *)tlv; + u32 reason_code = be32_to_cpu(dn_desc->deli_reason_code); + + rport = fc_find_rport_by_wwpn(shost, + be64_to_cpu(dn_desc->attached_wwpn)); + if (rport && + (rport->roles & FC_PORT_ROLE_FCP_TARGET || + rport->roles & FC_PORT_ROLE_NVME_TARGET)) { + attach_rport = rport; + fc_delivery_stats_update(reason_code, + &attach_rport->fpin_stats); + } + + if (fc_host->port_name == be64_to_cpu(dn_desc->attached_wwpn)) + fc_delivery_stats_update(reason_code, &fc_host->fpin_stats); +} + +/* + * fc_fpin_peer_congn_stats_update - routine to update Peer Congestion + * event statistics. + * @shost: host the FPIN was received on + * @tlv: pointer to peer congestion descriptor + * + */ +static void +fc_fpin_peer_congn_stats_update(struct Scsi_Host *shost, + struct fc_tlv_desc *tlv) +{ + u8 i; + struct fc_rport *rport = NULL; + struct fc_rport *attach_rport = NULL; + struct fc_fn_peer_congn_desc *pc_desc = + (struct fc_fn_peer_congn_desc *)tlv; + u16 event_type = be16_to_cpu(pc_desc->event_type); + u64 wwpn; + + rport = fc_find_rport_by_wwpn(shost, + be64_to_cpu(pc_desc->attached_wwpn)); + if (rport && + (rport->roles & FC_PORT_ROLE_FCP_TARGET || + rport->roles & FC_PORT_ROLE_NVME_TARGET)) { + attach_rport = rport; + fc_cn_stats_update(event_type, &attach_rport->fpin_stats); + } + + if (be32_to_cpu(pc_desc->pname_count) > 0) { + for (i = 0; + i < be32_to_cpu(pc_desc->pname_count); + i++) { + wwpn = be64_to_cpu(pc_desc->pname_list[i]); + rport = fc_find_rport_by_wwpn(shost, wwpn); + if (rport && + (rport->roles & FC_PORT_ROLE_FCP_TARGET || + rport->roles & FC_PORT_ROLE_NVME_TARGET)) { + if (rport == attach_rport) + continue; + fc_cn_stats_update(event_type, + &rport->fpin_stats); + } + } + } +} + +/* + * fc_fpin_congn_stats_update - routine to update Congestion + * event statistics. + * @shost: host the FPIN was received on + * @tlv: pointer to congestion descriptor + * + */ +static void +fc_fpin_congn_stats_update(struct Scsi_Host *shost, + struct fc_tlv_desc *tlv) +{ + struct fc_host_attrs *fc_host = shost_to_fc_host(shost); + struct fc_fn_congn_desc *congn = (struct fc_fn_congn_desc *)tlv; + + fc_cn_stats_update(be16_to_cpu(congn->event_type), + &fc_host->fpin_stats); +} + /** * fc_host_rcv_fpin - routine to process a received FPIN. * @shost: host the FPIN was received on @@ -642,6 +903,38 @@ EXPORT_SYMBOL(fc_host_post_vendor_event); void fc_host_fpin_rcv(struct Scsi_Host *shost, u32 fpin_len, char *fpin_buf) { + struct fc_els_fpin *fpin = (struct fc_els_fpin *)fpin_buf; + struct fc_tlv_desc *tlv; + u32 desc_cnt = 0, bytes_remain; + u32 dtag; + + /* Update Statistics */ + tlv = (struct fc_tlv_desc *)&fpin->fpin_desc[0]; + bytes_remain = fpin_len - offsetof(struct fc_els_fpin, fpin_desc); + bytes_remain = min_t(u32, bytes_remain, be32_to_cpu(fpin->desc_len)); + + while (bytes_remain >= FC_TLV_DESC_HDR_SZ && + bytes_remain >= FC_TLV_DESC_SZ_FROM_LENGTH(tlv)) { + dtag = be32_to_cpu(tlv->desc_tag); + switch (dtag) { + case ELS_DTAG_LNK_INTEGRITY: + fc_fpin_li_stats_update(shost, tlv); + break; + case ELS_DTAG_DELIVERY: + fc_fpin_delivery_stats_update(shost, tlv); + break; + case ELS_DTAG_PEER_CONGEST: + fc_fpin_peer_congn_stats_update(shost, tlv); + break; + case ELS_DTAG_CONGESTION: + fc_fpin_congn_stats_update(shost, tlv); + } + + desc_cnt++; + bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv); + tlv = fc_tlv_next_desc(tlv); + } + fc_host_post_fc_event(shost, fc_get_event_number(), FCH_EVT_LINK_FPIN, fpin_len, fpin_buf, 0); } diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 487a403ee51e..a636c1986e22 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -819,6 +819,7 @@ void fc_host_post_event(struct Scsi_Host *shost, u32 event_number, enum fc_host_event_code event_code, u32 event_data); void fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number, u32 data_len, char *data_buf, u64 vendor_id); +struct fc_rport *fc_find_rport_by_wwpn(struct Scsi_Host *shost, u64 wwpn); void fc_host_post_fc_event(struct Scsi_Host *shost, u32 event_number, enum fc_host_event_code event_code, u32 data_len, char *data_buf, u64 vendor_id); -- cgit v1.2.3 From 846101960fdbe312efac13ae4843410f516ff599 Mon Sep 17 00:00:00 2001 From: Shyam Sundar Date: Wed, 21 Oct 2020 02:27:14 -0700 Subject: scsi: fc: Add mechanism to update FPIN signal statistics Under fc_host_statistics add statistics for Congestion Signals that are delivered to the host as interrupt signals. Link: https://lore.kernel.org/r/20201021092715.22669-5-njavali@marvell.com Reviewed-by: James Smart Reviewed-by: Himanshu Madhani Signed-off-by: Shyam Sundar Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_fc.c | 5 +++++ include/scsi/scsi_transport_fc.h | 3 +++ 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 4dfa0e40d8e5..3f816ab1d845 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -2100,6 +2100,9 @@ fc_host_statistic(fc_xid_not_found); fc_host_statistic(fc_xid_busy); fc_host_statistic(fc_seq_not_found); fc_host_statistic(fc_non_bls_resp); +fc_host_statistic(cn_sig_warn); +fc_host_statistic(cn_sig_alarm); + #define fc_host_fpin_statistic(name) \ static ssize_t fc_host_fpinstat_##name(struct device *cd, \ @@ -2182,6 +2185,8 @@ static struct attribute *fc_statistics_attrs[] = { &device_attr_host_fc_xid_busy.attr, &device_attr_host_fc_seq_not_found.attr, &device_attr_host_fc_non_bls_resp.attr, + &device_attr_host_cn_sig_warn.attr, + &device_attr_host_cn_sig_alarm.attr, &device_attr_host_reset_statistics.attr, &device_attr_host_fpin_dn.attr, &device_attr_host_fpin_dn_unknown.attr, diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index a636c1986e22..c759b29e46c7 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -468,6 +468,9 @@ struct fc_host_statistics { u64 fc_seq_not_found; /* seq is not found for exchange */ u64 fc_non_bls_resp; /* a non BLS response frame with a sequence responder in new exch */ + /* Host Congestion Signals */ + u64 cn_sig_warn; + u64 cn_sig_alarm; }; -- cgit v1.2.3 From 170b7d2de29e6239b8dbc63a88de1fa9789b0d8d Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Mon, 19 Oct 2020 07:23:33 -0700 Subject: scsi: Remove unneeded break statements A break is not needed if it is preceded by a return or goto. Link: https://lore.kernel.org/r/20201019142333.16584-1-trix@redhat.com Signed-off-by: Tom Rix Signed-off-by: Martin K. Petersen --- drivers/scsi/aic94xx/aic94xx_task.c | 1 - drivers/scsi/be2iscsi/be_mgmt.c | 4 ---- drivers/scsi/bnx2fc/bnx2fc_hwi.c | 1 - drivers/scsi/fcoe/fcoe.c | 1 - drivers/scsi/hpsa.c | 1 - drivers/scsi/hptiop.c | 1 - drivers/scsi/ipr.c | 1 - drivers/scsi/isci/phy.c | 2 -- drivers/scsi/lpfc/lpfc_debugfs.c | 12 ++++-------- drivers/scsi/lpfc/lpfc_init.c | 1 - drivers/scsi/lpfc/lpfc_scsi.c | 1 - drivers/scsi/lpfc/lpfc_sli.c | 3 --- drivers/scsi/mvumi.c | 1 - drivers/scsi/pcmcia/nsp_cs.c | 2 -- drivers/scsi/qla2xxx/qla_mbx.c | 1 - drivers/scsi/st.c | 1 - drivers/scsi/sym53c8xx_2/sym_hipd.c | 1 - 17 files changed, 4 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c index f923ed019d4a..ed034192b3c3 100644 --- a/drivers/scsi/aic94xx/aic94xx_task.c +++ b/drivers/scsi/aic94xx/aic94xx_task.c @@ -269,7 +269,6 @@ Again: case TA_I_T_NEXUS_LOSS: opcode = dl->status_block[0]; goto Again; - break; case TF_INV_CONN_HANDLE: ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_DEVICE_UNKNOWN; diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 96d6e384b2b2..0d4928567265 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -1244,18 +1244,14 @@ beiscsi_adap_family_disp(struct device *dev, struct device_attribute *attr, case OC_DEVICE_ID2: return snprintf(buf, PAGE_SIZE, "Obsolete/Unsupported BE2 Adapter Family\n"); - break; case BE_DEVICE_ID2: case OC_DEVICE_ID3: return snprintf(buf, PAGE_SIZE, "BE3-R Adapter Family\n"); - break; case OC_SKH_ID1: return snprintf(buf, PAGE_SIZE, "Skyhawk-R Adapter Family\n"); - break; default: return snprintf(buf, PAGE_SIZE, "Unknown Adapter Family: 0x%x\n", dev_id); - break; } } diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c index 08992095ce7a..b37b0a9ec12d 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c +++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c @@ -770,7 +770,6 @@ static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe) } else printk(KERN_ERR PFX "SRR in progress\n"); goto ret_err_rqe; - break; default: break; } diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 0f9274960dc6..a4be6f439c47 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -1894,7 +1894,6 @@ static int fcoe_device_notification(struct notifier_block *notifier, mutex_unlock(&fcoe_config_mutex); fcoe_ctlr_device_delete(fcoe_ctlr_to_ctlr_dev(ctlr)); goto out; - break; case NETDEV_FEAT_CHANGE: fcoe_netdev_features_change(lport, netdev); break; diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 83ce4f11a589..45136e3a4efc 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -7442,7 +7442,6 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr) dev_warn(&pdev->dev, "base address is invalid\n"); return -1; - break; } } if (offset == pci_bar_addr - PCI_BASE_ADDRESS_0) diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index 6a2561f26e38..db4c7a7ff4dd 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -758,7 +758,6 @@ static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag, scp->result = SAM_STAT_CHECK_CONDITION; memcpy(scp->sense_buffer, &req->sg_list, SCSI_SENSE_BUFFERSIZE); goto skip_resid; - break; default: scp->result = DRIVER_INVALID << 24 | DID_ABORT << 16; diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index b0aa58d117cc..e451102b9a29 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -9487,7 +9487,6 @@ static pci_ers_result_t ipr_pci_error_detected(struct pci_dev *pdev, case pci_channel_io_perm_failure: ipr_pci_perm_failure(pdev); return PCI_ERS_RESULT_DISCONNECT; - break; default: break; } diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 7041e2e3ab48..1b87d9080ebe 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -753,7 +753,6 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code) default: phy_event_warn(iphy, state, event_code); return SCI_FAILURE; - break; } return SCI_SUCCESS; case SCI_PHY_SUB_AWAIT_IAF_UF: @@ -958,7 +957,6 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code) default: phy_event_warn(iphy, state, event_code); return SCI_FAILURE_INVALID_STATE; - break; } return SCI_SUCCESS; default: diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index c9a327b13e5c..325081ac6553 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -3341,7 +3341,6 @@ lpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes, break; case LPFC_PCI_CFG_BROWSE: /* browse all */ goto pcicfg_browse; - break; default: /* illegal count */ len = 0; @@ -4381,7 +4380,7 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, } } goto error_out; - break; + case LPFC_IDIAG_CQ: /* MBX complete queue */ if (phba->sli4_hba.mbx_cq && @@ -4433,7 +4432,7 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, } } goto error_out; - break; + case LPFC_IDIAG_MQ: /* MBX work queue */ if (phba->sli4_hba.mbx_wq && @@ -4447,7 +4446,7 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, goto pass_check; } goto error_out; - break; + case LPFC_IDIAG_WQ: /* ELS work queue */ if (phba->sli4_hba.els_wq && @@ -4487,9 +4486,8 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, } } } - goto error_out; - break; + case LPFC_IDIAG_RQ: /* HDR queue */ if (phba->sli4_hba.hdr_rq && @@ -4514,10 +4512,8 @@ lpfc_idiag_queacc_write(struct file *file, const char __user *buf, goto pass_check; } goto error_out; - break; default: goto error_out; - break; } pass_check: diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index ca25e54bb782..b6090357e8a5 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -7196,7 +7196,6 @@ lpfc_init_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) "1431 Invalid HBA PCI-device group: 0x%x\n", dev_grp); return -ENODEV; - break; } return 0; } diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 983eeb0e3d07..c3b02dab6e5c 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -4284,7 +4284,6 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) "1418 Invalid HBA PCI-device group: 0x%x\n", dev_grp); return -ENODEV; - break; } phba->lpfc_rampdown_queue_depth = lpfc_rampdown_queue_depth; phba->lpfc_scsi_cmd_iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index e158cd77d387..0f18f1ba8a28 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -9189,7 +9189,6 @@ lpfc_mbox_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) "1420 Invalid HBA PCI-device group: 0x%x\n", dev_grp); return -ENODEV; - break; } return 0; } @@ -10072,7 +10071,6 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, "2014 Invalid command 0x%x\n", iocbq->iocb.ulpCommand); return IOCB_ERROR; - break; } if (iocbq->iocb_flag & LPFC_IO_DIF_PASS) @@ -10234,7 +10232,6 @@ lpfc_sli_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) "1419 Invalid HBA PCI-device group: 0x%x\n", dev_grp); return -ENODEV; - break; } phba->lpfc_get_iocb_from_iocbq = lpfc_get_iocb_from_iocbq; return 0; diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c index 0354898d7cac..2f7a52bd653a 100644 --- a/drivers/scsi/mvumi.c +++ b/drivers/scsi/mvumi.c @@ -2296,7 +2296,6 @@ static int mvumi_cfg_hw_reg(struct mvumi_hba *mhba) break; default: return -1; - break; } return 0; diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index bc5a623519e7..bb3b3884f968 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1102,8 +1102,6 @@ static irqreturn_t nspintr(int irq, void *dev_id) nsp_index_write(base, SCSIBUSCTRL, SCSI_ATN | AUTODIRECTION | ACKENB); return IRQ_HANDLED; - break; - case PH_RESELECT: //nsp_dbg(NSP_DEBUG_INTR, "phase reselect"); // *sync_neg = SYNC_NOT_YET; diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 07afd0d8a8f3..40af7f1524ce 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -4030,7 +4030,6 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags); return; - break; case TOPO_FL: ha->current_topology = ISP_CFG_FL; break; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index e2e5356a997d..43f7624508a9 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -2846,7 +2846,6 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon case MTNOP: DEBC_printk(STp, "No op on tape.\n"); return 0; /* Should do something ? */ - break; case MTRETEN: cmd[0] = START_STOP; if (STp->immediate) { diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index a9fe092a4906..255a2d48d421 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -4596,7 +4596,6 @@ static void sym_int_sir(struct sym_hcb *np) scr_to_cpu(np->lastmsg), np->msgout[0]); } goto out_clrack; - break; default: goto out_reject; } -- cgit v1.2.3 From b9dd44fd79a1ed7ee8e7c7644ddbd803b6acfd9c Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Mon, 19 Oct 2020 12:19:50 -0700 Subject: scsi: message: fusion: Remove unneeded break A break is not needed if it is preceded by a return. Link: https://lore.kernel.org/r/20201019191950.10244-1-trix@redhat.com Signed-off-by: Tom Rix Signed-off-by: Martin K. Petersen --- drivers/message/fusion/mptbase.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 9903e9660a38..3078fac34e51 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -473,7 +473,6 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa) mpt_free_msg_frame(ioc, mf); mb(); return; - break; } mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); break; -- cgit v1.2.3 From c8ed1ff88c02e55bf9fa3244624e431f4f374077 Mon Sep 17 00:00:00 2001 From: Bodo Stroesser Date: Mon, 19 Oct 2020 13:51:18 +0200 Subject: scsi: target: tcmu: scatter_/gather_data_area() rework scatter_data_area() and gather_data_area() are not easy to understand since data is copied in nested loops over sg_list and tcmu dbi list. Since sg list can contain only partly filled pages, the loop has to be prepared to handle sg pages not matching dbi pages one by one. Existing implementation uses kmap_atomic()/kunmap_atomic() due to performance reasons. But instead of using these calls strictly nested for sg and dpi pages, the code holds the mappings in an overlapping way, which indeed is a bug that would trigger on archs using highmem. The scatterlist lib contains the sg_miter_start/_next/_stop functions which can be used to simplify such complicated loops. The new code now processes the dbi list in the outer loop, while sg list is handled by the inner one. That way the code can take advantage of the sg_miter_* family calls. Calling sg_miter_stop() after the end of the inner loop enforces strict nesting of atomic kmaps. Since the nested loops in scatter_/gather_data_area were very similar, I replaced them by the new helper function tcmu_copy_data(). Link: https://lore.kernel.org/r/20201019115118.11949-1-bostroesser@gmail.com Acked-by: Mike Christie Signed-off-by: Bodo Stroesser Signed-off-by: Martin K. Petersen --- drivers/target/target_core_user.c | 164 +++++++++++++++++--------------------- 1 file changed, 75 insertions(+), 89 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c index ea84d08747df..0458bfb143f8 100644 --- a/drivers/target/target_core_user.c +++ b/drivers/target/target_core_user.c @@ -586,14 +586,15 @@ static inline void tcmu_cmd_set_block_cnts(struct tcmu_cmd *cmd) } static int new_block_to_iov(struct tcmu_dev *udev, struct tcmu_cmd *cmd, - struct iovec **iov, int prev_dbi, int *remain) + struct iovec **iov, int prev_dbi, int len) { /* Get the next dbi */ int dbi = tcmu_cmd_get_dbi(cmd); + /* Do not add more than DATA_BLOCK_SIZE to iov */ - int len = min_t(int, DATA_BLOCK_SIZE, *remain); + if (len > DATA_BLOCK_SIZE) + len = DATA_BLOCK_SIZE; - *remain -= len; /* * The following code will gather and map the blocks to the same iovec * when the blocks are all next to each other. @@ -618,8 +619,8 @@ static void tcmu_setup_iovs(struct tcmu_dev *udev, struct tcmu_cmd *cmd, int dbi = -2; /* We prepare the IOVs for DMA_FROM_DEVICE transfer direction */ - while (data_length > 0) - dbi = new_block_to_iov(udev, cmd, iov, dbi, &data_length); + for (; data_length > 0; data_length -= DATA_BLOCK_SIZE) + dbi = new_block_to_iov(udev, cmd, iov, dbi, data_length); } static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd) @@ -688,67 +689,83 @@ static inline size_t head_to_end(size_t head, size_t size) #define UPDATE_HEAD(head, used, size) smp_store_release(&head, ((head % size) + used) % size) -static void scatter_data_area(struct tcmu_dev *udev, struct tcmu_cmd *tcmu_cmd, - struct iovec **iov) +#define TCMU_SG_TO_DATA_AREA 1 +#define TCMU_DATA_AREA_TO_SG 2 + +static inline void tcmu_copy_data(struct tcmu_dev *udev, + struct tcmu_cmd *tcmu_cmd, uint32_t direction, + struct scatterlist *sg, unsigned int sg_nents, + struct iovec **iov, size_t data_len) { - struct se_cmd *se_cmd = tcmu_cmd->se_cmd; /* start value of dbi + 1 must not be a valid dbi */ - int i, dbi = -2; - int block_remaining = 0; - int data_len = se_cmd->data_length; - void *from, *to = NULL; - size_t copy_bytes, offset; - struct scatterlist *sg; - struct page *page = NULL; - - for_each_sg(se_cmd->t_data_sg, sg, se_cmd->t_data_nents, i) { - int sg_remaining = sg->length; - from = kmap_atomic(sg_page(sg)) + sg->offset; - while (sg_remaining > 0) { - if (block_remaining == 0) { - if (to) { - flush_dcache_page(page); - kunmap_atomic(to); - } - - /* get next dbi and add to IOVs */ - dbi = new_block_to_iov(udev, tcmu_cmd, iov, dbi, - &data_len); - page = tcmu_get_block_page(udev, dbi); - to = kmap_atomic(page); - block_remaining = DATA_BLOCK_SIZE; - } + int dbi = -2; + size_t block_remaining, cp_len; + struct sg_mapping_iter sg_iter; + unsigned int sg_flags; + struct page *page; + void *data_page_start, *data_addr; - copy_bytes = min_t(size_t, sg_remaining, - block_remaining); - offset = DATA_BLOCK_SIZE - block_remaining; - memcpy(to + offset, from + sg->length - sg_remaining, - copy_bytes); + if (direction == TCMU_SG_TO_DATA_AREA) + sg_flags = SG_MITER_ATOMIC | SG_MITER_FROM_SG; + else + sg_flags = SG_MITER_ATOMIC | SG_MITER_TO_SG; + sg_miter_start(&sg_iter, sg, sg_nents, sg_flags); - sg_remaining -= copy_bytes; - block_remaining -= copy_bytes; + while (data_len) { + if (direction == TCMU_SG_TO_DATA_AREA) + dbi = new_block_to_iov(udev, tcmu_cmd, iov, dbi, + data_len); + else + dbi = tcmu_cmd_get_dbi(tcmu_cmd); + page = tcmu_get_block_page(udev, dbi); + if (direction == TCMU_DATA_AREA_TO_SG) + flush_dcache_page(page); + data_page_start = kmap_atomic(page); + block_remaining = DATA_BLOCK_SIZE; + + while (block_remaining && data_len) { + if (!sg_miter_next(&sg_iter)) { + /* set length to 0 to abort outer loop */ + data_len = 0; + pr_debug("tcmu_move_data: aborting data copy due to exhausted sg_list\n"); + break; + } + cp_len = min3(sg_iter.length, block_remaining, data_len); + + data_addr = data_page_start + + DATA_BLOCK_SIZE - block_remaining; + if (direction == TCMU_SG_TO_DATA_AREA) + memcpy(data_addr, sg_iter.addr, cp_len); + else + memcpy(sg_iter.addr, data_addr, cp_len); + + data_len -= cp_len; + block_remaining -= cp_len; + sg_iter.consumed = cp_len; } - kunmap_atomic(from - sg->offset); - } + sg_miter_stop(&sg_iter); - if (to) { - flush_dcache_page(page); - kunmap_atomic(to); + kunmap_atomic(data_page_start); + if (direction == TCMU_SG_TO_DATA_AREA) + flush_dcache_page(page); } } -static void gather_data_area(struct tcmu_dev *udev, struct tcmu_cmd *cmd, +static void scatter_data_area(struct tcmu_dev *udev, struct tcmu_cmd *tcmu_cmd, + struct iovec **iov) +{ + struct se_cmd *se_cmd = tcmu_cmd->se_cmd; + + tcmu_copy_data(udev, tcmu_cmd, TCMU_SG_TO_DATA_AREA, se_cmd->t_data_sg, + se_cmd->t_data_nents, iov, se_cmd->data_length); +} + +static void gather_data_area(struct tcmu_dev *udev, struct tcmu_cmd *tcmu_cmd, bool bidi, uint32_t read_len) { - struct se_cmd *se_cmd = cmd->se_cmd; - int i, dbi; - int block_remaining = 0; - void *from = NULL, *to; - size_t copy_bytes, offset; - struct scatterlist *sg, *data_sg; - struct page *page; + struct se_cmd *se_cmd = tcmu_cmd->se_cmd; + struct scatterlist *data_sg; unsigned int data_nents; - uint32_t count = 0; if (!bidi) { data_sg = se_cmd->t_data_sg; @@ -759,46 +776,15 @@ static void gather_data_area(struct tcmu_dev *udev, struct tcmu_cmd *cmd, * buffer blocks, and before gathering the Data-In buffer * the Data-Out buffer blocks should be skipped. */ - count = cmd->dbi_cnt - cmd->dbi_bidi_cnt; + tcmu_cmd_set_dbi_cur(tcmu_cmd, + tcmu_cmd->dbi_cnt - tcmu_cmd->dbi_bidi_cnt); data_sg = se_cmd->t_bidi_data_sg; data_nents = se_cmd->t_bidi_data_nents; } - tcmu_cmd_set_dbi_cur(cmd, count); - - for_each_sg(data_sg, sg, data_nents, i) { - int sg_remaining = sg->length; - to = kmap_atomic(sg_page(sg)) + sg->offset; - while (sg_remaining > 0 && read_len > 0) { - if (block_remaining == 0) { - if (from) - kunmap_atomic(from); - - block_remaining = DATA_BLOCK_SIZE; - dbi = tcmu_cmd_get_dbi(cmd); - page = tcmu_get_block_page(udev, dbi); - from = kmap_atomic(page); - flush_dcache_page(page); - } - copy_bytes = min_t(size_t, sg_remaining, - block_remaining); - if (read_len < copy_bytes) - copy_bytes = read_len; - offset = DATA_BLOCK_SIZE - block_remaining; - memcpy(to + sg->length - sg_remaining, from + offset, - copy_bytes); - - sg_remaining -= copy_bytes; - block_remaining -= copy_bytes; - read_len -= copy_bytes; - } - kunmap_atomic(to - sg->offset); - if (read_len == 0) - break; - } - if (from) - kunmap_atomic(from); + tcmu_copy_data(udev, tcmu_cmd, TCMU_DATA_AREA_TO_SG, data_sg, + data_nents, NULL, read_len); } static inline size_t spc_bitmap_free(unsigned long *bitmap, uint32_t thresh) -- cgit v1.2.3 From 62e3a931db60daf94fdb3159d685a5bc6ad4d0cf Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 20 Oct 2020 13:27:11 -0700 Subject: scsi: lpfc: Fix invalid sleeping context in lpfc_sli4_nvmet_alloc() The following calltrace was seen: BUG: sleeping function called from invalid context at mm/slab.h:494 ... Call Trace: dump_stack+0x9a/0xf0 ___might_sleep.cold.63+0x13d/0x178 slab_pre_alloc_hook+0x6a/0x90 kmem_cache_alloc_trace+0x3a/0x2d0 lpfc_sli4_nvmet_alloc+0x4c/0x280 [lpfc] lpfc_post_rq_buffer+0x2e7/0xa60 [lpfc] lpfc_sli4_hba_setup+0x6b4c/0xa4b0 [lpfc] lpfc_pci_probe_one_s4.isra.15+0x14f8/0x2280 [lpfc] lpfc_pci_probe_one+0x260/0x2880 [lpfc] local_pci_probe+0xd4/0x180 work_for_cpu_fn+0x51/0xa0 process_one_work+0x8f0/0x17b0 worker_thread+0x536/0xb50 kthread+0x30c/0x3d0 ret_from_fork+0x3a/0x50 A prior patch introduced a spin_lock_irqsave(hbalock) in the lpfc_post_rq_buffer() routine. Call trace is seen as the hbalock is held with interrupts disabled during a GFP_KERNEL allocation in lpfc_sli4_nvmet_alloc(). Fix by reordering locking so that hbalock not held when calling sli4_nvmet_alloc() (aka rqb_buf_list()). Link: https://lore.kernel.org/r/20201020202719.54726-2-james.smart@broadcom.com Fixes: 411de511c694 ("scsi: lpfc: Fix RQ empty firmware trap") Cc: # v4.17+ Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_mem.c | 4 +--- drivers/scsi/lpfc/lpfc_sli.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 27ff67e9edae..656f35eb853e 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -588,8 +588,6 @@ lpfc_sli4_rb_free(struct lpfc_hba *phba, struct hbq_dmabuf *dmab) * Description: Allocates a DMA-mapped receive buffer from the lpfc_hrb_pool PCI * pool along a non-DMA-mapped container for it. * - * Notes: Not interrupt-safe. Must be called with no locks held. - * * Returns: * pointer to HBQ on success * NULL on failure @@ -599,7 +597,7 @@ lpfc_sli4_nvmet_alloc(struct lpfc_hba *phba) { struct rqb_dmabuf *dma_buf; - dma_buf = kzalloc(sizeof(struct rqb_dmabuf), GFP_KERNEL); + dma_buf = kzalloc(sizeof(*dma_buf), GFP_KERNEL); if (!dma_buf) return NULL; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 0f18f1ba8a28..deed39d69979 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -7248,12 +7248,16 @@ lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq, struct rqb_dmabuf *rqb_buffer; LIST_HEAD(rqb_buf_list); - spin_lock_irqsave(&phba->hbalock, flags); rqbp = hrq->rqbp; for (i = 0; i < count; i++) { + spin_lock_irqsave(&phba->hbalock, flags); /* IF RQ is already full, don't bother */ - if (rqbp->buffer_count + i >= rqbp->entry_count - 1) + if (rqbp->buffer_count + i >= rqbp->entry_count - 1) { + spin_unlock_irqrestore(&phba->hbalock, flags); break; + } + spin_unlock_irqrestore(&phba->hbalock, flags); + rqb_buffer = rqbp->rqb_alloc_buffer(phba); if (!rqb_buffer) break; @@ -7262,6 +7266,8 @@ lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq, rqb_buffer->idx = idx; list_add_tail(&rqb_buffer->hbuf.list, &rqb_buf_list); } + + spin_lock_irqsave(&phba->hbalock, flags); while (!list_empty(&rqb_buf_list)) { list_remove_head(&rqb_buf_list, rqb_buffer, struct rqb_dmabuf, hbuf.list); -- cgit v1.2.3 From e7dab164a9aa457f89d4528452bdfc3e15ac98b6 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 20 Oct 2020 13:27:12 -0700 Subject: scsi: lpfc: Fix scheduling call while in softirq context in lpfc_unreg_rpi The following call trace was seen during HBA reset testing: BUG: scheduling while atomic: swapper/2/0/0x10000100 ... Call Trace: dump_stack+0x19/0x1b __schedule_bug+0x64/0x72 __schedule+0x782/0x840 __cond_resched+0x26/0x30 _cond_resched+0x3a/0x50 mempool_alloc+0xa0/0x170 lpfc_unreg_rpi+0x151/0x630 [lpfc] lpfc_sli_abts_recover_port+0x171/0x190 [lpfc] lpfc_sli4_abts_err_handler+0xb2/0x1f0 [lpfc] lpfc_sli4_io_xri_aborted+0x256/0x300 [lpfc] lpfc_sli4_sp_handle_abort_xri_wcqe.isra.51+0xa3/0x190 [lpfc] lpfc_sli4_fp_handle_cqe+0x89/0x4d0 [lpfc] __lpfc_sli4_process_cq+0xdb/0x2e0 [lpfc] __lpfc_sli4_hba_process_cq+0x41/0x100 [lpfc] lpfc_cq_poll_hdler+0x1a/0x30 [lpfc] irq_poll_softirq+0xc7/0x100 __do_softirq+0xf5/0x280 call_softirq+0x1c/0x30 do_softirq+0x65/0xa0 irq_exit+0x105/0x110 do_IRQ+0x56/0xf0 common_interrupt+0x16a/0x16a With the conversion to blk_io_poll for better interrupt latency in normal cases, it introduced this code path, executed when I/O aborts or logouts are seen, which attempts to allocate memory for a mailbox command to be issued. The allocation is GFP_KERNEL, thus it could attempt to sleep. Fix by creating a work element that performs the event handling for the remote port. This will have the mailbox commands and other items performed in the work element, not the irq. A much better method as the "irq" routine does not stall while performing all this deep handling code. Ensure that allocation failures are handled and send LOGO on failure. Additionally, enlarge the mailbox memory pool to reduce the possibility of additional allocation in this path. Link: https://lore.kernel.org/r/20201020202719.54726-3-james.smart@broadcom.com Fixes: 317aeb83c92b ("scsi: lpfc: Add blk_io_poll support for latency improvment") Cc: # v5.9+ Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 2 +- drivers/scsi/lpfc/lpfc_disc.h | 2 ++ drivers/scsi/lpfc/lpfc_hbadisc.c | 35 ++++++++++++++++++++++ drivers/scsi/lpfc/lpfc_init.c | 46 +++++++++++++++++------------ drivers/scsi/lpfc/lpfc_mem.c | 5 ++-- drivers/scsi/lpfc/lpfc_nvme.c | 18 +++++++---- drivers/scsi/lpfc/lpfc_sli.c | 64 ++++++++++++++++++++++++++++++++-------- drivers/scsi/lpfc/lpfc_sli4.h | 6 ++-- 8 files changed, 136 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 549adfaa97ce..93e507677bdc 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -753,7 +753,7 @@ struct lpfc_hba { #define HBA_SP_QUEUE_EVT 0x8 /* Slow-path qevt posted to worker thread*/ #define HBA_POST_RECEIVE_BUFFER 0x10 /* Rcv buffers need to be posted */ #define HBA_PERSISTENT_TOPO 0x20 /* Persistent topology support in hba */ -#define ELS_XRI_ABORT_EVENT 0x40 +#define ELS_XRI_ABORT_EVENT 0x40 /* ELS_XRI abort event was queued */ #define ASYNC_EVENT 0x80 #define LINK_DISABLED 0x100 /* Link disabled by user */ #define FCF_TS_INPROG 0x200 /* FCF table scan in progress */ diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 482e4a888dae..1437e44ade80 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h @@ -41,6 +41,7 @@ enum lpfc_work_type { LPFC_EVT_DEV_LOSS, LPFC_EVT_FASTPATH_MGMT_EVT, LPFC_EVT_RESET_HBA, + LPFC_EVT_RECOVER_PORT }; /* structure used to queue event to the discovery tasklet */ @@ -128,6 +129,7 @@ struct lpfc_nodelist { struct lpfc_vport *vport; struct lpfc_work_evt els_retry_evt; struct lpfc_work_evt dev_loss_evt; + struct lpfc_work_evt recovery_evt; struct kref kref; atomic_t cmd_pending; uint32_t cmd_qdepth; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index bb02fd8bc2dd..9746d2f4fcfa 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -552,6 +552,15 @@ lpfc_work_list_done(struct lpfc_hba *phba) fcf_inuse, nlp_did); break; + case LPFC_EVT_RECOVER_PORT: + ndlp = (struct lpfc_nodelist *)(evtp->evt_arg1); + lpfc_sli_abts_recover_port(ndlp->vport, ndlp); + free_evt = 0; + /* decrement the node reference count held for + * this queued work + */ + lpfc_nlp_put(ndlp); + break; case LPFC_EVT_ONLINE: if (phba->link_state < LPFC_LINK_DOWN) *(int *) (evtp->evt_arg1) = lpfc_online(phba); @@ -4515,6 +4524,8 @@ lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, INIT_LIST_HEAD(&ndlp->els_retry_evt.evt_listp); INIT_LIST_HEAD(&ndlp->dev_loss_evt.evt_listp); timer_setup(&ndlp->nlp_delayfunc, lpfc_els_retry_delay, 0); + INIT_LIST_HEAD(&ndlp->recovery_evt.evt_listp); + ndlp->nlp_DID = did; ndlp->vport = vport; ndlp->phba = vport->phba; @@ -5011,6 +5022,29 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) mempool_free(mbox, phba->mbox_mem_pool); acc_plogi = 1; } + } else { + lpfc_printf_vlog(vport, KERN_INFO, + LOG_NODE | LOG_DISCOVERY, + "1444 Failed to allocate mempool " + "unreg_rpi UNREG x%x, " + "DID x%x, flag x%x, " + "ndlp x%px\n", + ndlp->nlp_rpi, ndlp->nlp_DID, + ndlp->nlp_flag, ndlp); + + /* Because mempool_alloc failed, we + * will issue a LOGO here and keep the rpi alive if + * not unloading. + */ + if (!(vport->load_flag & FC_UNLOADING)) { + ndlp->nlp_flag &= ~NLP_UNREG_INP; + lpfc_issue_els_logo(vport, ndlp, 0); + ndlp->nlp_prev_state = ndlp->nlp_state; + lpfc_nlp_set_state(vport, ndlp, + NLP_STE_NPR_NODE); + } + + return 1; } lpfc_no_rpi(phba, ndlp); out: @@ -5214,6 +5248,7 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) list_del_init(&ndlp->els_retry_evt.evt_listp); list_del_init(&ndlp->dev_loss_evt.evt_listp); + list_del_init(&ndlp->recovery_evt.evt_listp); lpfc_cleanup_vports_rrqs(vport, ndlp); if (phba->sli_rev == LPFC_SLI_REV4) ndlp->nlp_flag |= NLP_RELEASE_RPI; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index b6090357e8a5..edfefff0214a 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -5958,18 +5958,21 @@ lpfc_sli4_async_grp5_evt(struct lpfc_hba *phba, void lpfc_sli4_async_event_proc(struct lpfc_hba *phba) { struct lpfc_cq_event *cq_event; + unsigned long iflags; /* First, declare the async event has been handled */ - spin_lock_irq(&phba->hbalock); + spin_lock_irqsave(&phba->hbalock, iflags); phba->hba_flag &= ~ASYNC_EVENT; - spin_unlock_irq(&phba->hbalock); + spin_unlock_irqrestore(&phba->hbalock, iflags); + /* Now, handle all the async events */ + spin_lock_irqsave(&phba->sli4_hba.asynce_list_lock, iflags); while (!list_empty(&phba->sli4_hba.sp_asynce_work_queue)) { - /* Get the first event from the head of the event queue */ - spin_lock_irq(&phba->hbalock); list_remove_head(&phba->sli4_hba.sp_asynce_work_queue, cq_event, struct lpfc_cq_event, list); - spin_unlock_irq(&phba->hbalock); + spin_unlock_irqrestore(&phba->sli4_hba.asynce_list_lock, + iflags); + /* Process the asynchronous event */ switch (bf_get(lpfc_trailer_code, &cq_event->cqe.mcqe_cmpl)) { case LPFC_TRAILER_CODE_LINK: @@ -6001,9 +6004,12 @@ void lpfc_sli4_async_event_proc(struct lpfc_hba *phba) &cq_event->cqe.mcqe_cmpl)); break; } + /* Free the completion event processed to the free pool */ lpfc_sli4_cq_event_release(phba, cq_event); + spin_lock_irqsave(&phba->sli4_hba.asynce_list_lock, iflags); } + spin_unlock_irqrestore(&phba->sli4_hba.asynce_list_lock, iflags); } /** @@ -6630,6 +6636,8 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) /* This abort list used by worker thread */ spin_lock_init(&phba->sli4_hba.sgl_list_lock); spin_lock_init(&phba->sli4_hba.nvmet_io_wait_lock); + spin_lock_init(&phba->sli4_hba.asynce_list_lock); + spin_lock_init(&phba->sli4_hba.els_xri_abrt_list_lock); /* * Initialize driver internal slow-path work queues @@ -6641,8 +6649,6 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) INIT_LIST_HEAD(&phba->sli4_hba.sp_queue_event); /* Asynchronous event CQ Event work queue list */ INIT_LIST_HEAD(&phba->sli4_hba.sp_asynce_work_queue); - /* Fast-path XRI aborted CQ Event work queue list */ - INIT_LIST_HEAD(&phba->sli4_hba.sp_fcp_xri_aborted_work_queue); /* Slow-path XRI aborted CQ Event work queue list */ INIT_LIST_HEAD(&phba->sli4_hba.sp_els_xri_aborted_work_queue); /* Receive queue CQ Event work queue list */ @@ -10173,26 +10179,28 @@ lpfc_sli4_cq_event_release(struct lpfc_hba *phba, static void lpfc_sli4_cq_event_release_all(struct lpfc_hba *phba) { - LIST_HEAD(cqelist); - struct lpfc_cq_event *cqe; + LIST_HEAD(cq_event_list); + struct lpfc_cq_event *cq_event; unsigned long iflags; /* Retrieve all the pending WCQEs from pending WCQE lists */ - spin_lock_irqsave(&phba->hbalock, iflags); - /* Pending FCP XRI abort events */ - list_splice_init(&phba->sli4_hba.sp_fcp_xri_aborted_work_queue, - &cqelist); + /* Pending ELS XRI abort events */ + spin_lock_irqsave(&phba->sli4_hba.els_xri_abrt_list_lock, iflags); list_splice_init(&phba->sli4_hba.sp_els_xri_aborted_work_queue, - &cqelist); + &cq_event_list); + spin_unlock_irqrestore(&phba->sli4_hba.els_xri_abrt_list_lock, iflags); + /* Pending asynnc events */ + spin_lock_irqsave(&phba->sli4_hba.asynce_list_lock, iflags); list_splice_init(&phba->sli4_hba.sp_asynce_work_queue, - &cqelist); - spin_unlock_irqrestore(&phba->hbalock, iflags); + &cq_event_list); + spin_unlock_irqrestore(&phba->sli4_hba.asynce_list_lock, iflags); - while (!list_empty(&cqelist)) { - list_remove_head(&cqelist, cqe, struct lpfc_cq_event, list); - lpfc_sli4_cq_event_release(phba, cqe); + while (!list_empty(&cq_event_list)) { + list_remove_head(&cq_event_list, cq_event, + struct lpfc_cq_event, list); + lpfc_sli4_cq_event_release(phba, cq_event); } } diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 656f35eb853e..79386e294fb9 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -46,6 +46,7 @@ #define LPFC_MEM_POOL_SIZE 64 /* max elem in non-DMA safety pool */ #define LPFC_DEVICE_DATA_POOL_SIZE 64 /* max elements in device data pool */ #define LPFC_RRQ_POOL_SIZE 256 /* max elements in non-DMA pool */ +#define LPFC_MBX_POOL_SIZE 256 /* max elements in MBX non-DMA pool */ int lpfc_mem_alloc_active_rrq_pool_s4(struct lpfc_hba *phba) { @@ -111,8 +112,8 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align) pool->current_count++; } - phba->mbox_mem_pool = mempool_create_kmalloc_pool(LPFC_MEM_POOL_SIZE, - sizeof(LPFC_MBOXQ_t)); + phba->mbox_mem_pool = mempool_create_kmalloc_pool(LPFC_MBX_POOL_SIZE, + sizeof(LPFC_MBOXQ_t)); if (!phba->mbox_mem_pool) goto fail_free_mbuf_pool; diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 0c39ed50998c..69f1a0457f51 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -2280,6 +2280,8 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport, int ret, i, pending = 0; struct lpfc_sli_ring *pring; struct lpfc_hba *phba = vport->phba; + struct lpfc_sli4_hdw_queue *qp; + int abts_scsi, abts_nvme; /* Host transport has to clean up and confirm requiring an indefinite * wait. Print a message if a 10 second wait expires and renew the @@ -2290,17 +2292,23 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport, ret = wait_for_completion_timeout(lport_unreg_cmp, wait_tmo); if (unlikely(!ret)) { pending = 0; + abts_scsi = 0; + abts_nvme = 0; for (i = 0; i < phba->cfg_hdw_queue; i++) { - pring = phba->sli4_hba.hdwq[i].io_wq->pring; + qp = &phba->sli4_hba.hdwq[i]; + pring = qp->io_wq->pring; if (!pring) continue; - if (pring->txcmplq_cnt) - pending += pring->txcmplq_cnt; + pending += pring->txcmplq_cnt; + abts_scsi += qp->abts_scsi_io_bufs; + abts_nvme += qp->abts_nvme_io_bufs; } lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6176 Lport x%px Localport x%px wait " - "timed out. Pending %d. Renewing.\n", - lport, vport->localport, pending); + "timed out. Pending %d [%d:%d]. " + "Renewing.\n", + lport, vport->localport, pending, + abts_scsi, abts_nvme); continue; } break; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index deed39d69979..e5a7cfa55b6c 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -10367,6 +10367,32 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba) return 0; } +static void +lpfc_sli_post_recovery_event(struct lpfc_hba *phba, + struct lpfc_nodelist *ndlp) +{ + unsigned long iflags; + struct lpfc_work_evt *evtp = &ndlp->recovery_evt; + + spin_lock_irqsave(&phba->hbalock, iflags); + if (!list_empty(&evtp->evt_listp)) { + spin_unlock_irqrestore(&phba->hbalock, iflags); + return; + } + + /* Incrementing the reference count until the queued work is done. */ + evtp->evt_arg1 = lpfc_nlp_get(ndlp); + if (!evtp->evt_arg1) { + spin_unlock_irqrestore(&phba->hbalock, iflags); + return; + } + evtp->evt = LPFC_EVT_RECOVER_PORT; + list_add_tail(&evtp->evt_listp, &phba->work_list); + spin_unlock_irqrestore(&phba->hbalock, iflags); + + lpfc_worker_wake_up(phba); +} + /* lpfc_sli_abts_err_handler - handle a failed ABTS request from an SLI3 port. * @phba: Pointer to HBA context object. * @iocbq: Pointer to iocb object. @@ -10457,7 +10483,7 @@ lpfc_sli4_abts_err_handler(struct lpfc_hba *phba, ext_status = axri->parameter & IOERR_PARAM_MASK; if ((bf_get(lpfc_wcqe_xa_status, axri) == IOSTAT_LOCAL_REJECT) && ((ext_status == IOERR_SEQUENCE_TIMEOUT) || (ext_status == 0))) - lpfc_sli_abts_recover_port(vport, ndlp); + lpfc_sli_post_recovery_event(phba, ndlp); } /** @@ -13065,23 +13091,30 @@ lpfc_sli_intr_handler(int irq, void *dev_id) void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba) { struct lpfc_cq_event *cq_event; + unsigned long iflags; /* First, declare the els xri abort event has been handled */ - spin_lock_irq(&phba->hbalock); + spin_lock_irqsave(&phba->hbalock, iflags); phba->hba_flag &= ~ELS_XRI_ABORT_EVENT; - spin_unlock_irq(&phba->hbalock); + spin_unlock_irqrestore(&phba->hbalock, iflags); + /* Now, handle all the els xri abort events */ + spin_lock_irqsave(&phba->sli4_hba.els_xri_abrt_list_lock, iflags); while (!list_empty(&phba->sli4_hba.sp_els_xri_aborted_work_queue)) { /* Get the first event from the head of the event queue */ - spin_lock_irq(&phba->hbalock); list_remove_head(&phba->sli4_hba.sp_els_xri_aborted_work_queue, cq_event, struct lpfc_cq_event, list); - spin_unlock_irq(&phba->hbalock); + spin_unlock_irqrestore(&phba->sli4_hba.els_xri_abrt_list_lock, + iflags); /* Notify aborted XRI for ELS work queue */ lpfc_sli4_els_xri_aborted(phba, &cq_event->cqe.wcqe_axri); + /* Free the event processed back to the free pool */ lpfc_sli4_cq_event_release(phba, cq_event); + spin_lock_irqsave(&phba->sli4_hba.els_xri_abrt_list_lock, + iflags); } + spin_unlock_irqrestore(&phba->sli4_hba.els_xri_abrt_list_lock, iflags); } /** @@ -13292,9 +13325,13 @@ lpfc_sli4_sp_handle_async_event(struct lpfc_hba *phba, struct lpfc_mcqe *mcqe) cq_event = lpfc_cq_event_setup(phba, mcqe, sizeof(struct lpfc_mcqe)); if (!cq_event) return false; - spin_lock_irqsave(&phba->hbalock, iflags); + + spin_lock_irqsave(&phba->sli4_hba.asynce_list_lock, iflags); list_add_tail(&cq_event->list, &phba->sli4_hba.sp_asynce_work_queue); + spin_unlock_irqrestore(&phba->sli4_hba.asynce_list_lock, iflags); + /* Set the async event flag */ + spin_lock_irqsave(&phba->hbalock, iflags); phba->hba_flag |= ASYNC_EVENT; spin_unlock_irqrestore(&phba->hbalock, iflags); @@ -13569,17 +13606,20 @@ lpfc_sli4_sp_handle_abort_xri_wcqe(struct lpfc_hba *phba, break; case LPFC_NVME_LS: /* NVME LS uses ELS resources */ case LPFC_ELS: - cq_event = lpfc_cq_event_setup( - phba, wcqe, sizeof(struct sli4_wcqe_xri_aborted)); - if (!cq_event) - return false; + cq_event = lpfc_cq_event_setup(phba, wcqe, sizeof(*wcqe)); + if (!cq_event) { + workposted = false; + break; + } cq_event->hdwq = cq->hdwq; - spin_lock_irqsave(&phba->hbalock, iflags); + spin_lock_irqsave(&phba->sli4_hba.els_xri_abrt_list_lock, + iflags); list_add_tail(&cq_event->list, &phba->sli4_hba.sp_els_xri_aborted_work_queue); /* Set the els xri abort event flag */ phba->hba_flag |= ELS_XRI_ABORT_EVENT; - spin_unlock_irqrestore(&phba->hbalock, iflags); + spin_unlock_irqrestore(&phba->sli4_hba.els_xri_abrt_list_lock, + iflags); workposted = true; break; default: diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index a966cdeb52ee..100cb1a94811 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -920,8 +920,9 @@ struct lpfc_sli4_hba { struct list_head sp_queue_event; struct list_head sp_cqe_event_pool; struct list_head sp_asynce_work_queue; - struct list_head sp_fcp_xri_aborted_work_queue; + spinlock_t asynce_list_lock; /* protect sp_asynce_work_queue list */ struct list_head sp_els_xri_aborted_work_queue; + spinlock_t els_xri_abrt_list_lock; /* protect els_xri_aborted list */ struct list_head sp_unsol_work_queue; struct lpfc_sli4_link link_state; struct lpfc_sli4_lnk_info lnk_info; @@ -1103,8 +1104,7 @@ void lpfc_sli4_async_event_proc(struct lpfc_hba *); void lpfc_sli4_fcf_redisc_event_proc(struct lpfc_hba *); int lpfc_sli4_resume_rpi(struct lpfc_nodelist *, void (*)(struct lpfc_hba *, LPFC_MBOXQ_t *), void *); -void lpfc_sli4_fcp_xri_abort_event_proc(struct lpfc_hba *); -void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *); +void lpfc_sli4_els_xri_abort_event_proc(struct lpfc_hba *phba); void lpfc_sli4_nvme_xri_aborted(struct lpfc_hba *phba, struct sli4_wcqe_xri_aborted *axri, struct lpfc_io_buf *lpfc_ncmd); -- cgit v1.2.3 From e5785d3ec32f5f44dd88cd7b398e496742630469 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 20 Oct 2020 13:27:13 -0700 Subject: scsi: lpfc: Re-fix use after free in lpfc_rq_buf_free() Commit 9816ef6ecbc1 ("scsi: lpfc: Use after free in lpfc_rq_buf_free()") was made to correct a use after free condition in lpfc_rq_buf_free(). Unfortunately, a subsequent patch cut on a tree without the fix inadvertently reverted the fix. Put the fix back: Move the freeing of the rqb_entry to after the print function that references it. Link: https://lore.kernel.org/r/20201020202719.54726-4-james.smart@broadcom.com Fixes: 411de511c694 ("scsi: lpfc: Fix RQ empty firmware trap") Cc: # v4.17+ Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 79386e294fb9..be54fbf5146f 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -721,7 +721,6 @@ lpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) drqe.address_hi = putPaddrHigh(rqb_entry->dbuf.phys); rc = lpfc_sli4_rq_put(rqb_entry->hrq, rqb_entry->drq, &hrqe, &drqe); if (rc < 0) { - (rqbp->rqb_free_buffer)(phba, rqb_entry); lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "6409 Cannot post to HRQ %d: %x %x %x " "DRQ %x %x\n", @@ -731,6 +730,7 @@ lpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) rqb_entry->hrq->entry_count, rqb_entry->drq->host_index, rqb_entry->drq->hba_index); + (rqbp->rqb_free_buffer)(phba, rqb_entry); } else { list_add_tail(&rqb_entry->hbuf.list, &rqbp->rqb_buffer_list); rqbp->buffer_count++; -- cgit v1.2.3 From 7cbef585a12a098e694d34e94c140b18fe0e9735 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 20 Oct 2020 13:27:14 -0700 Subject: scsi: lpfc: Removed unused macros in lpfc_attr.c Removed unused MRQ-related defines that are not referenced. Link: https://lore.kernel.org/r/20201020202719.54726-5-james.smart@broadcom.com Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index e94eac194676..2d810474875c 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -57,10 +57,6 @@ #define LPFC_MIN_DEVLOSS_TMO 1 #define LPFC_MAX_DEVLOSS_TMO 255 -#define LPFC_DEF_MRQ_POST 512 -#define LPFC_MIN_MRQ_POST 512 -#define LPFC_MAX_MRQ_POST 2048 - /* * Write key size should be multiple of 4. If write key is changed * make sure that library write key is also changed. -- cgit v1.2.3 From f5201f87ccafd8d80283c87490bbdf78f8a026bf Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 20 Oct 2020 13:27:15 -0700 Subject: scsi: lpfc: Fix duplicate wq_create_version check During code reviews duplicate code sections were found to determine the WQ Create version. The duplication was potentially overriding logic that validated page size. Link: https://lore.kernel.org/r/20201020202719.54726-6-james.smart@broadcom.com Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index e5a7cfa55b6c..eaa5fb5ea079 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -15893,12 +15893,6 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, else wq_create_version = LPFC_Q_CREATE_VERSION_0; - - if (phba->sli4_hba.pc_sli4_params.wqsize & LPFC_WQ_SZ128_SUPPORT) - wq_create_version = LPFC_Q_CREATE_VERSION_1; - else - wq_create_version = LPFC_Q_CREATE_VERSION_0; - switch (wq_create_version) { case LPFC_Q_CREATE_VERSION_1: bf_set(lpfc_mbx_wq_create_wqe_count, &wq_create->u.request_1, -- cgit v1.2.3 From 7c30bb62ed5db15cdb59f5722122fbed7421641c Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 20 Oct 2020 13:27:16 -0700 Subject: scsi: lpfc: Enlarge max_sectors in scsi host templates The driver supports arbitrarily large scatter-gather lists and the current value for max_sectors is limiting. Change max_sectors to the largest value. This was actually done prior but it only corrected one template and that template was later removed. So change the remaining 2 templates. Other areas which hard-set the sectors value should be inheriting what is in the template. Link: https://lore.kernel.org/r/20201020202719.54726-7-james.smart@broadcom.com Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 5 +---- drivers/scsi/lpfc/lpfc_scsi.c | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index edfefff0214a..e5879dc0cc8c 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -4343,16 +4343,13 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev) /* Seed physical port template */ memcpy(template, &lpfc_template, sizeof(*template)); - if (use_no_reset_hba) { + if (use_no_reset_hba) /* template is for a no reset SCSI Host */ - template->max_sectors = 0xffff; template->eh_host_reset_handler = NULL; - } /* Template for all vports this physical port creates */ memcpy(&phba->vport_template, &lpfc_template, sizeof(*template)); - phba->vport_template.max_sectors = 0xffff; phba->vport_template.shost_attrs = lpfc_vport_attrs; phba->vport_template.eh_bus_reset_handler = NULL; phba->vport_template.eh_host_reset_handler = NULL; diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c3b02dab6e5c..4ffdfd2c8604 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -6028,7 +6028,7 @@ struct scsi_host_template lpfc_template_nvme = { .sg_tablesize = 1, .cmd_per_lun = 1, .shost_attrs = lpfc_hba_attrs, - .max_sectors = 0xFFFF, + .max_sectors = 0xFFFFFFFF, .vendor_id = LPFC_NL_VENDOR_ID, .track_queue_depth = 0, }; @@ -6053,7 +6053,7 @@ struct scsi_host_template lpfc_template = { .sg_tablesize = LPFC_DEFAULT_SG_SEG_CNT, .cmd_per_lun = LPFC_CMD_PER_LUN, .shost_attrs = lpfc_hba_attrs, - .max_sectors = 0xFFFF, + .max_sectors = 0xFFFFFFFF, .vendor_id = LPFC_NL_VENDOR_ID, .change_queue_depth = scsi_change_queue_depth, .track_queue_depth = 1, -- cgit v1.2.3 From 8aaa7bcf07a2eea5ffb6d4ee776379c0e0154f6d Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 20 Oct 2020 13:27:17 -0700 Subject: scsi: lpfc: Add FDMI Vendor MIB support Created new attribute lpfc_enable_mi, which by default is enabled. Add command definition bits for SLI-4 parameters that recognize whether the adapter has MIB information support and what revision of MIB data. Using the adapter information, register vendor-specific MIB support with FDMI. The registration will be done every link up. During FDMI registration, encountered a couple of errors when reverting to FDMI rev1. Code needed to exist once reverting. Fixed these. Link: https://lore.kernel.org/r/20201020202719.54726-8-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 4 ++- drivers/scsi/lpfc/lpfc_attr.c | 10 +++++++ drivers/scsi/lpfc/lpfc_ct.c | 60 ++++++++++++++++++++++++++++++++++++++++ drivers/scsi/lpfc/lpfc_els.c | 6 ++++ drivers/scsi/lpfc/lpfc_hbadisc.c | 6 ++-- drivers/scsi/lpfc/lpfc_hw.h | 4 ++- drivers/scsi/lpfc/lpfc_hw4.h | 10 +++++-- drivers/scsi/lpfc/lpfc_init.c | 15 ++++++++++ drivers/scsi/lpfc/lpfc_sli4.h | 8 ++++++ 9 files changed, 117 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 93e507677bdc..3c77e02d36b0 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -744,7 +744,8 @@ struct lpfc_hba { #define LS_NPIV_FAB_SUPPORTED 0x2 /* Fabric supports NPIV */ #define LS_IGNORE_ERATT 0x4 /* intr handler should ignore ERATT */ #define LS_MDS_LINK_DOWN 0x8 /* MDS Diagnostics Link Down */ -#define LS_MDS_LOOPBACK 0x10 /* MDS Diagnostics Link Up (Loopback) */ +#define LS_MDS_LOOPBACK 0x10 /* MDS Diagnostics Link Up (Loopback) */ +#define LS_CT_VEN_RPA 0x20 /* Vendor RPA sent to switch */ uint32_t hba_flag; /* hba generic flags */ #define HBA_ERATT_HANDLED 0x1 /* This flag is set when eratt handled */ @@ -922,6 +923,7 @@ struct lpfc_hba { #define LPFC_ENABLE_NVME 2 #define LPFC_ENABLE_BOTH 3 uint32_t cfg_enable_pbde; + uint32_t cfg_enable_mi; struct nvmet_fc_target_port *targetport; lpfc_vpd_t vpd; /* vital product data */ diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 2d810474875c..0673d944c2a8 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -6134,6 +6134,14 @@ LPFC_BBCR_ATTR_RW(enable_bbcr, 1, 0, 1, "Enable BBC Recovery"); */ LPFC_ATTR_RW(enable_dpp, 1, 0, 1, "Enable Direct Packet Push"); +/* + * lpfc_enable_mi: Enable FDMI MIB + * 0 = disabled + * 1 = enabled (default) + * Value range is [0,1]. + */ +LPFC_ATTR_R(enable_mi, 1, 0, 1, "Enable MI"); + struct device_attribute *lpfc_hba_attrs[] = { &dev_attr_nvme_info, &dev_attr_scsi_stat, @@ -6251,6 +6259,7 @@ struct device_attribute *lpfc_hba_attrs[] = { &dev_attr_lpfc_ras_fwlog_func, &dev_attr_lpfc_enable_bbcr, &dev_attr_lpfc_enable_dpp, + &dev_attr_lpfc_enable_mi, NULL, }; @@ -7355,6 +7364,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) lpfc_irq_chann_init(phba, lpfc_irq_chann); lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr); lpfc_enable_dpp_init(phba, lpfc_enable_dpp); + lpfc_enable_mi_init(phba, lpfc_enable_mi); if (phba->sli_rev != LPFC_SLI_REV4) { /* NVME only supported on SLI4 */ diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index a8bf4d0d58f0..434e39d173da 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1959,6 +1959,7 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, vport->fdmi_port_mask = LPFC_FDMI1_PORT_ATTR; /* Start over */ lpfc_fdmi_cmd(vport, ndlp, cmd, 0); + return; } if (vport->fdmi_port_mask == LPFC_FDMI2_SMART_ATTR) { vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR; @@ -1968,12 +1969,21 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, return; case SLI_MGMT_RPA: + /* No retry on Vendor RPA */ + if (phba->link_flag & LS_CT_VEN_RPA) { + lpfc_printf_vlog(vport, KERN_ERR, + LOG_DISCOVERY | LOG_ELS, + "6460 VEN FDMI RPA failure\n"); + phba->link_flag &= ~LS_CT_VEN_RPA; + return; + } if (vport->fdmi_port_mask == LPFC_FDMI2_PORT_ATTR) { /* Fallback to FDMI-1 */ vport->fdmi_hba_mask = LPFC_FDMI1_HBA_ATTR; vport->fdmi_port_mask = LPFC_FDMI1_PORT_ATTR; /* Start over */ lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA, 0); + return; } if (vport->fdmi_port_mask == LPFC_FDMI2_SMART_ATTR) { vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR; @@ -2004,6 +2014,33 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, else lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPRT, 0); break; + case SLI_MGMT_RPA: + if (vport->port_type == LPFC_PHYSICAL_PORT && + phba->cfg_enable_mi && + phba->sli4_hba.pc_sli4_params.mi_ver > LPFC_MIB1_SUPPORT) { + /* mi is only for the phyical port, no vports */ + if (phba->link_flag & LS_CT_VEN_RPA) { + lpfc_printf_vlog(vport, KERN_INFO, + LOG_DISCOVERY | LOG_ELS, + "6449 VEN RPA Success\n"); + break; + } + + if (lpfc_fdmi_cmd(vport, ndlp, cmd, + LPFC_FDMI_VENDOR_ATTR_mi) == 0) + phba->link_flag |= LS_CT_VEN_RPA; + lpfc_printf_vlog(vport, KERN_INFO, + LOG_DISCOVERY | LOG_ELS, + "6458 Send MI FDMI:%x Flag x%x\n", + phba->sli4_hba.pc_sli4_params.mi_value, + phba->link_flag); + } else { + lpfc_printf_vlog(vport, KERN_INFO, + LOG_DISCOVERY | LOG_ELS, + "6459 No FDMI VEN MI support - " + "RPA Success\n"); + } + break; } return; } @@ -2974,6 +3011,28 @@ lpfc_fdmi_smart_attr_security(struct lpfc_vport *vport, return size; } +int +lpfc_fdmi_vendor_attr_mi(struct lpfc_vport *vport, + struct lpfc_fdmi_attr_def *ad) +{ + struct lpfc_hba *phba = vport->phba; + struct lpfc_fdmi_attr_entry *ae; + uint32_t len, size; + char mibrevision[16]; + + ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; + memset(ae, 0, 256); + sprintf(mibrevision, "ELXE2EM:%04d", + phba->sli4_hba.pc_sli4_params.mi_value); + strncpy(ae->un.AttrString, &mibrevision[0], sizeof(ae->un.AttrString)); + len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString)); + len += (len & 3) ? (4 - (len & 3)) : 4; + size = FOURBYTES + len; + ad->AttrLen = cpu_to_be16(size); + ad->AttrType = cpu_to_be16(RPRT_VENDOR_MI); + return size; +} + /* RHBA attribute jump table */ int (*lpfc_fdmi_hba_action[]) (struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) = { @@ -3025,6 +3084,7 @@ int (*lpfc_fdmi_port_action[]) lpfc_fdmi_smart_attr_port_info, /* bit20 RPRT_SMART_PORT_INFO */ lpfc_fdmi_smart_attr_qos, /* bit21 RPRT_SMART_QOS */ lpfc_fdmi_smart_attr_security, /* bit22 RPRT_SMART_SECURITY */ + lpfc_fdmi_vendor_attr_mi, /* bit23 RPRT_VENDOR_MI */ }; /** diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index b60945182db8..de3a59f2e3df 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -3335,6 +3335,12 @@ lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry) lpfc_els_free_iocb(phba, elsiocb); return 1; } + + /* Only keep the ndlp if RDF is being sent */ + if (!phba->cfg_enable_mi || + phba->sli4_hba.pc_sli4_params.mi_ver < LPFC_MIB3_SUPPORT) + return 0; + /* This will cause the callback-function lpfc_cmpl_els_cmd to * trigger the release of node. */ diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 9746d2f4fcfa..c61eb6032500 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -3205,7 +3205,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) } phba->fc_topology = bf_get(lpfc_mbx_read_top_topology, la); - phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED; + phba->link_flag &= ~(LS_NPIV_FAB_SUPPORTED | LS_CT_VEN_RPA); shost = lpfc_shost_from_vport(vport); if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { @@ -4133,7 +4133,9 @@ out: /* Issue SCR just before NameServer GID_FT Query */ lpfc_issue_els_scr(vport, 0); - lpfc_issue_els_rdf(vport, 0); + if (!phba->cfg_enable_mi || + phba->sli4_hba.pc_sli4_params.mi_ver < LPFC_MIB3_SUPPORT) + lpfc_issue_els_rdf(vport, 0); } vport->fc_ns_retry = 0; diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index c20034b3101c..28b8a394f796 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1465,7 +1465,7 @@ struct lpfc_fdmi_reg_portattr { #define LPFC_FDMI2_HBA_ATTR 0x0002efff /* - * Port Attrubute Types + * Port Attribute Types */ #define RPRT_SUPPORTED_FC4_TYPES 0x1 /* 32 byte binary array */ #define RPRT_SUPPORTED_SPEED 0x2 /* 32-bit unsigned int */ @@ -1483,6 +1483,7 @@ struct lpfc_fdmi_reg_portattr { #define RPRT_PORT_STATE 0x101 /* 32-bit unsigned int */ #define RPRT_DISC_PORT 0x102 /* 32-bit unsigned int */ #define RPRT_PORT_ID 0x103 /* 32-bit unsigned int */ +#define RPRT_VENDOR_MI 0xf047 /* vendor ascii string */ #define RPRT_SMART_SERVICE 0xf100 /* 4 to 256 byte ASCII string */ #define RPRT_SMART_GUID 0xf101 /* 8 byte WWNN + 8 byte WWPN */ #define RPRT_SMART_VERSION 0xf102 /* 4 to 256 byte ASCII string */ @@ -1515,6 +1516,7 @@ struct lpfc_fdmi_reg_portattr { #define LPFC_FDMI_SMART_ATTR_port_info 0x00100000 /* Vendor specific */ #define LPFC_FDMI_SMART_ATTR_qos 0x00200000 /* Vendor specific */ #define LPFC_FDMI_SMART_ATTR_security 0x00400000 /* Vendor specific */ +#define LPFC_FDMI_VENDOR_ATTR_mi 0x00800000 /* Vendor specific */ /* Bit mask for FDMI-1 defined PORT attributes */ #define LPFC_FDMI1_PORT_ATTR 0x0000003f diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 12e4e76233e6..49f5559f5fed 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -3506,8 +3506,14 @@ struct lpfc_sli4_parameters { #define cfg_max_tow_xri_MASK 0x0000ffff #define cfg_max_tow_xri_WORD word20 - uint32_t word21; /* RESERVED */ - uint32_t word22; /* RESERVED */ + uint32_t word21; +#define cfg_mib_bde_cnt_SHIFT 16 +#define cfg_mib_bde_cnt_MASK 0x000000ff +#define cfg_mib_bde_cnt_WORD word21 +#define cfg_mi_ver_SHIFT 0 +#define cfg_mi_ver_MASK 0x0000ffff +#define cfg_mi_ver_WORD word21 + uint32_t mib_size; uint32_t word23; /* RESERVED */ uint32_t word24; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index e5879dc0cc8c..aa7931a1750f 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -12314,6 +12314,21 @@ fcponly: else phba->nsler = 0; + /* Save PB info for use during HBA setup */ + sli4_params->mi_ver = bf_get(cfg_mi_ver, mbx_sli4_parameters); + sli4_params->mib_bde_cnt = bf_get(cfg_mib_bde_cnt, mbx_sli4_parameters); + sli4_params->mib_size = mbx_sli4_parameters->mib_size; + sli4_params->mi_value = LPFC_DFLT_MIB_VAL; + + /* Next we check for Vendor MIB support */ + if (sli4_params->mi_ver && phba->cfg_enable_mi) + phba->cfg_fdmi_on = LPFC_FDMI_SUPPORT; + + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "6461 MIB attr %d enable %d FDMI %d buf %d:%d\n", + sli4_params->mi_ver, phba->cfg_enable_mi, + sli4_params->mi_value, sli4_params->mib_bde_cnt, + sli4_params->mib_size); return 0; } diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 100cb1a94811..26f19c95380f 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h @@ -549,6 +549,14 @@ struct lpfc_pc_sli4_params { uint32_t hdr_pp_align; uint32_t sgl_pages_max; uint32_t sgl_pp_align; + uint32_t mib_size; + uint16_t mi_ver; +#define LPFC_MIB1_SUPPORT 1 +#define LPFC_MIB2_SUPPORT 2 +#define LPFC_MIB3_SUPPORT 3 + uint16_t mi_value; +#define LPFC_DFLT_MIB_VAL 2 + uint8_t mib_bde_cnt; uint8_t cqv; uint8_t mqv; uint8_t wqv; -- cgit v1.2.3 From b67b5944328219f8ac1e0496ae0f4e45f6d43855 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 20 Oct 2020 13:27:18 -0700 Subject: scsi: lpfc: Reject CT request for MIB commands Now that MIB support was registered with FDMI, the driver may receive CT requests for MIB-related commands. At this time, no command is supported. However, the driver needs to be graceful and reject the CT request. This patch adds identification of the requests as well as sending the reject response. Link: https://lore.kernel.org/r/20201020202719.54726-9-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_bsg.c | 21 +-- drivers/scsi/lpfc/lpfc_ct.c | 311 ++++++++++++++++++++++++++++++++++++++++--- drivers/scsi/lpfc/lpfc_hw.h | 3 + 3 files changed, 296 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 6f9d648a9b9c..5b66b8ea8363 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -939,28 +939,9 @@ lpfc_bsg_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, INIT_LIST_HEAD(&head); list_add_tail(&head, &piocbq->list); - if (piocbq->iocb.ulpBdeCount == 0 || - piocbq->iocb.un.cont64[0].tus.f.bdeSize == 0) - goto error_ct_unsol_exit; - - if (phba->link_state == LPFC_HBA_ERROR || - (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE))) - goto error_ct_unsol_exit; - - if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) - dmabuf = bdeBuf1; - else { - dma_addr = getPaddr(piocbq->iocb.un.cont64[0].addrHigh, - piocbq->iocb.un.cont64[0].addrLow); - dmabuf = lpfc_sli_ringpostbuf_get(phba, pring, dma_addr); - } - if (dmabuf == NULL) - goto error_ct_unsol_exit; - ct_req = (struct lpfc_sli_ct_request *)dmabuf->virt; + ct_req = (struct lpfc_sli_ct_request *)bdeBuf1; evt_req_id = ct_req->FsType; cmd = ct_req->CommandResponse.bits.CmdRsp; - if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) - lpfc_sli_ringpostbuf_put(phba, pring, dmabuf); spin_lock_irqsave(&phba->ct_ev_lock, flags); list_for_each_entry(evt, &phba->ct_ev_waiters, node) { diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 434e39d173da..b963e234d77d 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -99,21 +99,265 @@ lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, lpfc_ct_ignore_hbq_buffer(phba, piocbq, mp, size); } +/** + * lpfc_ct_unsol_cmpl : Completion callback function for unsol ct commands + * @phba : pointer to lpfc hba data structure. + * @cmdiocb : pointer to lpfc command iocb data structure. + * @rspiocb : pointer to lpfc response iocb data structure. + * + * This routine is the callback function for issuing unsol ct reject command. + * The memory allocated in the reject command path is freed up here. + **/ +static void +lpfc_ct_unsol_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + struct lpfc_iocbq *rspiocb) +{ + struct lpfc_nodelist *ndlp; + struct lpfc_dmabuf *mp, *bmp; + + ndlp = (struct lpfc_nodelist *)cmdiocb->context1; + if (ndlp) + lpfc_nlp_put(ndlp); + + mp = cmdiocb->context2; + bmp = cmdiocb->context3; + if (mp) { + lpfc_mbuf_free(phba, mp->virt, mp->phys); + kfree(mp); + cmdiocb->context2 = NULL; + } + + if (bmp) { + lpfc_mbuf_free(phba, bmp->virt, bmp->phys); + kfree(bmp); + cmdiocb->context3 = NULL; + } + + lpfc_sli_release_iocbq(phba, cmdiocb); +} + +/** + * lpfc_ct_reject_event : Issue reject for unhandled CT MIB commands + * @ndlp : pointer to a node-list data structure. + * ct_req : pointer to the CT request data structure. + * rx_id : rx_id of the received UNSOL CT command + * ox_id : ox_id of the UNSOL CT command + * + * This routine is invoked by the lpfc_ct_handle_mibreq routine for sending + * a reject response. Reject response is sent for the unhandled commands. + **/ +static void +lpfc_ct_reject_event(struct lpfc_nodelist *ndlp, + struct lpfc_sli_ct_request *ct_req, + u16 rx_id, u16 ox_id) +{ + struct lpfc_vport *vport = ndlp->vport; + struct lpfc_hba *phba = vport->phba; + struct lpfc_sli_ct_request *ct_rsp; + struct lpfc_iocbq *cmdiocbq = NULL; + struct lpfc_dmabuf *bmp = NULL; + struct lpfc_dmabuf *mp = NULL; + struct ulp_bde64 *bpl; + IOCB_t *icmd; + u8 rc = 0; + + /* fill in BDEs for command */ + mp = kmalloc(sizeof(*mp), GFP_KERNEL); + if (!mp) { + rc = 1; + goto ct_exit; + } + + mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &mp->phys); + if (!mp->virt) { + rc = 2; + goto ct_free_mp; + } + + /* Allocate buffer for Buffer ptr list */ + bmp = kmalloc(sizeof(*bmp), GFP_KERNEL); + if (!bmp) { + rc = 3; + goto ct_free_mpvirt; + } + + bmp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &bmp->phys); + if (!bmp->virt) { + rc = 4; + goto ct_free_bmp; + } + + INIT_LIST_HEAD(&mp->list); + INIT_LIST_HEAD(&bmp->list); + + bpl = (struct ulp_bde64 *)bmp->virt; + memset(bpl, 0, sizeof(struct ulp_bde64)); + bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys)); + bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys)); + bpl->tus.f.bdeFlags = BUFF_TYPE_BLP_64; + bpl->tus.f.bdeSize = (LPFC_CT_PREAMBLE - 4); + bpl->tus.w = le32_to_cpu(bpl->tus.w); + + ct_rsp = (struct lpfc_sli_ct_request *)mp->virt; + memset(ct_rsp, 0, sizeof(struct lpfc_sli_ct_request)); + + ct_rsp->RevisionId.bits.Revision = SLI_CT_REVISION; + ct_rsp->RevisionId.bits.InId = 0; + ct_rsp->FsType = ct_req->FsType; + ct_rsp->FsSubType = ct_req->FsSubType; + ct_rsp->CommandResponse.bits.Size = 0; + ct_rsp->CommandResponse.bits.CmdRsp = + cpu_to_be16(SLI_CT_RESPONSE_FS_RJT); + ct_rsp->ReasonCode = SLI_CT_REQ_NOT_SUPPORTED; + ct_rsp->Explanation = SLI_CT_NO_ADDITIONAL_EXPL; + + cmdiocbq = lpfc_sli_get_iocbq(phba); + if (!cmdiocbq) { + rc = 5; + goto ct_free_bmpvirt; + } + + icmd = &cmdiocbq->iocb; + icmd->un.genreq64.bdl.ulpIoTag32 = 0; + icmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys); + icmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys); + icmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64; + icmd->un.genreq64.bdl.bdeSize = sizeof(struct ulp_bde64); + icmd->un.genreq64.w5.hcsw.Fctl = (LS | LA); + icmd->un.genreq64.w5.hcsw.Dfctl = 0; + icmd->un.genreq64.w5.hcsw.Rctl = FC_RCTL_DD_SOL_CTL; + icmd->un.genreq64.w5.hcsw.Type = FC_TYPE_CT; + icmd->ulpCommand = CMD_XMIT_SEQUENCE64_CX; + icmd->ulpBdeCount = 1; + icmd->ulpLe = 1; + icmd->ulpClass = CLASS3; + + /* Save for completion so we can release these resources */ + cmdiocbq->context1 = lpfc_nlp_get(ndlp); + cmdiocbq->context2 = (uint8_t *)mp; + cmdiocbq->context3 = (uint8_t *)bmp; + cmdiocbq->iocb_cmpl = lpfc_ct_unsol_cmpl; + icmd->ulpContext = rx_id; /* Xri / rx_id */ + icmd->unsli3.rcvsli3.ox_id = ox_id; + icmd->un.ulpWord[3] = + phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; + icmd->ulpTimeout = (3 * phba->fc_ratov); + + cmdiocbq->retry = 0; + cmdiocbq->vport = vport; + cmdiocbq->context_un.ndlp = NULL; + cmdiocbq->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT; + + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0); + if (!rc) + return; + + rc = 6; + lpfc_nlp_put(ndlp); + lpfc_sli_release_iocbq(phba, cmdiocbq); +ct_free_bmpvirt: + lpfc_mbuf_free(phba, bmp->virt, bmp->phys); +ct_free_bmp: + kfree(bmp); +ct_free_mpvirt: + lpfc_mbuf_free(phba, mp->virt, mp->phys); +ct_free_mp: + kfree(mp); +ct_exit: + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "6440 Unsol CT: Rsp err %d Data: x%x\n", + rc, vport->fc_flag); +} + +/** + * lpfc_ct_handle_mibreq - Process an unsolicited CT MIB request data buffer + * @phba: pointer to lpfc hba data structure. + * @ctiocb: pointer to lpfc CT command iocb data structure. + * + * This routine is used for processing the IOCB associated with a unsolicited + * CT MIB request. It first determines whether there is an existing ndlp that + * matches the DID from the unsolicited IOCB. If not, it will return. + **/ +static void +lpfc_ct_handle_mibreq(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocbq) +{ + struct lpfc_sli_ct_request *ct_req; + struct lpfc_nodelist *ndlp = NULL; + struct lpfc_vport *vport = NULL; + IOCB_t *icmd = &ctiocbq->iocb; + u32 mi_cmd, vpi; + u32 did = 0; + + vpi = ctiocbq->iocb.unsli3.rcvsli3.vpi; + vport = lpfc_find_vport_by_vpid(phba, vpi); + if (!vport) { + lpfc_printf_log(phba, KERN_INFO, LOG_ELS, + "6437 Unsol CT: VPORT NULL vpi : x%x\n", + vpi); + return; + } + + did = ctiocbq->iocb.un.rcvels.remoteID; + if (icmd->ulpStatus) { + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "6438 Unsol CT: status:x%x/x%x did : x%x\n", + icmd->ulpStatus, icmd->un.ulpWord[4], did); + return; + } + + /* Ignore traffic received during vport shutdown */ + if (vport->fc_flag & FC_UNLOADING) + return; + + ndlp = lpfc_findnode_did(vport, did); + if (!ndlp) { + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "6439 Unsol CT: NDLP Not Found for DID : x%x", + did); + return; + } + + ct_req = ((struct lpfc_sli_ct_request *) + (((struct lpfc_dmabuf *)ctiocbq->context2)->virt)); + + mi_cmd = ct_req->CommandResponse.bits.CmdRsp; + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "6442 : MI Cmd : x%x Not Supported\n", mi_cmd); + lpfc_ct_reject_event(ndlp, ct_req, + ctiocbq->iocb.ulpContext, + ctiocbq->iocb.unsli3.rcvsli3.ox_id); +} + +/** + * lpfc_ct_unsol_event - Process an unsolicited event from a ct sli ring + * @phba: pointer to lpfc hba data structure. + * @pring: pointer to a SLI ring. + * @ctiocbq: pointer to lpfc ct iocb data structure. + * + * This routine is used to process an unsolicited event received from a SLI + * (Service Level Interface) ring. The actual processing of the data buffer + * associated with the unsolicited event is done by invoking appropriate routine + * after properly set up the iocb buffer from the SLI ring on which the + * unsolicited event was received. + **/ void lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, - struct lpfc_iocbq *piocbq) + struct lpfc_iocbq *ctiocbq) { struct lpfc_dmabuf *mp = NULL; - IOCB_t *icmd = &piocbq->iocb; + IOCB_t *icmd = &ctiocbq->iocb; int i; struct lpfc_iocbq *iocbq; - dma_addr_t paddr; + dma_addr_t dma_addr; uint32_t size; struct list_head head; - struct lpfc_dmabuf *bdeBuf; + struct lpfc_sli_ct_request *ct_req; + struct lpfc_dmabuf *bdeBuf1 = ctiocbq->context2; + struct lpfc_dmabuf *bdeBuf2 = ctiocbq->context3; - if (lpfc_bsg_ct_unsol_event(phba, pring, piocbq) == 0) - return; + ctiocbq->context1 = NULL; + ctiocbq->context2 = NULL; + ctiocbq->context3 = NULL; if (unlikely(icmd->ulpStatus == IOSTAT_NEED_BUFFER)) { lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ); @@ -127,46 +371,75 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, return; } - /* If there are no BDEs associated with this IOCB, - * there is nothing to do. + /* If there are no BDEs associated + * with this IOCB, there is nothing to do. */ if (icmd->ulpBdeCount == 0) return; + if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { + ctiocbq->context2 = bdeBuf1; + if (icmd->ulpBdeCount == 2) + ctiocbq->context3 = bdeBuf2; + } else { + dma_addr = getPaddr(icmd->un.cont64[0].addrHigh, + icmd->un.cont64[0].addrLow); + ctiocbq->context2 = lpfc_sli_ringpostbuf_get(phba, pring, + dma_addr); + if (icmd->ulpBdeCount == 2) { + dma_addr = getPaddr(icmd->un.cont64[1].addrHigh, + icmd->un.cont64[1].addrLow); + ctiocbq->context3 = lpfc_sli_ringpostbuf_get(phba, + pring, + dma_addr); + } + } + + ct_req = ((struct lpfc_sli_ct_request *) + (((struct lpfc_dmabuf *)ctiocbq->context2)->virt)); + + if (ct_req->FsType == SLI_CT_MANAGEMENT_SERVICE && + ct_req->FsSubType == SLI_CT_MIB_Subtypes) { + lpfc_ct_handle_mibreq(phba, ctiocbq); + } else { + if (!lpfc_bsg_ct_unsol_event(phba, pring, ctiocbq)) + return; + } + if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { INIT_LIST_HEAD(&head); - list_add_tail(&head, &piocbq->list); + list_add_tail(&head, &ctiocbq->list); list_for_each_entry(iocbq, &head, list) { icmd = &iocbq->iocb; if (icmd->ulpBdeCount == 0) continue; - bdeBuf = iocbq->context2; + bdeBuf1 = iocbq->context2; iocbq->context2 = NULL; size = icmd->un.cont64[0].tus.f.bdeSize; - lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf, size); - lpfc_in_buf_free(phba, bdeBuf); + lpfc_ct_unsol_buffer(phba, ctiocbq, bdeBuf1, size); + lpfc_in_buf_free(phba, bdeBuf1); if (icmd->ulpBdeCount == 2) { - bdeBuf = iocbq->context3; + bdeBuf2 = iocbq->context3; iocbq->context3 = NULL; size = icmd->unsli3.rcvsli3.bde2.tus.f.bdeSize; - lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf, + lpfc_ct_unsol_buffer(phba, ctiocbq, bdeBuf2, size); - lpfc_in_buf_free(phba, bdeBuf); + lpfc_in_buf_free(phba, bdeBuf2); } } list_del(&head); } else { INIT_LIST_HEAD(&head); - list_add_tail(&head, &piocbq->list); + list_add_tail(&head, &ctiocbq->list); list_for_each_entry(iocbq, &head, list) { icmd = &iocbq->iocb; if (icmd->ulpBdeCount == 0) lpfc_ct_unsol_buffer(phba, iocbq, NULL, 0); for (i = 0; i < icmd->ulpBdeCount; i++) { - paddr = getPaddr(icmd->un.cont64[i].addrHigh, - icmd->un.cont64[i].addrLow); + dma_addr = getPaddr(icmd->un.cont64[i].addrHigh, + icmd->un.cont64[i].addrLow); mp = lpfc_sli_ringpostbuf_get(phba, pring, - paddr); + dma_addr); size = icmd->un.cont64[i].tus.f.bdeSize; lpfc_ct_unsol_buffer(phba, iocbq, mp, size); lpfc_in_buf_free(phba, mp); diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 28b8a394f796..42682d95af52 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -1380,6 +1380,9 @@ struct lpfc_fdmi_reg_hba { struct lpfc_fdmi_reg_port_list rpl; }; +/******** MI MIB ********/ +#define SLI_CT_MIB_Subtypes 0x11 + /* * Register HBA Attributes (RHAT) */ -- cgit v1.2.3 From 56ae4919f9eddf1ed60dac1e13caa1720ebf67b5 Mon Sep 17 00:00:00 2001 From: James Smart Date: Tue, 20 Oct 2020 13:27:19 -0700 Subject: scsi: lpfc: Update lpfc version to 12.8.0.5 Update lpfc version to 12.8.0.5 Link: https://lore.kernel.org/r/20201020202719.54726-10-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index c657abf22b75..d91ee125abd0 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -20,7 +20,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "12.8.0.4" +#define LPFC_DRIVER_VERSION "12.8.0.5" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ -- cgit v1.2.3 From ae6b4e69a80de2cf89afe451424cc02f953a4a10 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 23 Oct 2020 18:33:14 +0200 Subject: scsi: doc: Fix some kernel-doc markups Some identifiers have different names between their prototypes and the kernel-doc markup. [mkp: fix whitespace] Link: https://lore.kernel.org/r/8ed7f149f25a363eea76e514c253c4e337c59379.1603469755.git.mchehab+huawei@kernel.org Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Martin K. Petersen --- drivers/scsi/iscsi_tcp.c | 4 ++-- drivers/scsi/libiscsi.c | 2 +- drivers/scsi/scsi_devinfo.c | 3 ++- drivers/scsi/scsi_lib.c | 6 +++--- drivers/scsi/scsi_transport_fc.c | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index df47557a02a3..a9ce6298b935 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -180,7 +180,7 @@ static void iscsi_sw_tcp_state_change(struct sock *sk) } /** - * iscsi_write_space - Called when more output buffer space is available + * iscsi_sw_tcp_write_space - Called when more output buffer space is available * @sk: socket space is available for **/ static void iscsi_sw_tcp_write_space(struct sock *sk) @@ -353,7 +353,7 @@ error: } /** - * iscsi_tcp_xmit_qlen - return the number of bytes queued for xmit + * iscsi_sw_tcp_xmit_qlen - return the number of bytes queued for xmit * @conn: iscsi connection */ static inline int iscsi_sw_tcp_xmit_qlen(struct iscsi_conn *conn) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 1e9c3171fa9f..8a4552f09dfe 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -777,7 +777,7 @@ int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); /** - * iscsi_cmd_rsp - SCSI Command Response processing + * iscsi_scsi_cmd_rsp - SCSI Command Response processing * @conn: iscsi connection * @hdr: iscsi header * @task: scsi command task diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index ba84244c1b4f..d92cec12454c 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -559,7 +559,8 @@ static int scsi_dev_info_list_add_str(char *dev_list) } /** - * get_device_flags - get device specific flags from the dynamic device list. + * scsi_get_device_flags - get device specific flags from the dynamic + * device list. * @sdev: &scsi_device to get flags for * @vendor: vendor name * @model: model name diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 60c7a7d74852..20a357563d3d 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1455,7 +1455,7 @@ static void scsi_softirq_done(struct request *rq) } /** - * scsi_dispatch_command - Dispatch a command to the low-level driver. + * scsi_dispatch_cmd - Dispatch a command to the low-level driver. * @cmd: command block we are dispatching. * * Return: nonzero return request was rejected and device's queue needs to be @@ -2335,7 +2335,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) EXPORT_SYMBOL(scsi_device_set_state); /** - * sdev_evt_emit - emit a single SCSI device uevent + * scsi_evt_emit - emit a single SCSI device uevent * @sdev: associated SCSI device * @evt: event to emit * @@ -2383,7 +2383,7 @@ static void scsi_evt_emit(struct scsi_device *sdev, struct scsi_event *evt) } /** - * sdev_evt_thread - send a uevent for each scsi event + * scsi_evt_thread - send a uevent for each scsi event * @work: work struct for scsi_device * * Dispatch queued events to their associated scsi_device kobjects diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 3f816ab1d845..a926e8f9e56e 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -892,7 +892,7 @@ fc_fpin_congn_stats_update(struct Scsi_Host *shost, } /** - * fc_host_rcv_fpin - routine to process a received FPIN. + * fc_host_fpin_rcv - routine to process a received FPIN. * @shost: host the FPIN was received on * @fpin_len: length of FPIN payload, in bytes * @fpin_buf: pointer to FPIN payload -- cgit v1.2.3 From e31ac898ac298b7a0451b0406769a024bd286e4d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 26 Oct 2020 17:06:12 +0100 Subject: scsi: libfc: Move scsi/fc_encode.h to libfc Most of this file is only used inside of libfc, so move it to where it is actually used, with only fc_fill_fc_hdr() left inside of the header. Link: https://lore.kernel.org/r/20201026160705.3706396-1-arnd@kernel.org Reported-by: kernel test robot Signed-off-by: Arnd Bergmann Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc.h | 1 - drivers/scsi/libfc/fc_elsct.c | 2 +- drivers/scsi/libfc/fc_encode.h | 699 ++++++++++++++++++++++++++++++++++++++ drivers/scsi/libfc/fc_exch.c | 1 - drivers/scsi/libfc/fc_fcp.c | 2 +- drivers/scsi/libfc/fc_libfc.c | 2 +- drivers/scsi/libfc/fc_lport.c | 2 +- drivers/scsi/libfc/fc_rport.c | 2 +- drivers/scsi/qedf/qedf.h | 1 - drivers/target/tcm_fc/tfc_cmd.c | 1 - drivers/target/tcm_fc/tfc_io.c | 1 - include/scsi/fc_encode.h | 727 ---------------------------------------- include/scsi/fc_frame.h | 30 ++ 13 files changed, 734 insertions(+), 737 deletions(-) create mode 100644 drivers/scsi/libfc/fc_encode.h delete mode 100644 include/scsi/fc_encode.h (limited to 'drivers') diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index b6e8ed757252..b4cea8b06ea1 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h @@ -51,7 +51,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c index 13a2e7c33cb1..8d3006edbe12 100644 --- a/drivers/scsi/libfc/fc_elsct.c +++ b/drivers/scsi/libfc/fc_elsct.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include "fc_encode.h" #include "fc_libfc.h" /** diff --git a/drivers/scsi/libfc/fc_encode.h b/drivers/scsi/libfc/fc_encode.h new file mode 100644 index 000000000000..18203cae04b2 --- /dev/null +++ b/drivers/scsi/libfc/fc_encode.h @@ -0,0 +1,699 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright(c) 2008 Intel Corporation. All rights reserved. + * + * Maintained at www.Open-FCoE.org + */ + +#ifndef _FC_ENCODE_H_ +#define _FC_ENCODE_H_ +#include +#include +#include + +/* + * F_CTL values for simple requests and responses. + */ +#define FC_FCTL_REQ (FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT) +#define FC_FCTL_RESP (FC_FC_EX_CTX | FC_FC_LAST_SEQ | \ + FC_FC_END_SEQ | FC_FC_SEQ_INIT) + +struct fc_ns_rft { + struct fc_ns_fid fid; /* port ID object */ + struct fc_ns_fts fts; /* FC4-types object */ +}; + +struct fc_ct_req { + struct fc_ct_hdr hdr; + union { + struct fc_ns_gid_ft gid; + struct fc_ns_rn_id rn; + struct fc_ns_rft rft; + struct fc_ns_rff_id rff; + struct fc_ns_fid fid; + struct fc_ns_rsnn snn; + struct fc_ns_rspn spn; + struct fc_fdmi_rhba rhba; + struct fc_fdmi_rpa rpa; + struct fc_fdmi_dprt dprt; + struct fc_fdmi_dhba dhba; + } payload; +}; + +/** + * fc_adisc_fill() - Fill in adisc request frame + * @lport: local port. + * @fp: fc frame where payload will be placed. + */ +static inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp) +{ + struct fc_els_adisc *adisc; + + adisc = fc_frame_payload_get(fp, sizeof(*adisc)); + memset(adisc, 0, sizeof(*adisc)); + adisc->adisc_cmd = ELS_ADISC; + put_unaligned_be64(lport->wwpn, &adisc->adisc_wwpn); + put_unaligned_be64(lport->wwnn, &adisc->adisc_wwnn); + hton24(adisc->adisc_port_id, lport->port_id); +} + +/** + * fc_ct_hdr_fill- fills ct header and reset ct payload + * returns pointer to ct request. + */ +static inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp, + unsigned int op, size_t req_size, + enum fc_ct_fs_type fs_type, + u8 subtype) +{ + struct fc_ct_req *ct; + size_t ct_plen; + + ct_plen = sizeof(struct fc_ct_hdr) + req_size; + ct = fc_frame_payload_get(fp, ct_plen); + memset(ct, 0, ct_plen); + ct->hdr.ct_rev = FC_CT_REV; + ct->hdr.ct_fs_type = fs_type; + ct->hdr.ct_fs_subtype = subtype; + ct->hdr.ct_cmd = htons((u16) op); + return ct; +} + +/** + * fc_ct_ns_fill() - Fill in a name service request frame + * @lport: local port. + * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries. + * @fp: frame to contain payload. + * @op: CT opcode. + * @r_ctl: pointer to FC header R_CTL. + * @fh_type: pointer to FC-4 type. + */ +static inline int fc_ct_ns_fill(struct fc_lport *lport, + u32 fc_id, struct fc_frame *fp, + unsigned int op, enum fc_rctl *r_ctl, + enum fc_fh_type *fh_type) +{ + struct fc_ct_req *ct; + size_t len; + + switch (op) { + case FC_NS_GPN_FT: + ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_gid_ft), + FC_FST_DIR, FC_NS_SUBTYPE); + ct->payload.gid.fn_fc4_type = FC_TYPE_FCP; + break; + + case FC_NS_GPN_ID: + ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_fid), + FC_FST_DIR, FC_NS_SUBTYPE); + ct->payload.gid.fn_fc4_type = FC_TYPE_FCP; + hton24(ct->payload.fid.fp_fid, fc_id); + break; + + case FC_NS_RFT_ID: + ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rft), + FC_FST_DIR, FC_NS_SUBTYPE); + hton24(ct->payload.rft.fid.fp_fid, lport->port_id); + ct->payload.rft.fts = lport->fcts; + break; + + case FC_NS_RFF_ID: + ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rff_id), + FC_FST_DIR, FC_NS_SUBTYPE); + hton24(ct->payload.rff.fr_fid.fp_fid, lport->port_id); + ct->payload.rff.fr_type = FC_TYPE_FCP; + if (lport->service_params & FCP_SPPF_INIT_FCN) + ct->payload.rff.fr_feat = FCP_FEAT_INIT; + if (lport->service_params & FCP_SPPF_TARG_FCN) + ct->payload.rff.fr_feat |= FCP_FEAT_TARG; + break; + + case FC_NS_RNN_ID: + ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rn_id), + FC_FST_DIR, FC_NS_SUBTYPE); + hton24(ct->payload.rn.fr_fid.fp_fid, lport->port_id); + put_unaligned_be64(lport->wwnn, &ct->payload.rn.fr_wwn); + break; + + case FC_NS_RSPN_ID: + len = strnlen(fc_host_symbolic_name(lport->host), 255); + ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rspn) + len, + FC_FST_DIR, FC_NS_SUBTYPE); + hton24(ct->payload.spn.fr_fid.fp_fid, lport->port_id); + strncpy(ct->payload.spn.fr_name, + fc_host_symbolic_name(lport->host), len); + ct->payload.spn.fr_name_len = len; + break; + + case FC_NS_RSNN_NN: + len = strnlen(fc_host_symbolic_name(lport->host), 255); + ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rsnn) + len, + FC_FST_DIR, FC_NS_SUBTYPE); + put_unaligned_be64(lport->wwnn, &ct->payload.snn.fr_wwn); + strncpy(ct->payload.snn.fr_name, + fc_host_symbolic_name(lport->host), len); + ct->payload.snn.fr_name_len = len; + break; + + default: + return -EINVAL; + } + *r_ctl = FC_RCTL_DD_UNSOL_CTL; + *fh_type = FC_TYPE_CT; + return 0; +} + +/** + * fc_ct_ms_fill() - Fill in a mgmt service request frame + * @lport: local port. + * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries. + * @fp: frame to contain payload. + * @op: CT opcode. + * @r_ctl: pointer to FC header R_CTL. + * @fh_type: pointer to FC-4 type. + */ +static inline int fc_ct_ms_fill(struct fc_lport *lport, + u32 fc_id, struct fc_frame *fp, + unsigned int op, enum fc_rctl *r_ctl, + enum fc_fh_type *fh_type) +{ + struct fc_ct_req *ct; + size_t len; + struct fc_fdmi_attr_entry *entry; + struct fs_fdmi_attrs *hba_attrs; + int numattrs = 0; + + switch (op) { + case FC_FDMI_RHBA: + numattrs = 10; + len = sizeof(struct fc_fdmi_rhba); + len -= sizeof(struct fc_fdmi_attr_entry); + len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN); + len += FC_FDMI_HBA_ATTR_NODENAME_LEN; + len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN; + len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN; + len += FC_FDMI_HBA_ATTR_MODEL_LEN; + len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN; + len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN; + len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN; + len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN; + len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN; + len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN; + ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, + FC_FDMI_SUBTYPE); + + /* HBA Identifier */ + put_unaligned_be64(lport->wwpn, &ct->payload.rhba.hbaid.id); + /* Number of Ports - always 1 */ + put_unaligned_be32(1, &ct->payload.rhba.port.numport); + /* Port Name */ + put_unaligned_be64(lport->wwpn, + &ct->payload.rhba.port.port[0].portname); + + /* HBA Attributes */ + put_unaligned_be32(numattrs, + &ct->payload.rhba.hba_attrs.numattrs); + hba_attrs = &ct->payload.rhba.hba_attrs; + entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr; + /* NodeName*/ + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_HBA_ATTR_NODENAME_LEN; + put_unaligned_be16(FC_FDMI_HBA_ATTR_NODENAME, + &entry->type); + put_unaligned_be16(len, &entry->len); + put_unaligned_be64(lport->wwnn, + (__be64 *)&entry->value[0]); + + /* Manufacturer */ + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + + FC_FDMI_HBA_ATTR_NODENAME_LEN); + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN; + put_unaligned_be16(FC_FDMI_HBA_ATTR_MANUFACTURER, + &entry->type); + put_unaligned_be16(len, &entry->len); + strncpy((char *)&entry->value, + fc_host_manufacturer(lport->host), + FC_FDMI_HBA_ATTR_MANUFACTURER_LEN); + + /* SerialNumber */ + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + + FC_FDMI_HBA_ATTR_MANUFACTURER_LEN); + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN; + put_unaligned_be16(FC_FDMI_HBA_ATTR_SERIALNUMBER, + &entry->type); + put_unaligned_be16(len, &entry->len); + strncpy((char *)&entry->value, + fc_host_serial_number(lport->host), + FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN); + + /* Model */ + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + + FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN); + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_HBA_ATTR_MODEL_LEN; + put_unaligned_be16(FC_FDMI_HBA_ATTR_MODEL, + &entry->type); + put_unaligned_be16(len, &entry->len); + strncpy((char *)&entry->value, + fc_host_model(lport->host), + FC_FDMI_HBA_ATTR_MODEL_LEN); + + /* Model Description */ + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + + FC_FDMI_HBA_ATTR_MODEL_LEN); + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN; + put_unaligned_be16(FC_FDMI_HBA_ATTR_MODELDESCRIPTION, + &entry->type); + put_unaligned_be16(len, &entry->len); + strncpy((char *)&entry->value, + fc_host_model_description(lport->host), + FC_FDMI_HBA_ATTR_MODELDESCR_LEN); + + /* Hardware Version */ + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + + FC_FDMI_HBA_ATTR_MODELDESCR_LEN); + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN; + put_unaligned_be16(FC_FDMI_HBA_ATTR_HARDWAREVERSION, + &entry->type); + put_unaligned_be16(len, &entry->len); + strncpy((char *)&entry->value, + fc_host_hardware_version(lport->host), + FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN); + + /* Driver Version */ + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + + FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN); + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN; + put_unaligned_be16(FC_FDMI_HBA_ATTR_DRIVERVERSION, + &entry->type); + put_unaligned_be16(len, &entry->len); + strncpy((char *)&entry->value, + fc_host_driver_version(lport->host), + FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN); + + /* OptionROM Version */ + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + + FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN); + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN; + put_unaligned_be16(FC_FDMI_HBA_ATTR_OPTIONROMVERSION, + &entry->type); + put_unaligned_be16(len, &entry->len); + strncpy((char *)&entry->value, + fc_host_optionrom_version(lport->host), + FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN); + + /* Firmware Version */ + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + + FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN); + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN; + put_unaligned_be16(FC_FDMI_HBA_ATTR_FIRMWAREVERSION, + &entry->type); + put_unaligned_be16(len, &entry->len); + strncpy((char *)&entry->value, + fc_host_firmware_version(lport->host), + FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN); + + /* OS Name and Version */ + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + + FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN); + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN; + put_unaligned_be16(FC_FDMI_HBA_ATTR_OSNAMEVERSION, + &entry->type); + put_unaligned_be16(len, &entry->len); + snprintf((char *)&entry->value, + FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN, + "%s v%s", + init_utsname()->sysname, + init_utsname()->release); + break; + case FC_FDMI_RPA: + numattrs = 6; + len = sizeof(struct fc_fdmi_rpa); + len -= sizeof(struct fc_fdmi_attr_entry); + len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN); + len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN; + len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN; + len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN; + len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN; + len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN; + len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN; + ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, + FC_FDMI_SUBTYPE); + + /* Port Name */ + put_unaligned_be64(lport->wwpn, + &ct->payload.rpa.port.portname); + + /* Port Attributes */ + put_unaligned_be32(numattrs, + &ct->payload.rpa.hba_attrs.numattrs); + + hba_attrs = &ct->payload.rpa.hba_attrs; + entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr; + + /* FC4 types */ + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN; + put_unaligned_be16(FC_FDMI_PORT_ATTR_FC4TYPES, + &entry->type); + put_unaligned_be16(len, &entry->len); + memcpy(&entry->value, fc_host_supported_fc4s(lport->host), + FC_FDMI_PORT_ATTR_FC4TYPES_LEN); + + /* Supported Speed */ + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + + FC_FDMI_PORT_ATTR_FC4TYPES_LEN); + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN; + put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDSPEED, + &entry->type); + put_unaligned_be16(len, &entry->len); + + put_unaligned_be32(fc_host_supported_speeds(lport->host), + &entry->value); + + /* Current Port Speed */ + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + + FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN); + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN; + put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTPORTSPEED, + &entry->type); + put_unaligned_be16(len, &entry->len); + put_unaligned_be32(lport->link_speed, + &entry->value); + + /* Max Frame Size */ + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + + FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN); + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN; + put_unaligned_be16(FC_FDMI_PORT_ATTR_MAXFRAMESIZE, + &entry->type); + put_unaligned_be16(len, &entry->len); + put_unaligned_be32(fc_host_maxframe_size(lport->host), + &entry->value); + + /* OS Device Name */ + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + + FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN); + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN; + put_unaligned_be16(FC_FDMI_PORT_ATTR_OSDEVICENAME, + &entry->type); + put_unaligned_be16(len, &entry->len); + /* Use the sysfs device name */ + strncpy((char *)&entry->value, + dev_name(&lport->host->shost_gendev), + strnlen(dev_name(&lport->host->shost_gendev), + FC_FDMI_PORT_ATTR_HOSTNAME_LEN)); + + /* Host Name */ + entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + + FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN); + len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; + len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN; + put_unaligned_be16(FC_FDMI_PORT_ATTR_HOSTNAME, + &entry->type); + put_unaligned_be16(len, &entry->len); + if (strlen(fc_host_system_hostname(lport->host))) + strncpy((char *)&entry->value, + fc_host_system_hostname(lport->host), + strnlen(fc_host_system_hostname(lport->host), + FC_FDMI_PORT_ATTR_HOSTNAME_LEN)); + else + strncpy((char *)&entry->value, + init_utsname()->nodename, + FC_FDMI_PORT_ATTR_HOSTNAME_LEN); + break; + case FC_FDMI_DPRT: + len = sizeof(struct fc_fdmi_dprt); + ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, + FC_FDMI_SUBTYPE); + /* Port Name */ + put_unaligned_be64(lport->wwpn, + &ct->payload.dprt.port.portname); + break; + case FC_FDMI_DHBA: + len = sizeof(struct fc_fdmi_dhba); + ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, + FC_FDMI_SUBTYPE); + /* HBA Identifier */ + put_unaligned_be64(lport->wwpn, &ct->payload.dhba.hbaid.id); + break; + default: + return -EINVAL; + } + *r_ctl = FC_RCTL_DD_UNSOL_CTL; + *fh_type = FC_TYPE_CT; + return 0; +} + +/** + * fc_ct_fill() - Fill in a common transport service request frame + * @lport: local port. + * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries. + * @fp: frame to contain payload. + * @op: CT opcode. + * @r_ctl: pointer to FC header R_CTL. + * @fh_type: pointer to FC-4 type. + */ +static inline int fc_ct_fill(struct fc_lport *lport, + u32 fc_id, struct fc_frame *fp, + unsigned int op, enum fc_rctl *r_ctl, + enum fc_fh_type *fh_type, u32 *did) +{ + int rc = -EINVAL; + + switch (fc_id) { + case FC_FID_MGMT_SERV: + rc = fc_ct_ms_fill(lport, fc_id, fp, op, r_ctl, fh_type); + *did = FC_FID_MGMT_SERV; + break; + case FC_FID_DIR_SERV: + default: + rc = fc_ct_ns_fill(lport, fc_id, fp, op, r_ctl, fh_type); + *did = FC_FID_DIR_SERV; + break; + } + + return rc; +} +/** + * fc_plogi_fill - Fill in plogi request frame + */ +static inline void fc_plogi_fill(struct fc_lport *lport, struct fc_frame *fp, + unsigned int op) +{ + struct fc_els_flogi *plogi; + struct fc_els_csp *csp; + struct fc_els_cssp *cp; + + plogi = fc_frame_payload_get(fp, sizeof(*plogi)); + memset(plogi, 0, sizeof(*plogi)); + plogi->fl_cmd = (u8) op; + put_unaligned_be64(lport->wwpn, &plogi->fl_wwpn); + put_unaligned_be64(lport->wwnn, &plogi->fl_wwnn); + + csp = &plogi->fl_csp; + csp->sp_hi_ver = 0x20; + csp->sp_lo_ver = 0x20; + csp->sp_bb_cred = htons(10); /* this gets set by gateway */ + csp->sp_bb_data = htons((u16) lport->mfs); + cp = &plogi->fl_cssp[3 - 1]; /* class 3 parameters */ + cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ); + csp->sp_features = htons(FC_SP_FT_CIRO); + csp->sp_tot_seq = htons(255); /* seq. we accept */ + csp->sp_rel_off = htons(0x1f); + csp->sp_e_d_tov = htonl(lport->e_d_tov); + + cp->cp_rdfs = htons((u16) lport->mfs); + cp->cp_con_seq = htons(255); + cp->cp_open_seq = 1; +} + +/** + * fc_flogi_fill - Fill in a flogi request frame. + */ +static inline void fc_flogi_fill(struct fc_lport *lport, struct fc_frame *fp) +{ + struct fc_els_csp *sp; + struct fc_els_cssp *cp; + struct fc_els_flogi *flogi; + + flogi = fc_frame_payload_get(fp, sizeof(*flogi)); + memset(flogi, 0, sizeof(*flogi)); + flogi->fl_cmd = (u8) ELS_FLOGI; + put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn); + put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn); + sp = &flogi->fl_csp; + sp->sp_hi_ver = 0x20; + sp->sp_lo_ver = 0x20; + sp->sp_bb_cred = htons(10); /* this gets set by gateway */ + sp->sp_bb_data = htons((u16) lport->mfs); + cp = &flogi->fl_cssp[3 - 1]; /* class 3 parameters */ + cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ); + if (lport->does_npiv) + sp->sp_features = htons(FC_SP_FT_NPIV); +} + +/** + * fc_fdisc_fill - Fill in a fdisc request frame. + */ +static inline void fc_fdisc_fill(struct fc_lport *lport, struct fc_frame *fp) +{ + struct fc_els_csp *sp; + struct fc_els_cssp *cp; + struct fc_els_flogi *fdisc; + + fdisc = fc_frame_payload_get(fp, sizeof(*fdisc)); + memset(fdisc, 0, sizeof(*fdisc)); + fdisc->fl_cmd = (u8) ELS_FDISC; + put_unaligned_be64(lport->wwpn, &fdisc->fl_wwpn); + put_unaligned_be64(lport->wwnn, &fdisc->fl_wwnn); + sp = &fdisc->fl_csp; + sp->sp_hi_ver = 0x20; + sp->sp_lo_ver = 0x20; + sp->sp_bb_cred = htons(10); /* this gets set by gateway */ + sp->sp_bb_data = htons((u16) lport->mfs); + cp = &fdisc->fl_cssp[3 - 1]; /* class 3 parameters */ + cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ); +} + +/** + * fc_logo_fill - Fill in a logo request frame. + */ +static inline void fc_logo_fill(struct fc_lport *lport, struct fc_frame *fp) +{ + struct fc_els_logo *logo; + + logo = fc_frame_payload_get(fp, sizeof(*logo)); + memset(logo, 0, sizeof(*logo)); + logo->fl_cmd = ELS_LOGO; + hton24(logo->fl_n_port_id, lport->port_id); + logo->fl_n_port_wwn = htonll(lport->wwpn); +} + +/** + * fc_rtv_fill - Fill in RTV (read timeout value) request frame. + */ +static inline void fc_rtv_fill(struct fc_lport *lport, struct fc_frame *fp) +{ + struct fc_els_rtv *rtv; + + rtv = fc_frame_payload_get(fp, sizeof(*rtv)); + memset(rtv, 0, sizeof(*rtv)); + rtv->rtv_cmd = ELS_RTV; +} + +/** + * fc_rec_fill - Fill in rec request frame + */ +static inline void fc_rec_fill(struct fc_lport *lport, struct fc_frame *fp) +{ + struct fc_els_rec *rec; + struct fc_exch *ep = fc_seq_exch(fr_seq(fp)); + + rec = fc_frame_payload_get(fp, sizeof(*rec)); + memset(rec, 0, sizeof(*rec)); + rec->rec_cmd = ELS_REC; + hton24(rec->rec_s_id, lport->port_id); + rec->rec_ox_id = htons(ep->oxid); + rec->rec_rx_id = htons(ep->rxid); +} + +/** + * fc_prli_fill - Fill in prli request frame + */ +static inline void fc_prli_fill(struct fc_lport *lport, struct fc_frame *fp) +{ + struct { + struct fc_els_prli prli; + struct fc_els_spp spp; + } *pp; + + pp = fc_frame_payload_get(fp, sizeof(*pp)); + memset(pp, 0, sizeof(*pp)); + pp->prli.prli_cmd = ELS_PRLI; + pp->prli.prli_spp_len = sizeof(struct fc_els_spp); + pp->prli.prli_len = htons(sizeof(*pp)); + pp->spp.spp_type = FC_TYPE_FCP; + pp->spp.spp_flags = FC_SPP_EST_IMG_PAIR; + pp->spp.spp_params = htonl(lport->service_params); +} + +/** + * fc_scr_fill - Fill in a scr request frame. + */ +static inline void fc_scr_fill(struct fc_lport *lport, struct fc_frame *fp) +{ + struct fc_els_scr *scr; + + scr = fc_frame_payload_get(fp, sizeof(*scr)); + memset(scr, 0, sizeof(*scr)); + scr->scr_cmd = ELS_SCR; + scr->scr_reg_func = ELS_SCRF_FULL; +} + +/** + * fc_els_fill - Fill in an ELS request frame + */ +static inline int fc_els_fill(struct fc_lport *lport, + u32 did, + struct fc_frame *fp, unsigned int op, + enum fc_rctl *r_ctl, enum fc_fh_type *fh_type) +{ + switch (op) { + case ELS_ADISC: + fc_adisc_fill(lport, fp); + break; + + case ELS_PLOGI: + fc_plogi_fill(lport, fp, ELS_PLOGI); + break; + + case ELS_FLOGI: + fc_flogi_fill(lport, fp); + break; + + case ELS_FDISC: + fc_fdisc_fill(lport, fp); + break; + + case ELS_LOGO: + fc_logo_fill(lport, fp); + break; + + case ELS_RTV: + fc_rtv_fill(lport, fp); + break; + + case ELS_REC: + fc_rec_fill(lport, fp); + break; + + case ELS_PRLI: + fc_prli_fill(lport, fp); + break; + + case ELS_SCR: + fc_scr_fill(lport, fp); + break; + + default: + return -EINVAL; + } + + *r_ctl = FC_RCTL_ELS_REQ; + *fh_type = FC_TYPE_ELS; + return 0; +} +#endif /* _FC_ENCODE_H_ */ diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 96a2952cf626..91e680b53523 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -20,7 +20,6 @@ #include #include -#include #include "fc_libfc.h" diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 7cfeb6886237..b43b5f62ee3e 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -26,8 +26,8 @@ #include #include -#include +#include "fc_encode.h" #include "fc_libfc.h" static struct kmem_cache *scsi_pkt_cachep; diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c index 19c4ab4e0f4d..0e6a1355d020 100644 --- a/drivers/scsi/libfc/fc_libfc.c +++ b/drivers/scsi/libfc/fc_libfc.c @@ -12,8 +12,8 @@ #include #include -#include +#include "fc_encode.h" #include "fc_libfc.h" MODULE_AUTHOR("Open-FCoE.org"); diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 6557fda85c5c..22826544da7e 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -84,9 +84,9 @@ #include #include -#include #include +#include "fc_encode.h" #include "fc_libfc.h" /* Fabric IDs to use for point-to-point mode, chosen on whims. */ diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index a60b228d13f1..56003208d2e7 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -58,8 +58,8 @@ #include #include -#include +#include "fc_encode.h" #include "fc_libfc.h" static struct workqueue_struct *rport_event_queue; diff --git a/drivers/scsi/qedf/qedf.h b/drivers/scsi/qedf/qedf.h index 0e2cbb164eeb..88a592d09433 100644 --- a/drivers/scsi/qedf/qedf.h +++ b/drivers/scsi/qedf/qedf.h @@ -11,7 +11,6 @@ #include #include #include -#include #include diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index a7ed56602c6c..9c8c38a549c6 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c index 6a38ff936389..bbe2e29612fa 100644 --- a/drivers/target/tcm_fc/tfc_io.c +++ b/drivers/target/tcm_fc/tfc_io.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h deleted file mode 100644 index c6660205d73f..000000000000 --- a/include/scsi/fc_encode.h +++ /dev/null @@ -1,727 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright(c) 2008 Intel Corporation. All rights reserved. - * - * Maintained at www.Open-FCoE.org - */ - -#ifndef _FC_ENCODE_H_ -#define _FC_ENCODE_H_ -#include -#include - -/* - * F_CTL values for simple requests and responses. - */ -#define FC_FCTL_REQ (FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT) -#define FC_FCTL_RESP (FC_FC_EX_CTX | FC_FC_LAST_SEQ | \ - FC_FC_END_SEQ | FC_FC_SEQ_INIT) - -struct fc_ns_rft { - struct fc_ns_fid fid; /* port ID object */ - struct fc_ns_fts fts; /* FC4-types object */ -}; - -struct fc_ct_req { - struct fc_ct_hdr hdr; - union { - struct fc_ns_gid_ft gid; - struct fc_ns_rn_id rn; - struct fc_ns_rft rft; - struct fc_ns_rff_id rff; - struct fc_ns_fid fid; - struct fc_ns_rsnn snn; - struct fc_ns_rspn spn; - struct fc_fdmi_rhba rhba; - struct fc_fdmi_rpa rpa; - struct fc_fdmi_dprt dprt; - struct fc_fdmi_dhba dhba; - } payload; -}; - -static inline void __fc_fill_fc_hdr(struct fc_frame_header *fh, - enum fc_rctl r_ctl, - u32 did, u32 sid, enum fc_fh_type type, - u32 f_ctl, u32 parm_offset) -{ - WARN_ON(r_ctl == 0); - fh->fh_r_ctl = r_ctl; - hton24(fh->fh_d_id, did); - hton24(fh->fh_s_id, sid); - fh->fh_type = type; - hton24(fh->fh_f_ctl, f_ctl); - fh->fh_cs_ctl = 0; - fh->fh_df_ctl = 0; - fh->fh_parm_offset = htonl(parm_offset); -} - -/** - * fill FC header fields in specified fc_frame - */ -static inline void fc_fill_fc_hdr(struct fc_frame *fp, enum fc_rctl r_ctl, - u32 did, u32 sid, enum fc_fh_type type, - u32 f_ctl, u32 parm_offset) -{ - struct fc_frame_header *fh; - - fh = fc_frame_header_get(fp); - __fc_fill_fc_hdr(fh, r_ctl, did, sid, type, f_ctl, parm_offset); -} - -/** - * fc_adisc_fill() - Fill in adisc request frame - * @lport: local port. - * @fp: fc frame where payload will be placed. - */ -static inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp) -{ - struct fc_els_adisc *adisc; - - adisc = fc_frame_payload_get(fp, sizeof(*adisc)); - memset(adisc, 0, sizeof(*adisc)); - adisc->adisc_cmd = ELS_ADISC; - put_unaligned_be64(lport->wwpn, &adisc->adisc_wwpn); - put_unaligned_be64(lport->wwnn, &adisc->adisc_wwnn); - hton24(adisc->adisc_port_id, lport->port_id); -} - -/** - * fc_ct_hdr_fill- fills ct header and reset ct payload - * returns pointer to ct request. - */ -static inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp, - unsigned int op, size_t req_size, - enum fc_ct_fs_type fs_type, - u8 subtype) -{ - struct fc_ct_req *ct; - size_t ct_plen; - - ct_plen = sizeof(struct fc_ct_hdr) + req_size; - ct = fc_frame_payload_get(fp, ct_plen); - memset(ct, 0, ct_plen); - ct->hdr.ct_rev = FC_CT_REV; - ct->hdr.ct_fs_type = fs_type; - ct->hdr.ct_fs_subtype = subtype; - ct->hdr.ct_cmd = htons((u16) op); - return ct; -} - -/** - * fc_ct_ns_fill() - Fill in a name service request frame - * @lport: local port. - * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries. - * @fp: frame to contain payload. - * @op: CT opcode. - * @r_ctl: pointer to FC header R_CTL. - * @fh_type: pointer to FC-4 type. - */ -static inline int fc_ct_ns_fill(struct fc_lport *lport, - u32 fc_id, struct fc_frame *fp, - unsigned int op, enum fc_rctl *r_ctl, - enum fc_fh_type *fh_type) -{ - struct fc_ct_req *ct; - size_t len; - - switch (op) { - case FC_NS_GPN_FT: - ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_gid_ft), - FC_FST_DIR, FC_NS_SUBTYPE); - ct->payload.gid.fn_fc4_type = FC_TYPE_FCP; - break; - - case FC_NS_GPN_ID: - ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_fid), - FC_FST_DIR, FC_NS_SUBTYPE); - ct->payload.gid.fn_fc4_type = FC_TYPE_FCP; - hton24(ct->payload.fid.fp_fid, fc_id); - break; - - case FC_NS_RFT_ID: - ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rft), - FC_FST_DIR, FC_NS_SUBTYPE); - hton24(ct->payload.rft.fid.fp_fid, lport->port_id); - ct->payload.rft.fts = lport->fcts; - break; - - case FC_NS_RFF_ID: - ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rff_id), - FC_FST_DIR, FC_NS_SUBTYPE); - hton24(ct->payload.rff.fr_fid.fp_fid, lport->port_id); - ct->payload.rff.fr_type = FC_TYPE_FCP; - if (lport->service_params & FCP_SPPF_INIT_FCN) - ct->payload.rff.fr_feat = FCP_FEAT_INIT; - if (lport->service_params & FCP_SPPF_TARG_FCN) - ct->payload.rff.fr_feat |= FCP_FEAT_TARG; - break; - - case FC_NS_RNN_ID: - ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rn_id), - FC_FST_DIR, FC_NS_SUBTYPE); - hton24(ct->payload.rn.fr_fid.fp_fid, lport->port_id); - put_unaligned_be64(lport->wwnn, &ct->payload.rn.fr_wwn); - break; - - case FC_NS_RSPN_ID: - len = strnlen(fc_host_symbolic_name(lport->host), 255); - ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rspn) + len, - FC_FST_DIR, FC_NS_SUBTYPE); - hton24(ct->payload.spn.fr_fid.fp_fid, lport->port_id); - strncpy(ct->payload.spn.fr_name, - fc_host_symbolic_name(lport->host), len); - ct->payload.spn.fr_name_len = len; - break; - - case FC_NS_RSNN_NN: - len = strnlen(fc_host_symbolic_name(lport->host), 255); - ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rsnn) + len, - FC_FST_DIR, FC_NS_SUBTYPE); - put_unaligned_be64(lport->wwnn, &ct->payload.snn.fr_wwn); - strncpy(ct->payload.snn.fr_name, - fc_host_symbolic_name(lport->host), len); - ct->payload.snn.fr_name_len = len; - break; - - default: - return -EINVAL; - } - *r_ctl = FC_RCTL_DD_UNSOL_CTL; - *fh_type = FC_TYPE_CT; - return 0; -} - -/** - * fc_ct_ms_fill() - Fill in a mgmt service request frame - * @lport: local port. - * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries. - * @fp: frame to contain payload. - * @op: CT opcode. - * @r_ctl: pointer to FC header R_CTL. - * @fh_type: pointer to FC-4 type. - */ -static inline int fc_ct_ms_fill(struct fc_lport *lport, - u32 fc_id, struct fc_frame *fp, - unsigned int op, enum fc_rctl *r_ctl, - enum fc_fh_type *fh_type) -{ - struct fc_ct_req *ct; - size_t len; - struct fc_fdmi_attr_entry *entry; - struct fs_fdmi_attrs *hba_attrs; - int numattrs = 0; - - switch (op) { - case FC_FDMI_RHBA: - numattrs = 10; - len = sizeof(struct fc_fdmi_rhba); - len -= sizeof(struct fc_fdmi_attr_entry); - len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN); - len += FC_FDMI_HBA_ATTR_NODENAME_LEN; - len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN; - len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN; - len += FC_FDMI_HBA_ATTR_MODEL_LEN; - len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN; - len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN; - len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN; - len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN; - len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN; - len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN; - ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, - FC_FDMI_SUBTYPE); - - /* HBA Identifier */ - put_unaligned_be64(lport->wwpn, &ct->payload.rhba.hbaid.id); - /* Number of Ports - always 1 */ - put_unaligned_be32(1, &ct->payload.rhba.port.numport); - /* Port Name */ - put_unaligned_be64(lport->wwpn, - &ct->payload.rhba.port.port[0].portname); - - /* HBA Attributes */ - put_unaligned_be32(numattrs, - &ct->payload.rhba.hba_attrs.numattrs); - hba_attrs = &ct->payload.rhba.hba_attrs; - entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr; - /* NodeName*/ - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_HBA_ATTR_NODENAME_LEN; - put_unaligned_be16(FC_FDMI_HBA_ATTR_NODENAME, - &entry->type); - put_unaligned_be16(len, &entry->len); - put_unaligned_be64(lport->wwnn, - (__be64 *)&entry->value[0]); - - /* Manufacturer */ - entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + - FC_FDMI_HBA_ATTR_NODENAME_LEN); - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_HBA_ATTR_MANUFACTURER_LEN; - put_unaligned_be16(FC_FDMI_HBA_ATTR_MANUFACTURER, - &entry->type); - put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, - fc_host_manufacturer(lport->host), - FC_FDMI_HBA_ATTR_MANUFACTURER_LEN); - - /* SerialNumber */ - entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + - FC_FDMI_HBA_ATTR_MANUFACTURER_LEN); - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN; - put_unaligned_be16(FC_FDMI_HBA_ATTR_SERIALNUMBER, - &entry->type); - put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, - fc_host_serial_number(lport->host), - FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN); - - /* Model */ - entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + - FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN); - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_HBA_ATTR_MODEL_LEN; - put_unaligned_be16(FC_FDMI_HBA_ATTR_MODEL, - &entry->type); - put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, - fc_host_model(lport->host), - FC_FDMI_HBA_ATTR_MODEL_LEN); - - /* Model Description */ - entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + - FC_FDMI_HBA_ATTR_MODEL_LEN); - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_HBA_ATTR_MODELDESCR_LEN; - put_unaligned_be16(FC_FDMI_HBA_ATTR_MODELDESCRIPTION, - &entry->type); - put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, - fc_host_model_description(lport->host), - FC_FDMI_HBA_ATTR_MODELDESCR_LEN); - - /* Hardware Version */ - entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + - FC_FDMI_HBA_ATTR_MODELDESCR_LEN); - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN; - put_unaligned_be16(FC_FDMI_HBA_ATTR_HARDWAREVERSION, - &entry->type); - put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, - fc_host_hardware_version(lport->host), - FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN); - - /* Driver Version */ - entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + - FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN); - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN; - put_unaligned_be16(FC_FDMI_HBA_ATTR_DRIVERVERSION, - &entry->type); - put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, - fc_host_driver_version(lport->host), - FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN); - - /* OptionROM Version */ - entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + - FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN); - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN; - put_unaligned_be16(FC_FDMI_HBA_ATTR_OPTIONROMVERSION, - &entry->type); - put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, - fc_host_optionrom_version(lport->host), - FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN); - - /* Firmware Version */ - entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + - FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN); - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN; - put_unaligned_be16(FC_FDMI_HBA_ATTR_FIRMWAREVERSION, - &entry->type); - put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, - fc_host_firmware_version(lport->host), - FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN); - - /* OS Name and Version */ - entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + - FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN); - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN; - put_unaligned_be16(FC_FDMI_HBA_ATTR_OSNAMEVERSION, - &entry->type); - put_unaligned_be16(len, &entry->len); - snprintf((char *)&entry->value, - FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN, - "%s v%s", - init_utsname()->sysname, - init_utsname()->release); - break; - case FC_FDMI_RPA: - numattrs = 6; - len = sizeof(struct fc_fdmi_rpa); - len -= sizeof(struct fc_fdmi_attr_entry); - len += (numattrs * FC_FDMI_ATTR_ENTRY_HEADER_LEN); - len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN; - len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN; - len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN; - len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN; - len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN; - len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN; - ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, - FC_FDMI_SUBTYPE); - - /* Port Name */ - put_unaligned_be64(lport->wwpn, - &ct->payload.rpa.port.portname); - - /* Port Attributes */ - put_unaligned_be32(numattrs, - &ct->payload.rpa.hba_attrs.numattrs); - - hba_attrs = &ct->payload.rpa.hba_attrs; - entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr; - - /* FC4 types */ - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN; - put_unaligned_be16(FC_FDMI_PORT_ATTR_FC4TYPES, - &entry->type); - put_unaligned_be16(len, &entry->len); - memcpy(&entry->value, fc_host_supported_fc4s(lport->host), - FC_FDMI_PORT_ATTR_FC4TYPES_LEN); - - /* Supported Speed */ - entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + - FC_FDMI_PORT_ATTR_FC4TYPES_LEN); - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN; - put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDSPEED, - &entry->type); - put_unaligned_be16(len, &entry->len); - - put_unaligned_be32(fc_host_supported_speeds(lport->host), - &entry->value); - - /* Current Port Speed */ - entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + - FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN); - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN; - put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTPORTSPEED, - &entry->type); - put_unaligned_be16(len, &entry->len); - put_unaligned_be32(lport->link_speed, - &entry->value); - - /* Max Frame Size */ - entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + - FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN); - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN; - put_unaligned_be16(FC_FDMI_PORT_ATTR_MAXFRAMESIZE, - &entry->type); - put_unaligned_be16(len, &entry->len); - put_unaligned_be32(fc_host_maxframe_size(lport->host), - &entry->value); - - /* OS Device Name */ - entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + - FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN); - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN; - put_unaligned_be16(FC_FDMI_PORT_ATTR_OSDEVICENAME, - &entry->type); - put_unaligned_be16(len, &entry->len); - /* Use the sysfs device name */ - strncpy((char *)&entry->value, - dev_name(&lport->host->shost_gendev), - strnlen(dev_name(&lport->host->shost_gendev), - FC_FDMI_PORT_ATTR_HOSTNAME_LEN)); - - /* Host Name */ - entry = (struct fc_fdmi_attr_entry *)((char *)entry->value + - FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN); - len = FC_FDMI_ATTR_ENTRY_HEADER_LEN; - len += FC_FDMI_PORT_ATTR_HOSTNAME_LEN; - put_unaligned_be16(FC_FDMI_PORT_ATTR_HOSTNAME, - &entry->type); - put_unaligned_be16(len, &entry->len); - if (strlen(fc_host_system_hostname(lport->host))) - strncpy((char *)&entry->value, - fc_host_system_hostname(lport->host), - strnlen(fc_host_system_hostname(lport->host), - FC_FDMI_PORT_ATTR_HOSTNAME_LEN)); - else - strncpy((char *)&entry->value, - init_utsname()->nodename, - FC_FDMI_PORT_ATTR_HOSTNAME_LEN); - break; - case FC_FDMI_DPRT: - len = sizeof(struct fc_fdmi_dprt); - ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, - FC_FDMI_SUBTYPE); - /* Port Name */ - put_unaligned_be64(lport->wwpn, - &ct->payload.dprt.port.portname); - break; - case FC_FDMI_DHBA: - len = sizeof(struct fc_fdmi_dhba); - ct = fc_ct_hdr_fill(fp, op, len, FC_FST_MGMT, - FC_FDMI_SUBTYPE); - /* HBA Identifier */ - put_unaligned_be64(lport->wwpn, &ct->payload.dhba.hbaid.id); - break; - default: - return -EINVAL; - } - *r_ctl = FC_RCTL_DD_UNSOL_CTL; - *fh_type = FC_TYPE_CT; - return 0; -} - -/** - * fc_ct_fill() - Fill in a common transport service request frame - * @lport: local port. - * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries. - * @fp: frame to contain payload. - * @op: CT opcode. - * @r_ctl: pointer to FC header R_CTL. - * @fh_type: pointer to FC-4 type. - */ -static inline int fc_ct_fill(struct fc_lport *lport, - u32 fc_id, struct fc_frame *fp, - unsigned int op, enum fc_rctl *r_ctl, - enum fc_fh_type *fh_type, u32 *did) -{ - int rc = -EINVAL; - - switch (fc_id) { - case FC_FID_MGMT_SERV: - rc = fc_ct_ms_fill(lport, fc_id, fp, op, r_ctl, fh_type); - *did = FC_FID_MGMT_SERV; - break; - case FC_FID_DIR_SERV: - default: - rc = fc_ct_ns_fill(lport, fc_id, fp, op, r_ctl, fh_type); - *did = FC_FID_DIR_SERV; - break; - } - - return rc; -} -/** - * fc_plogi_fill - Fill in plogi request frame - */ -static inline void fc_plogi_fill(struct fc_lport *lport, struct fc_frame *fp, - unsigned int op) -{ - struct fc_els_flogi *plogi; - struct fc_els_csp *csp; - struct fc_els_cssp *cp; - - plogi = fc_frame_payload_get(fp, sizeof(*plogi)); - memset(plogi, 0, sizeof(*plogi)); - plogi->fl_cmd = (u8) op; - put_unaligned_be64(lport->wwpn, &plogi->fl_wwpn); - put_unaligned_be64(lport->wwnn, &plogi->fl_wwnn); - - csp = &plogi->fl_csp; - csp->sp_hi_ver = 0x20; - csp->sp_lo_ver = 0x20; - csp->sp_bb_cred = htons(10); /* this gets set by gateway */ - csp->sp_bb_data = htons((u16) lport->mfs); - cp = &plogi->fl_cssp[3 - 1]; /* class 3 parameters */ - cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ); - csp->sp_features = htons(FC_SP_FT_CIRO); - csp->sp_tot_seq = htons(255); /* seq. we accept */ - csp->sp_rel_off = htons(0x1f); - csp->sp_e_d_tov = htonl(lport->e_d_tov); - - cp->cp_rdfs = htons((u16) lport->mfs); - cp->cp_con_seq = htons(255); - cp->cp_open_seq = 1; -} - -/** - * fc_flogi_fill - Fill in a flogi request frame. - */ -static inline void fc_flogi_fill(struct fc_lport *lport, struct fc_frame *fp) -{ - struct fc_els_csp *sp; - struct fc_els_cssp *cp; - struct fc_els_flogi *flogi; - - flogi = fc_frame_payload_get(fp, sizeof(*flogi)); - memset(flogi, 0, sizeof(*flogi)); - flogi->fl_cmd = (u8) ELS_FLOGI; - put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn); - put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn); - sp = &flogi->fl_csp; - sp->sp_hi_ver = 0x20; - sp->sp_lo_ver = 0x20; - sp->sp_bb_cred = htons(10); /* this gets set by gateway */ - sp->sp_bb_data = htons((u16) lport->mfs); - cp = &flogi->fl_cssp[3 - 1]; /* class 3 parameters */ - cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ); - if (lport->does_npiv) - sp->sp_features = htons(FC_SP_FT_NPIV); -} - -/** - * fc_fdisc_fill - Fill in a fdisc request frame. - */ -static inline void fc_fdisc_fill(struct fc_lport *lport, struct fc_frame *fp) -{ - struct fc_els_csp *sp; - struct fc_els_cssp *cp; - struct fc_els_flogi *fdisc; - - fdisc = fc_frame_payload_get(fp, sizeof(*fdisc)); - memset(fdisc, 0, sizeof(*fdisc)); - fdisc->fl_cmd = (u8) ELS_FDISC; - put_unaligned_be64(lport->wwpn, &fdisc->fl_wwpn); - put_unaligned_be64(lport->wwnn, &fdisc->fl_wwnn); - sp = &fdisc->fl_csp; - sp->sp_hi_ver = 0x20; - sp->sp_lo_ver = 0x20; - sp->sp_bb_cred = htons(10); /* this gets set by gateway */ - sp->sp_bb_data = htons((u16) lport->mfs); - cp = &fdisc->fl_cssp[3 - 1]; /* class 3 parameters */ - cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ); -} - -/** - * fc_logo_fill - Fill in a logo request frame. - */ -static inline void fc_logo_fill(struct fc_lport *lport, struct fc_frame *fp) -{ - struct fc_els_logo *logo; - - logo = fc_frame_payload_get(fp, sizeof(*logo)); - memset(logo, 0, sizeof(*logo)); - logo->fl_cmd = ELS_LOGO; - hton24(logo->fl_n_port_id, lport->port_id); - logo->fl_n_port_wwn = htonll(lport->wwpn); -} - -/** - * fc_rtv_fill - Fill in RTV (read timeout value) request frame. - */ -static inline void fc_rtv_fill(struct fc_lport *lport, struct fc_frame *fp) -{ - struct fc_els_rtv *rtv; - - rtv = fc_frame_payload_get(fp, sizeof(*rtv)); - memset(rtv, 0, sizeof(*rtv)); - rtv->rtv_cmd = ELS_RTV; -} - -/** - * fc_rec_fill - Fill in rec request frame - */ -static inline void fc_rec_fill(struct fc_lport *lport, struct fc_frame *fp) -{ - struct fc_els_rec *rec; - struct fc_exch *ep = fc_seq_exch(fr_seq(fp)); - - rec = fc_frame_payload_get(fp, sizeof(*rec)); - memset(rec, 0, sizeof(*rec)); - rec->rec_cmd = ELS_REC; - hton24(rec->rec_s_id, lport->port_id); - rec->rec_ox_id = htons(ep->oxid); - rec->rec_rx_id = htons(ep->rxid); -} - -/** - * fc_prli_fill - Fill in prli request frame - */ -static inline void fc_prli_fill(struct fc_lport *lport, struct fc_frame *fp) -{ - struct { - struct fc_els_prli prli; - struct fc_els_spp spp; - } *pp; - - pp = fc_frame_payload_get(fp, sizeof(*pp)); - memset(pp, 0, sizeof(*pp)); - pp->prli.prli_cmd = ELS_PRLI; - pp->prli.prli_spp_len = sizeof(struct fc_els_spp); - pp->prli.prli_len = htons(sizeof(*pp)); - pp->spp.spp_type = FC_TYPE_FCP; - pp->spp.spp_flags = FC_SPP_EST_IMG_PAIR; - pp->spp.spp_params = htonl(lport->service_params); -} - -/** - * fc_scr_fill - Fill in a scr request frame. - */ -static inline void fc_scr_fill(struct fc_lport *lport, struct fc_frame *fp) -{ - struct fc_els_scr *scr; - - scr = fc_frame_payload_get(fp, sizeof(*scr)); - memset(scr, 0, sizeof(*scr)); - scr->scr_cmd = ELS_SCR; - scr->scr_reg_func = ELS_SCRF_FULL; -} - -/** - * fc_els_fill - Fill in an ELS request frame - */ -static inline int fc_els_fill(struct fc_lport *lport, - u32 did, - struct fc_frame *fp, unsigned int op, - enum fc_rctl *r_ctl, enum fc_fh_type *fh_type) -{ - switch (op) { - case ELS_ADISC: - fc_adisc_fill(lport, fp); - break; - - case ELS_PLOGI: - fc_plogi_fill(lport, fp, ELS_PLOGI); - break; - - case ELS_FLOGI: - fc_flogi_fill(lport, fp); - break; - - case ELS_FDISC: - fc_fdisc_fill(lport, fp); - break; - - case ELS_LOGO: - fc_logo_fill(lport, fp); - break; - - case ELS_RTV: - fc_rtv_fill(lport, fp); - break; - - case ELS_REC: - fc_rec_fill(lport, fp); - break; - - case ELS_PRLI: - fc_prli_fill(lport, fp); - break; - - case ELS_SCR: - fc_scr_fill(lport, fp); - break; - - default: - return -EINVAL; - } - - *r_ctl = FC_RCTL_ELS_REQ; - *fh_type = FC_TYPE_ELS; - return 0; -} -#endif /* _FC_ENCODE_H_ */ diff --git a/include/scsi/fc_frame.h b/include/scsi/fc_frame.h index 41df2ba9dbaa..d544dc5057fc 100644 --- a/include/scsi/fc_frame.h +++ b/include/scsi/fc_frame.h @@ -246,4 +246,34 @@ static inline bool fc_frame_is_cmd(const struct fc_frame *fp) */ void fc_frame_leak_check(void); +static inline void __fc_fill_fc_hdr(struct fc_frame_header *fh, + enum fc_rctl r_ctl, + u32 did, u32 sid, enum fc_fh_type type, + u32 f_ctl, u32 parm_offset) +{ + WARN_ON(r_ctl == 0); + fh->fh_r_ctl = r_ctl; + hton24(fh->fh_d_id, did); + hton24(fh->fh_s_id, sid); + fh->fh_type = type; + hton24(fh->fh_f_ctl, f_ctl); + fh->fh_cs_ctl = 0; + fh->fh_df_ctl = 0; + fh->fh_parm_offset = htonl(parm_offset); +} + +/** + * fill FC header fields in specified fc_frame + */ +static inline void fc_fill_fc_hdr(struct fc_frame *fp, enum fc_rctl r_ctl, + u32 did, u32 sid, enum fc_fh_type type, + u32 f_ctl, u32 parm_offset) +{ + struct fc_frame_header *fh; + + fh = fc_frame_header_get(fp); + __fc_fill_fc_hdr(fh, r_ctl, did, sid, type, f_ctl, parm_offset); +} + + #endif /* _FC_FRAME_H_ */ -- cgit v1.2.3 From 8fd9efca86d083bb6fe8676ed4edd1c626d19367 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 26 Oct 2020 17:06:13 +0100 Subject: scsi: libfc: Work around -Warray-bounds warning Building libfc with gcc -Warray-bounds identifies a number of cases in one file where a strncpy() is performed into a single-byte character array: In file included from include/linux/bitmap.h:9, from include/linux/cpumask.h:12, from include/linux/smp.h:13, from include/linux/lockdep.h:14, from include/linux/spinlock.h:59, from include/linux/debugobjects.h:6, from include/linux/timer.h:8, from include/scsi/libfc.h:11, from drivers/scsi/libfc/fc_elsct.c:17: In function 'strncpy', inlined from 'fc_ct_ms_fill.constprop' at drivers/scsi/libfc/fc_encode.h:235:3: include/linux/string.h:290:30: warning: '__builtin_strncpy' offset [56, 135] from the object at 'pp' is out of the bounds of referenced subobject 'value' with type '__u8[1]' {aka 'unsigned char[1]'} at offset 56 [-Warray-bounds] 290 | #define __underlying_strncpy __builtin_strncpy | ^ include/linux/string.h:300:9: note: in expansion of macro '__underlying_strncpy' 300 | return __underlying_strncpy(p, q, size); | ^~~~~~~~~~~~~~~~~~~~ This is not a bug because the 1-byte array is used as an odd way to express a variable-length data field here. I tried to convert it to a flexible-array member, but in the end could not figure out why the sizeof(struct fc_fdmi_???) are used the way they are, and how to properly convert those. Work around this instead by abstracting the string copy in a slightly higher-level function fc_ct_hdr_fill() helper that strscpy() and memset() to achieve the same result as strncpy() but does not require a zero-terminated input and does not get checked for the array overflow because gcc (so far) does not understand the behavior of strscpy(). Link: https://lore.kernel.org/r/20201026160705.3706396-2-arnd@kernel.org Signed-off-by: Arnd Bergmann Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_encode.h | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_encode.h b/drivers/scsi/libfc/fc_encode.h index 18203cae04b2..602c97a651bc 100644 --- a/drivers/scsi/libfc/fc_encode.h +++ b/drivers/scsi/libfc/fc_encode.h @@ -163,6 +163,14 @@ static inline int fc_ct_ns_fill(struct fc_lport *lport, return 0; } +static inline void fc_ct_ms_fill_attr(struct fc_fdmi_attr_entry *entry, + const char *in, size_t len) +{ + int copied = strscpy(entry->value, in, len); + if (copied > 0) + memset(entry->value, copied, len - copied); +} + /** * fc_ct_ms_fill() - Fill in a mgmt service request frame * @lport: local port. @@ -232,7 +240,7 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport, put_unaligned_be16(FC_FDMI_HBA_ATTR_MANUFACTURER, &entry->type); put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, + fc_ct_ms_fill_attr(entry, fc_host_manufacturer(lport->host), FC_FDMI_HBA_ATTR_MANUFACTURER_LEN); @@ -244,7 +252,7 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport, put_unaligned_be16(FC_FDMI_HBA_ATTR_SERIALNUMBER, &entry->type); put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, + fc_ct_ms_fill_attr(entry, fc_host_serial_number(lport->host), FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN); @@ -256,7 +264,7 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport, put_unaligned_be16(FC_FDMI_HBA_ATTR_MODEL, &entry->type); put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, + fc_ct_ms_fill_attr(entry, fc_host_model(lport->host), FC_FDMI_HBA_ATTR_MODEL_LEN); @@ -268,7 +276,7 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport, put_unaligned_be16(FC_FDMI_HBA_ATTR_MODELDESCRIPTION, &entry->type); put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, + fc_ct_ms_fill_attr(entry, fc_host_model_description(lport->host), FC_FDMI_HBA_ATTR_MODELDESCR_LEN); @@ -280,7 +288,7 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport, put_unaligned_be16(FC_FDMI_HBA_ATTR_HARDWAREVERSION, &entry->type); put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, + fc_ct_ms_fill_attr(entry, fc_host_hardware_version(lport->host), FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN); @@ -292,7 +300,7 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport, put_unaligned_be16(FC_FDMI_HBA_ATTR_DRIVERVERSION, &entry->type); put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, + fc_ct_ms_fill_attr(entry, fc_host_driver_version(lport->host), FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN); @@ -304,7 +312,7 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport, put_unaligned_be16(FC_FDMI_HBA_ATTR_OPTIONROMVERSION, &entry->type); put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, + fc_ct_ms_fill_attr(entry, fc_host_optionrom_version(lport->host), FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN); @@ -316,7 +324,7 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport, put_unaligned_be16(FC_FDMI_HBA_ATTR_FIRMWAREVERSION, &entry->type); put_unaligned_be16(len, &entry->len); - strncpy((char *)&entry->value, + fc_ct_ms_fill_attr(entry, fc_host_firmware_version(lport->host), FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN); @@ -411,7 +419,7 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport, &entry->type); put_unaligned_be16(len, &entry->len); /* Use the sysfs device name */ - strncpy((char *)&entry->value, + fc_ct_ms_fill_attr(entry, dev_name(&lport->host->shost_gendev), strnlen(dev_name(&lport->host->shost_gendev), FC_FDMI_PORT_ATTR_HOSTNAME_LEN)); @@ -425,12 +433,12 @@ static inline int fc_ct_ms_fill(struct fc_lport *lport, &entry->type); put_unaligned_be16(len, &entry->len); if (strlen(fc_host_system_hostname(lport->host))) - strncpy((char *)&entry->value, + fc_ct_ms_fill_attr(entry, fc_host_system_hostname(lport->host), strnlen(fc_host_system_hostname(lport->host), FC_FDMI_PORT_ATTR_HOSTNAME_LEN)); else - strncpy((char *)&entry->value, + fc_ct_ms_fill_attr(entry, init_utsname()->nodename, FC_FDMI_PORT_ATTR_HOSTNAME_LEN); break; -- cgit v1.2.3 From 3fb52041a832a253f708c845dff081a0c4fef35e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 26 Oct 2020 22:49:07 +0100 Subject: scsi: libfc: Fix enum-conversion warning gcc -Wextra points out an assignment between two different enum types: drivers/scsi/libfc/fc_exch.c: In function 'fc_exch_setup_hdr': ../drivers/scsi/libfc/fc_exch.c:275:26: warning: implicit conversion from 'enum fc_class' to 'enum fc_sof' [-Wenum-conversion] This seems to be intentional, as the same numeric values are used here, so shut up the warning by adding an explicit cast. Link: https://lore.kernel.org/r/20201026214911.3892701-1-arnd@kernel.org Fixes: 42e9a92fe6a9 ("[SCSI] libfc: A modular Fibre Channel library") Signed-off-by: Arnd Bergmann Signed-off-by: Martin K. Petersen --- drivers/scsi/libfc/fc_exch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 91e680b53523..d71afae6191c 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -271,7 +271,7 @@ static void fc_exch_setup_hdr(struct fc_exch *ep, struct fc_frame *fp, if (f_ctl & FC_FC_END_SEQ) { fr_eof(fp) = FC_EOF_T; - if (fc_sof_needs_ack(ep->class)) + if (fc_sof_needs_ack((enum fc_sof)ep->class)) fr_eof(fp) = FC_EOF_N; /* * From F_CTL. -- cgit v1.2.3 From dd7143e27cb7dee8927d3ede59aff588c57bc224 Mon Sep 17 00:00:00 2001 From: Can Guo Date: Tue, 27 Oct 2020 12:10:36 -0700 Subject: scsi: ufs: Put HBA into LPM during clk gating During clock gating, after clocks are disabled, put HBA into LPM to save more power. Link: https://lore.kernel.org/r/52198e70bff750632740d78678a815256d697e43.1603825776.git.asutoshd@codeaurora.org Reviewed-by: Avri Altman Acked-by: Stanley Chu Signed-off-by: Can Guo Signed-off-by: Asutosh Das Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 9 +++++++-- drivers/scsi/ufs/ufshcd.h | 13 +++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index b8f573a02713..2309253d3101 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -245,6 +245,8 @@ static int ufshcd_wb_buf_flush_disable(struct ufs_hba *hba); static int ufshcd_wb_ctrl(struct ufs_hba *hba, bool enable); static int ufshcd_wb_toggle_flush_during_h8(struct ufs_hba *hba, bool set); static inline void ufshcd_wb_toggle_flush(struct ufs_hba *hba, bool enable); +static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba); +static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba); static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag) { @@ -1548,6 +1550,7 @@ static void ufshcd_ungate_work(struct work_struct *work) } spin_unlock_irqrestore(hba->host->host_lock, flags); + ufshcd_hba_vreg_set_hpm(hba); ufshcd_setup_clocks(hba, true); ufshcd_enable_irq(hba); @@ -1713,6 +1716,8 @@ static void ufshcd_gate_work(struct work_struct *work) /* If link is active, device ref_clk can't be switched off */ __ufshcd_setup_clocks(hba, false, true); + /* Put the host controller in low power mode if possible */ + ufshcd_hba_vreg_set_lpm(hba); /* * In case you are here to cancel this work the gating state * would be marked as REQ_CLKS_ON. In this case keep the state @@ -8405,13 +8410,13 @@ out: static void ufshcd_hba_vreg_set_lpm(struct ufs_hba *hba) { - if (ufshcd_is_link_off(hba)) + if (ufshcd_is_link_off(hba) || ufshcd_can_aggressive_pc(hba)) ufshcd_setup_hba_vreg(hba, false); } static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba) { - if (ufshcd_is_link_off(hba)) + if (ufshcd_is_link_off(hba) || ufshcd_can_aggressive_pc(hba)) ufshcd_setup_hba_vreg(hba, true); } diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 47eb1430274c..0fbb735bb70c 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -592,6 +592,13 @@ enum ufshcd_caps { * inline crypto engine, if it is present */ UFSHCD_CAP_CRYPTO = 1 << 8, + + /* + * This capability allows the controller regulators to be put into + * lpm mode aggressively during clock gating. + * This would increase power savings. + */ + UFSHCD_CAP_AGGR_POWER_COLLAPSE = 1 << 9, }; struct ufs_hba_variant_params { @@ -829,6 +836,12 @@ return true; #endif } +static inline bool ufshcd_can_aggressive_pc(struct ufs_hba *hba) +{ + return !!(ufshcd_is_link_hibern8(hba) && + (hba->caps & UFSHCD_CAP_AGGR_POWER_COLLAPSE)); +} + static inline bool ufshcd_is_auto_hibern8_supported(struct ufs_hba *hba) { return (hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT) && -- cgit v1.2.3 From 61906fd465c0dba963485a138626bde82dbc6f7e Mon Sep 17 00:00:00 2001 From: Asutosh Das Date: Tue, 27 Oct 2020 12:10:37 -0700 Subject: scsi: ufs: qcom: Enable aggressive power collapse for ufs HBA Enabling this capability to let HBA power-collapse more often to save power. Link: https://lore.kernel.org/r/1306284ab2215425ca0a3d9c802574cbd6d35ea7.1603825776.git.asutoshd@codeaurora.org Reviewed-by: Can Guo Reviewed-by: Avri Altman Signed-off-by: Asutosh Das Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-qcom.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index f9d6ef356540..9a19c6d15d3b 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -863,6 +863,7 @@ static void ufs_qcom_set_caps(struct ufs_hba *hba) hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND; hba->caps |= UFSHCD_CAP_WB_EN; hba->caps |= UFSHCD_CAP_CRYPTO; + hba->caps |= UFSHCD_CAP_AGGR_POWER_COLLAPSE; if (host->hw_ver.major >= 0x2) { host->caps = UFS_QCOM_CAP_QUNIPRO | -- cgit v1.2.3 From 4f1826b8e56ffb5c0b7243a7b573bb521b919dfb Mon Sep 17 00:00:00 2001 From: ching Huang Date: Tue, 27 Oct 2020 11:31:31 +0800 Subject: scsi: arcmsr: Configure the default command timeout value Allow configuring the default command timeout value for devices attached to arcmsr controllers. Link: https://lore.kernel.org/r/27c0cda7fd103f05021adaf67490e9298ed5cc3f.camel@areca.com.tw Signed-off-by: ching Huang Signed-off-by: Martin K. Petersen --- drivers/scsi/arcmsr/arcmsr.h | 1 + drivers/scsi/arcmsr/arcmsr_hba.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index 5d054d5c70a5..0f6abd233614 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h @@ -83,6 +83,7 @@ struct device_attribute; #define PCI_DEVICE_ID_ARECA_1886 0x188A #define ARCMSR_HOURS (1000 * 60 * 60 * 4) #define ARCMSR_MINUTES (1000 * 60 * 60) +#define ARCMSR_DEFAULT_TIMEOUT 90 /* ********************************************************************************** ** diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index e4fdb473b990..7cfae1decd12 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -99,6 +99,10 @@ static int set_date_time = 0; module_param(set_date_time, int, S_IRUGO); MODULE_PARM_DESC(set_date_time, " send date, time to iop(0 ~ 1), set_date_time=1(enable), default(=0) is disable"); +static int cmd_timeout = ARCMSR_DEFAULT_TIMEOUT; +module_param(cmd_timeout, int, S_IRUGO); +MODULE_PARM_DESC(cmd_timeout, " scsi cmd timeout(0 ~ 120 sec.), default is 90"); + #define ARCMSR_SLEEPTIME 10 #define ARCMSR_RETRYCOUNT 12 @@ -140,6 +144,7 @@ static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); static void arcmsr_free_irq(struct pci_dev *, struct AdapterControlBlock *); static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb); static void arcmsr_set_iop_datetime(struct timer_list *); +static int arcmsr_slave_config(struct scsi_device *sdev); static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth) { if (queue_depth > ARCMSR_MAX_CMD_PERLUN) @@ -155,6 +160,7 @@ static struct scsi_host_template arcmsr_scsi_host_template = { .eh_abort_handler = arcmsr_abort, .eh_bus_reset_handler = arcmsr_bus_reset, .bios_param = arcmsr_bios_param, + .slave_configure = arcmsr_slave_config, .change_queue_depth = arcmsr_adjust_disk_queue_depth, .can_queue = ARCMSR_DEFAULT_OUTSTANDING_CMD, .this_id = ARCMSR_SCSI_INITIATOR_ID, @@ -3256,6 +3262,16 @@ static int arcmsr_queue_command_lck(struct scsi_cmnd *cmd, static DEF_SCSI_QCMD(arcmsr_queue_command) +static int arcmsr_slave_config(struct scsi_device *sdev) +{ + unsigned int dev_timeout; + + dev_timeout = sdev->request_queue->rq_timeout; + if ((cmd_timeout > 0) && ((cmd_timeout * HZ) > dev_timeout)) + blk_queue_rq_timeout(sdev->request_queue, cmd_timeout * HZ); + return 0; +} + static void arcmsr_get_adapter_config(struct AdapterControlBlock *pACB, uint32_t *rwbuffer) { int count; -- cgit v1.2.3 From eb3b956d2c9bfd86ca38ea5ce6343efcbacff641 Mon Sep 17 00:00:00 2001 From: ching Huang Date: Tue, 27 Oct 2020 11:39:13 +0800 Subject: scsi: arcmsr: Ensure getting a free ccb is done under the spin_lock Ensure getting a free ccb is done under the spin_lock. Link: https://lore.kernel.org/r/f3ec374cada762149911ff35e92a68a15a7d0327.camel@areca.com.tw Signed-off-by: ching Huang Signed-off-by: Martin K. Petersen --- drivers/scsi/arcmsr/arcmsr_hba.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 7cfae1decd12..127fe50e6b12 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -3162,10 +3162,12 @@ message_out: static struct CommandControlBlock *arcmsr_get_freeccb(struct AdapterControlBlock *acb) { - struct list_head *head = &acb->ccb_free_list; + struct list_head *head; struct CommandControlBlock *ccb = NULL; unsigned long flags; + spin_lock_irqsave(&acb->ccblist_lock, flags); + head = &acb->ccb_free_list; if (!list_empty(head)) { ccb = list_entry(head->next, struct CommandControlBlock, list); list_del_init(&ccb->list); -- cgit v1.2.3 From 0b524abc2dd13c95a4427f91406c5a69ccca2ccb Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Wed, 28 Oct 2020 19:30:48 +0100 Subject: scsi: zfcp: Lift Input Queue tasklet from qdio Shift the IRQ tasklet processing from the qdio layer into zfcp. This will allow for a good amount of cleanups in qdio, and provides future opportunity to improve the IRQ processing inside zfcp. We continue to use the qdio layer's internal tasklet/timer mechanism (ie. scan_threshold etc) to check for Request Queue completions. Initially we planned to check for such completions after inspecting the Response Queue - this should typically work, but there's a theoretical race where the device only presents the Request Queue completions _after_ all Response Queue processing has finished. If the Request Queue is then also _completely_ full, we could send no further IOs and thus get no interrupt that would trigger an inspection of the Request Queue. So for now stick to the old model, where we can trust that such a race would be recovered by qdio's internal timer. Code-flow wise, this establishes two levels of control: 1. The qdio layer will only deliver IRQs to the device driver if the QDIO_IRQ_DISABLED flag is cleared. zfcp manages this through qdio_start_irq() / qdio_stop_irq(). The initial state is DISABLED, and zfcp_qdio_open() schedules zfcp's IRQ tasklet once during startup to explicitly enable IRQ delivery. 2. The zfcp tasklet is initialized with tasklet_disable(), and only gets enabled once we open the qdio device. When closing the qdio device, we must disable the tasklet _before_ disabling IRQ delivery (otherwise a concurrently running tasklet could re-enable IRQ delivery after we disabled it). A final tasklet_kill() during teardown ensures that no lingering tasklet_schedule() is still accessing the tasklet structure. Link: https://lore.kernel.org/r/94a765211c48b74a7b91c5e60b158de01db98d43.1603908167.git.bblock@linux.ibm.com Reviewed-by: Benjamin Block Signed-off-by: Julian Wiedmann Signed-off-by: Benjamin Block Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_qdio.c | 39 +++++++++++++++++++++++++++++++++++++++ drivers/s390/scsi/zfcp_qdio.h | 2 ++ 2 files changed, 41 insertions(+) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index a8a514074084..9fc045ddf66d 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -131,6 +131,33 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdires2"); } +static void zfcp_qdio_irq_tasklet(struct tasklet_struct *tasklet) +{ + struct zfcp_qdio *qdio = from_tasklet(qdio, tasklet, irq_tasklet); + struct ccw_device *cdev = qdio->adapter->ccw_device; + unsigned int start, error; + int completed; + + /* Check the Response Queue, and kick off the Request Queue tasklet: */ + completed = qdio_get_next_buffers(cdev, 0, &start, &error); + if (completed < 0) + return; + if (completed > 0) + zfcp_qdio_int_resp(cdev, error, 0, start, completed, + (unsigned long) qdio); + + if (qdio_start_irq(cdev)) + /* More work pending: */ + tasklet_schedule(&qdio->irq_tasklet); +} + +static void zfcp_qdio_poll(struct ccw_device *cdev, unsigned long data) +{ + struct zfcp_qdio *qdio = (struct zfcp_qdio *) data; + + tasklet_schedule(&qdio->irq_tasklet); +} + static struct qdio_buffer_element * zfcp_qdio_sbal_chain(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) { @@ -332,6 +359,8 @@ void zfcp_qdio_close(struct zfcp_qdio *qdio) wake_up(&qdio->req_q_wq); + tasklet_disable(&qdio->irq_tasklet); + qdio_stop_irq(adapter->ccw_device); qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR); /* cleanup used outbound sbals */ @@ -387,6 +416,7 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio) init_data.no_output_qs = 1; init_data.input_handler = zfcp_qdio_int_resp; init_data.output_handler = zfcp_qdio_int_req; + init_data.irq_poll = zfcp_qdio_poll; init_data.int_parm = (unsigned long) qdio; init_data.input_sbal_addr_array = input_sbals; init_data.output_sbal_addr_array = output_sbals; @@ -433,6 +463,11 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio) atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q); atomic_or(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status); + /* Enable processing for QDIO interrupts: */ + tasklet_enable(&qdio->irq_tasklet); + /* This results in a qdio_start_irq(): */ + tasklet_schedule(&qdio->irq_tasklet); + zfcp_qdio_shost_update(adapter, qdio); return 0; @@ -450,6 +485,8 @@ void zfcp_qdio_destroy(struct zfcp_qdio *qdio) if (!qdio) return; + tasklet_kill(&qdio->irq_tasklet); + if (qdio->adapter->ccw_device) qdio_free(qdio->adapter->ccw_device); @@ -475,6 +512,8 @@ int zfcp_qdio_setup(struct zfcp_adapter *adapter) spin_lock_init(&qdio->req_q_lock); spin_lock_init(&qdio->stat_lock); + tasklet_setup(&qdio->irq_tasklet, zfcp_qdio_irq_tasklet); + tasklet_disable(&qdio->irq_tasklet); adapter->qdio = qdio; return 0; diff --git a/drivers/s390/scsi/zfcp_qdio.h b/drivers/s390/scsi/zfcp_qdio.h index 6b43d6b254be..9c1f310db155 100644 --- a/drivers/s390/scsi/zfcp_qdio.h +++ b/drivers/s390/scsi/zfcp_qdio.h @@ -10,6 +10,7 @@ #ifndef ZFCP_QDIO_H #define ZFCP_QDIO_H +#include #include #define ZFCP_QDIO_SBALE_LEN PAGE_SIZE @@ -44,6 +45,7 @@ struct zfcp_qdio { u64 req_q_util; atomic_t req_q_full; wait_queue_head_t req_q_wq; + struct tasklet_struct irq_tasklet; struct zfcp_adapter *adapter; u16 max_sbale_per_sbal; u16 max_sbale_per_req; -- cgit v1.2.3 From 84e7b4169f949f8185a5adf0f0bfb893030d0fda Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Wed, 28 Oct 2020 19:30:49 +0100 Subject: scsi: zfcp: Remove orphaned function declarations drivers/s390/scsi/zfcp_ext.h: zfcp_sg_free_table - only declaration left after commit 58f3ead54752 ("scsi: zfcp: move SG table helper from aux to fc and make them static") drivers/s390/scsi/zfcp_ext.h: zfcp_sg_setup_table - only declaration left after commit 58f3ead54752 ("scsi: zfcp: move SG table helper from aux to fc and make them static") Link: https://lore.kernel.org/r/6854ae03c5c65805f746774eeb0f2869fcd6c397.1603908167.git.bblock@linux.ibm.com Reviewed-by: Steffen Maier Reviewed-by: Benjamin Block Signed-off-by: Vasily Gorbik Signed-off-by: Benjamin Block Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_ext.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 3ef5d74331c3..8b50f580584c 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -20,8 +20,6 @@ extern struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *, u64); extern struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *); extern struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *, u64, u32, u32); -extern void zfcp_sg_free_table(struct scatterlist *, int); -extern int zfcp_sg_setup_table(struct scatterlist *, int); extern void zfcp_adapter_release(struct kref *); extern void zfcp_adapter_unregister(struct zfcp_adapter *); -- cgit v1.2.3 From efd321768d2e0e85083b83aefb15c949d4c8930f Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Wed, 28 Oct 2020 19:30:50 +0100 Subject: scsi: zfcp: Clarify & assert the stat_lock locking in zfcp_qdio_send() Explain why the plain spin_lock() suffices in current code, even when the stat_lock is also used by zfcp_qdio_int_req() in tasklet context. We could also promote the spin_lock() to a spin_lock_irqsave(), but that would just obfuscate the locking even further. Link: https://lore.kernel.org/r/b023b1472630f4bf9fce580577d7bb49de89ccbf.1603908167.git.bblock@linux.ibm.com Reviewed-by: Benjamin Block Reviewed-by: Steffen Maier Signed-off-by: Julian Wiedmann Signed-off-by: Benjamin Block Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_qdio.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 9fc045ddf66d..23ab16d65f2a 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -10,6 +10,7 @@ #define KMSG_COMPONENT "zfcp" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt +#include #include #include #include "zfcp_ext.h" @@ -283,6 +284,13 @@ int zfcp_qdio_send(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req) int retval; u8 sbal_number = q_req->sbal_number; + /* + * This should actually be a spin_lock_bh(stat_lock), to protect against + * zfcp_qdio_int_req() in tasklet context. + * But we can't do so (and are safe), as we always get called with IRQs + * disabled by spin_lock_irq[save](req_q_lock). + */ + lockdep_assert_irqs_disabled(); spin_lock(&qdio->stat_lock); zfcp_qdio_account(qdio); spin_unlock(&qdio->stat_lock); -- cgit v1.2.3 From a6c37abe6988eb33a5f301e252ee41ed22b8df8d Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Wed, 28 Oct 2020 19:30:51 +0100 Subject: scsi: zfcp: Process Version Change events Handle notifications for a concurrent change of the FCP Channel firmware. Update the relevant user-visible fields to provide accurate data. Link: https://lore.kernel.org/r/d2c7bc57c6cf1b65eabbf7a5d0e3927b9f65647f.1603908167.git.bblock@linux.ibm.com Reviewed-by: Steffen Maier Reviewed-by: Benjamin Block Signed-off-by: Julian Wiedmann Signed-off-by: Benjamin Block Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_fsf.c | 16 ++++++++++++++++ drivers/s390/scsi/zfcp_fsf.h | 10 ++++++++++ 2 files changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 6cb963a06777..afa95e04eceb 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -242,6 +242,19 @@ static void zfcp_fsf_status_read_link_down(struct zfcp_fsf_req *req) } } +static void +zfcp_fsf_status_read_version_change(struct zfcp_adapter *adapter, + struct fsf_status_read_buffer *sr_buf) +{ + if (sr_buf->status_subtype == FSF_STATUS_READ_SUB_LIC_CHANGE) { + u32 version = sr_buf->payload.version_change.current_version; + + WRITE_ONCE(adapter->fsf_lic_version, version); + snprintf(fc_host_firmware_version(adapter->scsi_host), + FC_VERSION_STRING_SIZE, "%#08x", version); + } +} + static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) { struct zfcp_adapter *adapter = req->adapter; @@ -300,6 +313,9 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: adapter->adapter_features = sr_buf->payload.word[0]; break; + case FSF_STATUS_READ_VERSION_CHANGE: + zfcp_fsf_status_read_version_change(adapter, sr_buf); + break; } mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data); diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 09d73d0061ef..26ad7a0c5ce3 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -134,6 +134,7 @@ #define FSF_STATUS_READ_LINK_UP 0x00000006 #define FSF_STATUS_READ_NOTIFICATION_LOST 0x00000009 #define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C +#define FSF_STATUS_READ_VERSION_CHANGE 0x0000000D /* status subtypes for link down */ #define FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK 0x00000000 @@ -143,6 +144,9 @@ /* status subtypes for unsolicited status notification lost */ #define FSF_STATUS_READ_SUB_INCOMING_ELS 0x00000001 +/* status subtypes for version change */ +#define FSF_STATUS_READ_SUB_LIC_CHANGE 0x00000001 + /* topologie that is detected by the adapter */ #define FSF_TOPO_P2P 0x00000001 #define FSF_TOPO_FABRIC 0x00000002 @@ -226,6 +230,11 @@ struct fsf_link_down_info { u8 vendor_specific_code; } __attribute__ ((packed)); +struct fsf_version_change { + u32 current_version; + u32 previous_version; +} __packed; + struct fsf_status_read_buffer { u32 status_type; u32 status_subtype; @@ -242,6 +251,7 @@ struct fsf_status_read_buffer { u32 word[FSF_STATUS_READ_PAYLOAD_SIZE/sizeof(u32)]; struct fsf_link_down_info link_down_info; struct fsf_bit_error_payload bit_error; + struct fsf_version_change version_change; } payload; } __attribute__ ((packed)); -- cgit v1.2.3 From d90196317484b69bb46b7144c6e0e1a4f581200d Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Wed, 28 Oct 2020 19:30:52 +0100 Subject: scsi: zfcp: Handle event-lost notification for Version Change events As recovery for a lost Version Change event, trigger an Exchange Config Data cmd to retrieve the current FW version. Doing so requires process context (as eg. zfcp_qdio_sbal_get() might need to sleep), so defer from tasklet context into a work item. Link: https://lore.kernel.org/r/297c7be2944c3714863fcd22d531d910312d29f0.1603908167.git.bblock@linux.ibm.com Suggested-by: Steffen Maier Reviewed-by: Steffen Maier Reviewed-by: Benjamin Block Signed-off-by: Julian Wiedmann Signed-off-by: Benjamin Block Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_aux.c | 11 +++++++++++ drivers/s390/scsi/zfcp_def.h | 1 + drivers/s390/scsi/zfcp_fsf.c | 3 +++ drivers/s390/scsi/zfcp_fsf.h | 1 + 4 files changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 18b713a616de..768873dd55b8 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -292,6 +292,14 @@ static void _zfcp_status_read_scheduler(struct work_struct *work) stat_work)); } +static void zfcp_version_change_lost_work(struct work_struct *work) +{ + struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter, + version_change_lost_work); + + zfcp_fsf_exchange_config_data_sync(adapter->qdio, NULL); +} + static void zfcp_print_sl(struct seq_file *m, struct service_level *sl) { struct zfcp_adapter *adapter = @@ -353,6 +361,8 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device) INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler); INIT_DELAYED_WORK(&adapter->scan_work, zfcp_fc_scan_ports); INIT_WORK(&adapter->ns_up_work, zfcp_fc_sym_name_update); + INIT_WORK(&adapter->version_change_lost_work, + zfcp_version_change_lost_work); adapter->next_port_scan = jiffies; @@ -429,6 +439,7 @@ void zfcp_adapter_unregister(struct zfcp_adapter *adapter) cancel_delayed_work_sync(&adapter->scan_work); cancel_work_sync(&adapter->stat_work); cancel_work_sync(&adapter->ns_up_work); + cancel_work_sync(&adapter->version_change_lost_work); zfcp_destroy_adapter_work_queue(adapter); zfcp_fc_wka_ports_force_offline(adapter->gs); diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index da8a5ceb615c..f656d74a5f94 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -201,6 +201,7 @@ struct zfcp_adapter { struct zfcp_fc_events events; unsigned long next_port_scan; struct zfcp_diag_adapter *diagnostics; + struct work_struct version_change_lost_work; }; struct zfcp_port { diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index afa95e04eceb..7593a9667b3e 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -309,6 +309,9 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) case FSF_STATUS_READ_NOTIFICATION_LOST: if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS) zfcp_fc_conditional_port_scan(adapter); + if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_VERSION_CHANGE) + queue_work(adapter->work_queue, + &adapter->version_change_lost_work); break; case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: adapter->adapter_features = sr_buf->payload.word[0]; diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 26ad7a0c5ce3..5e6b601af980 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -143,6 +143,7 @@ /* status subtypes for unsolicited status notification lost */ #define FSF_STATUS_READ_SUB_INCOMING_ELS 0x00000001 +#define FSF_STATUS_READ_SUB_VERSION_CHANGE 0x00000100 /* status subtypes for version change */ #define FSF_STATUS_READ_SUB_LIC_CHANGE 0x00000001 -- cgit v1.2.3 From b22a0fac8c056e88fc72f7241fa9077b804634a6 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Tue, 27 Oct 2020 18:38:34 +0530 Subject: scsi: mpt3sas: Define hba_port structure Define a new hba_port structure which holds the following variables: - port_id: Port ID of the narrow/wide port of the HBA - sas_address: SAS Address of the remote device that is attached to the current HBA port - phy_mask: HBA's phy bits to which above SAS addressed device is attached - flags: This field is used to refresh port details during HBA reset Link: https://lore.kernel.org/r/20201027130847.9962-2-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index bc8beb10f3fc..2dde574ccff2 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -420,6 +420,7 @@ struct Mpi2ManufacturingPage11_t { * @flags: MPT_TARGET_FLAGS_XXX flags * @deleted: target flaged for deletion * @tm_busy: target is busy with TM request. + * @port: hba port entry containing target's port number info * @sas_dev: The sas_device associated with this target * @pcie_dev: The pcie device associated with this target */ @@ -432,6 +433,7 @@ struct MPT3SAS_TARGET { u32 flags; u8 deleted; u8 tm_busy; + struct hba_port *port; struct _sas_device *sas_dev; struct _pcie_device *pcie_dev; }; @@ -534,6 +536,7 @@ struct _internal_cmd { * addition routine. * @chassis_slot: chassis slot * @is_chassis_slot_valid: chassis slot valid or not + * @port: hba port entry containing device's port number info */ struct _sas_device { struct list_head list; @@ -560,6 +563,7 @@ struct _sas_device { u8 is_chassis_slot_valid; u8 connector_name[5]; struct kref refcount; + struct hba_port *port; }; static inline void sas_device_get(struct _sas_device *s) @@ -730,6 +734,7 @@ struct _boot_device { * @remote_identify: attached device identification * @rphy: sas transport rphy object * @port: sas transport wide/narrow port object + * @hba_port: hba port entry containing port's port number info * @phy_list: _sas_phy list objects belonging to this port */ struct _sas_port { @@ -738,6 +743,7 @@ struct _sas_port { struct sas_identify remote_identify; struct sas_rphy *rphy; struct sas_port *port; + struct hba_port *hba_port; struct list_head phy_list; }; @@ -751,6 +757,7 @@ struct _sas_port { * @handle: device handle for this phy * @attached_handle: device handle for attached device * @phy_belongs_to_port: port has been created for this phy + * @port: hba port entry containing port number info */ struct _sas_phy { struct list_head port_siblings; @@ -761,6 +768,7 @@ struct _sas_phy { u16 handle; u16 attached_handle; u8 phy_belongs_to_port; + struct hba_port *port; }; /** @@ -776,6 +784,7 @@ struct _sas_phy { * @responding: used in _scsih_expander_device_mark_responding * @phy: a list of phys that make up this sas_host/expander * @sas_port_list: list of ports attached to this sas_host/expander + * @port: hba port entry containing node's port number info */ struct _sas_node { struct list_head list; @@ -787,11 +796,11 @@ struct _sas_node { u16 enclosure_handle; u64 enclosure_logical_id; u8 responding; + struct hba_port *port; struct _sas_phy *phy; struct list_head sas_port_list; }; - /** * struct _enclosure_node - enclosure information * @list: list of enclosures @@ -1009,6 +1018,27 @@ struct reply_post_struct { dma_addr_t reply_post_free_dma; }; +/** + * struct hba_port - Saves each HBA's Wide/Narrow port info + * @sas_address: sas address of this wide/narrow port's attached device + * @phy_mask: HBA PHY's belonging to this port + * @port_id: port number + * @flags: hba port flags + */ +struct hba_port { + struct list_head list; + u64 sas_address; + u32 phy_mask; + u8 port_id; + u8 flags; +}; + +/* hba port flags */ +#define HBA_PORT_FLAG_DIRTY_PORT 0x01 +#define HBA_PORT_FLAG_NEW_PORT 0x02 + +#define MULTIPATH_DISABLED_PORT_ID 0xFF + typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); /** * struct MPT3SAS_ADAPTER - per adapter struct @@ -1191,6 +1221,7 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); * which ensures the syncrhonization between cli/sysfs_show path. * @atomic_desc_capable: Atomic Request Descriptor support. * @GET_MSIX_INDEX: Get the msix index of high iops queues. + * @port_table_list: list containing HBA's wide/narrow port's info */ struct MPT3SAS_ADAPTER { struct list_head list; @@ -1483,6 +1514,8 @@ struct MPT3SAS_ADAPTER { PUT_SMID_IO_FP_HIP put_smid_hi_priority; PUT_SMID_DEFAULT put_smid_default; GET_MSIX_INDEX get_msix_index_for_smlio; + + struct list_head port_table_list; }; struct mpt3sas_debugfs_buffer { -- cgit v1.2.3 From e238e71b6cb2b7b06224b31eb31892d1acb75f1d Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Tue, 27 Oct 2020 18:38:35 +0530 Subject: scsi: mpt3sas: Allocate memory for hba_port objects Allocate hba_port object whenever a new HBA's wide/narrow port is identified while processing the SASIOUnitPage0's phy data and add this object to port_table_list. Deallocate these objects during driver unload. Link: https://lore.kernel.org/r/20201027130847.9962-3-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 73 ++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 5f845d7094fc..fc28f7bc30b6 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -356,6 +356,30 @@ _scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number, SlotNumber)) ? 1 : 0; } +/** + * mpt3sas_get_port_by_id - get hba port entry corresponding to provided + * port number from port list + * @ioc: per adapter object + * @port_id: port number + * + * Search for hba port entry corresponding to provided port number, + * if available return port object otherwise return NULL. + */ +struct hba_port * +mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, u8 port_id) +{ + struct hba_port *port, *port_next; + + list_for_each_entry_safe(port, port_next, + &ioc->port_table_list, list) { + if (port->port_id == port_id && + !(port->flags & HBA_PORT_FLAG_DIRTY_PORT)) + return port; + } + + return NULL; +} + /** * _scsih_is_boot_device - search for matching boot device. * @sas_address: sas address @@ -5732,7 +5756,8 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc) Mpi2ConfigReply_t mpi_reply; Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; u16 attached_handle; - u8 link_rate; + u8 link_rate, port_id; + struct hba_port *port; dtmprintk(ioc, ioc_info(ioc, "updating handles for sas_host(0x%016llx)\n", @@ -5756,13 +5781,28 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc) for (i = 0; i < ioc->sas_hba.num_phys ; i++) { link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4; if (i == 0) - ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> - PhyData[0].ControllerDevHandle); + ioc->sas_hba.handle = le16_to_cpu( + sas_iounit_pg0->PhyData[0].ControllerDevHandle); + port_id = sas_iounit_pg0->PhyData[i].Port; + if (!(mpt3sas_get_port_by_id(ioc, port_id))) { + port = kzalloc(sizeof(struct hba_port), GFP_KERNEL); + if (!port) + goto out; + + port->port_id = port_id; + ioc_info(ioc, + "hba_port entry: %p, port: %d is added to hba_port list\n", + port, port->port_id); + if (ioc->shost_recovery) + port->flags = HBA_PORT_FLAG_NEW_PORT; + list_add_tail(&port->list, &ioc->port_table_list); + } ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i]. AttachedDevHandle); if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5) link_rate = MPI2_SAS_NEG_LINK_RATE_1_5; + ioc->sas_hba.phy[i].port = mpt3sas_get_port_by_id(ioc, port_id); mpt3sas_transport_update_links(ioc, ioc->sas_hba.sas_address, attached_handle, i, link_rate); } @@ -5789,7 +5829,8 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc) u16 ioc_status; u16 sz; u8 device_missing_delay; - u8 num_phys; + u8 num_phys, port_id; + struct hba_port *port; mpt3sas_config_get_number_hba_phys(ioc, &num_phys); if (!num_phys) { @@ -5882,8 +5923,24 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc) if (i == 0) ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> PhyData[0].ControllerDevHandle); + + port_id = sas_iounit_pg0->PhyData[i].Port; + if (!(mpt3sas_get_port_by_id(ioc, port_id))) { + port = kzalloc(sizeof(struct hba_port), GFP_KERNEL); + if (!port) + goto out; + + port->port_id = port_id; + ioc_info(ioc, + "hba_port entry: %p, port: %d is added to hba_port list\n", + port, port->port_id); + list_add_tail(&port->list, + &ioc->port_table_list); + } + ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; ioc->sas_hba.phy[i].phy_id = i; + ioc->sas_hba.phy[i].port = mpt3sas_get_port_by_id(ioc, port_id); mpt3sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i], phy_pg0, ioc->sas_hba.parent_dev); } @@ -10136,6 +10193,7 @@ static void scsih_remove(struct pci_dev *pdev) struct workqueue_struct *wq; unsigned long flags; Mpi2ConfigReply_t mpi_reply; + struct hba_port *port, *port_next; if (_scsih_get_shost_and_ioc(pdev, &shost, &ioc)) return; @@ -10198,6 +10256,12 @@ static void scsih_remove(struct pci_dev *pdev) mpt3sas_port->remote_identify.sas_address); } + list_for_each_entry_safe(port, port_next, + &ioc->port_table_list, list) { + list_del(&port->list); + kfree(port); + } + /* free phys attached to the sas_host */ if (ioc->sas_hba.num_phys) { kfree(ioc->sas_hba.phy); @@ -10987,6 +11051,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) INIT_LIST_HEAD(&ioc->delayed_event_ack_list); INIT_LIST_HEAD(&ioc->delayed_tr_volume_list); INIT_LIST_HEAD(&ioc->reply_queue_list); + INIT_LIST_HEAD(&ioc->port_table_list); sprintf(ioc->name, "%s_cm%d", ioc->driver_name, ioc->id); -- cgit v1.2.3 From 78ca700342a5df21d80515a36ba17c4962efb35b Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Tue, 27 Oct 2020 18:38:36 +0530 Subject: scsi: mpt3sas: Rearrange _scsih_mark_responding_sas_device() Rearrange _scsih_mark_responding_sas_device function. No functional change. Link: https://lore.kernel.org/r/20201027130847.9962-4-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 116 +++++++++++++++++------------------ 1 file changed, 58 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index fc28f7bc30b6..160260efc64c 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -8742,69 +8742,69 @@ Mpi2SasDevicePage0_t *sas_device_pg0) } spin_lock_irqsave(&ioc->sas_device_lock, flags); list_for_each_entry(sas_device, &ioc->sas_device_list, list) { - if ((sas_device->sas_address == le64_to_cpu( - sas_device_pg0->SASAddress)) && (sas_device->slot == - le16_to_cpu(sas_device_pg0->Slot))) { - sas_device->responding = 1; - starget = sas_device->starget; - if (starget && starget->hostdata) { - sas_target_priv_data = starget->hostdata; - sas_target_priv_data->tm_busy = 0; - sas_target_priv_data->deleted = 0; - } else - sas_target_priv_data = NULL; - if (starget) { - starget_printk(KERN_INFO, starget, - "handle(0x%04x), sas_addr(0x%016llx)\n", - le16_to_cpu(sas_device_pg0->DevHandle), - (unsigned long long) - sas_device->sas_address); + if (sas_device->sas_address != le64_to_cpu( + sas_device_pg0->SASAddress)) + continue; + if (sas_device->slot != le16_to_cpu(sas_device_pg0->Slot)) + continue; + sas_device->responding = 1; + starget = sas_device->starget; + if (starget && starget->hostdata) { + sas_target_priv_data = starget->hostdata; + sas_target_priv_data->tm_busy = 0; + sas_target_priv_data->deleted = 0; + } else + sas_target_priv_data = NULL; + if (starget) { + starget_printk(KERN_INFO, starget, + "handle(0x%04x), sas_addr(0x%016llx)\n", + le16_to_cpu(sas_device_pg0->DevHandle), + (unsigned long long) + sas_device->sas_address); - if (sas_device->enclosure_handle != 0) - starget_printk(KERN_INFO, starget, - "enclosure logical id(0x%016llx)," - " slot(%d)\n", - (unsigned long long) - sas_device->enclosure_logical_id, - sas_device->slot); - } - if (le16_to_cpu(sas_device_pg0->Flags) & - MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { - sas_device->enclosure_level = - sas_device_pg0->EnclosureLevel; - memcpy(&sas_device->connector_name[0], - &sas_device_pg0->ConnectorName[0], 4); - } else { - sas_device->enclosure_level = 0; - sas_device->connector_name[0] = '\0'; - } + if (sas_device->enclosure_handle != 0) + starget_printk(KERN_INFO, starget, + "enclosure logical id(0x%016llx), slot(%d)\n", + (unsigned long long) + sas_device->enclosure_logical_id, + sas_device->slot); + } + if (le16_to_cpu(sas_device_pg0->Flags) & + MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { + sas_device->enclosure_level = + sas_device_pg0->EnclosureLevel; + memcpy(&sas_device->connector_name[0], + &sas_device_pg0->ConnectorName[0], 4); + } else { + sas_device->enclosure_level = 0; + sas_device->connector_name[0] = '\0'; + } - sas_device->enclosure_handle = - le16_to_cpu(sas_device_pg0->EnclosureHandle); - sas_device->is_chassis_slot_valid = 0; - if (enclosure_dev) { - sas_device->enclosure_logical_id = le64_to_cpu( - enclosure_dev->pg0.EnclosureLogicalID); - if (le16_to_cpu(enclosure_dev->pg0.Flags) & - MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID) { - sas_device->is_chassis_slot_valid = 1; - sas_device->chassis_slot = - enclosure_dev->pg0.ChassisSlot; - } + sas_device->enclosure_handle = + le16_to_cpu(sas_device_pg0->EnclosureHandle); + sas_device->is_chassis_slot_valid = 0; + if (enclosure_dev) { + sas_device->enclosure_logical_id = le64_to_cpu( + enclosure_dev->pg0.EnclosureLogicalID); + if (le16_to_cpu(enclosure_dev->pg0.Flags) & + MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID) { + sas_device->is_chassis_slot_valid = 1; + sas_device->chassis_slot = + enclosure_dev->pg0.ChassisSlot; } + } - if (sas_device->handle == le16_to_cpu( - sas_device_pg0->DevHandle)) - goto out; - pr_info("\thandle changed from(0x%04x)!!!\n", - sas_device->handle); - sas_device->handle = le16_to_cpu( - sas_device_pg0->DevHandle); - if (sas_target_priv_data) - sas_target_priv_data->handle = - le16_to_cpu(sas_device_pg0->DevHandle); + if (sas_device->handle == le16_to_cpu( + sas_device_pg0->DevHandle)) goto out; - } + pr_info("\thandle changed from(0x%04x)!!!\n", + sas_device->handle); + sas_device->handle = le16_to_cpu( + sas_device_pg0->DevHandle); + if (sas_target_priv_data) + sas_target_priv_data->handle = + le16_to_cpu(sas_device_pg0->DevHandle); + goto out; } out: spin_unlock_irqrestore(&ioc->sas_device_lock, flags); -- cgit v1.2.3 From e2f0cdf7525353d87ed4f51ea69ca7986070ddd5 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Tue, 27 Oct 2020 18:38:37 +0530 Subject: scsi: mpt3sas: Update hba_port's sas_address & phy_mask Update hba_port's sas_address & phy_mask fields whenever a direct expander or sas/sata target devices are added or removed. When any direct attached device is discovered then driver: - Gets the hba_port object corresponding to device's PhysicalPort number; - Updates the hba_port's sas_address field with device's SAS Address; - Updates the hba_port's phy_mask filed with device's narrow/wide port Phy number bits; - If a sas/sata end device (not only direct-attached devices) is added then corresponding sas_device object's port variable is assigned with hba_port object's address whose port_id matches the device's PhysicalPort number. - If an expander device is added then corresponding sas_expander object's port variable is assigned with hba_port object's address whose port_id matches the expander device's PhysicalPort number. When any direct attached device is detached then driver will delete the hba_port object corresponding to device's PhysicalPort number. Whenever any HBA phy's link (of direct attached device's port) comes up then update the phy_mask field of corresponding hba_port object. Link: https://lore.kernel.org/r/20201027130847.9962-5-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 7 +-- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 81 ++++++++++++++++++++++++-------- drivers/scsi/mpt3sas/mpt3sas_transport.c | 65 +++++++++++++++++++++++-- 3 files changed, 126 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 2dde574ccff2..aef872aa509d 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1792,16 +1792,17 @@ extern struct scsi_transport_template *mpt3sas_transport_template; u8 mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply); struct _sas_port *mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, - u16 handle, u64 sas_address); + u16 handle, u64 sas_address, struct hba_port *port); void mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, - u64 sas_address_parent); + u64 sas_address_parent, struct hba_port *port); int mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy *mpt3sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev); int mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy *mpt3sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev); void mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address, u16 handle, u8 phy_number, u8 link_rate); + u64 sas_address, u16 handle, u8 phy_number, u8 link_rate, + struct hba_port *port); extern struct sas_function_template mpt3sas_transport_functions; extern struct scsi_transport_template *mpt3sas_transport_template; /* trigger data externs */ diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 160260efc64c..11cb9619c01c 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -908,7 +908,7 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc, } if (!mpt3sas_transport_port_add(ioc, sas_device->handle, - sas_device->sas_address_parent)) { + sas_device->sas_address_parent, sas_device->port)) { _scsih_sas_device_remove(ioc, sas_device); } else if (!sas_device->starget) { /* @@ -919,7 +919,8 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc, if (!ioc->is_driver_loading) { mpt3sas_transport_port_remove(ioc, sas_device->sas_address, - sas_device->sas_address_parent); + sas_device->sas_address_parent, + sas_device->port); _scsih_sas_device_remove(ioc, sas_device); } } else @@ -1768,6 +1769,7 @@ scsih_target_alloc(struct scsi_target *starget) if (pcie_device) { sas_target_priv_data->handle = pcie_device->handle; sas_target_priv_data->sas_address = pcie_device->wwid; + sas_target_priv_data->port = NULL; sas_target_priv_data->pcie_dev = pcie_device; pcie_device->starget = starget; pcie_device->id = starget->id; @@ -1791,6 +1793,7 @@ scsih_target_alloc(struct scsi_target *starget) if (sas_device) { sas_target_priv_data->handle = sas_device->handle; sas_target_priv_data->sas_address = sas_device->sas_address; + sas_target_priv_data->port = sas_device->port; sas_target_priv_data->sas_dev = sas_device; sas_device->starget = starget; sas_device->id = starget->id; @@ -5804,7 +5807,8 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc) link_rate = MPI2_SAS_NEG_LINK_RATE_1_5; ioc->sas_hba.phy[i].port = mpt3sas_get_port_by_id(ioc, port_id); mpt3sas_transport_update_links(ioc, ioc->sas_hba.sas_address, - attached_handle, i, link_rate); + attached_handle, i, link_rate, + ioc->sas_hba.phy[i].port); } out: kfree(sas_iounit_pg0); @@ -5994,6 +5998,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) int i; unsigned long flags; struct _sas_port *mpt3sas_port = NULL; + u8 port_id; int rc = 0; @@ -6026,6 +6031,8 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) __FILE__, __LINE__, __func__); return -1; } + + port_id = expander_pg0.PhysicalPort; if (sas_address_parent != ioc->sas_hba.sas_address) { spin_lock_irqsave(&ioc->sas_node_lock, flags); sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc, @@ -6059,6 +6066,13 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) sas_expander->num_phys = expander_pg0.NumPhys; sas_expander->sas_address_parent = sas_address_parent; sas_expander->sas_address = sas_address; + sas_expander->port = mpt3sas_get_port_by_id(ioc, port_id); + if (!sas_expander->port) { + ioc_err(ioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + rc = -1; + goto out_fail; + } ioc_info(ioc, "expander_add: handle(0x%04x), parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", handle, parent_handle, @@ -6077,7 +6091,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) INIT_LIST_HEAD(&sas_expander->sas_port_list); mpt3sas_port = mpt3sas_transport_port_add(ioc, handle, - sas_address_parent); + sas_address_parent, sas_expander->port); if (!mpt3sas_port) { ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); @@ -6096,6 +6110,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) } sas_expander->phy[i].handle = handle; sas_expander->phy[i].phy_id = i; + sas_expander->phy[i].port = mpt3sas_get_port_by_id(ioc, port_id); if ((mpt3sas_transport_add_expander_phy(ioc, &sas_expander->phy[i], expander_pg1, @@ -6123,7 +6138,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) if (mpt3sas_port) mpt3sas_transport_port_remove(ioc, sas_expander->sas_address, - sas_address_parent); + sas_address_parent, sas_expander->port); kfree(sas_expander); return rc; } @@ -6388,6 +6403,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u32 ioc_status; u64 sas_address; u32 device_info; + u8 port_id; if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { @@ -6424,6 +6440,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, sas_device_pg0.AccessStatus)) return -1; + port_id = sas_device_pg0.PhysicalPort; sas_device = mpt3sas_get_sdev_by_addr(ioc, sas_address); if (sas_device) { @@ -6466,6 +6483,12 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, sas_device->phy = sas_device_pg0.PhyNum; sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) & MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0; + sas_device->port = mpt3sas_get_port_by_id(ioc, port_id); + if (!sas_device->port) { + ioc_err(ioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out; + } if (le16_to_cpu(sas_device_pg0.Flags) & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { @@ -6499,6 +6522,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, else _scsih_sas_device_add(ioc, sas_device); +out: sas_device_put(sas_device); return 0; } @@ -6539,7 +6563,8 @@ _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc, if (!ioc->hide_drives) mpt3sas_transport_port_remove(ioc, sas_device->sas_address, - sas_device->sas_address_parent); + sas_device->sas_address_parent, + sas_device->port); ioc_info(ioc, "removing handle(0x%04x), sas_addr(0x%016llx)\n", sas_device->handle, (u64)sas_device->sas_address); @@ -6650,6 +6675,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, u64 sas_address; unsigned long flags; u8 link_rate, prev_link_rate; + struct hba_port *port; Mpi2EventDataSasTopologyChangeList_t *event_data = (Mpi2EventDataSasTopologyChangeList_t *) fw_event->event_data; @@ -6671,6 +6697,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, } parent_handle = le16_to_cpu(event_data->ExpanderDevHandle); + port = mpt3sas_get_port_by_id(ioc, event_data->PhysicalPort); /* handle expander add */ if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED) @@ -6683,6 +6710,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, if (sas_expander) { sas_address = sas_expander->sas_address; max_phys = sas_expander->num_phys; + port = sas_expander->port; } else if (parent_handle < ioc->sas_hba.num_phys) { sas_address = ioc->sas_hba.sas_address; max_phys = ioc->sas_hba.num_phys; @@ -6725,7 +6753,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, break; mpt3sas_transport_update_links(ioc, sas_address, - handle, phy_number, link_rate); + handle, phy_number, link_rate, port); if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5) break; @@ -6744,7 +6772,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, break; mpt3sas_transport_update_links(ioc, sas_address, - handle, phy_number, link_rate); + handle, phy_number, link_rate, port); _scsih_add_device(ioc, handle, phy_number, 0); @@ -8300,7 +8328,8 @@ _scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc, parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) mpt3sas_transport_update_links(ioc, sas_address, handle, - sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); + sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5, + mpt3sas_get_port_by_id(ioc, sas_device_pg0.PhysicalPort)); _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum); _scsih_add_device(ioc, handle, 0, 1); @@ -8606,7 +8635,9 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc, parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) mpt3sas_transport_update_links(ioc, sas_address, handle, - sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); + sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5, + mpt3sas_get_port_by_id(ioc, + sas_device_pg0.PhysicalPort)); _scsih_add_device(ioc, handle, 0, 1); @@ -9345,7 +9376,8 @@ _scsih_refresh_expander_links(struct MPT3SAS_ADAPTER *ioc, mpt3sas_transport_update_links(ioc, sas_expander->sas_address, le16_to_cpu(expander_pg1.AttachedDevHandle), i, - expander_pg1.NegotiatedLinkRate >> 4); + expander_pg1.NegotiatedLinkRate >> 4, + sas_expander->port); } } @@ -9364,7 +9396,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) Mpi2RaidPhysDiskPage0_t pd_pg0; Mpi2EventIrConfigElement_t element; Mpi2ConfigReply_t mpi_reply; - u8 phys_disk_num; + u8 phys_disk_num, port_id; u16 ioc_status; u16 handle, parent_handle; u64 sas_address; @@ -9454,9 +9486,11 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) ioc_info(ioc, "\tBEFORE adding phys disk: handle (0x%04x), sas_addr(0x%016llx)\n", handle, (u64)le64_to_cpu(sas_device_pg0.SASAddress)); + port_id = sas_device_pg0.PhysicalPort; mpt3sas_transport_update_links(ioc, sas_address, handle, sas_device_pg0.PhyNum, - MPI2_SAS_NEG_LINK_RATE_1_5); + MPI2_SAS_NEG_LINK_RATE_1_5, + mpt3sas_get_port_by_id(ioc, port_id)); set_bit(handle, ioc->pd_handles); retry_count = 0; /* This will retry adding the end device. @@ -9542,6 +9576,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) if (!(_scsih_is_end_device( le32_to_cpu(sas_device_pg0.DeviceInfo)))) continue; + port_id = sas_device_pg0.PhysicalPort; sas_device = mpt3sas_get_sdev_by_addr(ioc, le64_to_cpu(sas_device_pg0.SASAddress)); if (sas_device) { @@ -9554,7 +9589,8 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) handle, (u64)le64_to_cpu(sas_device_pg0.SASAddress)); mpt3sas_transport_update_links(ioc, sas_address, handle, - sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); + sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5, + mpt3sas_get_port_by_id(ioc, port_id)); retry_count = 0; /* This will retry adding the end device. * _scsih_add_device() will decide on retries and @@ -9997,7 +10033,7 @@ _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc, } mpt3sas_transport_port_remove(ioc, sas_expander->sas_address, - sas_expander->sas_address_parent); + sas_expander->sas_address_parent, sas_expander->port); ioc_info(ioc, "expander_remove: handle(0x%04x), sas_addr(0x%016llx)\n", sas_expander->handle, (unsigned long long) @@ -10341,6 +10377,7 @@ _scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc) unsigned long flags; int rc; int tid; + struct hba_port *port; /* no Bios, return immediately */ if (!ioc->bios_pg3.BiosVersion) @@ -10382,19 +10419,24 @@ _scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc) handle = sas_device->handle; sas_address_parent = sas_device->sas_address_parent; sas_address = sas_device->sas_address; + port = sas_device->port; list_move_tail(&sas_device->list, &ioc->sas_device_list); spin_unlock_irqrestore(&ioc->sas_device_lock, flags); if (ioc->hide_drives) return; + + if (!port) + return; + if (!mpt3sas_transport_port_add(ioc, handle, - sas_address_parent)) { + sas_address_parent, port)) { _scsih_sas_device_remove(ioc, sas_device); } else if (!sas_device->starget) { if (!ioc->is_driver_loading) { mpt3sas_transport_port_remove(ioc, sas_address, - sas_address_parent); + sas_address_parent, port); _scsih_sas_device_remove(ioc, sas_device); } } @@ -10482,7 +10524,7 @@ _scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc) while ((sas_device = get_next_sas_device(ioc))) { if (!mpt3sas_transport_port_add(ioc, sas_device->handle, - sas_device->sas_address_parent)) { + sas_device->sas_address_parent, sas_device->port)) { _scsih_sas_device_remove(ioc, sas_device); sas_device_put(sas_device); continue; @@ -10496,7 +10538,8 @@ _scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc) if (!ioc->is_driver_loading) { mpt3sas_transport_port_remove(ioc, sas_device->sas_address, - sas_device->sas_address_parent); + sas_device->sas_address_parent, + sas_device->port); _scsih_sas_device_remove(ioc, sas_device); sas_device_put(sas_device); continue; diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index 6ec5b7f33dfd..aab3b1451e31 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -594,6 +594,7 @@ _transport_sanity_check(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node, * @ioc: per adapter object * @handle: handle of attached device * @sas_address: sas address of parent expander or sas host + * @port: hba port entry * Context: This function will acquire ioc->sas_node_lock. * * Adding new port object to the sas_node->sas_port_list. @@ -602,7 +603,7 @@ _transport_sanity_check(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node, */ struct _sas_port * mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, - u64 sas_address) + u64 sas_address, struct hba_port *hba_port) { struct _sas_phy *mpt3sas_phy, *next; struct _sas_port *mpt3sas_port; @@ -613,6 +614,12 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, int i; struct sas_port *port; + if (!hba_port) { + ioc_err(ioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return NULL; + } + mpt3sas_port = kzalloc(sizeof(struct _sas_port), GFP_KERNEL); if (!mpt3sas_port) { @@ -646,6 +653,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, goto out_fail; } + mpt3sas_port->hba_port = hba_port; _transport_sanity_check(ioc, sas_node, mpt3sas_port->remote_identify.sas_address); @@ -653,8 +661,12 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, if (sas_node->phy[i].remote_identify.sas_address != mpt3sas_port->remote_identify.sas_address) continue; + if (sas_node->phy[i].port != hba_port) + continue; list_add_tail(&sas_node->phy[i].port_siblings, &mpt3sas_port->phy_list); + if (sas_node->handle <= ioc->sas_hba.num_phys) + hba_port->phy_mask |= (1 << i); mpt3sas_port->num_phys++; } @@ -686,14 +698,21 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, mpt3sas_phy->phy_id); sas_port_add_phy(port, mpt3sas_phy->phy); mpt3sas_phy->phy_belongs_to_port = 1; + mpt3sas_phy->port = hba_port; } mpt3sas_port->port = port; - if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) + if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) { rphy = sas_end_device_alloc(port); - else + if (sas_node->handle <= ioc->sas_hba.num_phys) + hba_port->sas_address = sas_device->sas_address; + } else { rphy = sas_expander_alloc(port, mpt3sas_port->remote_identify.device_type); + if (sas_node->handle <= ioc->sas_hba.num_phys) + hba_port->sas_address = + mpt3sas_port->remote_identify.sas_address; + } rphy->identify = mpt3sas_port->remote_identify; @@ -751,6 +770,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, * @ioc: per adapter object * @sas_address: sas address of attached device * @sas_address_parent: sas address of parent expander or sas host + * @port: hba port entry * Context: This function will acquire ioc->sas_node_lock. * * Removing object and freeing associated memory from the @@ -758,7 +778,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, */ void mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, - u64 sas_address_parent) + u64 sas_address_parent, struct hba_port *port) { int i; unsigned long flags; @@ -766,6 +786,10 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, struct _sas_node *sas_node; u8 found = 0; struct _sas_phy *mpt3sas_phy, *next_phy; + struct hba_port *hba_port_next, *hba_port = NULL; + + if (!port) + return; spin_lock_irqsave(&ioc->sas_node_lock, flags); sas_node = _transport_sas_node_find_by_sas_address(ioc, @@ -778,6 +802,8 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, port_list) { if (mpt3sas_port->remote_identify.sas_address != sas_address) continue; + if (mpt3sas_port->hba_port != port) + continue; found = 1; list_del(&mpt3sas_port->port_list); goto out; @@ -788,6 +814,21 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, return; } + if (sas_node->handle <= ioc->sas_hba.num_phys) { + list_for_each_entry_safe(hba_port, hba_port_next, + &ioc->port_table_list, list) { + if (hba_port != port) + continue; + if (hba_port->sas_address != sas_address) + continue; + ioc_info(ioc, + "remove hba_port entry: %p port: %d from hba_port list\n", + hba_port, hba_port->port_id); + list_del(&hba_port->list); + kfree(hba_port); + } + } + for (i = 0; i < sas_node->num_phys; i++) { if (sas_node->phy[i].remote_identify.sas_address == sas_address) memset(&sas_node->phy[i].remote_identify, 0 , @@ -961,14 +1002,19 @@ mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy * @handle: attached device handle * @phy_number: phy number * @link_rate: new link rate + * @port: hba port entry + * + * Return nothing. */ void mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address, u16 handle, u8 phy_number, u8 link_rate) + u64 sas_address, u16 handle, u8 phy_number, u8 link_rate, + struct hba_port *port) { unsigned long flags; struct _sas_node *sas_node; struct _sas_phy *mpt3sas_phy; + struct hba_port *hba_port = NULL; if (ioc->shost_recovery || ioc->pci_error_recovery) return; @@ -988,6 +1034,15 @@ mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc, &mpt3sas_phy->remote_identify); _transport_add_phy_to_an_existing_port(ioc, sas_node, mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address); + if (sas_node->handle <= ioc->sas_hba.num_phys) { + list_for_each_entry(hba_port, + &ioc->port_table_list, list) { + if (hba_port->sas_address == sas_address && + hba_port == port) + hba_port->phy_mask |= + (1 << mpt3sas_phy->phy_id); + } + } } else memset(&mpt3sas_phy->remote_identify, 0 , sizeof(struct sas_identify)); -- cgit v1.2.3 From 7d310f241001e090cf1ec0f3ae836b38d8c6ebec Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Tue, 27 Oct 2020 18:38:38 +0530 Subject: scsi: mpt3sas: Get device objects using sas_address & portID Currently driver retrieves the sas_device/sas_expander objects from corresponding object's lists using just device's SAS Address. Make driver retrieve the objects from the corresponding objects list using device's SAS Address and PhysicalPort (or PortID) number. PhysicalPort number is the port number of the HBA through which this device is accessed. Link: https://lore.kernel.org/r/20201027130847.9962-6-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 16 ++- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 175 +++++++++++++++++++++---------- drivers/scsi/mpt3sas/mpt3sas_transport.c | 74 ++++++++----- 3 files changed, 178 insertions(+), 87 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index aef872aa509d..b5d1fc5b665b 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1652,20 +1652,26 @@ int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle); void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle); -void mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address); +void mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, + struct hba_port *port); void mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address); + u64 sas_address, struct hba_port *port); u8 mpt3sas_check_for_pending_internal_cmds(struct MPT3SAS_ADAPTER *ioc, u16 smid); +struct hba_port * +mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, u8 port); struct _sas_node *mpt3sas_scsih_expander_find_by_handle( struct MPT3SAS_ADAPTER *ioc, u16 handle); struct _sas_node *mpt3sas_scsih_expander_find_by_sas_address( - struct MPT3SAS_ADAPTER *ioc, u64 sas_address); + struct MPT3SAS_ADAPTER *ioc, u64 sas_address, + struct hba_port *port); struct _sas_device *mpt3sas_get_sdev_by_addr( - struct MPT3SAS_ADAPTER *ioc, u64 sas_address); + struct MPT3SAS_ADAPTER *ioc, u64 sas_address, + struct hba_port *port); struct _sas_device *__mpt3sas_get_sdev_by_addr( - struct MPT3SAS_ADAPTER *ioc, u64 sas_address); + struct MPT3SAS_ADAPTER *ioc, u64 sas_address, + struct hba_port *port); struct _sas_device *mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle); struct _pcie_device *mpt3sas_get_pdev_by_handle(struct MPT3SAS_ADAPTER *ioc, diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 11cb9619c01c..0bc68cde2f42 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -638,48 +638,67 @@ mpt3sas_get_pdev_from_target(struct MPT3SAS_ADAPTER *ioc, return ret; } +/** + * mpt3sas_get_sdev_by_addr - get _sas_device object corresponding to provided + * sas address from sas_device_list list + * @ioc: per adapter object + * @port: port number + * + * Search for _sas_device object corresponding to provided sas address, + * if available return _sas_device object address otherwise return NULL. + */ struct _sas_device * __mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address) + u64 sas_address, struct hba_port *port) { struct _sas_device *sas_device; + if (!port) + return NULL; + assert_spin_locked(&ioc->sas_device_lock); - list_for_each_entry(sas_device, &ioc->sas_device_list, list) - if (sas_device->sas_address == sas_address) - goto found_device; + list_for_each_entry(sas_device, &ioc->sas_device_list, list) { + if (sas_device->sas_address != sas_address) + continue; + if (sas_device->port != port) + continue; + sas_device_get(sas_device); + return sas_device; + } - list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) - if (sas_device->sas_address == sas_address) - goto found_device; + list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) { + if (sas_device->sas_address != sas_address) + continue; + if (sas_device->port != port) + continue; + sas_device_get(sas_device); + return sas_device; + } return NULL; - -found_device: - sas_device_get(sas_device); - return sas_device; } /** * mpt3sas_get_sdev_by_addr - sas device search * @ioc: per adapter object * @sas_address: sas address + * @port: hba port entry * Context: Calling function should acquire ioc->sas_device_lock * - * This searches for sas_device based on sas_address, then return sas_device - * object. + * This searches for sas_device based on sas_address & port number, + * then return sas_device object. */ struct _sas_device * mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address) + u64 sas_address, struct hba_port *port) { struct _sas_device *sas_device; unsigned long flags; spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_device = __mpt3sas_get_sdev_by_addr(ioc, - sas_address); + sas_address, port); spin_unlock_irqrestore(&ioc->sas_device_lock, flags); return sas_device; @@ -848,13 +867,17 @@ _scsih_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) } /** - * mpt3sas_device_remove_by_sas_address - removing device object by sas address + * mpt3sas_device_remove_by_sas_address - removing device object by + * sas address & port number * @ioc: per adapter object * @sas_address: device sas_address + * @port: hba port entry + * + * Return nothing. */ void mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address) + u64 sas_address, struct hba_port *port) { struct _sas_device *sas_device; unsigned long flags; @@ -863,7 +886,7 @@ mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc, return; spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_addr(ioc, sas_address); + sas_device = __mpt3sas_get_sdev_by_addr(ioc, sas_address, port); if (sas_device) { list_del_init(&sas_device->list); sas_device_put(sas_device); @@ -1457,21 +1480,26 @@ out: * mpt3sas_scsih_expander_find_by_sas_address - expander device search * @ioc: per adapter object * @sas_address: sas address + * @port: hba port entry * Context: Calling function should acquire ioc->sas_node_lock. * - * This searches for expander device based on sas_address, then returns the - * sas_node object. + * This searches for expander device based on sas_address & port number, + * then returns the sas_node object. */ struct _sas_node * mpt3sas_scsih_expander_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address) + u64 sas_address, struct hba_port *port) { - struct _sas_node *sas_expander, *r; + struct _sas_node *sas_expander, *r = NULL; + + if (!port) + return r; - r = NULL; list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { if (sas_expander->sas_address != sas_address) continue; + if (sas_expander->port != port) + continue; r = sas_expander; goto out; } @@ -1788,7 +1816,7 @@ scsih_target_alloc(struct scsi_target *starget) spin_lock_irqsave(&ioc->sas_device_lock, flags); rphy = dev_to_rphy(starget->dev.parent); sas_device = __mpt3sas_get_sdev_by_addr(ioc, - rphy->identify.sas_address); + rphy->identify.sas_address, NULL); if (sas_device) { sas_target_priv_data->handle = sas_device->handle; @@ -1949,7 +1977,8 @@ scsih_slave_alloc(struct scsi_device *sdev) } else if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_device = __mpt3sas_get_sdev_by_addr(ioc, - sas_target_priv_data->sas_address); + sas_target_priv_data->sas_address, + sas_target_priv_data->port); if (sas_device && (sas_device->starget == NULL)) { sdev_printk(KERN_INFO, sdev, "%s : sas_device->starget set to starget @ %d\n", @@ -2554,7 +2583,8 @@ scsih_slave_configure(struct scsi_device *sdev) spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_device = __mpt3sas_get_sdev_by_addr(ioc, - sas_device_priv_data->sas_target->sas_address); + sas_device_priv_data->sas_target->sas_address, + sas_device_priv_data->sas_target->port); if (!sas_device) { spin_unlock_irqrestore(&ioc->sas_device_lock, flags); dfailprintk(ioc, @@ -3669,11 +3699,13 @@ _scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc) * _scsih_ublock_io_device - prepare device to be deleted * @ioc: per adapter object * @sas_address: sas address + * @port: hba port entry * * unblock then put device in offline state */ static void -_scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address) +_scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, + u64 sas_address, struct hba_port *port) { struct MPT3SAS_DEVICE *sas_device_priv_data; struct scsi_device *sdev; @@ -3685,6 +3717,8 @@ _scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address) if (sas_device_priv_data->sas_target->sas_address != sas_address) continue; + if (sas_device_priv_data->sas_target->port != port) + continue; if (sas_device_priv_data->block) _scsih_internal_device_unblock(sdev, sas_device_priv_data); @@ -3785,7 +3819,8 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT3SAS_ADAPTER *ioc, SAS_END_DEVICE) { spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_device = __mpt3sas_get_sdev_by_addr(ioc, - mpt3sas_port->remote_identify.sas_address); + mpt3sas_port->remote_identify.sas_address, + mpt3sas_port->hba_port); if (sas_device) { set_bit(sas_device->handle, ioc->blocking_handles); @@ -3804,7 +3839,8 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT3SAS_ADAPTER *ioc, SAS_FANOUT_EXPANDER_DEVICE) { expander_sibling = mpt3sas_scsih_expander_find_by_sas_address( - ioc, mpt3sas_port->remote_identify.sas_address); + ioc, mpt3sas_port->remote_identify.sas_address, + mpt3sas_port->hba_port); _scsih_block_io_to_children_attached_to_ex(ioc, expander_sibling); } @@ -3893,6 +3929,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) struct _tr_list *delayed_tr; u32 ioc_state; u8 tr_method = 0; + struct hba_port *port = NULL; if (ioc->pci_error_recovery) { dewtprintk(ioc, @@ -3921,6 +3958,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) sas_target_priv_data = sas_device->starget->hostdata; sas_target_priv_data->deleted = 1; sas_address = sas_device->sas_address; + port = sas_device->port; } spin_unlock_irqrestore(&ioc->sas_device_lock, flags); if (!sas_device) { @@ -3968,7 +4006,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) pcie_device->enclosure_level, pcie_device->connector_name)); } - _scsih_ublock_io_device(ioc, sas_address); + _scsih_ublock_io_device(ioc, sas_address, port); sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE; } @@ -6036,7 +6074,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) if (sas_address_parent != ioc->sas_hba.sas_address) { spin_lock_irqsave(&ioc->sas_node_lock, flags); sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc, - sas_address_parent); + sas_address_parent, mpt3sas_get_port_by_id(ioc, port_id)); spin_unlock_irqrestore(&ioc->sas_node_lock, flags); if (!sas_expander) { rc = _scsih_expander_add(ioc, parent_handle); @@ -6048,7 +6086,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) spin_lock_irqsave(&ioc->sas_node_lock, flags); sas_address = le64_to_cpu(expander_pg0.SASAddress); sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc, - sas_address); + sas_address, mpt3sas_get_port_by_id(ioc, port_id)); spin_unlock_irqrestore(&ioc->sas_node_lock, flags); if (sas_expander) @@ -6149,7 +6187,8 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) * @sas_address: expander sas_address */ void -mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address) +mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, + struct hba_port *port) { struct _sas_node *sas_expander; unsigned long flags; @@ -6157,9 +6196,12 @@ mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address) if (ioc->shost_recovery) return; + if (!port) + return; + spin_lock_irqsave(&ioc->sas_node_lock, flags); sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc, - sas_address); + sas_address, port); spin_unlock_irqrestore(&ioc->sas_node_lock, flags); if (sas_expander) _scsih_expander_node_remove(ioc, sas_expander); @@ -6282,7 +6324,7 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, { Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t sas_device_pg0; - struct _sas_device *sas_device; + struct _sas_device *sas_device = NULL; struct _enclosure_node *enclosure_dev = NULL; u32 ioc_status; unsigned long flags; @@ -6290,6 +6332,7 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, struct scsi_target *starget; struct MPT3SAS_TARGET *sas_target_priv_data; u32 device_info; + struct hba_port *port; if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) @@ -6312,8 +6355,11 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_address = le64_to_cpu(sas_device_pg0.SASAddress); + port = mpt3sas_get_port_by_id(ioc, sas_device_pg0.PhysicalPort); + if (!port) + goto out_unlock; sas_device = __mpt3sas_get_sdev_by_addr(ioc, - sas_address); + sas_address, port); if (!sas_device) goto out_unlock; @@ -6369,7 +6415,7 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, goto out_unlock; spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - _scsih_ublock_io_device(ioc, sas_address); + _scsih_ublock_io_device(ioc, sas_address, port); if (sas_device) sas_device_put(sas_device); @@ -6442,7 +6488,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, port_id = sas_device_pg0.PhysicalPort; sas_device = mpt3sas_get_sdev_by_addr(ioc, - sas_address); + sas_address, mpt3sas_get_port_by_id(ioc, port_id)); if (sas_device) { clear_bit(handle, ioc->pend_os_device_add); sas_device_put(sas_device); @@ -6555,7 +6601,8 @@ _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc, if (sas_device->starget && sas_device->starget->hostdata) { sas_target_priv_data = sas_device->starget->hostdata; sas_target_priv_data->deleted = 1; - _scsih_ublock_io_device(ioc, sas_device->sas_address); + _scsih_ublock_io_device(ioc, sas_device->sas_address, + sas_device->port); sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE; } @@ -6787,7 +6834,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, /* handle expander removal */ if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING && sas_expander) - mpt3sas_expander_remove(ioc, sas_address); + mpt3sas_expander_remove(ioc, sas_address, port); return 0; } @@ -6888,7 +6935,7 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc, spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_address = le64_to_cpu(event_data->SASAddress); sas_device = __mpt3sas_get_sdev_by_addr(ioc, - sas_address); + sas_address, mpt3sas_get_port_by_id(ioc, event_data->PhysicalPort)); if (!sas_device || !sas_device->starget) goto out; @@ -7037,7 +7084,7 @@ _scsih_pcie_device_remove_from_sml(struct MPT3SAS_ADAPTER *ioc, if (pcie_device->starget && pcie_device->starget->hostdata) { sas_target_priv_data = pcie_device->starget->hostdata; sas_target_priv_data->deleted = 1; - _scsih_ublock_io_device(ioc, pcie_device->wwid); + _scsih_ublock_io_device(ioc, pcie_device->wwid, NULL); sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE; } @@ -7159,7 +7206,7 @@ _scsih_pcie_check_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) spin_unlock_irqrestore(&ioc->pcie_device_lock, flags); pcie_device_put(pcie_device); - _scsih_ublock_io_device(ioc, wwid); + _scsih_ublock_io_device(ioc, wwid, NULL); return; } @@ -8762,6 +8809,8 @@ Mpi2SasDevicePage0_t *sas_device_pg0) struct _sas_device *sas_device = NULL; struct _enclosure_node *enclosure_dev = NULL; unsigned long flags; + struct hba_port *port = mpt3sas_get_port_by_id( + ioc, sas_device_pg0->PhysicalPort); if (sas_device_pg0->EnclosureHandle) { enclosure_dev = @@ -8778,6 +8827,8 @@ Mpi2SasDevicePage0_t *sas_device_pg0) continue; if (sas_device->slot != le16_to_cpu(sas_device_pg0->Slot)) continue; + if (sas_device->port != port) + continue; sas_device->responding = 1; starget = sas_device->starget; if (starget && starget->hostdata) { @@ -9186,6 +9237,8 @@ _scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc, u16 handle = le16_to_cpu(expander_pg0->DevHandle); u16 enclosure_handle = le16_to_cpu(expander_pg0->EnclosureHandle); u64 sas_address = le64_to_cpu(expander_pg0->SASAddress); + struct hba_port *port = mpt3sas_get_port_by_id( + ioc, expander_pg0->PhysicalPort); if (enclosure_handle) enclosure_dev = @@ -9196,6 +9249,8 @@ _scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc, list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { if (sas_expander->sas_address != sas_address) continue; + if (sas_expander->port != port) + continue; sas_expander->responding = 1; if (enclosure_dev) { @@ -9252,9 +9307,10 @@ _scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc) handle = le16_to_cpu(expander_pg0.DevHandle); sas_address = le64_to_cpu(expander_pg0.SASAddress); - pr_info("\texpander present: handle(0x%04x), sas_addr(0x%016llx)\n", - handle, - (unsigned long long)sas_address); + pr_info( + "\texpander present: handle(0x%04x), sas_addr(0x%016llx), port:%d\n", + handle, (unsigned long long)sas_address, + expander_pg0.PhysicalPort); _scsih_mark_responding_expander(ioc, &expander_pg0); } @@ -9426,8 +9482,10 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) } handle = le16_to_cpu(expander_pg0.DevHandle); spin_lock_irqsave(&ioc->sas_node_lock, flags); + port_id = expander_pg0.PhysicalPort; expander_device = mpt3sas_scsih_expander_find_by_sas_address( - ioc, le64_to_cpu(expander_pg0.SASAddress)); + ioc, le64_to_cpu(expander_pg0.SASAddress), + mpt3sas_get_port_by_id(ioc, port_id)); spin_unlock_irqrestore(&ioc->sas_node_lock, flags); if (expander_device) _scsih_refresh_expander_links(ioc, expander_device, @@ -9578,7 +9636,8 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) continue; port_id = sas_device_pg0.PhysicalPort; sas_device = mpt3sas_get_sdev_by_addr(ioc, - le64_to_cpu(sas_device_pg0.SASAddress)); + le64_to_cpu(sas_device_pg0.SASAddress), + mpt3sas_get_port_by_id(ioc, port_id)); if (sas_device) { sas_device_put(sas_device); continue; @@ -10023,21 +10082,25 @@ _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc, if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) mpt3sas_device_remove_by_sas_address(ioc, - mpt3sas_port->remote_identify.sas_address); + mpt3sas_port->remote_identify.sas_address, + mpt3sas_port->hba_port); else if (mpt3sas_port->remote_identify.device_type == SAS_EDGE_EXPANDER_DEVICE || mpt3sas_port->remote_identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) mpt3sas_expander_remove(ioc, - mpt3sas_port->remote_identify.sas_address); + mpt3sas_port->remote_identify.sas_address, + mpt3sas_port->hba_port); } mpt3sas_transport_port_remove(ioc, sas_expander->sas_address, sas_expander->sas_address_parent, sas_expander->port); - ioc_info(ioc, "expander_remove: handle(0x%04x), sas_addr(0x%016llx)\n", - sas_expander->handle, (unsigned long long) - sas_expander->sas_address); + ioc_info(ioc, + "expander_remove: handle(0x%04x), sas_addr(0x%016llx), port:%d\n", + sas_expander->handle, (unsigned long long) + sas_expander->sas_address, + sas_expander->port->port_id); spin_lock_irqsave(&ioc->sas_node_lock, flags); list_del(&sas_expander->list); @@ -10283,13 +10346,15 @@ static void scsih_remove(struct pci_dev *pdev) if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) mpt3sas_device_remove_by_sas_address(ioc, - mpt3sas_port->remote_identify.sas_address); + mpt3sas_port->remote_identify.sas_address, + mpt3sas_port->hba_port); else if (mpt3sas_port->remote_identify.device_type == SAS_EDGE_EXPANDER_DEVICE || mpt3sas_port->remote_identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) mpt3sas_expander_remove(ioc, - mpt3sas_port->remote_identify.sas_address); + mpt3sas_port->remote_identify.sas_address, + mpt3sas_port->hba_port); } list_for_each_entry_safe(port, port_next, diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index aab3b1451e31..54c004e96170 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -64,6 +64,7 @@ * _transport_sas_node_find_by_sas_address - sas node search * @ioc: per adapter object * @sas_address: sas address of expander or sas host + * @port: hba port entry * Context: Calling function should acquire ioc->sas_node_lock. * * Search for either hba phys or expander device based on handle, then returns @@ -71,13 +72,13 @@ */ static struct _sas_node * _transport_sas_node_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address) + u64 sas_address, struct hba_port *port) { if (ioc->sas_hba.sas_address == sas_address) return &ioc->sas_hba; else return mpt3sas_scsih_expander_find_by_sas_address(ioc, - sas_address); + sas_address, port); } /** @@ -439,6 +440,7 @@ _transport_delete_port(struct MPT3SAS_ADAPTER *ioc, struct _sas_port *mpt3sas_port) { u64 sas_address = mpt3sas_port->remote_identify.sas_address; + struct hba_port *port = mpt3sas_port->hba_port; enum sas_device_type device_type = mpt3sas_port->remote_identify.device_type; @@ -448,10 +450,11 @@ _transport_delete_port(struct MPT3SAS_ADAPTER *ioc, ioc->logging_level |= MPT_DEBUG_TRANSPORT; if (device_type == SAS_END_DEVICE) - mpt3sas_device_remove_by_sas_address(ioc, sas_address); + mpt3sas_device_remove_by_sas_address(ioc, + sas_address, port); else if (device_type == SAS_EDGE_EXPANDER_DEVICE || device_type == SAS_FANOUT_EXPANDER_DEVICE) - mpt3sas_expander_remove(ioc, sas_address); + mpt3sas_expander_remove(ioc, sas_address, port); ioc->logging_level &= ~MPT_DEBUG_TRANSPORT; } @@ -571,18 +574,21 @@ _transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc, * @ioc: per adapter object * @sas_node: sas node object (either expander or sas host) * @sas_address: sas address of device being added + * @port: hba port entry * * See the explanation above from _transport_delete_duplicate_port */ static void _transport_sanity_check(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node, - u64 sas_address) + u64 sas_address, struct hba_port *port) { int i; for (i = 0; i < sas_node->num_phys; i++) { if (sas_node->phy[i].remote_identify.sas_address != sas_address) continue; + if (sas_node->phy[i].port != port) + continue; if (sas_node->phy[i].phy_belongs_to_port == 1) _transport_del_phy_from_an_existing_port(ioc, sas_node, &sas_node->phy[i]); @@ -631,7 +637,8 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, INIT_LIST_HEAD(&mpt3sas_port->port_list); INIT_LIST_HEAD(&mpt3sas_port->phy_list); spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address); + sas_node = _transport_sas_node_find_by_sas_address(ioc, + sas_address, hba_port); spin_unlock_irqrestore(&ioc->sas_node_lock, flags); if (!sas_node) { @@ -655,7 +662,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, mpt3sas_port->hba_port = hba_port; _transport_sanity_check(ioc, sas_node, - mpt3sas_port->remote_identify.sas_address); + mpt3sas_port->remote_identify.sas_address, hba_port); for (i = 0; i < sas_node->num_phys; i++) { if (sas_node->phy[i].remote_identify.sas_address != @@ -676,6 +683,18 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, goto out_fail; } + if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) { + sas_device = mpt3sas_get_sdev_by_addr(ioc, + mpt3sas_port->remote_identify.sas_address, + mpt3sas_port->hba_port); + if (!sas_device) { + ioc_err(ioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out_fail; + } + sas_device->pend_sas_rphy_add = 1; + } + if (!sas_node->parent_dev) { ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); @@ -716,18 +735,6 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, rphy->identify = mpt3sas_port->remote_identify; - if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) { - sas_device = mpt3sas_get_sdev_by_addr(ioc, - mpt3sas_port->remote_identify.sas_address); - if (!sas_device) { - dfailprintk(ioc, - ioc_info(ioc, "failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__)); - goto out_fail; - } - sas_device->pend_sas_rphy_add = 1; - } - if ((sas_rphy_add(rphy))) { ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); @@ -793,7 +800,7 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, spin_lock_irqsave(&ioc->sas_node_lock, flags); sas_node = _transport_sas_node_find_by_sas_address(ioc, - sas_address_parent); + sas_address_parent, port); if (!sas_node) { spin_unlock_irqrestore(&ioc->sas_node_lock, flags); return; @@ -1020,7 +1027,8 @@ mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc, return; spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address); + sas_node = _transport_sas_node_find_by_sas_address(ioc, + sas_address, port); if (!sas_node) { spin_unlock_irqrestore(&ioc->sas_node_lock, flags); return; @@ -1267,10 +1275,13 @@ _transport_get_linkerrors(struct sas_phy *phy) unsigned long flags; Mpi2ConfigReply_t mpi_reply; Mpi2SasPhyPage1_t phy_pg1; + struct hba_port *port = phy->hostdata; + int port_id = port->port_id; spin_lock_irqsave(&ioc->sas_node_lock, flags); if (_transport_sas_node_find_by_sas_address(ioc, - phy->identify.sas_address) == NULL) { + phy->identify.sas_address, + mpt3sas_get_port_by_id(ioc, port_id)) == NULL) { spin_unlock_irqrestore(&ioc->sas_node_lock, flags); return -EINVAL; } @@ -1321,7 +1332,7 @@ _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_device = __mpt3sas_get_sdev_by_addr(ioc, - rphy->identify.sas_address); + rphy->identify.sas_address, 0); if (sas_device) { *identifier = sas_device->enclosure_logical_id; rc = 0; @@ -1351,7 +1362,7 @@ _transport_get_bay_identifier(struct sas_rphy *rphy) spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_device = __mpt3sas_get_sdev_by_addr(ioc, - rphy->identify.sas_address); + rphy->identify.sas_address, 0); if (sas_device) { rc = sas_device->slot; sas_device_put(sas_device); @@ -1554,11 +1565,14 @@ _transport_phy_reset(struct sas_phy *phy, int hard_reset) struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy); Mpi2SasIoUnitControlReply_t mpi_reply; Mpi2SasIoUnitControlRequest_t mpi_request; + struct hba_port *port = phy->hostdata; + int port_id = port->port_id; unsigned long flags; spin_lock_irqsave(&ioc->sas_node_lock, flags); if (_transport_sas_node_find_by_sas_address(ioc, - phy->identify.sas_address) == NULL) { + phy->identify.sas_address, + mpt3sas_get_port_by_id(ioc, port_id)) == NULL) { spin_unlock_irqrestore(&ioc->sas_node_lock, flags); return -EINVAL; } @@ -1611,10 +1625,13 @@ _transport_phy_enable(struct sas_phy *phy, int enable) int rc = 0; unsigned long flags; int i, discovery_active; + struct hba_port *port = phy->hostdata; + int port_id = port->port_id; spin_lock_irqsave(&ioc->sas_node_lock, flags); if (_transport_sas_node_find_by_sas_address(ioc, - phy->identify.sas_address) == NULL) { + phy->identify.sas_address, + mpt3sas_get_port_by_id(ioc, port_id)) == NULL) { spin_unlock_irqrestore(&ioc->sas_node_lock, flags); return -EINVAL; } @@ -1748,10 +1765,13 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) int i; int rc = 0; unsigned long flags; + struct hba_port *port = phy->hostdata; + int port_id = port->port_id; spin_lock_irqsave(&ioc->sas_node_lock, flags); if (_transport_sas_node_find_by_sas_address(ioc, - phy->identify.sas_address) == NULL) { + phy->identify.sas_address, + mpt3sas_get_port_by_id(ioc, port_id)) == NULL) { spin_unlock_irqrestore(&ioc->sas_node_lock, flags); return -EINVAL; } -- cgit v1.2.3 From c71ccf93c00c0cef062c2371e9a614526fee9adb Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Tue, 27 Oct 2020 18:38:39 +0530 Subject: scsi: mpt3sas: Rename transport_del_phy_from_an_existing_port() Renamed _transport_add_phy_to_an_existing_port() to mpt3sas_transport_add_phy_to_an_existing_port() and _transport_del_phy_from_an_existing_port() to mpt3sas_transport_del_phy_from_an_existing_port() as the driver needs to call these functions from outside mpt3sas_transport.c file. Added extra function argument 'port' of type struct hba_port to above functions and check for portID before adding/removing the phy from the _sas_port object. I.e. add/remove the phy from _sas_port object only if _sas_port's port object and phy's port object are the same. Link: https://lore.kernel.org/r/20201027130847.9962-7-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 7 +++++++ drivers/scsi/mpt3sas/mpt3sas_transport.c | 35 +++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index b5d1fc5b665b..24db6273e5f5 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1811,6 +1811,13 @@ void mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc, struct hba_port *port); extern struct sas_function_template mpt3sas_transport_functions; extern struct scsi_transport_template *mpt3sas_transport_template; +void +mpt3sas_transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc, + struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy); +void +mpt3sas_transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc, + struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy, + u64 sas_address, struct hba_port *port); /* trigger data externs */ void mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc, struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data); diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index 54c004e96170..560ce323646f 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -503,16 +503,17 @@ _transport_add_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_port *mpt3sas_port, } /** - * _transport_add_phy_to_an_existing_port - adding new phy to existing port + * mpt3sas_transport_add_phy_to_an_existing_port - adding new phy to existing port * @ioc: per adapter object * @sas_node: sas node object (either expander or sas host) * @mpt3sas_phy: mpt3sas per phy object * @sas_address: sas address of device/expander were phy needs to be added to + * @port: hba port entry */ -static void -_transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc, +void +mpt3sas_transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy, - u64 sas_address) + u64 sas_address, struct hba_port *port) { struct _sas_port *mpt3sas_port; struct _sas_phy *phy_srch; @@ -520,11 +521,16 @@ _transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc, if (mpt3sas_phy->phy_belongs_to_port == 1) return; + if (!port) + return; + list_for_each_entry(mpt3sas_port, &sas_node->sas_port_list, port_list) { if (mpt3sas_port->remote_identify.sas_address != sas_address) continue; + if (mpt3sas_port->hba_port != port) + continue; list_for_each_entry(phy_srch, &mpt3sas_port->phy_list, port_siblings) { if (phy_srch == mpt3sas_phy) @@ -537,13 +543,13 @@ _transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc, } /** - * _transport_del_phy_from_an_existing_port - delete phy from existing port + * mpt3sas_transport_del_phy_from_an_existing_port - delete phy from existing port * @ioc: per adapter object * @sas_node: sas node object (either expander or sas host) * @mpt3sas_phy: mpt3sas per phy object */ -static void -_transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc, +void +mpt3sas_transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy) { struct _sas_port *mpt3sas_port, *next; @@ -559,7 +565,11 @@ _transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc, if (phy_srch != mpt3sas_phy) continue; - if (mpt3sas_port->num_phys == 1) + /* + * Don't delete port during host reset, + * just delete phy. + */ + if (mpt3sas_port->num_phys == 1 && !ioc->shost_recovery) _transport_delete_port(ioc, mpt3sas_port); else _transport_delete_phy(ioc, mpt3sas_port, @@ -590,8 +600,8 @@ _transport_sanity_check(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node, if (sas_node->phy[i].port != port) continue; if (sas_node->phy[i].phy_belongs_to_port == 1) - _transport_del_phy_from_an_existing_port(ioc, sas_node, - &sas_node->phy[i]); + mpt3sas_transport_del_phy_from_an_existing_port(ioc, + sas_node, &sas_node->phy[i]); } } @@ -1040,8 +1050,6 @@ mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc, if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) { _transport_set_identify(ioc, handle, &mpt3sas_phy->remote_identify); - _transport_add_phy_to_an_existing_port(ioc, sas_node, - mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address); if (sas_node->handle <= ioc->sas_hba.num_phys) { list_for_each_entry(hba_port, &ioc->port_table_list, list) { @@ -1051,6 +1059,9 @@ mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc, (1 << mpt3sas_phy->phy_id); } } + mpt3sas_transport_add_phy_to_an_existing_port(ioc, sas_node, + mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address, + port); } else memset(&mpt3sas_phy->remote_identify, 0 , sizeof(struct sas_identify)); -- cgit v1.2.3 From 6df6be9168f50369ba843f2a12fe8537effbaff1 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Tue, 27 Oct 2020 18:38:40 +0530 Subject: scsi: mpt3sas: Get sas_device objects using device's rphy In the following scsi_host_template and sas_function_template callback functions the driver does not have PhysicalPort number information to retrieve the sas_device object using SAS Address & PhysicalPort number. In these callback functions the device's rphy object is used to retrieve sas_device object for the device. .target_alloc, .get_enclosure_identifier .get_bay_identifier When a rphy (of type sas_rphy) object is allocated then its address is saved in corresponding sas_device object's rphy field. In __mpt3sas_get_sdev_by_rphy(), the driver loops over all the sas_device objects from sas_device_list list to retrieve the sas_device objects whose rphy matches the provided rphy. Link: https://lore.kernel.org/r/20201027130847.9962-8-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 5 ++++ drivers/scsi/mpt3sas/mpt3sas_scsih.c | 41 ++++++++++++++++++++++++++++++-- drivers/scsi/mpt3sas/mpt3sas_transport.c | 7 +++--- 3 files changed, 47 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 24db6273e5f5..047d234cc784 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -537,6 +537,8 @@ struct _internal_cmd { * @chassis_slot: chassis slot * @is_chassis_slot_valid: chassis slot valid or not * @port: hba port entry containing device's port number info + * @rphy: device's sas_rphy address used to identify this device structure in + * target_alloc callback function */ struct _sas_device { struct list_head list; @@ -564,6 +566,7 @@ struct _sas_device { u8 connector_name[5]; struct kref refcount; struct hba_port *port; + struct sas_rphy *rphy; }; static inline void sas_device_get(struct _sas_device *s) @@ -1681,6 +1684,8 @@ void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc); struct _raid_device * mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle); void mpt3sas_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth); +struct _sas_device * +__mpt3sas_get_sdev_by_rphy(struct MPT3SAS_ADAPTER *ioc, struct sas_rphy *rphy); /* config shared API */ u8 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 0bc68cde2f42..50eea398c23e 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -638,6 +638,44 @@ mpt3sas_get_pdev_from_target(struct MPT3SAS_ADAPTER *ioc, return ret; } + +/** + * __mpt3sas_get_sdev_by_rphy - sas device search + * @ioc: per adapter object + * @rphy: sas_rphy pointer + * + * Context: This function will acquire ioc->sas_device_lock and will release + * before returning the sas_device object. + * + * This searches for sas_device from rphy object + * then return sas_device object. + */ +struct _sas_device * +__mpt3sas_get_sdev_by_rphy(struct MPT3SAS_ADAPTER *ioc, + struct sas_rphy *rphy) +{ + struct _sas_device *sas_device; + + assert_spin_locked(&ioc->sas_device_lock); + + list_for_each_entry(sas_device, &ioc->sas_device_list, list) { + if (sas_device->rphy != rphy) + continue; + sas_device_get(sas_device); + return sas_device; + } + + sas_device = NULL; + list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) { + if (sas_device->rphy != rphy) + continue; + sas_device_get(sas_device); + return sas_device; + } + + return NULL; +} + /** * mpt3sas_get_sdev_by_addr - get _sas_device object corresponding to provided * sas address from sas_device_list list @@ -1815,8 +1853,7 @@ scsih_target_alloc(struct scsi_target *starget) /* sas/sata devices */ spin_lock_irqsave(&ioc->sas_device_lock, flags); rphy = dev_to_rphy(starget->dev.parent); - sas_device = __mpt3sas_get_sdev_by_addr(ioc, - rphy->identify.sas_address, NULL); + sas_device = __mpt3sas_get_sdev_by_rphy(ioc, rphy); if (sas_device) { sas_target_priv_data->handle = sas_device->handle; diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index 560ce323646f..3cc78c214ec4 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -733,6 +733,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, mpt3sas_port->port = port; if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) { rphy = sas_end_device_alloc(port); + sas_device->rphy = rphy; if (sas_node->handle <= ioc->sas_hba.num_phys) hba_port->sas_address = sas_device->sas_address; } else { @@ -1342,8 +1343,7 @@ _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) int rc; spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_addr(ioc, - rphy->identify.sas_address, 0); + sas_device = __mpt3sas_get_sdev_by_rphy(ioc, rphy); if (sas_device) { *identifier = sas_device->enclosure_logical_id; rc = 0; @@ -1372,8 +1372,7 @@ _transport_get_bay_identifier(struct sas_rphy *rphy) int rc; spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_addr(ioc, - rphy->identify.sas_address, 0); + sas_device = __mpt3sas_get_sdev_by_rphy(ioc, rphy); if (sas_device) { rc = sas_device->slot; sas_device_put(sas_device); -- cgit v1.2.3 From a5e99fda017218516d3c66bec5ed346283ae722b Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Tue, 27 Oct 2020 18:38:41 +0530 Subject: scsi: mpt3sas: Update hba_port objects after host reset During host reset there is a chance that the Port number allocated by the firmware for the attached devices may change. Also, it may be possible that some HBA phy's can go down/come up after reset. As a result, the driver can't just trust the HBA Port table that it has populated before host reset as valid. Instead it has to update the HBA Port table in such a way that it shouldn't disturb the drives which are still accessible even after host reset. Use the following algorithm to update the HBA Port table during host reset: I. After host reset operation and before marking the devices as responding/non-responding, create a temporary Port table called "New Port table" by parsing each of the HBA phy's Phy data info read from SAS IOUnit Page0: a. Check whether Phy's negotiated link rate is greater than 1.5Gbps, if not go to next Phy; b. Get the SAS Address of the attached device; c. Create a new entry in the "New Port table" with SAS Address field filled with attached device's SAS Address, port number with Phy's Port number (read from SAS IOUnit Page0) and enable bit in the 'Phy mask' field corresponding to current Phy number. New entry is created only if the driver can't find an entry in the "New Port table" which matches with attached device 'SAS Address' & 'Port Number'. If it finds an entry with matches with attached device 'SAS Address' & 'Port Number' then the driver takes that matched entry and will enable current Phy number bit in the 'Phy mask' field; d. After parsing all the HBA phy's info, the driver will have complete Port table info in "New Port table". II. Mark all the existing sas_device & sas_expander device structures as 'dirty'. III. Mark each entry of the HBA Port lists as 'dirty'. IV. Take each entry from 'New Port table' one by one and check whether the entry has any corresponding matched entry (which is marked as 'dirty') in the HBA Port table or not. While looking for a corresponding matched entry, look for matched entry in the sequence from top row to bottom row listed in the following table. If you find any matched entry (according to any of the rules tabulated below) then perform the action mentioned in the 'Action' column in that matched rule. =========================================================================== |Search |SAS | Phy Mask | Port | Possibilities| Action | |every |Address | or | Number | | required | |entry |matched?| subset of| matched?| | | |in below| | phy mask | | | | |sequence| | matched? | | | | =========================================================================== | 1 |matched | matched | matched | nothing |* unmark HBA port | | | | | | changed |table entry as | | | | | | |dirty | --------------------------------------------------------------------------- | 2 |matched | matched | not | port number |* Update port | | | | | matched | is changed |number in the | | | | | | |matched port table | | | | | | |entry | | | | | | |* unmask HBA port | | | | | | |table entry as | | | | | | |dirty | --------------------------------------------------------------------------- | 3.a |matched | subset of| matched |some phys |* Add these new | | | | phy mask | (or) |might have |phys to current | | | | matched | not |enabled which |port in STL | | | | | matched |are previously|* Update phy mask | | | | | (but |disabled |field in HBA's port| | | | | first | |table's matched | | | | | look for| |entry, | | | | | matched | |* Update port | | | | | one) | |number in the | | | | | | |matched port | | | | | | |table entry (if | | | | | | |port number is | | | | | | |changed), | | | | | | |* Unmask HBA port | | | | | | |table entry as | | | | | | |dirty | --------------------------------------------------------------------------- | 3.b |matched | subset of| matched |some phys |*Remove these phys | | | | phy mask | (or) |might have |from current port | | | | matched | not |disabled which|in STL | | | | | matched |are previously|* Update phy mask | | | | | (but |enabled |field in HBA's port| | | | | first | |tables's matched | | | | | look for| |entry, | | | | | matched | |*Update port number| | | | | one) | |in the matched port| | | | | | |table entry (if | | | | | | |port number is | | | | | | |changed), | | | | | | |* Unmask HBA port | | | | | | |table entry as | | | | | | |dirty | --------------------------------------------------------------------------- | 4 |matched | not | matched |A cable |*Remove old phys & | | | | matched | (or) |attached to an|new phys to current| | | | | not |expander is |port in STL | | | | | matched |changed to |* Update phy mask | | | | | |another HBA |field in HBA's port| | | | | |port during |tables's matched | | | | | |reset |entry, | | | | | | |*Update port number| | | | | | |in the matched port| | | | | | |table entry (if | | | | | | |port number is | | | | | | |changed), | | | | | | |* Unmask HBA port | | | | | | |table entry as | | | | | | |dirty | --------------------------------------------------------------------------- V. Delete the hba_port objects which are still marked as dirty. Link: https://lore.kernel.org/r/20201027130847.9962-9-sreekanth.reddy@broadcom.com Reported-by: kernel test robot Reported-by: Dan Carpenter Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 338 +++++++++++++++++++++++++++++++++++ 1 file changed, 338 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 50eea398c23e..289faef0058a 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -5816,6 +5816,342 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) return 0; } +/** + * _scsih_get_port_table_after_reset - Construct temporary port table + * @ioc: per adapter object + * @port_table: address where port table needs to be constructed + * + * return number of HBA port entries available after reset. + */ +static int +_scsih_get_port_table_after_reset(struct MPT3SAS_ADAPTER *ioc, + struct hba_port *port_table) +{ + u16 sz, ioc_status; + int i, j; + Mpi2ConfigReply_t mpi_reply; + Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; + u16 attached_handle; + u64 attached_sas_addr; + u8 found = 0, port_count = 0, port_id; + + sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys + * sizeof(Mpi2SasIOUnit0PhyData_t)); + sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); + if (!sas_iounit_pg0) { + ioc_err(ioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return port_count; + } + + if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, + sas_iounit_pg0, sz)) != 0) + goto out; + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) + goto out; + for (i = 0; i < ioc->sas_hba.num_phys; i++) { + found = 0; + if ((sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4) < + MPI2_SAS_NEG_LINK_RATE_1_5) + continue; + attached_handle = + le16_to_cpu(sas_iounit_pg0->PhyData[i].AttachedDevHandle); + if (_scsih_get_sas_address( + ioc, attached_handle, &attached_sas_addr) != 0) { + ioc_err(ioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + continue; + } + + for (j = 0; j < port_count; j++) { + port_id = sas_iounit_pg0->PhyData[i].Port; + if (port_table[j].port_id == port_id && + port_table[j].sas_address == attached_sas_addr) { + port_table[j].phy_mask |= (1 << i); + found = 1; + break; + } + } + + if (found) + continue; + + port_id = sas_iounit_pg0->PhyData[i].Port; + port_table[port_count].port_id = port_id; + port_table[port_count].phy_mask = (1 << i); + port_table[port_count].sas_address = attached_sas_addr; + port_count++; + } +out: + kfree(sas_iounit_pg0); + return port_count; +} + +enum hba_port_matched_codes { + NOT_MATCHED = 0, + MATCHED_WITH_ADDR_AND_PHYMASK, + MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT, + MATCHED_WITH_ADDR_AND_SUBPHYMASK, + MATCHED_WITH_ADDR, +}; + +/** + * _scsih_look_and_get_matched_port_entry - Get matched hba port entry + * from HBA port table + * @ioc: per adapter object + * @port_entry - hba port entry from temporary port table which needs to be + * searched for matched entry in the HBA port table + * @matched_port_entry - save matched hba port entry here + * @count - count of matched entries + * + * return type of matched entry found. + */ +static enum hba_port_matched_codes +_scsih_look_and_get_matched_port_entry(struct MPT3SAS_ADAPTER *ioc, + struct hba_port *port_entry, + struct hba_port **matched_port_entry, int *count) +{ + struct hba_port *port_table_entry, *matched_port = NULL; + enum hba_port_matched_codes matched_code = NOT_MATCHED; + int lcount = 0; + *matched_port_entry = NULL; + + list_for_each_entry(port_table_entry, &ioc->port_table_list, list) { + if (!(port_table_entry->flags & HBA_PORT_FLAG_DIRTY_PORT)) + continue; + + if ((port_table_entry->sas_address == port_entry->sas_address) + && (port_table_entry->phy_mask == port_entry->phy_mask)) { + matched_code = MATCHED_WITH_ADDR_AND_PHYMASK; + matched_port = port_table_entry; + break; + } + + if ((port_table_entry->sas_address == port_entry->sas_address) + && (port_table_entry->phy_mask & port_entry->phy_mask) + && (port_table_entry->port_id == port_entry->port_id)) { + matched_code = MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT; + matched_port = port_table_entry; + continue; + } + + if ((port_table_entry->sas_address == port_entry->sas_address) + && (port_table_entry->phy_mask & port_entry->phy_mask)) { + if (matched_code == + MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT) + continue; + matched_code = MATCHED_WITH_ADDR_AND_SUBPHYMASK; + matched_port = port_table_entry; + continue; + } + + if (port_table_entry->sas_address == port_entry->sas_address) { + if (matched_code == + MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT) + continue; + if (matched_code == MATCHED_WITH_ADDR_AND_SUBPHYMASK) + continue; + matched_code = MATCHED_WITH_ADDR; + matched_port = port_table_entry; + lcount++; + } + } + + *matched_port_entry = matched_port; + if (matched_code == MATCHED_WITH_ADDR) + *count = lcount; + return matched_code; +} + +/** + * _scsih_del_phy_part_of_anther_port - remove phy if it + * is a part of anther port + *@ioc: per adapter object + *@port_table: port table after reset + *@index: hba port entry index + *@port_count: number of ports available after host reset + *@offset: HBA phy bit offset + * + */ +static void +_scsih_del_phy_part_of_anther_port(struct MPT3SAS_ADAPTER *ioc, + struct hba_port *port_table, + int index, u8 port_count, int offset) +{ + struct _sas_node *sas_node = &ioc->sas_hba; + u32 i, found = 0; + + for (i = 0; i < port_count; i++) { + if (i == index) + continue; + + if (port_table[i].phy_mask & (1 << offset)) { + mpt3sas_transport_del_phy_from_an_existing_port( + ioc, sas_node, &sas_node->phy[offset]); + found = 1; + break; + } + } + if (!found) + port_table[index].phy_mask |= (1 << offset); +} + +/** + * _scsih_add_or_del_phys_from_existing_port - add/remove phy to/from + * right port + *@ioc: per adapter object + *@hba_port_entry: hba port table entry + *@port_table: temporary port table + *@index: hba port entry index + *@port_count: number of ports available after host reset + * + */ +static void +_scsih_add_or_del_phys_from_existing_port(struct MPT3SAS_ADAPTER *ioc, + struct hba_port *hba_port_entry, struct hba_port *port_table, + int index, int port_count) +{ + u32 phy_mask, offset = 0; + struct _sas_node *sas_node = &ioc->sas_hba; + + phy_mask = hba_port_entry->phy_mask ^ port_table[index].phy_mask; + + for (offset = 0; offset < ioc->sas_hba.num_phys; offset++) { + if (phy_mask & (1 << offset)) { + if (!(port_table[index].phy_mask & (1 << offset))) { + _scsih_del_phy_part_of_anther_port( + ioc, port_table, index, port_count, + offset); + continue; + } + if (sas_node->phy[offset].phy_belongs_to_port) + mpt3sas_transport_del_phy_from_an_existing_port( + ioc, sas_node, &sas_node->phy[offset]); + mpt3sas_transport_add_phy_to_an_existing_port( + ioc, sas_node, &sas_node->phy[offset], + hba_port_entry->sas_address, + hba_port_entry); + } + } +} + +/** + * _scsih_del_dirty_port_entries - delete dirty port entries from port list + * after host reset + *@ioc: per adapter object + * + */ +static void +_scsih_del_dirty_port_entries(struct MPT3SAS_ADAPTER *ioc) +{ + struct hba_port *port, *port_next; + + list_for_each_entry_safe(port, port_next, + &ioc->port_table_list, list) { + if (!(port->flags & HBA_PORT_FLAG_DIRTY_PORT) || + port->flags & HBA_PORT_FLAG_NEW_PORT) + continue; + + drsprintk(ioc, ioc_info(ioc, + "Deleting port table entry %p having Port: %d\t Phy_mask 0x%08x\n", + port, port->port_id, port->phy_mask)); + list_del(&port->list); + kfree(port); + } +} + +/** + * _scsih_sas_port_refresh - Update HBA port table after host reset + * @ioc: per adapter object + */ +static void +_scsih_sas_port_refresh(struct MPT3SAS_ADAPTER *ioc) +{ + u32 port_count = 0; + struct hba_port *port_table; + struct hba_port *port_table_entry; + struct hba_port *port_entry = NULL; + int i, j, count = 0, lcount = 0; + int ret; + u64 sas_addr; + + drsprintk(ioc, ioc_info(ioc, + "updating ports for sas_host(0x%016llx)\n", + (unsigned long long)ioc->sas_hba.sas_address)); + + port_table = kcalloc(ioc->sas_hba.num_phys, + sizeof(struct hba_port), GFP_KERNEL); + if (!port_table) + return; + + port_count = _scsih_get_port_table_after_reset(ioc, port_table); + if (!port_count) + return; + + drsprintk(ioc, ioc_info(ioc, "New Port table\n")); + for (j = 0; j < port_count; j++) + drsprintk(ioc, ioc_info(ioc, + "Port: %d\t Phy_mask 0x%08x\t sas_addr(0x%016llx)\n", + port_table[j].port_id, + port_table[j].phy_mask, port_table[j].sas_address)); + + list_for_each_entry(port_table_entry, &ioc->port_table_list, list) + port_table_entry->flags |= HBA_PORT_FLAG_DIRTY_PORT; + + drsprintk(ioc, ioc_info(ioc, "Old Port table\n")); + port_table_entry = NULL; + list_for_each_entry(port_table_entry, &ioc->port_table_list, list) { + drsprintk(ioc, ioc_info(ioc, + "Port: %d\t Phy_mask 0x%08x\t sas_addr(0x%016llx)\n", + port_table_entry->port_id, + port_table_entry->phy_mask, + port_table_entry->sas_address)); + } + + for (j = 0; j < port_count; j++) { + ret = _scsih_look_and_get_matched_port_entry(ioc, + &port_table[j], &port_entry, &count); + if (!port_entry) { + drsprintk(ioc, ioc_info(ioc, + "No Matched entry for sas_addr(0x%16llx), Port:%d\n", + port_table[j].sas_address, + port_table[j].port_id)); + continue; + } + + switch (ret) { + case MATCHED_WITH_ADDR_SUBPHYMASK_AND_PORT: + case MATCHED_WITH_ADDR_AND_SUBPHYMASK: + _scsih_add_or_del_phys_from_existing_port(ioc, + port_entry, port_table, j, port_count); + break; + case MATCHED_WITH_ADDR: + sas_addr = port_table[j].sas_address; + for (i = 0; i < port_count; i++) { + if (port_table[i].sas_address == sas_addr) + lcount++; + } + + if (count > 1 || lcount > 1) + port_entry = NULL; + else + _scsih_add_or_del_phys_from_existing_port(ioc, + port_entry, port_table, j, port_count); + } + + if (!port_entry) + continue; + + if (port_entry->port_id != port_table[j].port_id) + port_entry->port_id = port_table[j].port_id; + port_entry->flags &= ~HBA_PORT_FLAG_DIRTY_PORT; + port_entry->phy_mask = port_table[j].phy_mask; + } + + port_table_entry = NULL; +} + /** * _scsih_sas_host_refresh - refreshing sas host object contents * @ioc: per adapter object @@ -9790,6 +10126,7 @@ mpt3sas_scsih_reset_done_handler(struct MPT3SAS_ADAPTER *ioc) dtmprintk(ioc, ioc_info(ioc, "%s: MPT3_IOC_DONE_RESET\n", __func__)); if ((!ioc->is_driver_loading) && !(disable_discovery > 0 && !ioc->sas_hba.num_phys)) { + _scsih_sas_port_refresh(ioc); _scsih_prep_device_scan(ioc); _scsih_create_enclosure_list_after_reset(ioc); _scsih_search_responding_sas_devices(ioc); @@ -9837,6 +10174,7 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) ssleep(1); } _scsih_remove_unresponding_devices(ioc); + _scsih_del_dirty_port_entries(ioc); _scsih_scan_for_devices_after_reset(ioc); _scsih_set_nvme_max_shutdown_latency(ioc); break; -- cgit v1.2.3 From 9d0348a9d8e35142b809d0b92534312a22f6fd78 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Tue, 27 Oct 2020 18:38:42 +0530 Subject: scsi: mpt3sas: Set valid PhysicalPort in SMPPassThrough The driver currently sets PhysicalPort field to 0xFF for SMPPassthrough Request message. In zoning topologies this SMPPassthrough command always operates on devices in one zone (default zone) even when user issues SMP command for other zone drives. Define _transport_get_port_id_by_rphy() and _transport_get_port_id_by_sas_phy() helper functions to get Physical Port number from sas_rphy & sas_phy respectively for SMPPassthrough request message so that SMP Passthrough request message is sent to intended zone device. Link: https://lore.kernel.org/r/20201027130847.9962-10-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 + drivers/scsi/mpt3sas/mpt3sas_scsih.c | 1 + drivers/scsi/mpt3sas/mpt3sas_transport.c | 75 +++++++++++++++++++++++++++++--- 3 files changed, 72 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 047d234cc784..a8e42d1ba2e5 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -788,6 +788,7 @@ struct _sas_phy { * @phy: a list of phys that make up this sas_host/expander * @sas_port_list: list of ports attached to this sas_host/expander * @port: hba port entry containing node's port number info + * @rphy: sas_rphy object of this expander */ struct _sas_node { struct list_head list; @@ -802,6 +803,7 @@ struct _sas_node { struct hba_port *port; struct _sas_phy *phy; struct list_head sas_port_list; + struct sas_rphy *rphy; }; /** diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 289faef0058a..020687e5cc8f 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -6510,6 +6510,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) goto out_fail; } sas_expander->parent_dev = &mpt3sas_port->rphy->dev; + sas_expander->rphy = mpt3sas_port->rphy; for (i = 0 ; i < sas_expander->num_phys ; i++) { if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply, diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index 3cc78c214ec4..d52d8b3161f2 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -60,6 +60,24 @@ #include "mpt3sas_base.h" +/** + * _transport_get_port_id_by_sas_phy - get zone's port id that Phy belong to + * @phy - sas_phy object + * + * Return Port number + */ +static inline u8 +_transport_get_port_id_by_sas_phy(struct sas_phy *phy) +{ + u8 port_id = 0xFF; + struct hba_port *port = phy->hostdata; + + if (port) + port_id = port->port_id; + + return port_id; +} + /** * _transport_sas_node_find_by_sas_address - sas node search * @ioc: per adapter object @@ -81,6 +99,49 @@ _transport_sas_node_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc, sas_address, port); } +/** + * _transport_get_port_id_by_rphy - Get Port number from rphy object + * @ioc: per adapter object + * @rphy: sas_rphy object + * + * Returns Port number. + */ +static u8 +_transport_get_port_id_by_rphy(struct MPT3SAS_ADAPTER *ioc, + struct sas_rphy *rphy) +{ + struct _sas_node *sas_expander; + struct _sas_device *sas_device; + unsigned long flags; + u8 port_id = 0xFF; + + if (!rphy) + return port_id; + + if (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE || + rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) { + spin_lock_irqsave(&ioc->sas_node_lock, flags); + list_for_each_entry(sas_expander, + &ioc->sas_expander_list, list) { + if (sas_expander->rphy == rphy) { + port_id = sas_expander->port->port_id; + break; + } + } + spin_unlock_irqrestore(&ioc->sas_node_lock, flags); + } else if (rphy->identify.device_type == SAS_END_DEVICE) { + spin_lock_irqsave(&ioc->sas_device_lock, flags); + sas_device = __mpt3sas_get_sdev_by_rphy(ioc, rphy); + if (sas_device) { + port_id = sas_device->port->port_id; + sas_device_put(sas_device); + } + spin_unlock_irqrestore(&ioc->sas_device_lock, flags); + } + + return port_id; +} + /** * _transport_convert_phy_link_rate - * @link_rate: link rate returned from mpt firmware @@ -289,7 +350,7 @@ struct rep_manu_reply { */ static int _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address, struct sas_expander_device *edev) + u64 sas_address, struct sas_expander_device *edev, u8 port_id) { Mpi2SmpPassthroughRequest_t *mpi_request; Mpi2SmpPassthroughReply_t *mpi_reply; @@ -356,7 +417,7 @@ _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc, memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; - mpi_request->PhysicalPort = 0xFF; + mpi_request->PhysicalPort = port_id; mpi_request->SASAddress = cpu_to_le64(sas_address); mpi_request->RequestDataLength = cpu_to_le16(data_out_sz); psge = &mpi_request->SGL; @@ -772,7 +833,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) _transport_expander_report_manufacture(ioc, mpt3sas_port->remote_identify.sas_address, - rphy_to_expander_device(rphy)); + rphy_to_expander_device(rphy), hba_port->port_id); return mpt3sas_port; out_fail: @@ -923,6 +984,7 @@ mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); phy->maximum_linkrate = _transport_convert_phy_link_rate( phy_pg0.ProgrammedLinkRate >> 4); + phy->hostdata = mpt3sas_phy->port; if ((sas_phy_add(phy))) { ioc_err(ioc, "failure at %s:%d/%s()!\n", @@ -993,6 +1055,7 @@ mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); phy->maximum_linkrate = _transport_convert_phy_link_rate( expander_pg1.ProgrammedLinkRate >> 4); + phy->hostdata = mpt3sas_phy->port; if ((sas_phy_add(phy))) { ioc_err(ioc, "failure at %s:%d/%s()!\n", @@ -1197,7 +1260,7 @@ _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc, memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; - mpi_request->PhysicalPort = 0xFF; + mpi_request->PhysicalPort = _transport_get_port_id_by_sas_phy(phy); mpi_request->VF_ID = 0; /* TODO */ mpi_request->VP_ID = 0; mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address); @@ -1493,7 +1556,7 @@ _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc, memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; - mpi_request->PhysicalPort = 0xFF; + mpi_request->PhysicalPort = _transport_get_port_id_by_sas_phy(phy); mpi_request->VF_ID = 0; /* TODO */ mpi_request->VP_ID = 0; mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address); @@ -1983,7 +2046,7 @@ _transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost, memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; - mpi_request->PhysicalPort = 0xFF; + mpi_request->PhysicalPort = _transport_get_port_id_by_rphy(ioc, rphy); mpi_request->SASAddress = (rphy) ? cpu_to_le64(rphy->identify.sas_address) : cpu_to_le64(ioc->sas_hba.sas_address); -- cgit v1.2.3 From ccc59923ba8d44ecf7cb60135e9934bbb619da10 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Tue, 27 Oct 2020 18:38:43 +0530 Subject: scsi: mpt3sas: Handling HBA vSES device Each direct attached device will have a unique Port ID, but with an exception. HBA vSES may use the same Port ID of another direct attached device Port's ID. As a result, special handling is needed for vSES. Create a virtual_phy object when a new HBA vSES device is detected and add this virtual_phy object to vphys_list of port ID's hba_port object. When the HBA vSES device is removed then remove the corresponding virtual_phy object from its parent's hba_port's vphy_list and free this virtual_vphy object. In hba_port object add vphy_mask field to hold the list of HBA phy bits which are assigned to vSES devices. Also add vphy_list list to hold list of virtual_phy objects which holds the same portID of current hba_port's portID. Also, add a hba_vphy field in _sas_phy object to determine whether this _sas_phy object belongs to vSES device or not. - Allocate a virtual_phy object whenever a virtual phy is detected while processing the SASIOUnitPage0's phy data. And this allocated virtual_phy object to corresponding PortID's hba_port's vphy_list. - When a vSES device is added to the SML then initialize the corresponding virtual_phy objects's sas_address field with vSES device's SAS Address. - Free this virtual_phy object during driver unload time and when this vSES device is removed. Link: https://lore.kernel.org/r/20201027130847.9962-11-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 23 +++++++ drivers/scsi/mpt3sas/mpt3sas_scsih.c | 106 +++++++++++++++++++++++++++++++ drivers/scsi/mpt3sas/mpt3sas_transport.c | 80 +++++++++++++++++++---- 3 files changed, 198 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index a8e42d1ba2e5..e7d047adbe86 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -771,6 +771,7 @@ struct _sas_phy { u16 handle; u16 attached_handle; u8 phy_belongs_to_port; + u8 hba_vphy; struct hba_port *port; }; @@ -1023,12 +1024,29 @@ struct reply_post_struct { dma_addr_t reply_post_free_dma; }; +/** + * struct virtual_phy - vSES phy structure + * sas_address: SAS Address of vSES device + * phy_mask: vSES device's phy number + * flags: flags used to manage this structure + */ +struct virtual_phy { + struct list_head list; + u64 sas_address; + u32 phy_mask; + u8 flags; +}; + +#define MPT_VPHY_FLAG_DIRTY_PHY 0x01 + /** * struct hba_port - Saves each HBA's Wide/Narrow port info * @sas_address: sas address of this wide/narrow port's attached device * @phy_mask: HBA PHY's belonging to this port * @port_id: port number * @flags: hba port flags + * @vphys_mask : mask of vSES devices Phy number + * @vphys_list : list containing vSES device structures */ struct hba_port { struct list_head list; @@ -1036,6 +1054,8 @@ struct hba_port { u32 phy_mask; u8 port_id; u8 flags; + u32 vphys_mask; + struct list_head vphys_list; }; /* hba port flags */ @@ -1688,6 +1708,9 @@ mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle); void mpt3sas_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth); struct _sas_device * __mpt3sas_get_sdev_by_rphy(struct MPT3SAS_ADAPTER *ioc, struct sas_rphy *rphy); +struct virtual_phy * +mpt3sas_get_vphy_by_phy(struct MPT3SAS_ADAPTER *ioc, + struct hba_port *port, u32 phy); /* config shared API */ u8 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 020687e5cc8f..1b880f1c3be6 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -380,6 +380,30 @@ mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, u8 port_id) return NULL; } +/** + * mpt3sas_get_vphy_by_phy - get virtual_phy object corresponding to phy number + * @ioc: per adapter object + * @port: hba_port object + * @phy: phy number + * + * Return virtual_phy object corresponding to phy number. + */ +struct virtual_phy * +mpt3sas_get_vphy_by_phy(struct MPT3SAS_ADAPTER *ioc, + struct hba_port *port, u32 phy) +{ + struct virtual_phy *vphy, *vphy_next; + + if (!port->vphys_mask) + return NULL; + + list_for_each_entry_safe(vphy, vphy_next, &port->vphys_list, list) { + if (vphy->phy_mask & (1 << phy)) + return vphy; + } + return NULL; +} + /** * _scsih_is_boot_device - search for matching boot device. * @sas_address: sas address @@ -6152,6 +6176,47 @@ _scsih_sas_port_refresh(struct MPT3SAS_ADAPTER *ioc) port_table_entry = NULL; } +/** + * _scsih_alloc_vphy - allocate virtual_phy object + * @ioc: per adapter object + * @port_id: Port ID number + * @phy_num: HBA Phy number + * + * Returns allocated virtual_phy object. + */ +static struct virtual_phy * +_scsih_alloc_vphy(struct MPT3SAS_ADAPTER *ioc, u8 port_id, u8 phy_num) +{ + struct virtual_phy *vphy; + struct hba_port *port; + + port = mpt3sas_get_port_by_id(ioc, port_id); + if (!port) + return NULL; + + vphy = mpt3sas_get_vphy_by_phy(ioc, port, phy_num); + if (!vphy) { + vphy = kzalloc(sizeof(struct virtual_phy), GFP_KERNEL); + if (!vphy) + return NULL; + + /* + * Enable bit corresponding to HBA phy number on its + * parent hba_port object's vphys_mask field. + */ + port->vphys_mask |= (1 << phy_num); + vphy->phy_mask |= (1 << phy_num); + + INIT_LIST_HEAD(&port->vphys_list); + list_add_tail(&vphy->list, &port->vphys_list); + + ioc_info(ioc, + "vphy entry: %p, port id: %d, phy:%d is added to port's vphys_list\n", + vphy, port->port_id, phy_num); + } + return vphy; +} + /** * _scsih_sas_host_refresh - refreshing sas host object contents * @ioc: per adapter object @@ -6172,6 +6237,7 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc) u16 attached_handle; u8 link_rate, port_id; struct hba_port *port; + Mpi2SasPhyPage0_t phy_pg0; dtmprintk(ioc, ioc_info(ioc, "updating handles for sas_host(0x%016llx)\n", @@ -6211,6 +6277,31 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc) port->flags = HBA_PORT_FLAG_NEW_PORT; list_add_tail(&port->list, &ioc->port_table_list); } + /* + * Check whether current Phy belongs to HBA vSES device or not. + */ + if (le32_to_cpu(sas_iounit_pg0->PhyData[i].ControllerPhyDeviceInfo) & + MPI2_SAS_DEVICE_INFO_SEP && + (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) { + if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, + &phy_pg0, i))) { + ioc_err(ioc, + "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out; + } + if (!(le32_to_cpu(phy_pg0.PhyInfo) & + MPI2_SAS_PHYINFO_VIRTUAL_PHY)) + continue; + /* + * Allocate a virtual_phy object for vSES device, if + * this vSES device is hot added. + */ + if (!_scsih_alloc_vphy(ioc, port_id, i)) + goto out; + ioc->sas_hba.phy[i].hba_vphy = 1; + } + ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i]. AttachedDevHandle); @@ -6353,6 +6444,21 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc) &ioc->port_table_list); } + /* + * Check whether current Phy belongs to HBA vSES device or not. + */ + if ((le32_to_cpu(phy_pg0.PhyInfo) & + MPI2_SAS_PHYINFO_VIRTUAL_PHY) && + (phy_pg0.NegotiatedLinkRate >> 4) >= + MPI2_SAS_NEG_LINK_RATE_1_5) { + /* + * Allocate a virtual_phy object for vSES device. + */ + if (!_scsih_alloc_vphy(ioc, port_id, i)) + goto out; + ioc->sas_hba.phy[i].hba_vphy = 1; + } + ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; ioc->sas_hba.phy[i].phy_id = i; ioc->sas_hba.phy[i].port = mpt3sas_get_port_by_id(ioc, port_id); diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index d52d8b3161f2..256dae106ec6 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -690,6 +690,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, struct _sas_device *sas_device = NULL; int i; struct sas_port *port; + struct virtual_phy *vphy = NULL; if (!hba_port) { ioc_err(ioc, "failure at %s:%d/%s()!\n", @@ -743,9 +744,20 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, continue; list_add_tail(&sas_node->phy[i].port_siblings, &mpt3sas_port->phy_list); - if (sas_node->handle <= ioc->sas_hba.num_phys) - hba_port->phy_mask |= (1 << i); mpt3sas_port->num_phys++; + if (sas_node->handle <= ioc->sas_hba.num_phys) { + if (!sas_node->phy[i].hba_vphy) { + hba_port->phy_mask |= (1 << i); + continue; + } + + vphy = mpt3sas_get_vphy_by_phy(ioc, hba_port, i); + if (!vphy) { + ioc_err(ioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + goto out_fail; + } + } } if (!mpt3sas_port->num_phys) { @@ -795,8 +807,14 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) { rphy = sas_end_device_alloc(port); sas_device->rphy = rphy; - if (sas_node->handle <= ioc->sas_hba.num_phys) - hba_port->sas_address = sas_device->sas_address; + if (sas_node->handle <= ioc->sas_hba.num_phys) { + if (!vphy) + hba_port->sas_address = + sas_device->sas_address; + else + vphy->sas_address = + sas_device->sas_address; + } } else { rphy = sas_expander_alloc(port, mpt3sas_port->remote_identify.device_type); @@ -866,6 +884,7 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, u8 found = 0; struct _sas_phy *mpt3sas_phy, *next_phy; struct hba_port *hba_port_next, *hba_port = NULL; + struct virtual_phy *vphy, *vphy_next = NULL; if (!port) return; @@ -894,17 +913,56 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, } if (sas_node->handle <= ioc->sas_hba.num_phys) { + if (port->vphys_mask) { + list_for_each_entry_safe(vphy, vphy_next, + &port->vphys_list, list) { + if (vphy->sas_address != sas_address) + continue; + ioc_info(ioc, + "remove vphy entry: %p of port:%p,from %d port's vphys list\n", + vphy, port, port->port_id); + port->vphys_mask &= ~vphy->phy_mask; + list_del(&vphy->list); + kfree(vphy); + } + } + list_for_each_entry_safe(hba_port, hba_port_next, &ioc->port_table_list, list) { if (hba_port != port) continue; - if (hba_port->sas_address != sas_address) - continue; - ioc_info(ioc, - "remove hba_port entry: %p port: %d from hba_port list\n", - hba_port, hba_port->port_id); - list_del(&hba_port->list); - kfree(hba_port); + /* + * Delete hba_port object if + * - hba_port object's sas address matches with current + * removed device's sas address and no vphy's + * associated with it. + * - Current removed device is a vSES device and + * none of the other direct attached device have + * this vSES device's port number (hence hba_port + * object sas_address field will be zero). + */ + if ((hba_port->sas_address == sas_address || + !hba_port->sas_address) && !hba_port->vphys_mask) { + ioc_info(ioc, + "remove hba_port entry: %p port: %d from hba_port list\n", + hba_port, hba_port->port_id); + list_del(&hba_port->list); + kfree(hba_port); + } else if (hba_port->sas_address == sas_address && + hba_port->vphys_mask) { + /* + * Current removed device is a non vSES device + * and a vSES device has the same port number + * as of current device's port number. Hence + * only clear the sas_address filed, don't + * delete the hba_port object. + */ + ioc_info(ioc, + "clearing sas_address from hba_port entry: %p port: %d from hba_port list\n", + hba_port, hba_port->port_id); + port->sas_address = 0; + } + break; } } -- cgit v1.2.3 From 34b0a78532f61e6059a26c0252fbc28c73761384 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Tue, 27 Oct 2020 18:38:44 +0530 Subject: scsi: mpt3sas: Add bypass_dirty_port_flag parameter Added a new parameter bypass_dirty_port_flag in function mpt3sas_get_port_by_id(). When this parameter is set to one then search for matching hba port entry from port_table_list even when this hba_port entry is marked as dirty. Link: https://lore.kernel.org/r/20201027130847.9962-12-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 3 +- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 63 +++++++++++++++++++------------- drivers/scsi/mpt3sas/mpt3sas_transport.c | 8 ++-- 3 files changed, 44 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index e7d047adbe86..cca14ab570f5 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1684,7 +1684,8 @@ void mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc, u8 mpt3sas_check_for_pending_internal_cmds(struct MPT3SAS_ADAPTER *ioc, u16 smid); struct hba_port * -mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, u8 port); +mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, u8 port, + u8 bypass_dirty_port_flag); struct _sas_node *mpt3sas_scsih_expander_find_by_handle( struct MPT3SAS_ADAPTER *ioc, u16 handle); diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 1b880f1c3be6..a35c5f33666c 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -361,20 +361,27 @@ _scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number, * port number from port list * @ioc: per adapter object * @port_id: port number + * @bypass_dirty_port_flag: when set look the matching hba port entry even + * if hba port entry is marked as dirty. * * Search for hba port entry corresponding to provided port number, * if available return port object otherwise return NULL. */ struct hba_port * -mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, u8 port_id) +mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, + u8 port_id, u8 bypass_dirty_port_flag) { struct hba_port *port, *port_next; list_for_each_entry_safe(port, port_next, &ioc->port_table_list, list) { - if (port->port_id == port_id && - !(port->flags & HBA_PORT_FLAG_DIRTY_PORT)) + if (port->port_id != port_id) + continue; + if (bypass_dirty_port_flag) return port; + if (port->flags & HBA_PORT_FLAG_DIRTY_PORT) + continue; + return port; } return NULL; @@ -6190,7 +6197,7 @@ _scsih_alloc_vphy(struct MPT3SAS_ADAPTER *ioc, u8 port_id, u8 phy_num) struct virtual_phy *vphy; struct hba_port *port; - port = mpt3sas_get_port_by_id(ioc, port_id); + port = mpt3sas_get_port_by_id(ioc, port_id, 0); if (!port) return NULL; @@ -6264,7 +6271,7 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc) ioc->sas_hba.handle = le16_to_cpu( sas_iounit_pg0->PhyData[0].ControllerDevHandle); port_id = sas_iounit_pg0->PhyData[i].Port; - if (!(mpt3sas_get_port_by_id(ioc, port_id))) { + if (!(mpt3sas_get_port_by_id(ioc, port_id, 0))) { port = kzalloc(sizeof(struct hba_port), GFP_KERNEL); if (!port) goto out; @@ -6307,7 +6314,8 @@ _scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc) AttachedDevHandle); if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5) link_rate = MPI2_SAS_NEG_LINK_RATE_1_5; - ioc->sas_hba.phy[i].port = mpt3sas_get_port_by_id(ioc, port_id); + ioc->sas_hba.phy[i].port = + mpt3sas_get_port_by_id(ioc, port_id, 0); mpt3sas_transport_update_links(ioc, ioc->sas_hba.sas_address, attached_handle, i, link_rate, ioc->sas_hba.phy[i].port); @@ -6431,7 +6439,7 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc) PhyData[0].ControllerDevHandle); port_id = sas_iounit_pg0->PhyData[i].Port; - if (!(mpt3sas_get_port_by_id(ioc, port_id))) { + if (!(mpt3sas_get_port_by_id(ioc, port_id, 0))) { port = kzalloc(sizeof(struct hba_port), GFP_KERNEL); if (!port) goto out; @@ -6461,7 +6469,8 @@ _scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc) ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; ioc->sas_hba.phy[i].phy_id = i; - ioc->sas_hba.phy[i].port = mpt3sas_get_port_by_id(ioc, port_id); + ioc->sas_hba.phy[i].port = + mpt3sas_get_port_by_id(ioc, port_id, 0); mpt3sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i], phy_pg0, ioc->sas_hba.parent_dev); } @@ -6553,7 +6562,8 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) if (sas_address_parent != ioc->sas_hba.sas_address) { spin_lock_irqsave(&ioc->sas_node_lock, flags); sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc, - sas_address_parent, mpt3sas_get_port_by_id(ioc, port_id)); + sas_address_parent, + mpt3sas_get_port_by_id(ioc, port_id, 0)); spin_unlock_irqrestore(&ioc->sas_node_lock, flags); if (!sas_expander) { rc = _scsih_expander_add(ioc, parent_handle); @@ -6565,7 +6575,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) spin_lock_irqsave(&ioc->sas_node_lock, flags); sas_address = le64_to_cpu(expander_pg0.SASAddress); sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc, - sas_address, mpt3sas_get_port_by_id(ioc, port_id)); + sas_address, mpt3sas_get_port_by_id(ioc, port_id, 0)); spin_unlock_irqrestore(&ioc->sas_node_lock, flags); if (sas_expander) @@ -6583,7 +6593,7 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) sas_expander->num_phys = expander_pg0.NumPhys; sas_expander->sas_address_parent = sas_address_parent; sas_expander->sas_address = sas_address; - sas_expander->port = mpt3sas_get_port_by_id(ioc, port_id); + sas_expander->port = mpt3sas_get_port_by_id(ioc, port_id, 0); if (!sas_expander->port) { ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); @@ -6628,7 +6638,8 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) } sas_expander->phy[i].handle = handle; sas_expander->phy[i].phy_id = i; - sas_expander->phy[i].port = mpt3sas_get_port_by_id(ioc, port_id); + sas_expander->phy[i].port = + mpt3sas_get_port_by_id(ioc, port_id, 0); if ((mpt3sas_transport_add_expander_phy(ioc, &sas_expander->phy[i], expander_pg1, @@ -6835,7 +6846,7 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_address = le64_to_cpu(sas_device_pg0.SASAddress); - port = mpt3sas_get_port_by_id(ioc, sas_device_pg0.PhysicalPort); + port = mpt3sas_get_port_by_id(ioc, sas_device_pg0.PhysicalPort, 0); if (!port) goto out_unlock; sas_device = __mpt3sas_get_sdev_by_addr(ioc, @@ -6968,7 +6979,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, port_id = sas_device_pg0.PhysicalPort; sas_device = mpt3sas_get_sdev_by_addr(ioc, - sas_address, mpt3sas_get_port_by_id(ioc, port_id)); + sas_address, mpt3sas_get_port_by_id(ioc, port_id, 0)); if (sas_device) { clear_bit(handle, ioc->pend_os_device_add); sas_device_put(sas_device); @@ -7009,7 +7020,7 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, sas_device->phy = sas_device_pg0.PhyNum; sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) & MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0; - sas_device->port = mpt3sas_get_port_by_id(ioc, port_id); + sas_device->port = mpt3sas_get_port_by_id(ioc, port_id, 0); if (!sas_device->port) { ioc_err(ioc, "failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); @@ -7224,7 +7235,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, } parent_handle = le16_to_cpu(event_data->ExpanderDevHandle); - port = mpt3sas_get_port_by_id(ioc, event_data->PhysicalPort); + port = mpt3sas_get_port_by_id(ioc, event_data->PhysicalPort, 0); /* handle expander add */ if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED) @@ -7415,7 +7426,8 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc, spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_address = le64_to_cpu(event_data->SASAddress); sas_device = __mpt3sas_get_sdev_by_addr(ioc, - sas_address, mpt3sas_get_port_by_id(ioc, event_data->PhysicalPort)); + sas_address, + mpt3sas_get_port_by_id(ioc, event_data->PhysicalPort, 0)); if (!sas_device || !sas_device->starget) goto out; @@ -8856,7 +8868,8 @@ _scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc, if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) mpt3sas_transport_update_links(ioc, sas_address, handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5, - mpt3sas_get_port_by_id(ioc, sas_device_pg0.PhysicalPort)); + mpt3sas_get_port_by_id(ioc, + sas_device_pg0.PhysicalPort, 0)); _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum); _scsih_add_device(ioc, handle, 0, 1); @@ -9164,7 +9177,7 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc, mpt3sas_transport_update_links(ioc, sas_address, handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5, mpt3sas_get_port_by_id(ioc, - sas_device_pg0.PhysicalPort)); + sas_device_pg0.PhysicalPort, 0)); _scsih_add_device(ioc, handle, 0, 1); @@ -9290,7 +9303,7 @@ Mpi2SasDevicePage0_t *sas_device_pg0) struct _enclosure_node *enclosure_dev = NULL; unsigned long flags; struct hba_port *port = mpt3sas_get_port_by_id( - ioc, sas_device_pg0->PhysicalPort); + ioc, sas_device_pg0->PhysicalPort, 0); if (sas_device_pg0->EnclosureHandle) { enclosure_dev = @@ -9718,7 +9731,7 @@ _scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc, u16 enclosure_handle = le16_to_cpu(expander_pg0->EnclosureHandle); u64 sas_address = le64_to_cpu(expander_pg0->SASAddress); struct hba_port *port = mpt3sas_get_port_by_id( - ioc, expander_pg0->PhysicalPort); + ioc, expander_pg0->PhysicalPort, 0); if (enclosure_handle) enclosure_dev = @@ -9965,7 +9978,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) port_id = expander_pg0.PhysicalPort; expander_device = mpt3sas_scsih_expander_find_by_sas_address( ioc, le64_to_cpu(expander_pg0.SASAddress), - mpt3sas_get_port_by_id(ioc, port_id)); + mpt3sas_get_port_by_id(ioc, port_id, 0)); spin_unlock_irqrestore(&ioc->sas_node_lock, flags); if (expander_device) _scsih_refresh_expander_links(ioc, expander_device, @@ -10028,7 +10041,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) mpt3sas_transport_update_links(ioc, sas_address, handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5, - mpt3sas_get_port_by_id(ioc, port_id)); + mpt3sas_get_port_by_id(ioc, port_id, 0)); set_bit(handle, ioc->pd_handles); retry_count = 0; /* This will retry adding the end device. @@ -10117,7 +10130,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) port_id = sas_device_pg0.PhysicalPort; sas_device = mpt3sas_get_sdev_by_addr(ioc, le64_to_cpu(sas_device_pg0.SASAddress), - mpt3sas_get_port_by_id(ioc, port_id)); + mpt3sas_get_port_by_id(ioc, port_id, 0)); if (sas_device) { sas_device_put(sas_device); continue; @@ -10129,7 +10142,7 @@ _scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) (u64)le64_to_cpu(sas_device_pg0.SASAddress)); mpt3sas_transport_update_links(ioc, sas_address, handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5, - mpt3sas_get_port_by_id(ioc, port_id)); + mpt3sas_get_port_by_id(ioc, port_id, 0)); retry_count = 0; /* This will retry adding the end device. * _scsih_add_device() will decide on retries and diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index 256dae106ec6..0d06025d7102 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -1414,7 +1414,7 @@ _transport_get_linkerrors(struct sas_phy *phy) spin_lock_irqsave(&ioc->sas_node_lock, flags); if (_transport_sas_node_find_by_sas_address(ioc, phy->identify.sas_address, - mpt3sas_get_port_by_id(ioc, port_id)) == NULL) { + mpt3sas_get_port_by_id(ioc, port_id, 0)) == NULL) { spin_unlock_irqrestore(&ioc->sas_node_lock, flags); return -EINVAL; } @@ -1703,7 +1703,7 @@ _transport_phy_reset(struct sas_phy *phy, int hard_reset) spin_lock_irqsave(&ioc->sas_node_lock, flags); if (_transport_sas_node_find_by_sas_address(ioc, phy->identify.sas_address, - mpt3sas_get_port_by_id(ioc, port_id)) == NULL) { + mpt3sas_get_port_by_id(ioc, port_id, 0)) == NULL) { spin_unlock_irqrestore(&ioc->sas_node_lock, flags); return -EINVAL; } @@ -1762,7 +1762,7 @@ _transport_phy_enable(struct sas_phy *phy, int enable) spin_lock_irqsave(&ioc->sas_node_lock, flags); if (_transport_sas_node_find_by_sas_address(ioc, phy->identify.sas_address, - mpt3sas_get_port_by_id(ioc, port_id)) == NULL) { + mpt3sas_get_port_by_id(ioc, port_id, 0)) == NULL) { spin_unlock_irqrestore(&ioc->sas_node_lock, flags); return -EINVAL; } @@ -1902,7 +1902,7 @@ _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) spin_lock_irqsave(&ioc->sas_node_lock, flags); if (_transport_sas_node_find_by_sas_address(ioc, phy->identify.sas_address, - mpt3sas_get_port_by_id(ioc, port_id)) == NULL) { + mpt3sas_get_port_by_id(ioc, port_id, 0)) == NULL) { spin_unlock_irqrestore(&ioc->sas_node_lock, flags); return -EINVAL; } -- cgit v1.2.3 From ffa381d6373b10e83dbdac425fb72affc64084f3 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Tue, 27 Oct 2020 18:38:45 +0530 Subject: scsi: mpt3sas: Handle vSES vphy object during HBA reset During HBA reset the Port ID of vSES device may change. As a result, it is necessary to refresh virtual_phy objects after reset. Each Port's vphy_list table needs to be updated after updating the HBA port table. The algorithm is as follows: - Loop over each port entry from HBA port table * Loop over each virtual phy entry from port's vphys_list table - Mark virtual phy entry as dirty by setting dirty bit in virtual phy entry's flags field - Read SASIOUnitPage0 page - Loop over each HBA Phy's Phy data from SASIOUnitPage0 * If phy's remote attached device is not SES device then continue with processing next HBA Phy's Phy data; * Read SASPhyPage0 data for this Phy number and determine whether current phy is a virtual phy or not. If it is not a virtual phy then continue with next Phy data; * Get the current phy's remote attached vSES device's SAS Address; * Loop over each port entry from HBA port table - If Port's vphys_mask field is zero then continue with next Port entry, - Loop over each virtual phy entry from Port's vphy_list table - If the current phy's remote SAS Address is different from virtual phy entry's SAS Address then continue with next virtual phy entry, - Set bit corresponding to current phy number in virtual phy entry's phy_mask field, - Get the HBA port table's Port entry corresponding to Phy data's 'Port' value, * If there is no Port entry corresponding to Phy data's 'Port' value in HBA port table then create a new port entry and add it to HBA port table. - If this retrieved Port entry is the same as the current Port entry then don't do anything, just clear the dirty bit from virtual phy entry's flag field and continue with processing next HBA Phy's Phy data. - If this retrieved Port entry is different from the current Port entry then move the current virtual phy entry from current Port's vphys_list to retrieved Port entry's vphys_list. * Clear current phy bit in current Port entry's vphys_mask and set the current phy bit in the retrieved Port entry's vphys_mask field. * Clear the dirty bit from virtual phy entry's flag field and continue with next HBA Phy's Phy data. - Delete the 'virtual phy' entries and HBA's 'Port table' entries which are still marked as 'dirty'. Link: https://lore.kernel.org/r/20201027130847.9962-13-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 233 +++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index a35c5f33666c..e5188f469d6a 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -5847,6 +5847,204 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) return 0; } +/** + * _scsih_update_vphys_after_reset - update the Port's + * vphys_list after reset + * @ioc: per adapter object + * + * Returns nothing. + */ +static void +_scsih_update_vphys_after_reset(struct MPT3SAS_ADAPTER *ioc) +{ + u16 sz, ioc_status; + int i; + Mpi2ConfigReply_t mpi_reply; + Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; + u16 attached_handle; + u64 attached_sas_addr; + u8 found = 0, port_id; + Mpi2SasPhyPage0_t phy_pg0; + struct hba_port *port, *port_next, *mport; + struct virtual_phy *vphy, *vphy_next; + struct _sas_device *sas_device; + + /* + * Mark all the vphys objects as dirty. + */ + list_for_each_entry_safe(port, port_next, + &ioc->port_table_list, list) { + if (!port->vphys_mask) + continue; + list_for_each_entry_safe(vphy, vphy_next, + &port->vphys_list, list) { + vphy->flags |= MPT_VPHY_FLAG_DIRTY_PHY; + } + } + + /* + * Read SASIOUnitPage0 to get each HBA Phy's data. + */ + sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + + (ioc->sas_hba.num_phys * sizeof(Mpi2SasIOUnit0PhyData_t)); + sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); + if (!sas_iounit_pg0) { + ioc_err(ioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + return; + } + if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, + sas_iounit_pg0, sz)) != 0) + goto out; + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) + goto out; + /* + * Loop over each HBA Phy. + */ + for (i = 0; i < ioc->sas_hba.num_phys; i++) { + /* + * Check whether Phy's Negotiation Link Rate is > 1.5G or not. + */ + if ((sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4) < + MPI2_SAS_NEG_LINK_RATE_1_5) + continue; + /* + * Check whether Phy is connected to SEP device or not, + * if it is SEP device then read the Phy's SASPHYPage0 data to + * determine whether Phy is a virtual Phy or not. if it is + * virtual phy then it is conformed that the attached remote + * device is a HBA's vSES device. + */ + if (!(le32_to_cpu( + sas_iounit_pg0->PhyData[i].ControllerPhyDeviceInfo) & + MPI2_SAS_DEVICE_INFO_SEP)) + continue; + + if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0, + i))) { + ioc_err(ioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + continue; + } + + if (!(le32_to_cpu(phy_pg0.PhyInfo) & + MPI2_SAS_PHYINFO_VIRTUAL_PHY)) + continue; + /* + * Get the vSES device's SAS Address. + */ + attached_handle = le16_to_cpu( + sas_iounit_pg0->PhyData[i].AttachedDevHandle); + if (_scsih_get_sas_address(ioc, attached_handle, + &attached_sas_addr) != 0) { + ioc_err(ioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); + continue; + } + + found = 0; + port = port_next = NULL; + /* + * Loop over each virtual_phy object from + * each port's vphys_list. + */ + list_for_each_entry_safe(port, + port_next, &ioc->port_table_list, list) { + if (!port->vphys_mask) + continue; + list_for_each_entry_safe(vphy, vphy_next, + &port->vphys_list, list) { + /* + * Continue with next virtual_phy object + * if the object is not marked as dirty. + */ + if (!(vphy->flags & MPT_VPHY_FLAG_DIRTY_PHY)) + continue; + + /* + * Continue with next virtual_phy object + * if the object's SAS Address is not equals + * to current Phy's vSES device SAS Address. + */ + if (vphy->sas_address != attached_sas_addr) + continue; + /* + * Enable current Phy number bit in object's + * phy_mask field. + */ + if (!(vphy->phy_mask & (1 << i))) + vphy->phy_mask = (1 << i); + /* + * Get hba_port object from hba_port table + * corresponding to current phy's Port ID. + * if there is no hba_port object corresponding + * to Phy's Port ID then create a new hba_port + * object & add to hba_port table. + */ + port_id = sas_iounit_pg0->PhyData[i].Port; + mport = mpt3sas_get_port_by_id(ioc, port_id, 1); + if (!mport) { + mport = kzalloc( + sizeof(struct hba_port), GFP_KERNEL); + if (!mport) + break; + mport->port_id = port_id; + ioc_info(ioc, + "%s: hba_port entry: %p, port: %d is added to hba_port list\n", + __func__, mport, mport->port_id); + list_add_tail(&mport->list, + &ioc->port_table_list); + } + /* + * If mport & port pointers are not pointing to + * same hba_port object then it means that vSES + * device's Port ID got changed after reset and + * hence move current virtual_phy object from + * port's vphys_list to mport's vphys_list. + */ + if (port != mport) { + if (!mport->vphys_mask) + INIT_LIST_HEAD( + &mport->vphys_list); + mport->vphys_mask |= (1 << i); + port->vphys_mask &= ~(1 << i); + list_move(&vphy->list, + &mport->vphys_list); + sas_device = mpt3sas_get_sdev_by_addr( + ioc, attached_sas_addr, port); + if (sas_device) + sas_device->port = mport; + } + /* + * Earlier while updating the hba_port table, + * it is determined that there is no other + * direct attached device with mport's Port ID, + * Hence mport was marked as dirty. Only vSES + * device has this Port ID, so unmark the mport + * as dirt. + */ + if (mport->flags & HBA_PORT_FLAG_DIRTY_PORT) { + mport->sas_address = 0; + mport->phy_mask = 0; + mport->flags &= + ~HBA_PORT_FLAG_DIRTY_PORT; + } + /* + * Unmark current virtual_phy object as dirty. + */ + vphy->flags &= ~MPT_VPHY_FLAG_DIRTY_PHY; + found = 1; + break; + } + if (found) + break; + } + } +out: + kfree(sas_iounit_pg0); +} + /** * _scsih_get_port_table_after_reset - Construct temporary port table * @ioc: per adapter object @@ -6067,6 +6265,39 @@ _scsih_add_or_del_phys_from_existing_port(struct MPT3SAS_ADAPTER *ioc, } } +/** + * _scsih_del_dirty_vphy - delete virtual_phy objects marked as dirty. + * @ioc: per adapter object + * + * Returns nothing. + */ +static void +_scsih_del_dirty_vphy(struct MPT3SAS_ADAPTER *ioc) +{ + struct hba_port *port, *port_next; + struct virtual_phy *vphy, *vphy_next; + + list_for_each_entry_safe(port, port_next, + &ioc->port_table_list, list) { + if (!port->vphys_mask) + continue; + list_for_each_entry_safe(vphy, vphy_next, + &port->vphys_list, list) { + if (vphy->flags & MPT_VPHY_FLAG_DIRTY_PHY) { + drsprintk(ioc, ioc_info(ioc, + "Deleting vphy %p entry from port id: %d\t, Phy_mask 0x%08x\n", + vphy, port->port_id, + vphy->phy_mask)); + port->vphys_mask &= ~vphy->phy_mask; + list_del(&vphy->list); + kfree(vphy); + } + } + if (!port->vphys_mask && !port->sas_address) + port->flags |= HBA_PORT_FLAG_DIRTY_PORT; + } +} + /** * _scsih_del_dirty_port_entries - delete dirty port entries from port list * after host reset @@ -10247,6 +10478,7 @@ mpt3sas_scsih_reset_done_handler(struct MPT3SAS_ADAPTER *ioc) if ((!ioc->is_driver_loading) && !(disable_discovery > 0 && !ioc->sas_hba.num_phys)) { _scsih_sas_port_refresh(ioc); + _scsih_update_vphys_after_reset(ioc); _scsih_prep_device_scan(ioc); _scsih_create_enclosure_list_after_reset(ioc); _scsih_search_responding_sas_devices(ioc); @@ -10294,6 +10526,7 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) ssleep(1); } _scsih_remove_unresponding_devices(ioc); + _scsih_del_dirty_vphy(ioc); _scsih_del_dirty_port_entries(ioc); _scsih_scan_for_devices_after_reset(ioc); _scsih_set_nvme_max_shutdown_latency(ioc); -- cgit v1.2.3 From 324c122fc0a41d258239c853854eefd186ae1290 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Tue, 27 Oct 2020 18:38:46 +0530 Subject: scsi: mpt3sas: Add module parameter multipath_on_hba Add module parameter multipath_on_hba to enable/disable multi-port path topology support. By default this feature is enabled on SAS3.5 HBA device and disabled on SAS3 &SAS2.5 HBA devices. When this feature is disabled then driver uses a default PhysicalPort(PortID) number i.e. 255 instead of the PhysicalPort number provided by HBA firmware. Link: https://lore.kernel.org/r/20201027130847.9962-14-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 + drivers/scsi/mpt3sas/mpt3sas_ctl.c | 6 ++- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 69 ++++++++++++++++++++++++++++++-- drivers/scsi/mpt3sas/mpt3sas_transport.c | 6 ++- 4 files changed, 76 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index cca14ab570f5..badd8230cce2 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1246,6 +1246,7 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); * which ensures the syncrhonization between cli/sysfs_show path. * @atomic_desc_capable: Atomic Request Descriptor support. * @GET_MSIX_INDEX: Get the msix index of high iops queues. + * @multipath_on_hba: flag to determine multipath on hba is enabled or not * @port_table_list: list containing HBA's wide/narrow port's info */ struct MPT3SAS_ADAPTER { @@ -1540,6 +1541,7 @@ struct MPT3SAS_ADAPTER { PUT_SMID_DEFAULT put_smid_default; GET_MSIX_INDEX get_msix_index_for_smlio; + u8 multipath_on_hba; struct list_head port_table_list; }; diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index 0f2b681449e6..b21aa55768ae 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -902,8 +902,10 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, (Mpi2SmpPassthroughRequest_t *)mpi_request; u8 *data; - /* ioc determines which port to use */ - smp_request->PhysicalPort = 0xFF; + if (!ioc->multipath_on_hba) { + /* ioc determines which port to use */ + smp_request->PhysicalPort = 0xFF; + } if (smp_request->PassthroughFlags & MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE) data = (u8 *)&smp_request->SGL; diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index e5188f469d6a..005268aa0515 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -159,6 +159,15 @@ module_param(enable_sdev_max_qd, bool, 0444); MODULE_PARM_DESC(enable_sdev_max_qd, "Enable sdev max qd as can_queue, def=disabled(0)"); +static int multipath_on_hba = -1; +module_param(multipath_on_hba, int, 0); +MODULE_PARM_DESC(multipath_on_hba, + "Multipath support to add same target device\n\t\t" + "as many times as it is visible to HBA from various paths\n\t\t" + "(by default:\n\t\t" + "\t SAS 2.0 & SAS 3.0 HBA - This will be disabled,\n\t\t" + "\t SAS 3.5 HBA - This will be enabled)"); + /* raid transport support */ static struct raid_template *mpt3sas_raid_template; static struct raid_template *mpt2sas_raid_template; @@ -373,6 +382,14 @@ mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, { struct hba_port *port, *port_next; + /* + * When multipath_on_hba is disabled then + * search the hba_port entry using default + * port id i.e. 255 + */ + if (!ioc->multipath_on_hba) + port_id = MULTIPATH_DISABLED_PORT_ID; + list_for_each_entry_safe(port, port_next, &ioc->port_table_list, list) { if (port->port_id != port_id) @@ -384,6 +401,24 @@ mpt3sas_get_port_by_id(struct MPT3SAS_ADAPTER *ioc, return port; } + /* + * Allocate hba_port object for default port id (i.e. 255) + * when multipath_on_hba is disabled for the HBA. + * And add this object to port_table_list. + */ + if (!ioc->multipath_on_hba) { + port = kzalloc(sizeof(struct hba_port), GFP_KERNEL); + if (!port) + return NULL; + + port->port_id = port_id; + ioc_info(ioc, + "hba_port entry: %p, port: %d is added to hba_port list\n", + port, port->port_id); + list_add_tail(&port->list, + &ioc->port_table_list); + return port; + } return NULL; } @@ -10014,6 +10049,7 @@ _scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc) u16 ioc_status; u64 sas_address; u16 handle; + u8 port; ioc_info(ioc, "search for expanders: start\n"); @@ -10031,10 +10067,12 @@ _scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc) handle = le16_to_cpu(expander_pg0.DevHandle); sas_address = le64_to_cpu(expander_pg0.SASAddress); + port = expander_pg0.PhysicalPort; pr_info( "\texpander present: handle(0x%04x), sas_addr(0x%016llx), port:%d\n", handle, (unsigned long long)sas_address, - expander_pg0.PhysicalPort); + (ioc->multipath_on_hba ? + port : MULTIPATH_DISABLED_PORT_ID)); _scsih_mark_responding_expander(ioc, &expander_pg0); } @@ -10477,8 +10515,10 @@ mpt3sas_scsih_reset_done_handler(struct MPT3SAS_ADAPTER *ioc) dtmprintk(ioc, ioc_info(ioc, "%s: MPT3_IOC_DONE_RESET\n", __func__)); if ((!ioc->is_driver_loading) && !(disable_discovery > 0 && !ioc->sas_hba.num_phys)) { - _scsih_sas_port_refresh(ioc); - _scsih_update_vphys_after_reset(ioc); + if (ioc->multipath_on_hba) { + _scsih_sas_port_refresh(ioc); + _scsih_update_vphys_after_reset(ioc); + } _scsih_prep_device_scan(ioc); _scsih_create_enclosure_list_after_reset(ioc); _scsih_search_responding_sas_devices(ioc); @@ -11766,6 +11806,12 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS; break; } + + if (multipath_on_hba == -1 || multipath_on_hba == 0) + ioc->multipath_on_hba = 0; + else + ioc->multipath_on_hba = 1; + break; case MPI25_VERSION: case MPI26_VERSION: @@ -11827,6 +11873,23 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->combined_reply_index_count = MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT_G3; } + + switch (ioc->is_gen35_ioc) { + case 0: + if (multipath_on_hba == -1 || multipath_on_hba == 0) + ioc->multipath_on_hba = 0; + else + ioc->multipath_on_hba = 1; + break; + case 1: + if (multipath_on_hba == -1 || multipath_on_hba > 0) + ioc->multipath_on_hba = 1; + else + ioc->multipath_on_hba = 0; + default: + break; + } + break; default: return -ENODEV; diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index 0d06025d7102..6f4708224755 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c @@ -912,7 +912,8 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, return; } - if (sas_node->handle <= ioc->sas_hba.num_phys) { + if (sas_node->handle <= ioc->sas_hba.num_phys && + (ioc->multipath_on_hba)) { if (port->vphys_mask) { list_for_each_entry_safe(vphy, vphy_next, &port->vphys_list, list) { @@ -1172,7 +1173,8 @@ mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc, if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) { _transport_set_identify(ioc, handle, &mpt3sas_phy->remote_identify); - if (sas_node->handle <= ioc->sas_hba.num_phys) { + if ((sas_node->handle <= ioc->sas_hba.num_phys) && + (ioc->multipath_on_hba)) { list_for_each_entry(hba_port, &ioc->port_table_list, list) { if (hba_port->sas_address == sas_address && -- cgit v1.2.3 From 2030745877bdd2ecbeb43ff1846242d004482587 Mon Sep 17 00:00:00 2001 From: Sreekanth Reddy Date: Tue, 27 Oct 2020 18:38:47 +0530 Subject: scsi: mpt3sas: Bump driver version to 35.101.00.00 Bump mpt3sas driver version to 35.101.00.00 Link: https://lore.kernel.org/r/20201027130847.9962-15-sreekanth.reddy@broadcom.com Signed-off-by: Sreekanth Reddy Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index badd8230cce2..7dab579dbc20 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -76,9 +76,9 @@ #define MPT3SAS_DRIVER_NAME "mpt3sas" #define MPT3SAS_AUTHOR "Avago Technologies " #define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" -#define MPT3SAS_DRIVER_VERSION "35.100.00.00" +#define MPT3SAS_DRIVER_VERSION "35.101.00.00" #define MPT3SAS_MAJOR_VERSION 35 -#define MPT3SAS_MINOR_VERSION 100 +#define MPT3SAS_MINOR_VERSION 101 #define MPT3SAS_BUILD_VERSION 0 #define MPT3SAS_RELEASE_VERSION 00 -- cgit v1.2.3 From 077054215a7f787e389a807ece8a39247abbbc1e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 30 Oct 2020 17:44:19 +0100 Subject: scsi: aacraid: Improve compat_ioctl handlers The use of compat_alloc_user_space() can be easily replaced by handling compat arguments in the regular handler, and this will make it work for big-endian kernels as well, which at the moment get an invalid indirect pointer argument. Calling aac_ioctl() instead of aac_compat_do_ioctl() means the compat and native code paths behave the same way again, which they stopped when the adapter health check was added only in the native function. Link: https://lore.kernel.org/r/20201030164450.1253641-1-arnd@kernel.org Fixes: 572ee53a9bad ("scsi: aacraid: check adapter health") Reviewed-by: Christoph Hellwig Signed-off-by: Arnd Bergmann Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/commctrl.c | 22 +++++++++++++-- drivers/scsi/aacraid/linit.c | 61 ++--------------------------------------- 2 files changed, 22 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index e3e157a74988..1b1da162f5f6 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -25,6 +25,7 @@ #include #include #include +#include #include /* ssleep prototype */ #include #include @@ -226,6 +227,12 @@ static int open_getadapter_fib(struct aac_dev * dev, void __user *arg) return status; } +struct compat_fib_ioctl { + u32 fibctx; + s32 wait; + compat_uptr_t fib; +}; + /** * next_getadapter_fib - get the next fib * @dev: adapter to use @@ -243,8 +250,19 @@ static int next_getadapter_fib(struct aac_dev * dev, void __user *arg) struct list_head * entry; unsigned long flags; - if(copy_from_user((void *)&f, arg, sizeof(struct fib_ioctl))) - return -EFAULT; + if (in_compat_syscall()) { + struct compat_fib_ioctl cf; + + if (copy_from_user(&cf, arg, sizeof(struct compat_fib_ioctl))) + return -EFAULT; + + f.fibctx = cf.fibctx; + f.wait = cf.wait; + f.fib = compat_ptr(cf.fib); + } else { + if (copy_from_user(&f, arg, sizeof(struct fib_ioctl))) + return -EFAULT; + } /* * Verify that the HANDLE passed in was a valid AdapterFibContext * diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 8f3772480582..0a82afaf4028 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1182,63 +1182,6 @@ static long aac_cfg_ioctl(struct file *file, return aac_do_ioctl(aac, cmd, (void __user *)arg); } -#ifdef CONFIG_COMPAT -static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long arg) -{ - long ret; - switch (cmd) { - case FSACTL_MINIPORT_REV_CHECK: - case FSACTL_SENDFIB: - case FSACTL_OPEN_GET_ADAPTER_FIB: - case FSACTL_CLOSE_GET_ADAPTER_FIB: - case FSACTL_SEND_RAW_SRB: - case FSACTL_GET_PCI_INFO: - case FSACTL_QUERY_DISK: - case FSACTL_DELETE_DISK: - case FSACTL_FORCE_DELETE_DISK: - case FSACTL_GET_CONTAINERS: - case FSACTL_SEND_LARGE_FIB: - ret = aac_do_ioctl(dev, cmd, (void __user *)arg); - break; - - case FSACTL_GET_NEXT_ADAPTER_FIB: { - struct fib_ioctl __user *f; - - f = compat_alloc_user_space(sizeof(*f)); - ret = 0; - if (clear_user(f, sizeof(*f))) - ret = -EFAULT; - if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32))) - ret = -EFAULT; - if (!ret) - ret = aac_do_ioctl(dev, cmd, f); - break; - } - - default: - ret = -ENOIOCTLCMD; - break; - } - return ret; -} - -static int aac_compat_ioctl(struct scsi_device *sdev, unsigned int cmd, - void __user *arg) -{ - struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata; - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; - return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg); -} - -static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long arg) -{ - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; - return aac_compat_do_ioctl(file->private_data, cmd, arg); -} -#endif - static ssize_t aac_show_model(struct device *device, struct device_attribute *attr, char *buf) { @@ -1523,7 +1466,7 @@ static const struct file_operations aac_cfg_fops = { .owner = THIS_MODULE, .unlocked_ioctl = aac_cfg_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = aac_compat_cfg_ioctl, + .compat_ioctl = aac_cfg_ioctl, #endif .open = aac_cfg_open, .llseek = noop_llseek, @@ -1536,7 +1479,7 @@ static struct scsi_host_template aac_driver_template = { .info = aac_info, .ioctl = aac_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = aac_compat_ioctl, + .compat_ioctl = aac_ioctl, #endif .queuecommand = aac_queuecommand, .bios_param = aac_biosparm, -- cgit v1.2.3 From 381d34e376e3d9d27730fda8a0e870600e6c8196 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 30 Oct 2020 17:44:20 +0100 Subject: scsi: megaraid_sas: Check user-provided offsets It sounds unwise to let user space pass an unchecked 32-bit offset into a kernel structure in an ioctl. This is an unsigned variable, so checking the upper bound for the size of the structure it points into is sufficient to avoid data corruption, but as the pointer might also be unaligned, it has to be written carefully as well. While I stumbled over this problem by reading the code, I did not continue checking the function for further problems like it. Link: https://lore.kernel.org/r/20201030164450.1253641-2-arnd@kernel.org Fixes: c4a3e0a529ab ("[SCSI] MegaRAID SAS RAID: new driver") Cc: # v2.6.15+ Reviewed-by: Christoph Hellwig Signed-off-by: Arnd Bergmann Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 41cd66fc7d81..5e31bd364a5b 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -8134,7 +8134,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, int error = 0, i; void *sense = NULL; dma_addr_t sense_handle; - unsigned long *sense_ptr; + void *sense_ptr; u32 opcode = 0; int ret = DCMD_SUCCESS; @@ -8257,6 +8257,13 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, } if (ioc->sense_len) { + /* make sure the pointer is part of the frame */ + if (ioc->sense_off > + (sizeof(union megasas_frame) - sizeof(__le64))) { + error = -EINVAL; + goto out; + } + sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len, &sense_handle, GFP_KERNEL); if (!sense) { @@ -8264,12 +8271,11 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, goto out; } - sense_ptr = - (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off); + sense_ptr = (void *)cmd->frame + ioc->sense_off; if (instance->consistent_mask_64bit) - *sense_ptr = cpu_to_le64(sense_handle); + put_unaligned_le64(sense_handle, sense_ptr); else - *sense_ptr = cpu_to_le32(sense_handle); + put_unaligned_le32(sense_handle, sense_ptr); } /* -- cgit v1.2.3 From bba84aeccafb57f3f175bbab0658a7facd611d18 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 30 Oct 2020 17:44:21 +0100 Subject: scsi: megaraid_sas: Simplify compat_ioctl handling There have been several attempts to fix serious problems in the compat handling in megasas_mgmt_compat_ioctl_fw(), and it also uses the compat_alloc_user_space() function. Folding the compat handling into the regular ioctl function with in_compat_syscall() simplifies it a lot and avoids some of the remaining problems: - missing handling of unaligned pointers - overflowing the ioc->frame.raw array from invalid input - compat_alloc_user_space() Link: https://lore.kernel.org/r/20201030164450.1253641-3-arnd@kernel.org Reviewed-by: Christoph Hellwig Signed-off-by: Arnd Bergmann Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas.h | 2 - drivers/scsi/megaraid/megaraid_sas_base.c | 118 ++++++++++++------------------ 2 files changed, 46 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 5e4137f10e0e..0f808d63580e 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -2605,7 +2605,6 @@ struct megasas_aen { u32 class_locale_word; } __attribute__ ((packed)); -#ifdef CONFIG_COMPAT struct compat_megasas_iocpacket { u16 host_no; u16 __pad1; @@ -2621,7 +2620,6 @@ struct compat_megasas_iocpacket { } __attribute__ ((packed)); #define MEGASAS_IOC_FIRMWARE32 _IOWR('M', 1, struct compat_megasas_iocpacket) -#endif #define MEGASAS_IOC_FIRMWARE _IOWR('M', 1, struct megasas_iocpacket) #define MEGASAS_IOC_GET_AEN _IOW('M', 3, struct megasas_aen) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 5e31bd364a5b..242cefc61ca5 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -8319,16 +8319,19 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, * copy out the sense */ if (ioc->sense_len) { + void __user *uptr; /* * sense_ptr points to the location that has the user * sense buffer address */ - sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw + - ioc->sense_off); + sense_ptr = (void *)ioc->frame.raw + ioc->sense_off; + if (in_compat_syscall()) + uptr = compat_ptr(get_unaligned((compat_uptr_t *) + sense_ptr)); + else + uptr = get_unaligned((void __user **)sense_ptr); - if (copy_to_user((void __user *)((unsigned long) - get_unaligned((unsigned long *)sense_ptr)), - sense, ioc->sense_len)) { + if (copy_to_user(uptr, sense, ioc->sense_len)) { dev_err(&instance->pdev->dev, "Failed to copy out to user " "sense data\n"); error = -EFAULT; @@ -8371,6 +8374,38 @@ out: return error; } +static struct megasas_iocpacket * +megasas_compat_iocpacket_get_user(void __user *arg) +{ + struct megasas_iocpacket *ioc; + struct compat_megasas_iocpacket __user *cioc = arg; + size_t size; + int err = -EFAULT; + int i; + + ioc = kzalloc(sizeof(*ioc), GFP_KERNEL); + if (!ioc) + return ERR_PTR(-ENOMEM); + size = offsetof(struct megasas_iocpacket, frame) + sizeof(ioc->frame); + if (copy_from_user(ioc, arg, size)) + goto out; + + for (i = 0; i < MAX_IOCTL_SGE; i++) { + compat_uptr_t iov_base; + + if (get_user(iov_base, &cioc->sgl[i].iov_base) || + get_user(ioc->sgl[i].iov_len, &cioc->sgl[i].iov_len)) + goto out; + + ioc->sgl[i].iov_base = compat_ptr(iov_base); + } + + return ioc; +out: + kfree(ioc); + return ERR_PTR(err); +} + static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) { struct megasas_iocpacket __user *user_ioc = @@ -8379,7 +8414,11 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) struct megasas_instance *instance; int error; - ioc = memdup_user(user_ioc, sizeof(*ioc)); + if (in_compat_syscall()) + ioc = megasas_compat_iocpacket_get_user(user_ioc); + else + ioc = memdup_user(user_ioc, sizeof(struct megasas_iocpacket)); + if (IS_ERR(ioc)) return PTR_ERR(ioc); @@ -8484,78 +8523,13 @@ megasas_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } #ifdef CONFIG_COMPAT -static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) -{ - struct compat_megasas_iocpacket __user *cioc = - (struct compat_megasas_iocpacket __user *)arg; - struct megasas_iocpacket __user *ioc = - compat_alloc_user_space(sizeof(struct megasas_iocpacket)); - int i; - int error = 0; - compat_uptr_t ptr; - u32 local_sense_off; - u32 local_sense_len; - u32 user_sense_off; - - if (clear_user(ioc, sizeof(*ioc))) - return -EFAULT; - - if (copy_in_user(&ioc->host_no, &cioc->host_no, sizeof(u16)) || - copy_in_user(&ioc->sgl_off, &cioc->sgl_off, sizeof(u32)) || - copy_in_user(&ioc->sense_off, &cioc->sense_off, sizeof(u32)) || - copy_in_user(&ioc->sense_len, &cioc->sense_len, sizeof(u32)) || - copy_in_user(ioc->frame.raw, cioc->frame.raw, 128) || - copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32))) - return -EFAULT; - - /* - * The sense_ptr is used in megasas_mgmt_fw_ioctl only when - * sense_len is not null, so prepare the 64bit value under - * the same condition. - */ - if (get_user(local_sense_off, &ioc->sense_off) || - get_user(local_sense_len, &ioc->sense_len) || - get_user(user_sense_off, &cioc->sense_off)) - return -EFAULT; - - if (local_sense_off != user_sense_off) - return -EINVAL; - - if (local_sense_len) { - void __user **sense_ioc_ptr = - (void __user **)((u8 *)((unsigned long)&ioc->frame.raw) + local_sense_off); - compat_uptr_t *sense_cioc_ptr = - (compat_uptr_t *)(((unsigned long)&cioc->frame.raw) + user_sense_off); - if (get_user(ptr, sense_cioc_ptr) || - put_user(compat_ptr(ptr), sense_ioc_ptr)) - return -EFAULT; - } - - for (i = 0; i < MAX_IOCTL_SGE; i++) { - if (get_user(ptr, &cioc->sgl[i].iov_base) || - put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) || - copy_in_user(&ioc->sgl[i].iov_len, - &cioc->sgl[i].iov_len, sizeof(compat_size_t))) - return -EFAULT; - } - - error = megasas_mgmt_ioctl_fw(file, (unsigned long)ioc); - - if (copy_in_user(&cioc->frame.hdr.cmd_status, - &ioc->frame.hdr.cmd_status, sizeof(u8))) { - printk(KERN_DEBUG "megasas: error copy_in_user cmd_status\n"); - return -EFAULT; - } - return error; -} - static long megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { case MEGASAS_IOC_FIRMWARE32: - return megasas_mgmt_compat_ioctl_fw(file, arg); + return megasas_mgmt_ioctl_fw(file, arg); case MEGASAS_IOC_GET_AEN: return megasas_mgmt_ioctl_aen(file, arg); } -- cgit v1.2.3 From b455233dcc403e3eb955a642dd69b6676e12b245 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Sun, 1 Nov 2020 00:32:08 +0100 Subject: scsi: target: Rename struct sense_info to sense_detail This helps distinguish it from the SCSI sense INFORMATION field. Link: https://lore.kernel.org/r/20201031233211.5207-2-ddiss@suse.de Reviewed-by: Mike Christie Signed-off-by: David Disseldorp Signed-off-by: Martin K. Petersen --- drivers/target/target_core_transport.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index ff26ab0a5f60..caa3a7b34826 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3094,14 +3094,14 @@ bool transport_wait_for_tasks(struct se_cmd *cmd) } EXPORT_SYMBOL(transport_wait_for_tasks); -struct sense_info { +struct sense_detail { u8 key; u8 asc; u8 ascq; bool add_sector_info; }; -static const struct sense_info sense_info_table[] = { +static const struct sense_detail sense_detail_table[] = { [TCM_NO_SENSE] = { .key = NOT_READY }, @@ -3261,39 +3261,39 @@ static const struct sense_info sense_info_table[] = { */ static void translate_sense_reason(struct se_cmd *cmd, sense_reason_t reason) { - const struct sense_info *si; + const struct sense_detail *sd; u8 *buffer = cmd->sense_buffer; int r = (__force int)reason; u8 key, asc, ascq; bool desc_format = target_sense_desc_format(cmd->se_dev); - if (r < ARRAY_SIZE(sense_info_table) && sense_info_table[r].key) - si = &sense_info_table[r]; + if (r < ARRAY_SIZE(sense_detail_table) && sense_detail_table[r].key) + sd = &sense_detail_table[r]; else - si = &sense_info_table[(__force int) + sd = &sense_detail_table[(__force int) TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE]; - key = si->key; + key = sd->key; if (reason == TCM_CHECK_CONDITION_UNIT_ATTENTION) { if (!core_scsi3_ua_for_check_condition(cmd, &key, &asc, &ascq)) { cmd->scsi_status = SAM_STAT_BUSY; return; } - } else if (si->asc == 0) { + } else if (sd->asc == 0) { WARN_ON_ONCE(cmd->scsi_asc == 0); asc = cmd->scsi_asc; ascq = cmd->scsi_ascq; } else { - asc = si->asc; - ascq = si->ascq; + asc = sd->asc; + ascq = sd->ascq; } cmd->se_cmd_flags |= SCF_EMULATED_TASK_SENSE; cmd->scsi_status = SAM_STAT_CHECK_CONDITION; cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER; scsi_build_sense_buffer(desc_format, buffer, key, asc, ascq); - if (si->add_sector_info) + if (sd->add_sector_info) WARN_ON_ONCE(scsi_set_sense_information(buffer, cmd->scsi_sense_length, cmd->bad_sector) < 0); -- cgit v1.2.3 From 8dd992fb67f33a0777fb4bee1e22a5ee5530f024 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Sun, 1 Nov 2020 00:32:09 +0100 Subject: scsi: target: Rename cmd.bad_sector to cmd.sense_info cmd.bad_sector currently gets packed into the sense INFORMATION field for TCM_LOGICAL_BLOCK_{GUARD,APP_TAG,REF_TAG}_CHECK_FAILED errors, which carry an .add_sector_info flag in the sense_detail_table to ensure this. In preparation for propagating a byte offset on COMPARE AND WRITE TCM_MISCOMPARE_VERIFY error, rename cmd.bad_sector to cmd.sense_info and sense_detail.add_sector_info to sense_detail.add_sense_info so that it better reflects the sense INFORMATION field destination. [ddiss: update previously overlooked ib_isert] Link: https://lore.kernel.org/r/20201031233211.5207-3-ddiss@suse.de Reviewed-by: Mike Christie Signed-off-by: David Disseldorp Signed-off-by: Martin K. Petersen --- drivers/infiniband/ulp/isert/ib_isert.c | 4 ++-- drivers/target/target_core_sbc.c | 2 +- drivers/target/target_core_transport.c | 12 ++++++------ include/target/target_core_base.h | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 436e17f1d0e5..a3ba0c4d0d39 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1528,12 +1528,12 @@ isert_check_pi_status(struct se_cmd *se_cmd, struct ib_mr *sig_mr) } sec_offset_err = mr_status.sig_err.sig_err_offset; do_div(sec_offset_err, block_size); - se_cmd->bad_sector = sec_offset_err + se_cmd->t_task_lba; + se_cmd->sense_info = sec_offset_err + se_cmd->t_task_lba; isert_err("PI error found type %d at sector 0x%llx " "expected 0x%x vs actual 0x%x\n", mr_status.sig_err.err_type, - (unsigned long long)se_cmd->bad_sector, + (unsigned long long)se_cmd->sense_info, mr_status.sig_err.expected, mr_status.sig_err.actual); ret = 1; diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 6e8b8d30938f..5f77dd95f1b9 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -1439,7 +1439,7 @@ sbc_dif_verify(struct se_cmd *cmd, sector_t start, unsigned int sectors, if (rc) { kunmap_atomic(daddr - dsg->offset); kunmap_atomic(paddr - psg->offset); - cmd->bad_sector = sector; + cmd->sense_info = sector; return rc; } next: diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index caa3a7b34826..c6f45c12d564 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3098,7 +3098,7 @@ struct sense_detail { u8 key; u8 asc; u8 ascq; - bool add_sector_info; + bool add_sense_info; }; static const struct sense_detail sense_detail_table[] = { @@ -3201,19 +3201,19 @@ static const struct sense_detail sense_detail_table[] = { .key = ABORTED_COMMAND, .asc = 0x10, .ascq = 0x01, /* LOGICAL BLOCK GUARD CHECK FAILED */ - .add_sector_info = true, + .add_sense_info = true, }, [TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED] = { .key = ABORTED_COMMAND, .asc = 0x10, .ascq = 0x02, /* LOGICAL BLOCK APPLICATION TAG CHECK FAILED */ - .add_sector_info = true, + .add_sense_info = true, }, [TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED] = { .key = ABORTED_COMMAND, .asc = 0x10, .ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */ - .add_sector_info = true, + .add_sense_info = true, }, [TCM_COPY_TARGET_DEVICE_NOT_REACHABLE] = { .key = COPY_ABORTED, @@ -3293,10 +3293,10 @@ static void translate_sense_reason(struct se_cmd *cmd, sense_reason_t reason) cmd->scsi_status = SAM_STAT_CHECK_CONDITION; cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER; scsi_build_sense_buffer(desc_format, buffer, key, asc, ascq); - if (sd->add_sector_info) + if (sd->add_sense_info) WARN_ON_ONCE(scsi_set_sense_information(buffer, cmd->scsi_sense_length, - cmd->bad_sector) < 0); + cmd->sense_info) < 0); } int diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 549947d407cf..7ee2bee46b3a 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -540,7 +540,7 @@ struct se_cmd { struct scatterlist *t_prot_sg; unsigned int t_prot_nents; sense_reason_t pi_err; - sector_t bad_sector; + u64 sense_info; int cpuid; }; -- cgit v1.2.3 From ab628b9fc8c231655e52ed2b4a50758a633a2c63 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Sun, 1 Nov 2020 00:32:10 +0100 Subject: scsi: target: Split out COMPARE AND WRITE memcmp into helper In preparation for finding and returning the miscompare offset. Link: https://lore.kernel.org/r/20201031233211.5207-4-ddiss@suse.de Reviewed-by: Mike Christie Signed-off-by: David Disseldorp Signed-off-by: Martin K. Petersen --- drivers/target/target_core_sbc.c | 121 ++++++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 5f77dd95f1b9..22d0cbba6ff3 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -434,20 +434,75 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success, return ret; } +/* + * compare @cmp_len bytes of @read_sgl with @cmp_sgl. On miscompare return + * TCM_MISCOMPARE_VERIFY. + */ +static sense_reason_t +compare_and_write_do_cmp(struct scatterlist *read_sgl, unsigned int read_nents, + struct scatterlist *cmp_sgl, unsigned int cmp_nents, + unsigned int cmp_len) +{ + unsigned char *buf = NULL; + struct scatterlist *sg; + sense_reason_t ret; + unsigned int offset; + size_t rc; + int i; + + buf = kzalloc(cmp_len, GFP_KERNEL); + if (!buf) { + ret = TCM_OUT_OF_RESOURCES; + goto out; + } + + rc = sg_copy_to_buffer(cmp_sgl, cmp_nents, buf, cmp_len); + if (!rc) { + pr_err("sg_copy_to_buffer() failed for compare_and_write\n"); + ret = TCM_OUT_OF_RESOURCES; + goto out; + } + /* + * Compare SCSI READ payload against verify payload + */ + offset = 0; + for_each_sg(read_sgl, sg, read_nents, i) { + unsigned int len = min(sg->length, cmp_len); + unsigned char *addr = kmap_atomic(sg_page(sg)); + + if (memcmp(addr, buf + offset, len)) { + pr_warn("Detected MISCOMPARE for addr: %p buf: %p\n", + addr, buf + offset); + kunmap_atomic(addr); + ret = TCM_MISCOMPARE_VERIFY; + goto out; + } + kunmap_atomic(addr); + + offset += len; + cmp_len -= len; + if (!cmp_len) + break; + } + pr_debug("COMPARE AND WRITE read data matches compare data\n"); + ret = TCM_NO_SENSE; +out: + kfree(buf); + return ret; +} + static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool success, int *post_ret) { struct se_device *dev = cmd->se_dev; struct sg_table write_tbl = { }; - struct scatterlist *write_sg, *sg; - unsigned char *buf = NULL, *addr; + struct scatterlist *write_sg; struct sg_mapping_iter m; - unsigned int offset = 0, len; - unsigned int nlbas = cmd->t_task_nolb; + unsigned int len; unsigned int block_size = dev->dev_attrib.block_size; - unsigned int compare_len = (nlbas * block_size); + unsigned int compare_len = (cmd->t_task_nolb * block_size); sense_reason_t ret = TCM_NO_SENSE; - int rc, i; + int i; /* * Handle early failure in transport_generic_request_failure(), @@ -473,12 +528,13 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes goto out; } - buf = kzalloc(cmd->data_length, GFP_KERNEL); - if (!buf) { - pr_err("Unable to allocate compare_and_write buf\n"); - ret = TCM_OUT_OF_RESOURCES; + ret = compare_and_write_do_cmp(cmd->t_bidi_data_sg, + cmd->t_bidi_data_nents, + cmd->t_data_sg, + cmd->t_data_nents, + compare_len); + if (ret) goto out; - } if (sg_alloc_table(&write_tbl, cmd->t_data_nents, GFP_KERNEL) < 0) { pr_err("Unable to allocate compare_and_write sg\n"); @@ -486,44 +542,9 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes goto out; } write_sg = write_tbl.sgl; - /* - * Setup verify and write data payloads from total NumberLBAs. - */ - rc = sg_copy_to_buffer(cmd->t_data_sg, cmd->t_data_nents, buf, - cmd->data_length); - if (!rc) { - pr_err("sg_copy_to_buffer() failed for compare_and_write\n"); - ret = TCM_OUT_OF_RESOURCES; - goto out; - } - /* - * Compare against SCSI READ payload against verify payload - */ - for_each_sg(cmd->t_bidi_data_sg, sg, cmd->t_bidi_data_nents, i) { - addr = (unsigned char *)kmap_atomic(sg_page(sg)); - if (!addr) { - ret = TCM_OUT_OF_RESOURCES; - goto out; - } - - len = min(sg->length, compare_len); - - if (memcmp(addr, buf + offset, len)) { - pr_warn("Detected MISCOMPARE for addr: %p buf: %p\n", - addr, buf + offset); - kunmap_atomic(addr); - goto miscompare; - } - kunmap_atomic(addr); - - offset += len; - compare_len -= len; - if (!compare_len) - break; - } i = 0; - len = cmd->t_task_nolb * block_size; + len = compare_len; sg_miter_start(&m, cmd->t_data_sg, cmd->t_data_nents, SG_MITER_TO_SG); /* * Currently assumes NoLB=1 and SGLs are PAGE_SIZE.. @@ -568,13 +589,8 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes __target_execute_cmd(cmd, false); - kfree(buf); return ret; -miscompare: - pr_warn("Target/%s: Send MISCOMPARE check condition and sense\n", - dev->transport->name); - ret = TCM_MISCOMPARE_VERIFY; out: /* * In the MISCOMPARE or failure case, unlock ->caw_sem obtained in @@ -582,7 +598,6 @@ out: */ up(&dev->caw_sem); sg_free_table(&write_tbl); - kfree(buf); return ret; } -- cgit v1.2.3 From 749c226cf56ed47ae76c57b2f7f6b8f01b5797c4 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Sun, 1 Nov 2020 00:32:11 +0100 Subject: scsi: target: Return COMPARE AND WRITE miscompare offsets SBC-4 r15 5.3 COMPARE AND WRITE command states: if the compare operation does not indicate a match, then terminate the command with CHECK CONDITION status with the sense key set to MISCOMPARE and the additional sense code set to MISCOMPARE DURING VERIFY OPERATION. In the sense data (see 4.18 and SPC-5) the offset from the start of the Data-Out Buffer to the first byte of data that was not equal shall be reported in the INFORMATION field. This change implements the missing logic to report the miscompare offset in the sense data INFORMATION field. As an optimization, byte-by-byte miscompare offset calculation is only performed after memcmp() mismatch. Link: https://lore.kernel.org/r/20201031233211.5207-5-ddiss@suse.de Signed-off-by: David Disseldorp Signed-off-by: Martin K. Petersen --- drivers/target/target_core_sbc.c | 36 ++++++++++++++++++++++++---------- drivers/target/target_core_transport.c | 1 + 2 files changed, 27 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 22d0cbba6ff3..f7c527a826fd 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -435,13 +435,13 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success, } /* - * compare @cmp_len bytes of @read_sgl with @cmp_sgl. On miscompare return - * TCM_MISCOMPARE_VERIFY. + * compare @cmp_len bytes of @read_sgl with @cmp_sgl. On miscompare, fill + * @miscmp_off and return TCM_MISCOMPARE_VERIFY. */ static sense_reason_t compare_and_write_do_cmp(struct scatterlist *read_sgl, unsigned int read_nents, struct scatterlist *cmp_sgl, unsigned int cmp_nents, - unsigned int cmp_len) + unsigned int cmp_len, unsigned int *miscmp_off) { unsigned char *buf = NULL; struct scatterlist *sg; @@ -466,18 +466,24 @@ compare_and_write_do_cmp(struct scatterlist *read_sgl, unsigned int read_nents, * Compare SCSI READ payload against verify payload */ offset = 0; + ret = TCM_NO_SENSE; for_each_sg(read_sgl, sg, read_nents, i) { unsigned int len = min(sg->length, cmp_len); unsigned char *addr = kmap_atomic(sg_page(sg)); if (memcmp(addr, buf + offset, len)) { - pr_warn("Detected MISCOMPARE for addr: %p buf: %p\n", - addr, buf + offset); - kunmap_atomic(addr); + unsigned int i; + + for (i = 0; i < len && addr[i] == buf[offset + i]; i++) + ; + *miscmp_off = offset + i; + pr_warn("Detected MISCOMPARE at offset %u\n", + *miscmp_off); ret = TCM_MISCOMPARE_VERIFY; - goto out; } kunmap_atomic(addr); + if (ret != TCM_NO_SENSE) + goto out; offset += len; cmp_len -= len; @@ -485,7 +491,6 @@ compare_and_write_do_cmp(struct scatterlist *read_sgl, unsigned int read_nents, break; } pr_debug("COMPARE AND WRITE read data matches compare data\n"); - ret = TCM_NO_SENSE; out: kfree(buf); return ret; @@ -501,6 +506,7 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes unsigned int len; unsigned int block_size = dev->dev_attrib.block_size; unsigned int compare_len = (cmd->t_task_nolb * block_size); + unsigned int miscmp_off = 0; sense_reason_t ret = TCM_NO_SENSE; int i; @@ -532,8 +538,18 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes cmd->t_bidi_data_nents, cmd->t_data_sg, cmd->t_data_nents, - compare_len); - if (ret) + compare_len, + &miscmp_off); + if (ret == TCM_MISCOMPARE_VERIFY) { + /* + * SBC-4 r15: 5.3 COMPARE AND WRITE command + * In the sense data (see 4.18 and SPC-5) the offset from the + * start of the Data-Out Buffer to the first byte of data that + * was not equal shall be reported in the INFORMATION field. + */ + cmd->sense_info = miscmp_off; + goto out; + } else if (ret) goto out; if (sg_alloc_table(&write_tbl, cmd->t_data_nents, GFP_KERNEL) < 0) { diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c6f45c12d564..693ed3fe4388 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3196,6 +3196,7 @@ static const struct sense_detail sense_detail_table[] = { .key = MISCOMPARE, .asc = 0x1d, /* MISCOMPARE DURING VERIFY OPERATION */ .ascq = 0x00, + .add_sense_info = true, }, [TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED] = { .key = ABORTED_COMMAND, -- cgit v1.2.3 From 4a9435b7b04ed8bb39e2c563d93b522bc226b16f Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sun, 1 Nov 2020 06:38:12 -0800 Subject: scsi: bnx2fc: Remove unneeded semicolon A semicolon is not needed after a switch statement. Link: https://lore.kernel.org/r/20201101143812.2283642-1-trix@redhat.com Reviewed-by: Saurav Kashyap Signed-off-by: Tom Rix Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 6890bbe04a8c..a436adb6092d 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -2275,7 +2275,7 @@ static int bnx2fc_ctlr_enabled(struct fcoe_ctlr_device *cdev) case FCOE_CTLR_UNUSED: default: return -ENOTSUPP; - }; + } } enum bnx2fc_create_link_state { -- cgit v1.2.3 From 00c00807a11002f56ca5d87463ac892c794f122f Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Sun, 1 Nov 2020 06:40:17 -0800 Subject: scsi: fcoe: Remove unneeded semicolon A semicolon is not needed after a switch statement. Link: https://lore.kernel.org/r/20201101144017.2284047-1-trix@redhat.com Signed-off-by: Tom Rix Signed-off-by: Martin K. Petersen --- drivers/scsi/fcoe/fcoe.c | 2 +- drivers/scsi/fcoe/fcoe_sysfs.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index a4be6f439c47..03bf49adaafe 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -2023,7 +2023,7 @@ static int fcoe_ctlr_enabled(struct fcoe_ctlr_device *cdev) case FCOE_CTLR_UNUSED: default: return -ENOTSUPP; - }; + } } /** diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c index ffef2c8eddc6..af658aa38fed 100644 --- a/drivers/scsi/fcoe/fcoe_sysfs.c +++ b/drivers/scsi/fcoe/fcoe_sysfs.c @@ -312,7 +312,7 @@ static ssize_t store_ctlr_mode(struct device *dev, default: LIBFCOE_SYSFS_DBG(ctlr, "Mode change not supported.\n"); return -ENOTSUPP; - }; + } } static FCOE_DEVICE_ATTR(ctlr, mode, S_IRUGO | S_IWUSR, @@ -346,7 +346,7 @@ static ssize_t store_ctlr_enabled(struct device *dev, break; case FCOE_CTLR_UNUSED: return -ENOTSUPP; - }; + } rc = ctlr->f->set_fcoe_ctlr_enabled(ctlr); if (rc) -- cgit v1.2.3 From a2b5d6f975a499bd50919a409c6a7c4cbf9d8a58 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sun, 1 Nov 2020 12:59:27 -0600 Subject: scsi: target: Fix LUN ref count handling Fix two bugs in the LUN refcounting: 1. For the TCM_WRITE_PROTECTED case we were returning an error after taking a ref to the LUN, but never dropping it (caller just send status and drops cmd ref). 2. We still need to do a percpu_ref_tryget_live for the virt LUN 0 like we do for other LUNs, because the TPG code does the refcount/wait process like it does with other LUNs. Link: https://lore.kernel.org/r/1604257174-4524-2-git-send-email-michael.christie@oracle.com Reviewed-by: Himanshu Madhani Signed-off-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/target/target_core_device.c | 43 +++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 405d82d44717..1f673fbc28f9 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -65,6 +65,16 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd) atomic_long_add(se_cmd->data_length, &deve->read_bytes); + if ((se_cmd->data_direction == DMA_TO_DEVICE) && + deve->lun_access_ro) { + pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN" + " Access for 0x%08llx\n", + se_cmd->se_tfo->fabric_name, + se_cmd->orig_fe_lun); + rcu_read_unlock(); + return TCM_WRITE_PROTECTED; + } + se_lun = rcu_dereference(deve->se_lun); if (!percpu_ref_tryget_live(&se_lun->lun_ref)) { @@ -76,17 +86,6 @@ transport_lookup_cmd_lun(struct se_cmd *se_cmd) se_cmd->pr_res_key = deve->pr_res_key; se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD; se_cmd->lun_ref_active = true; - - if ((se_cmd->data_direction == DMA_TO_DEVICE) && - deve->lun_access_ro) { - pr_err("TARGET_CORE[%s]: Detected WRITE_PROTECTED LUN" - " Access for 0x%08llx\n", - se_cmd->se_tfo->fabric_name, - se_cmd->orig_fe_lun); - rcu_read_unlock(); - ret = TCM_WRITE_PROTECTED; - goto ref_dev; - } } out_unlock: rcu_read_unlock(); @@ -106,21 +105,20 @@ out_unlock: return TCM_NON_EXISTENT_LUN; } - se_lun = se_sess->se_tpg->tpg_virt_lun0; - se_cmd->se_lun = se_sess->se_tpg->tpg_virt_lun0; - se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD; - - percpu_ref_get(&se_lun->lun_ref); - se_cmd->lun_ref_active = true; - /* * Force WRITE PROTECT for virtual LUN 0 */ if ((se_cmd->data_direction != DMA_FROM_DEVICE) && - (se_cmd->data_direction != DMA_NONE)) { - ret = TCM_WRITE_PROTECTED; - goto ref_dev; - } + (se_cmd->data_direction != DMA_NONE)) + return TCM_WRITE_PROTECTED; + + se_lun = se_sess->se_tpg->tpg_virt_lun0; + if (!percpu_ref_tryget_live(&se_lun->lun_ref)) + return TCM_NON_EXISTENT_LUN; + + se_cmd->se_lun = se_sess->se_tpg->tpg_virt_lun0; + se_cmd->se_cmd_flags |= SCF_SE_LUN_CMD; + se_cmd->lun_ref_active = true; } /* * RCU reference protected by percpu se_lun->lun_ref taken above that @@ -128,7 +126,6 @@ out_unlock: * pointer can be kfree_rcu() by the final se_lun->lun_group put via * target_core_fabric_configfs.c:target_fabric_port_release */ -ref_dev: se_cmd->se_dev = rcu_dereference_raw(se_lun->lun_se_dev); atomic_long_inc(&se_cmd->se_dev->num_cmds); -- cgit v1.2.3 From 02dd4914b0bcb8fd8f8cad9817f5715a17466261 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sun, 1 Nov 2020 12:59:28 -0600 Subject: scsi: target: Fix cmd_count ref leak percpu_ref_init sets the refcount to 1 and percpu_ref_kill drops it. Drivers like iSCSI and loop do not call target_sess_cmd_list_set_waiting during session shutdown, though, so they have been calling percpu_ref_exit with a refcount still taken and leaking the cmd_counts memory. Link: https://lore.kernel.org/r/1604257174-4524-3-git-send-email-michael.christie@oracle.com Reviewed-by: Himanshu Madhani Signed-off-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/target/target_core_transport.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 693ed3fe4388..46fc2ffc42b4 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -238,6 +238,14 @@ EXPORT_SYMBOL(transport_init_session); void transport_uninit_session(struct se_session *se_sess) { + /* + * Drivers like iscsi and loop do not call + * target_sess_cmd_list_set_waiting during session shutdown so we + * have to drop the ref taken at init time here. + */ + if (!se_sess->sess_tearing_down) + percpu_ref_put(&se_sess->cmd_count); + percpu_ref_exit(&se_sess->cmd_count); } -- cgit v1.2.3 From 8f394da36a361cbe0e1e8b1d4213e5598c8095ac Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sun, 1 Nov 2020 12:59:29 -0600 Subject: scsi: qla2xxx: Drop TARGET_SCF_LOOKUP_LUN_FROM_TAG Only the __qlt_24xx_handle_abts() code path does not know the LUN for an abort and it uses the TARGET_SCF_LOOKUP_LUN_FROM_TAG flag to have LIO core look it up. LIO uses target_lookup_lun_from_tag to go from cmd tag to LUN for the driver. However, qla2xxx has a tcm_qla2xxx_find_cmd_by_tag() which does almost the same thing as the LIO helper (it finds the cmd but does not return the LUN). This patch has qla2xxx use its internal helper. Link: https://lore.kernel.org/r/1604257174-4524-4-git-send-email-michael.christie@oracle.com Cc: Nilesh Javali Reviewed-by: Himanshu Madhani Signed-off-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_target.c | 21 +++++++++++---------- drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4 +--- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index a27a625839e6..f88548b8b84e 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -2083,6 +2083,7 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, struct qla_hw_data *ha = vha->hw; struct qla_tgt_mgmt_cmd *mcmd; struct qla_qpair_hint *h = &vha->vha_tgt.qla_tgt->qphints[0]; + struct qla_tgt_cmd *abort_cmd; ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f, "qla_target(%d): task abort (tag=%d)\n", @@ -2110,17 +2111,17 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, */ mcmd->se_cmd.cpuid = h->cpuid; - if (ha->tgt.tgt_ops->find_cmd_by_tag) { - struct qla_tgt_cmd *abort_cmd; - - abort_cmd = ha->tgt.tgt_ops->find_cmd_by_tag(sess, + abort_cmd = ha->tgt.tgt_ops->find_cmd_by_tag(sess, le32_to_cpu(abts->exchange_addr_to_abort)); - if (abort_cmd && abort_cmd->qpair) { - mcmd->qpair = abort_cmd->qpair; - mcmd->se_cmd.cpuid = abort_cmd->se_cmd.cpuid; - mcmd->abort_io_attr = abort_cmd->atio.u.isp24.attr; - mcmd->flags = QLA24XX_MGMT_ABORT_IO_ATTR_VALID; - } + if (!abort_cmd) + return -EIO; + mcmd->unpacked_lun = abort_cmd->se_cmd.orig_fe_lun; + + if (abort_cmd->qpair) { + mcmd->qpair = abort_cmd->qpair; + mcmd->se_cmd.cpuid = abort_cmd->se_cmd.cpuid; + mcmd->abort_io_attr = abort_cmd->atio.u.isp24.attr; + mcmd->flags = QLA24XX_MGMT_ABORT_IO_ATTR_VALID; } INIT_WORK(&mcmd->work, qlt_do_tmr_work); diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 61017acd3458..f5a91bf8be94 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -574,13 +574,11 @@ static int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, u64 lun, struct fc_port *sess = mcmd->sess; struct se_cmd *se_cmd = &mcmd->se_cmd; int transl_tmr_func = 0; - int flags = TARGET_SCF_ACK_KREF; switch (tmr_func) { case QLA_TGT_ABTS: pr_debug("%ld: ABTS received\n", sess->vha->host_no); transl_tmr_func = TMR_ABORT_TASK; - flags |= TARGET_SCF_LOOKUP_LUN_FROM_TAG; break; case QLA_TGT_2G_ABORT_TASK: pr_debug("%ld: 2G Abort Task received\n", sess->vha->host_no); @@ -613,7 +611,7 @@ static int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, u64 lun, } return target_submit_tmr(se_cmd, sess->se_sess, NULL, lun, mcmd, - transl_tmr_func, GFP_ATOMIC, tag, flags); + transl_tmr_func, GFP_ATOMIC, tag, TARGET_SCF_ACK_KREF); } static struct qla_tgt_cmd *tcm_qla2xxx_find_cmd_by_tag(struct fc_port *sess, -- cgit v1.2.3 From 27b0efd15d5247ada0c2ed9cbc77fd3fb3b1f26d Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sun, 1 Nov 2020 12:59:30 -0600 Subject: scsi: target: Remove TARGET_SCF_LOOKUP_LUN_FROM_TAG TARGET_SCF_LOOKUP_LUN_FROM_TAG is no longer used so remove it. Link: https://lore.kernel.org/r/1604257174-4524-5-git-send-email-michael.christie@oracle.com Reviewed-by: Himanshu Madhani Signed-off-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/target/target_core_transport.c | 33 --------------------------------- include/target/target_core_base.h | 1 - 2 files changed, 34 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 46fc2ffc42b4..faf1bab454d4 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1772,29 +1772,6 @@ static void target_complete_tmr_failure(struct work_struct *work) transport_cmd_check_stop_to_fabric(se_cmd); } -static bool target_lookup_lun_from_tag(struct se_session *se_sess, u64 tag, - u64 *unpacked_lun) -{ - struct se_cmd *se_cmd; - unsigned long flags; - bool ret = false; - - spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); - list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) { - if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) - continue; - - if (se_cmd->tag == tag) { - *unpacked_lun = se_cmd->orig_fe_lun; - ret = true; - break; - } - } - spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); - - return ret; -} - /** * target_submit_tmr - lookup unpacked lun and submit uninitialized se_cmd * for TMR CDBs @@ -1842,16 +1819,6 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess, core_tmr_release_req(se_cmd->se_tmr_req); return ret; } - /* - * If this is ABORT_TASK with no explicit fabric provided LUN, - * go ahead and search active session tags for a match to figure - * out unpacked_lun for the original se_cmd. - */ - if (tm_type == TMR_ABORT_TASK && (flags & TARGET_SCF_LOOKUP_LUN_FROM_TAG)) { - if (!target_lookup_lun_from_tag(se_sess, tag, - &se_cmd->orig_fe_lun)) - goto failure; - } ret = transport_lookup_tmr_lun(se_cmd); if (ret) diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 7ee2bee46b3a..7d632593c398 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -195,7 +195,6 @@ enum target_sc_flags_table { TARGET_SCF_ACK_KREF = 0x02, TARGET_SCF_UNKNOWN_SIZE = 0x04, TARGET_SCF_USE_CPUID = 0x08, - TARGET_SCF_LOOKUP_LUN_FROM_TAG = 0x10, }; /* fabric independent task management function values */ -- cgit v1.2.3 From 605e74025f953b995a3a241ead43bde71c1c99b5 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sun, 1 Nov 2020 12:59:31 -0600 Subject: scsi: qla2xxx: Move sess cmd list/lock to driver Except for debug output in the shutdown path, tcm_qla2xxx is the only driver using the se_session sess_cmd_list. Move the list to that driver to facilitate removing the sess_cmd_lock from the main I/O path for the rest of the drivers. Link: https://lore.kernel.org/r/1604257174-4524-6-git-send-email-michael.christie@oracle.com Cc: Nilesh Javali Reviewed-by: Himanshu Madhani Signed-off-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 2 ++ drivers/scsi/qla2xxx/qla_init.c | 3 ++ drivers/scsi/qla2xxx/qla_target.c | 1 + drivers/scsi/qla2xxx/qla_target.h | 1 + drivers/scsi/qla2xxx/tcm_qla2xxx.c | 57 +++++++++++++++++++++++--------------- 5 files changed, 42 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 4f0486fe30dd..ed9b10f8537d 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2493,6 +2493,8 @@ typedef struct fc_port { int generation; struct se_session *se_sess; + struct list_head sess_cmd_list; + spinlock_t sess_cmd_lock; struct kref sess_kref; struct qla_tgt *tgt; unsigned long expires; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 898c70b8ebbf..5626e9b6949f 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -4974,6 +4974,9 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) INIT_LIST_HEAD(&fcport->gnl_entry); INIT_LIST_HEAD(&fcport->list); + INIT_LIST_HEAD(&fcport->sess_cmd_list); + spin_lock_init(&fcport->sess_cmd_lock); + return fcport; } diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index f88548b8b84e..6603caddc054 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -4292,6 +4292,7 @@ static struct qla_tgt_cmd *qlt_get_tag(scsi_qla_host_t *vha, cmd->cmd_type = TYPE_TGT_CMD; memcpy(&cmd->atio, atio, sizeof(*atio)); + INIT_LIST_HEAD(&cmd->sess_cmd_list); cmd->state = QLA_TGT_STATE_NEW; cmd->tgt = vha->vha_tgt.qla_tgt; qlt_incr_num_pend_cmds(vha); diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 1cff7c69d448..10e5e6c8087d 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -856,6 +856,7 @@ struct qla_tgt_cmd { uint8_t cmd_type; uint8_t pad[7]; struct se_cmd se_cmd; + struct list_head sess_cmd_list; struct fc_port *sess; struct qla_qpair *qpair; uint32_t reset_count; diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index f5a91bf8be94..e122da98eda7 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -255,6 +255,7 @@ static void tcm_qla2xxx_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd) static void tcm_qla2xxx_complete_free(struct work_struct *work) { struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); + unsigned long flags; cmd->cmd_in_wq = 0; @@ -265,6 +266,10 @@ static void tcm_qla2xxx_complete_free(struct work_struct *work) cmd->trc_flags |= TRC_CMD_FREE; cmd->cmd_sent_to_fw = 0; + spin_lock_irqsave(&cmd->sess->sess_cmd_lock, flags); + list_del_init(&cmd->sess_cmd_list); + spin_unlock_irqrestore(&cmd->sess->sess_cmd_lock, flags); + transport_generic_free_cmd(&cmd->se_cmd, 0); } @@ -451,13 +456,14 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd, struct se_portal_group *se_tpg; struct tcm_qla2xxx_tpg *tpg; #endif - int flags = TARGET_SCF_ACK_KREF; + int target_flags = TARGET_SCF_ACK_KREF; + unsigned long flags; if (bidi) - flags |= TARGET_SCF_BIDI_OP; + target_flags |= TARGET_SCF_BIDI_OP; if (se_cmd->cpuid != WORK_CPU_UNBOUND) - flags |= TARGET_SCF_USE_CPUID; + target_flags |= TARGET_SCF_USE_CPUID; sess = cmd->sess; if (!sess) { @@ -479,11 +485,15 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd, return 0; } #endif - cmd->qpair->tgt_counters.qla_core_sbt_cmd++; + + spin_lock_irqsave(&sess->sess_cmd_lock, flags); + list_add_tail(&cmd->sess_cmd_list, &sess->sess_cmd_list); + spin_unlock_irqrestore(&sess->sess_cmd_lock, flags); + return target_submit_cmd(se_cmd, se_sess, cdb, &cmd->sense_buffer[0], - cmd->unpacked_lun, data_length, fcp_task_attr, - data_dir, flags); + cmd->unpacked_lun, data_length, fcp_task_attr, + data_dir, target_flags); } static void tcm_qla2xxx_handle_data_work(struct work_struct *work) @@ -617,25 +627,20 @@ static int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, u64 lun, static struct qla_tgt_cmd *tcm_qla2xxx_find_cmd_by_tag(struct fc_port *sess, uint64_t tag) { - struct qla_tgt_cmd *cmd = NULL; - struct se_cmd *secmd; + struct qla_tgt_cmd *cmd; unsigned long flags; if (!sess->se_sess) return NULL; - spin_lock_irqsave(&sess->se_sess->sess_cmd_lock, flags); - list_for_each_entry(secmd, &sess->se_sess->sess_cmd_list, se_cmd_list) { - /* skip task management functions, including tmr->task_cmd */ - if (secmd->se_cmd_flags & SCF_SCSI_TMR_CDB) - continue; - - if (secmd->tag == tag) { - cmd = container_of(secmd, struct qla_tgt_cmd, se_cmd); - break; - } + spin_lock_irqsave(&sess->sess_cmd_lock, flags); + list_for_each_entry(cmd, &sess->sess_cmd_list, sess_cmd_list) { + if (cmd->se_cmd.tag == tag) + goto done; } - spin_unlock_irqrestore(&sess->se_sess->sess_cmd_lock, flags); + cmd = NULL; +done: + spin_unlock_irqrestore(&sess->sess_cmd_lock, flags); return cmd; } @@ -765,11 +770,19 @@ static void tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd) static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd) { - struct qla_tgt_cmd *cmd = container_of(se_cmd, - struct qla_tgt_cmd, se_cmd); + struct qla_tgt_cmd *cmd; + unsigned long flags; - if (qlt_abort_cmd(cmd)) + if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) return; + + cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); + + spin_lock_irqsave(&cmd->sess->sess_cmd_lock, flags); + list_del_init(&cmd->sess_cmd_list); + spin_unlock_irqrestore(&cmd->sess->sess_cmd_lock, flags); + + qlt_abort_cmd(cmd); } static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *, -- cgit v1.2.3 From 6f55b06f9b0722607cbac2140875d790395435f2 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sun, 1 Nov 2020 12:59:32 -0600 Subject: scsi: target: Drop sess_cmd_lock from I/O path Drop the sess_cmd_lock by: - Removing the sess_cmd_list use from LIO core, because it's been moved to qla2xxx. - Removing sess_tearing_down check in the I/O path. Instead of using that bit and the sess_cmd_lock, we rely on the cmd_count percpu ref. To do this we switch to percpu_ref_kill_and_confirm/percpu_ref_tryget_live. Link: https://lore.kernel.org/r/1604257174-4524-7-git-send-email-michael.christie@oracle.com Reviewed-by: Himanshu Madhani Signed-off-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/infiniband/ulp/isert/ib_isert.c | 2 +- drivers/infiniband/ulp/srpt/ib_srpt.c | 2 +- drivers/scsi/qla2xxx/tcm_qla2xxx.c | 9 +--- drivers/target/target_core_tpg.c | 2 +- drivers/target/target_core_transport.c | 77 ++++++++++++++------------------- drivers/target/tcm_fc/tfc_sess.c | 2 +- include/target/target_core_base.h | 6 +-- include/target/target_core_fabric.h | 2 +- 8 files changed, 43 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index a3ba0c4d0d39..67f65dcb15a6 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -2471,7 +2471,7 @@ isert_wait4cmds(struct iscsi_conn *conn) isert_info("iscsi_conn %p\n", conn); if (conn->sess) { - target_sess_cmd_list_set_waiting(conn->sess->se_sess); + target_stop_session(conn->sess->se_sess); target_wait_for_sess_cmds(conn->sess->se_sess); } } diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 0065eb17ae36..8377113c85ba 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -2084,7 +2084,7 @@ static void srpt_release_channel_work(struct work_struct *w) se_sess = ch->sess; BUG_ON(!se_sess); - target_sess_cmd_list_set_waiting(se_sess); + target_stop_session(se_sess); target_wait_for_sess_cmds(se_sess); target_remove_session(se_sess); diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index e122da98eda7..784b43f18181 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -368,15 +368,10 @@ static void tcm_qla2xxx_put_sess(struct fc_port *sess) static void tcm_qla2xxx_close_session(struct se_session *se_sess) { struct fc_port *sess = se_sess->fabric_sess_ptr; - struct scsi_qla_host *vha; - unsigned long flags; BUG_ON(!sess); - vha = sess->vha; - spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); - target_sess_cmd_list_set_waiting(se_sess); - spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); + target_stop_session(se_sess); sess->explicit_logout = 1; tcm_qla2xxx_put_sess(sess); @@ -831,7 +826,7 @@ static void tcm_qla2xxx_clear_nacl_from_fcport_map(struct fc_port *sess) static void tcm_qla2xxx_shutdown_sess(struct fc_port *sess) { - target_sess_cmd_list_set_waiting(sess->se_sess); + target_stop_session(sess->se_sess); } static int tcm_qla2xxx_init_nodeacl(struct se_node_acl *se_nacl, diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index 62aa5fa63ac0..736847c933e5 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -328,7 +328,7 @@ static void target_shutdown_sessions(struct se_node_acl *acl) restart: spin_lock_irqsave(&acl->nacl_sess_lock, flags); list_for_each_entry(sess, &acl->acl_sess_list, sess_acl_list) { - if (sess->sess_tearing_down) + if (atomic_read(&sess->stopped)) continue; list_del_init(&sess->sess_acl_list); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index faf1bab454d4..485317c02056 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -215,7 +215,7 @@ static void target_release_sess_cmd_refcnt(struct percpu_ref *ref) { struct se_session *sess = container_of(ref, typeof(*sess), cmd_count); - wake_up(&sess->cmd_list_wq); + wake_up(&sess->cmd_count_wq); } /** @@ -228,9 +228,10 @@ int transport_init_session(struct se_session *se_sess) { INIT_LIST_HEAD(&se_sess->sess_list); INIT_LIST_HEAD(&se_sess->sess_acl_list); - INIT_LIST_HEAD(&se_sess->sess_cmd_list); spin_lock_init(&se_sess->sess_cmd_lock); - init_waitqueue_head(&se_sess->cmd_list_wq); + init_waitqueue_head(&se_sess->cmd_count_wq); + init_completion(&se_sess->stop_done); + atomic_set(&se_sess->stopped, 0); return percpu_ref_init(&se_sess->cmd_count, target_release_sess_cmd_refcnt, 0, GFP_KERNEL); } @@ -239,11 +240,11 @@ EXPORT_SYMBOL(transport_init_session); void transport_uninit_session(struct se_session *se_sess) { /* - * Drivers like iscsi and loop do not call - * target_sess_cmd_list_set_waiting during session shutdown so we - * have to drop the ref taken at init time here. + * Drivers like iscsi and loop do not call target_stop_session + * during session shutdown so we have to drop the ref taken at init + * time here. */ - if (!se_sess->sess_tearing_down) + if (!atomic_read(&se_sess->stopped)) percpu_ref_put(&se_sess->cmd_count); percpu_ref_exit(&se_sess->cmd_count); @@ -1632,9 +1633,8 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess if (flags & TARGET_SCF_UNKNOWN_SIZE) se_cmd->unknown_data_length = 1; /* - * Obtain struct se_cmd->cmd_kref reference and add new cmd to - * se_sess->sess_cmd_list. A second kref_get here is necessary - * for fabrics using TARGET_SCF_ACK_KREF that expect a second + * Obtain struct se_cmd->cmd_kref reference. A second kref_get here is + * necessary for fabrics using TARGET_SCF_ACK_KREF that expect a second * kref_put() to happen during fabric packet acknowledgement. */ ret = target_get_sess_cmd(se_cmd, flags & TARGET_SCF_ACK_KREF); @@ -2763,14 +2763,13 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks) EXPORT_SYMBOL(transport_generic_free_cmd); /** - * target_get_sess_cmd - Add command to active ->sess_cmd_list + * target_get_sess_cmd - Verify the session is accepting cmds and take ref * @se_cmd: command descriptor to add * @ack_kref: Signal that fabric will perform an ack target_put_sess_cmd() */ int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref) { struct se_session *se_sess = se_cmd->se_sess; - unsigned long flags; int ret = 0; /* @@ -2785,15 +2784,8 @@ int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref) se_cmd->se_cmd_flags |= SCF_ACK_KREF; } - spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); - if (se_sess->sess_tearing_down) { + if (!percpu_ref_tryget_live(&se_sess->cmd_count)) ret = -ESHUTDOWN; - goto out; - } - list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list); - percpu_ref_get(&se_sess->cmd_count); -out: - spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); if (ret && ack_kref) target_put_sess_cmd(se_cmd); @@ -2818,13 +2810,6 @@ static void target_release_cmd_kref(struct kref *kref) struct se_session *se_sess = se_cmd->se_sess; struct completion *free_compl = se_cmd->free_compl; struct completion *abrt_compl = se_cmd->abrt_compl; - unsigned long flags; - - if (se_sess) { - spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); - list_del_init(&se_cmd->se_cmd_list); - spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); - } target_free_cmd_mem(se_cmd); se_cmd->se_tfo->release_cmd(se_cmd); @@ -2952,21 +2937,25 @@ void target_show_cmd(const char *pfx, struct se_cmd *cmd) } EXPORT_SYMBOL(target_show_cmd); +static void target_stop_session_confirm(struct percpu_ref *ref) +{ + struct se_session *se_sess = container_of(ref, struct se_session, + cmd_count); + complete_all(&se_sess->stop_done); +} + /** - * target_sess_cmd_list_set_waiting - Set sess_tearing_down so no new commands are queued. - * @se_sess: session to flag + * target_stop_session - Stop new IO from being queued on the session. + * @se_sess: session to stop */ -void target_sess_cmd_list_set_waiting(struct se_session *se_sess) +void target_stop_session(struct se_session *se_sess) { - unsigned long flags; - - spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); - se_sess->sess_tearing_down = 1; - spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); - - percpu_ref_kill(&se_sess->cmd_count); + pr_debug("Stopping session queue.\n"); + if (atomic_cmpxchg(&se_sess->stopped, 0, 1) == 0) + percpu_ref_kill_and_confirm(&se_sess->cmd_count, + target_stop_session_confirm); } -EXPORT_SYMBOL(target_sess_cmd_list_set_waiting); +EXPORT_SYMBOL(target_stop_session); /** * target_wait_for_sess_cmds - Wait for outstanding commands @@ -2974,19 +2963,19 @@ EXPORT_SYMBOL(target_sess_cmd_list_set_waiting); */ void target_wait_for_sess_cmds(struct se_session *se_sess) { - struct se_cmd *cmd; int ret; - WARN_ON_ONCE(!se_sess->sess_tearing_down); + WARN_ON_ONCE(!atomic_read(&se_sess->stopped)); do { - ret = wait_event_timeout(se_sess->cmd_list_wq, + pr_debug("Waiting for running cmds to complete.\n"); + ret = wait_event_timeout(se_sess->cmd_count_wq, percpu_ref_is_zero(&se_sess->cmd_count), 180 * HZ); - list_for_each_entry(cmd, &se_sess->sess_cmd_list, se_cmd_list) - target_show_cmd("session shutdown: still waiting for ", - cmd); } while (ret <= 0); + + wait_for_completion(&se_sess->stop_done); + pr_debug("Waiting for cmds done.\n"); } EXPORT_SYMBOL(target_wait_for_sess_cmds); diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 4fd6a1de947c..23ce506d5402 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -275,7 +275,7 @@ static struct ft_sess *ft_sess_delete(struct ft_tport *tport, u32 port_id) static void ft_close_sess(struct ft_sess *sess) { - target_sess_cmd_list_set_waiting(sess->se_sess); + target_stop_session(sess->se_sess); target_wait_for_sess_cmds(sess->se_sess); ft_sess_put(sess); } diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 7d632593c398..c858dc060381 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -608,7 +608,7 @@ static inline struct se_node_acl *fabric_stat_to_nacl(struct config_item *item) } struct se_session { - unsigned sess_tearing_down:1; + atomic_t stopped; u64 sess_bin_isid; enum target_prot_op sup_prot_ops; enum target_prot_type sess_prot_type; @@ -618,9 +618,9 @@ struct se_session { struct percpu_ref cmd_count; struct list_head sess_list; struct list_head sess_acl_list; - struct list_head sess_cmd_list; spinlock_t sess_cmd_lock; - wait_queue_head_t cmd_list_wq; + wait_queue_head_t cmd_count_wq; + struct completion stop_done; void *sess_cmd_map; struct sbitmap_queue sess_tag_pool; }; diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h index 6adf4d71acf6..d60a3eb7517a 100644 --- a/include/target/target_core_fabric.h +++ b/include/target/target_core_fabric.h @@ -178,7 +178,7 @@ int transport_send_check_condition_and_sense(struct se_cmd *, int target_send_busy(struct se_cmd *cmd); int target_get_sess_cmd(struct se_cmd *, bool); int target_put_sess_cmd(struct se_cmd *); -void target_sess_cmd_list_set_waiting(struct se_session *); +void target_stop_session(struct se_session *se_sess); void target_wait_for_sess_cmds(struct se_session *); void target_show_cmd(const char *pfx, struct se_cmd *cmd); -- cgit v1.2.3 From 1526d9f10c6184031e42afad0adbdde1213e8ad1 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sun, 1 Nov 2020 12:59:33 -0600 Subject: scsi: target: Make state_list per CPU Do a state_list/execute_task_lock per CPU, so we can do submissions from different CPUs without contention with each other. Note: tcm_fc was passing TARGET_SCF_USE_CPUID, but never set cpuid. The assumption is that it wanted to set the cpuid to the CPU it was submitting from so it will get this behavior with this patch. [mkp: s/printk/pr_err/ + resolve COMPARE AND WRITE patch conflict] Link: https://lore.kernel.org/r/1604257174-4524-8-git-send-email-michael.christie@oracle.com Reviewed-by: Himanshu Madhani Signed-off-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/target/target_core_device.c | 16 +++- drivers/target/target_core_tmr.c | 166 +++++++++++++++++---------------- drivers/target/target_core_transport.c | 27 +++--- drivers/target/tcm_fc/tfc_cmd.c | 2 +- include/target/target_core_base.h | 13 ++- 5 files changed, 126 insertions(+), 98 deletions(-) (limited to 'drivers') diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 1f673fbc28f9..7787c527aad3 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -721,11 +721,24 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) { struct se_device *dev; struct se_lun *xcopy_lun; + int i; dev = hba->backend->ops->alloc_device(hba, name); if (!dev) return NULL; + dev->queues = kcalloc(nr_cpu_ids, sizeof(*dev->queues), GFP_KERNEL); + if (!dev->queues) { + dev->transport->free_device(dev); + return NULL; + } + + dev->queue_cnt = nr_cpu_ids; + for (i = 0; i < dev->queue_cnt; i++) { + INIT_LIST_HEAD(&dev->queues[i].state_list); + spin_lock_init(&dev->queues[i].lock); + } + dev->se_hba = hba; dev->transport = hba->backend->ops; dev->transport_flags = dev->transport->transport_flags_default; @@ -735,9 +748,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) INIT_LIST_HEAD(&dev->dev_sep_list); INIT_LIST_HEAD(&dev->dev_tmr_list); INIT_LIST_HEAD(&dev->delayed_cmd_list); - INIT_LIST_HEAD(&dev->state_list); INIT_LIST_HEAD(&dev->qf_cmd_list); - spin_lock_init(&dev->execute_task_lock); spin_lock_init(&dev->delayed_cmd_lock); spin_lock_init(&dev->dev_reservation_lock); spin_lock_init(&dev->se_port_lock); @@ -1010,6 +1021,7 @@ void target_free_device(struct se_device *dev) if (dev->transport->free_prot) dev->transport->free_prot(dev); + kfree(dev->queues); dev->transport->free_device(dev); } diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index e4513ef09159..7347285471fa 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -121,57 +121,61 @@ void core_tmr_abort_task( unsigned long flags; bool rc; u64 ref_tag; - - spin_lock_irqsave(&dev->execute_task_lock, flags); - list_for_each_entry_safe(se_cmd, next, &dev->state_list, state_list) { - - if (se_sess != se_cmd->se_sess) - continue; - - /* skip task management functions, including tmr->task_cmd */ - if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) - continue; - - ref_tag = se_cmd->tag; - if (tmr->ref_task_tag != ref_tag) - continue; - - printk("ABORT_TASK: Found referenced %s task_tag: %llu\n", - se_cmd->se_tfo->fabric_name, ref_tag); - - spin_lock(&se_sess->sess_cmd_lock); - rc = __target_check_io_state(se_cmd, se_sess, 0); - spin_unlock(&se_sess->sess_cmd_lock); - if (!rc) - continue; - - list_move_tail(&se_cmd->state_list, &aborted_list); - se_cmd->state_active = false; - - spin_unlock_irqrestore(&dev->execute_task_lock, flags); - - /* - * Ensure that this ABORT request is visible to the LU RESET - * code. - */ - if (!tmr->tmr_dev) - WARN_ON_ONCE(transport_lookup_tmr_lun(tmr->task_cmd) < - 0); - - if (dev->transport->tmr_notify) - dev->transport->tmr_notify(dev, TMR_ABORT_TASK, - &aborted_list); - - list_del_init(&se_cmd->state_list); - target_put_cmd_and_wait(se_cmd); - - printk("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for" - " ref_tag: %llu\n", ref_tag); - tmr->response = TMR_FUNCTION_COMPLETE; - atomic_long_inc(&dev->aborts_complete); - return; + int i; + + for (i = 0; i < dev->queue_cnt; i++) { + spin_lock_irqsave(&dev->queues[i].lock, flags); + list_for_each_entry_safe(se_cmd, next, &dev->queues[i].state_list, + state_list) { + if (se_sess != se_cmd->se_sess) + continue; + + /* + * skip task management functions, including + * tmr->task_cmd + */ + if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) + continue; + + ref_tag = se_cmd->tag; + if (tmr->ref_task_tag != ref_tag) + continue; + + pr_err("ABORT_TASK: Found referenced %s task_tag: %llu\n", + se_cmd->se_tfo->fabric_name, ref_tag); + + spin_lock(&se_sess->sess_cmd_lock); + rc = __target_check_io_state(se_cmd, se_sess, 0); + spin_unlock(&se_sess->sess_cmd_lock); + if (!rc) + continue; + + list_move_tail(&se_cmd->state_list, &aborted_list); + se_cmd->state_active = false; + spin_unlock_irqrestore(&dev->queues[i].lock, flags); + + /* + * Ensure that this ABORT request is visible to the LU + * RESET code. + */ + if (!tmr->tmr_dev) + WARN_ON_ONCE(transport_lookup_tmr_lun(tmr->task_cmd) < 0); + + if (dev->transport->tmr_notify) + dev->transport->tmr_notify(dev, TMR_ABORT_TASK, + &aborted_list); + + list_del_init(&se_cmd->state_list); + target_put_cmd_and_wait(se_cmd); + + pr_err("ABORT_TASK: Sending TMR_FUNCTION_COMPLETE for ref_tag: %llu\n", + ref_tag); + tmr->response = TMR_FUNCTION_COMPLETE; + atomic_long_inc(&dev->aborts_complete); + return; + } + spin_unlock_irqrestore(&dev->queues[i].lock, flags); } - spin_unlock_irqrestore(&dev->execute_task_lock, flags); if (dev->transport->tmr_notify) dev->transport->tmr_notify(dev, TMR_ABORT_TASK, &aborted_list); @@ -273,7 +277,7 @@ static void core_tmr_drain_state_list( struct se_session *sess; struct se_cmd *cmd, *next; unsigned long flags; - int rc; + int rc, i; /* * Complete outstanding commands with TASK_ABORTED SAM status. @@ -297,35 +301,39 @@ static void core_tmr_drain_state_list( * Note that this seems to be independent of TAS (Task Aborted Status) * in the Control Mode Page. */ - spin_lock_irqsave(&dev->execute_task_lock, flags); - list_for_each_entry_safe(cmd, next, &dev->state_list, state_list) { - /* - * For PREEMPT_AND_ABORT usage, only process commands - * with a matching reservation key. - */ - if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd)) - continue; - - /* - * Not aborting PROUT PREEMPT_AND_ABORT CDB.. - */ - if (prout_cmd == cmd) - continue; - - sess = cmd->se_sess; - if (WARN_ON_ONCE(!sess)) - continue; - - spin_lock(&sess->sess_cmd_lock); - rc = __target_check_io_state(cmd, tmr_sess, tas); - spin_unlock(&sess->sess_cmd_lock); - if (!rc) - continue; - - list_move_tail(&cmd->state_list, &drain_task_list); - cmd->state_active = false; + for (i = 0; i < dev->queue_cnt; i++) { + spin_lock_irqsave(&dev->queues[i].lock, flags); + list_for_each_entry_safe(cmd, next, &dev->queues[i].state_list, + state_list) { + /* + * For PREEMPT_AND_ABORT usage, only process commands + * with a matching reservation key. + */ + if (target_check_cdb_and_preempt(preempt_and_abort_list, + cmd)) + continue; + + /* + * Not aborting PROUT PREEMPT_AND_ABORT CDB.. + */ + if (prout_cmd == cmd) + continue; + + sess = cmd->se_sess; + if (WARN_ON_ONCE(!sess)) + continue; + + spin_lock(&sess->sess_cmd_lock); + rc = __target_check_io_state(cmd, tmr_sess, tas); + spin_unlock(&sess->sess_cmd_lock); + if (!rc) + continue; + + list_move_tail(&cmd->state_list, &drain_task_list); + cmd->state_active = false; + } + spin_unlock_irqrestore(&dev->queues[i].lock, flags); } - spin_unlock_irqrestore(&dev->execute_task_lock, flags); if (dev->transport->tmr_notify) dev->transport->tmr_notify(dev, preempt_and_abort_list ? diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 485317c02056..fca4bd079d02 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -659,12 +659,12 @@ static void target_remove_from_state_list(struct se_cmd *cmd) if (!dev) return; - spin_lock_irqsave(&dev->execute_task_lock, flags); + spin_lock_irqsave(&dev->queues[cmd->cpuid].lock, flags); if (cmd->state_active) { list_del(&cmd->state_list); cmd->state_active = false; } - spin_unlock_irqrestore(&dev->execute_task_lock, flags); + spin_unlock_irqrestore(&dev->queues[cmd->cpuid].lock, flags); } /* @@ -875,10 +875,7 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) INIT_WORK(&cmd->work, success ? target_complete_ok_work : target_complete_failure_work); - if (cmd->se_cmd_flags & SCF_USE_CPUID) - queue_work_on(cmd->cpuid, target_completion_wq, &cmd->work); - else - queue_work(target_completion_wq, &cmd->work); + queue_work_on(cmd->cpuid, target_completion_wq, &cmd->work); } EXPORT_SYMBOL(target_complete_cmd); @@ -906,12 +903,13 @@ static void target_add_to_state_list(struct se_cmd *cmd) struct se_device *dev = cmd->se_dev; unsigned long flags; - spin_lock_irqsave(&dev->execute_task_lock, flags); + spin_lock_irqsave(&dev->queues[cmd->cpuid].lock, flags); if (!cmd->state_active) { - list_add_tail(&cmd->state_list, &dev->state_list); + list_add_tail(&cmd->state_list, + &dev->queues[cmd->cpuid].state_list); cmd->state_active = true; } - spin_unlock_irqrestore(&dev->execute_task_lock, flags); + spin_unlock_irqrestore(&dev->queues[cmd->cpuid].lock, flags); } /* @@ -1399,6 +1397,9 @@ void transport_init_se_cmd( cmd->sense_buffer = sense_buffer; cmd->orig_fe_lun = unpacked_lun; + if (!(cmd->se_cmd_flags & SCF_USE_CPUID)) + cmd->cpuid = smp_processor_id(); + cmd->state_active = false; } EXPORT_SYMBOL(transport_init_se_cmd); @@ -1616,6 +1617,9 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess BUG_ON(!se_tpg); BUG_ON(se_cmd->se_tfo || se_cmd->se_sess); BUG_ON(in_interrupt()); + + if (flags & TARGET_SCF_USE_CPUID) + se_cmd->se_cmd_flags |= SCF_USE_CPUID; /* * Initialize se_cmd for target operation. From this point * exceptions are handled by sending exception status via @@ -1625,11 +1629,6 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess data_length, data_dir, task_attr, sense, unpacked_lun); - if (flags & TARGET_SCF_USE_CPUID) - se_cmd->se_cmd_flags |= SCF_USE_CPUID; - else - se_cmd->cpuid = WORK_CPU_UNBOUND; - if (flags & TARGET_SCF_UNKNOWN_SIZE) se_cmd->unknown_data_length = 1; /* diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 9c8c38a549c6..768f250680d9 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -550,7 +550,7 @@ static void ft_send_work(struct work_struct *work) if (target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb, &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun), ntohl(fcp->fc_dl), task_attr, data_dir, - TARGET_SCF_ACK_KREF | TARGET_SCF_USE_CPUID)) + TARGET_SCF_ACK_KREF)) goto err; pr_debug("r_ctl %x target_submit_cmd %p\n", fh->fh_r_ctl, cmd); diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index c858dc060381..63dd12124139 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -540,6 +540,10 @@ struct se_cmd { unsigned int t_prot_nents; sense_reason_t pi_err; u64 sense_info; + /* + * CPU LIO will execute the cmd on. Defaults to the CPU the cmd is + * initialized on. Drivers can override. + */ int cpuid; }; @@ -760,6 +764,11 @@ struct se_dev_stat_grps { struct config_group scsi_lu_group; }; +struct se_device_queue { + struct list_head state_list; + spinlock_t lock; +}; + struct se_device { /* RELATIVE TARGET PORT IDENTIFER Counter */ u16 dev_rpti_counter; @@ -792,7 +801,6 @@ struct se_device { atomic_t dev_qf_count; u32 export_count; spinlock_t delayed_cmd_lock; - spinlock_t execute_task_lock; spinlock_t dev_reservation_lock; unsigned int dev_reservation_flags; #define DRF_SPC2_RESERVATIONS 0x00000001 @@ -811,7 +819,6 @@ struct se_device { struct list_head dev_tmr_list; struct work_struct qf_work_queue; struct list_head delayed_cmd_list; - struct list_head state_list; struct list_head qf_cmd_list; /* Pointer to associated SE HBA */ struct se_hba *se_hba; @@ -838,6 +845,8 @@ struct se_device { /* For se_lun->lun_se_dev RCU read-side critical access */ u32 hba_index; struct rcu_head rcu_head; + int queue_cnt; + struct se_device_queue *queues; }; struct se_hba { -- cgit v1.2.3 From 94a0dfcf7d33ea96bf3eb0c33e4239942a4ff087 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Sun, 1 Nov 2020 12:59:34 -0600 Subject: scsi: tcm_loop: Allow queues, can_queue and cmd_per_lun to be settable Make can_queue, nr_hw_queues and cmd_per_lun settable by the user instead of hard coding them. Link: https://lore.kernel.org/r/1604257174-4524-9-git-send-email-michael.christie@oracle.com Reviewed-by: Himanshu Madhani Signed-off-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/target/loopback/tcm_loop.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index 16d5a4e117a2..badba437e5f9 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -46,6 +46,15 @@ static int tcm_loop_hba_no_cnt; static int tcm_loop_queue_status(struct se_cmd *se_cmd); +static unsigned int tcm_loop_nr_hw_queues = 1; +module_param_named(nr_hw_queues, tcm_loop_nr_hw_queues, uint, 0644); + +static unsigned int tcm_loop_can_queue = 1024; +module_param_named(can_queue, tcm_loop_can_queue, uint, 0644); + +static unsigned int tcm_loop_cmd_per_lun = 1024; +module_param_named(cmd_per_lun, tcm_loop_cmd_per_lun, uint, 0644); + /* * Called from struct target_core_fabric_ops->check_stop_free() */ @@ -305,10 +314,8 @@ static struct scsi_host_template tcm_loop_driver_template = { .eh_abort_handler = tcm_loop_abort_task, .eh_device_reset_handler = tcm_loop_device_reset, .eh_target_reset_handler = tcm_loop_target_reset, - .can_queue = 1024, .this_id = -1, .sg_tablesize = 256, - .cmd_per_lun = 1024, .max_sectors = 0xFFFF, .dma_boundary = PAGE_SIZE - 1, .module = THIS_MODULE, @@ -342,6 +349,9 @@ static int tcm_loop_driver_probe(struct device *dev) sh->max_lun = 0; sh->max_channel = 0; sh->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE; + sh->nr_hw_queues = tcm_loop_nr_hw_queues; + sh->can_queue = tcm_loop_can_queue; + sh->cmd_per_lun = tcm_loop_cmd_per_lun; host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION | SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION | -- cgit v1.2.3 From 7640e1eb8c5de33dafa6c68fd4389214ff9ec1f9 Mon Sep 17 00:00:00 2001 From: peter chang Date: Mon, 2 Nov 2020 22:25:25 +0530 Subject: scsi: pm80xx: Make mpi_build_cmd locking consistent Driver submits all internal requests (like abort_task, event acknowledgment etc.) through inbound queue 0. While submitting those, driver does not acquire any lock and this may lead to a race when there is an I/O request coming in on CPU0 and submitted through inbound queue 0. To avoid this, lock acquisition has been moved to pm8001_mpi_build_cmd(). All command submission will go through this path. Link: https://lore.kernel.org/r/20201102165528.26510-2-Viswas.G@microchip.com.com Acked-by: Jack Wang Signed-off-by: peter chang Signed-off-by: Viswas G Signed-off-by: Ruksar Devadi Signed-off-by: Radha Ramachandran Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_hwi.c | 21 +++++++++++++++------ drivers/scsi/pm8001/pm80xx_hwi.c | 8 -------- 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 2b7b2954ec31..597d7a096a97 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -1356,12 +1356,19 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, { u32 Header = 0, hpriority = 0, bc = 1, category = 0x02; void *pMessage; - - if (pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size, - &pMessage) < 0) { + unsigned long flags; + int q_index = circularQ - pm8001_ha->inbnd_q_tbl; + int rv = -1; + + WARN_ON(q_index >= PM8001_MAX_INB_NUM); + spin_lock_irqsave(&circularQ->iq_lock, flags); + rv = pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size, + &pMessage); + if (rv < 0) { PM8001_IO_DBG(pm8001_ha, - pm8001_printk("No free mpi buffer\n")); - return -ENOMEM; + pm8001_printk("No free mpi buffer\n")); + rv = -ENOMEM; + goto done; } if (nb > (pm8001_ha->iomb_size - sizeof(struct mpi_msg_hdr))) @@ -1384,7 +1391,9 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, pm8001_printk("INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n", responseQueue, opCode, circularQ->producer_idx, circularQ->consumer_index)); - return 0; +done: + spin_unlock_irqrestore(&circularQ->iq_lock, flags); + return rv; } u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg, diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 7593f248afb2..5fe50e0effcd 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -4281,7 +4281,6 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, char *preq_dma_addr = NULL; __le64 tmp_addr; u32 i, length; - unsigned long flags; memset(&smp_cmd, 0, sizeof(smp_cmd)); /* @@ -4377,10 +4376,8 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd, pm8001_ha->smp_exp_mode, length); - spin_lock_irqsave(&circularQ->iq_lock, flags); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &smp_cmd, sizeof(smp_cmd), 0); - spin_unlock_irqrestore(&circularQ->iq_lock, flags); if (rc) goto err_out_2; return 0; @@ -4444,7 +4441,6 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, u64 phys_addr, start_addr, end_addr; u32 end_addr_high, end_addr_low; struct inbound_queue_table *circularQ; - unsigned long flags; u32 q_index, cpu_id; u32 opc = OPC_INB_SSPINIIOSTART; memset(&ssp_cmd, 0, sizeof(ssp_cmd)); @@ -4582,10 +4578,8 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, ssp_cmd.esgl = 0; } } - spin_lock_irqsave(&circularQ->iq_lock, flags); ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, sizeof(ssp_cmd), q_index); - spin_unlock_irqrestore(&circularQ->iq_lock, flags); return ret; } @@ -4819,10 +4813,8 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, } } } - spin_lock_irqsave(&circularQ->iq_lock, flags); ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, sizeof(sata_cmd), q_index); - spin_unlock_irqrestore(&circularQ->iq_lock, flags); return ret; } -- cgit v1.2.3 From 4a2efd4b89fcaa6e9a7b4ce49a441afaacba00ea Mon Sep 17 00:00:00 2001 From: Viswas G Date: Mon, 2 Nov 2020 22:25:26 +0530 Subject: scsi: pm80xx: Make running_req atomic Incorrect value of the running_req was causing the driver unload to be stuck during the SAS lldd_dev_gone notification handling. During SATA I/O completion, for some error status values, the driver schedules the event handler and running_req is decremented from that. However, there are some other error status values (like IO_DS_IN_RECOVERY, IO_XFER_ERR_LAST_PIO_DATAIN_CRC_ERR) where the I/O has already been completed by fw/driver so running_req is not decremented. Also during NCQ error handling, driver itself will initiate READ_LOG_EXT and ABORT_ALL. When libsas/libata initiate READ_LOG_EXT (0x2F), driver increments running_req. This will be completed by the driver in pm80xx_chip_sata_req(), but running_req was not decremented. Link: https://lore.kernel.org/r/20201102165528.26510-3-Viswas.G@microchip.com.com Acked-by: Jack Wang Signed-off-by: Viswas G Signed-off-by: Ruksar Devadi Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_hwi.c | 58 +++++++++++++++++----- drivers/scsi/pm8001/pm8001_init.c | 2 +- drivers/scsi/pm8001/pm8001_sas.c | 11 +++-- drivers/scsi/pm8001/pm8001_sas.h | 2 +- drivers/scsi/pm8001/pm80xx_hwi.c | 101 ++++++++++++++++++++++++++++++++++---- 5 files changed, 147 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 597d7a096a97..9e9a546da959 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -1587,7 +1587,7 @@ void pm8001_work_fn(struct work_struct *work) ts->stat = SAS_QUEUE_FULL; pm8001_dev = ccb->device; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); spin_lock_irqsave(&t->task_state_lock, flags1); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; @@ -1942,7 +1942,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) sas_ssp_task_response(pm8001_ha->dev, t, iu); } if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_ABORTED: PM8001_IO_DBG(pm8001_ha, @@ -1958,7 +1958,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->stat = SAS_DATA_UNDERRUN; ts->residual = param; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_NO_DEVICE: PM8001_IO_DBG(pm8001_ha, @@ -2172,7 +2172,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->stat = SAS_DATA_OVERRUN; ts->residual = 0; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_BREAK: PM8001_IO_DBG(pm8001_ha, @@ -2487,7 +2487,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk("response to large\n")); } if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_ABORTED: PM8001_IO_DBG(pm8001_ha, @@ -2495,7 +2495,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; /* following cases are to do cases */ case IO_UNDERFLOW: @@ -2506,19 +2506,23 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->stat = SAS_DATA_UNDERRUN; ts->residual = param; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_NO_DEVICE: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n")); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_PHY_DOWN; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_BREAK: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_BREAK\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_INTERRUPTED; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_PHY_NOT_READY: PM8001_IO_DBG(pm8001_ha, @@ -2526,6 +2530,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: PM8001_IO_DBG(pm8001_ha, @@ -2534,6 +2540,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_EPROTO; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: PM8001_IO_DBG(pm8001_ha, @@ -2541,6 +2549,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_BREAK: PM8001_IO_DBG(pm8001_ha, @@ -2548,6 +2558,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: PM8001_IO_DBG(pm8001_ha, @@ -2587,6 +2599,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_CONN_RATE; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY: PM8001_IO_DBG(pm8001_ha, @@ -2610,48 +2624,64 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_WRONG_DEST; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_NAK_RECEIVED: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_ACK_NAK_TIMEOUT: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_DMA: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_DMA\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_SATA_LINK_TIMEOUT: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_SATA_LINK_TIMEOUT\n")); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_DEV_NO_RESPONSE; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_REJECTED_NCQ_MODE: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_UNDERRUN; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_OPEN_RETRY_TIMEOUT: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_PORT_IN_RESET: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_PORT_IN_RESET\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_DS_NON_OPERATIONAL: PM8001_IO_DBG(pm8001_ha, @@ -2672,6 +2702,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk(" IO_DS_IN_RECOVERY\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_DS_IN_ERROR: PM8001_IO_DBG(pm8001_ha, @@ -2693,6 +2725,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; default: PM8001_DEVIO_DBG(pm8001_ha, @@ -2700,6 +2734,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; } spin_lock_irqsave(&t->task_state_lock, flags); @@ -2776,7 +2812,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->stat = SAS_DATA_OVERRUN; ts->residual = 0; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_BREAK: PM8001_IO_DBG(pm8001_ha, @@ -2976,7 +3012,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAM_STAT_GOOD; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_ABORTED: PM8001_IO_DBG(pm8001_ha, @@ -2984,7 +3020,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_OVERFLOW: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n")); @@ -2992,7 +3028,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->stat = SAS_DATA_OVERRUN; ts->residual = 0; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_NO_DEVICE: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n")); diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 3cf3e58b6979..fb471ad3720a 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -412,7 +412,7 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, pm8001_ha->devices[i].dev_type = SAS_PHY_UNUSED; pm8001_ha->devices[i].id = i; pm8001_ha->devices[i].device_id = PM8001_MAX_DEVICES; - pm8001_ha->devices[i].running_req = 0; + atomic_set(&pm8001_ha->devices[i].running_req, 0); } pm8001_ha->flags = PM8001F_INIT_TIME; /* Initialize tags */ diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 9889bab7d31c..d6e0bc588698 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -456,9 +456,11 @@ static int pm8001_task_exec(struct sas_task *task, ccb->device = pm8001_dev; switch (task_proto) { case SAS_PROTOCOL_SMP: + atomic_inc(&pm8001_dev->running_req); rc = pm8001_task_prep_smp(pm8001_ha, ccb); break; case SAS_PROTOCOL_SSP: + atomic_inc(&pm8001_dev->running_req); if (is_tmf) rc = pm8001_task_prep_ssp_tm(pm8001_ha, ccb, tmf); @@ -467,6 +469,7 @@ static int pm8001_task_exec(struct sas_task *task, break; case SAS_PROTOCOL_SATA: case SAS_PROTOCOL_STP: + atomic_inc(&pm8001_dev->running_req); rc = pm8001_task_prep_ata(pm8001_ha, ccb); break; default: @@ -479,13 +482,13 @@ static int pm8001_task_exec(struct sas_task *task, if (rc) { PM8001_IO_DBG(pm8001_ha, pm8001_printk("rc is %x\n", rc)); + atomic_dec(&pm8001_dev->running_req); goto err_out_tag; } /* TODO: select normal or high priority */ spin_lock(&t->task_state_lock); t->task_state_flags |= SAS_TASK_AT_INITIATOR; spin_unlock(&t->task_state_lock); - pm8001_dev->running_req++; } while (0); rc = 0; goto out_done; @@ -886,11 +889,11 @@ static void pm8001_dev_gone_notify(struct domain_device *dev) PM8001_DISC_DBG(pm8001_ha, pm8001_printk("found dev[%d:%x] is gone.\n", pm8001_dev->device_id, pm8001_dev->dev_type)); - if (pm8001_dev->running_req) { + if (atomic_read(&pm8001_dev->running_req)) { spin_unlock_irqrestore(&pm8001_ha->lock, flags); pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , dev, 1, 0); - while (pm8001_dev->running_req) + while (atomic_read(&pm8001_dev->running_req)) msleep(20); spin_lock_irqsave(&pm8001_ha->lock, flags); } @@ -968,7 +971,7 @@ void pm8001_open_reject_retry( ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); spin_lock_irqsave(&task->task_state_lock, flags1); task->task_state_flags &= ~SAS_TASK_STATE_PENDING; task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 95663e138083..091574721ea1 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -293,7 +293,7 @@ struct pm8001_device { struct completion *dcompletion; struct completion *setds_completion; u32 device_id; - u32 running_req; + atomic_t running_req; }; struct pm8001_prd_imt { diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 5fe50e0effcd..1ba93fb76093 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -1960,13 +1960,15 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) sas_ssp_task_response(pm8001_ha->dev, t, iu); } if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_ABORTED: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_ABORTED IOMB Tag\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_UNDERFLOW: /* SSP Completion with error */ @@ -1977,13 +1979,15 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->stat = SAS_DATA_UNDERRUN; ts->residual = param; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_NO_DEVICE: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n")); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_PHY_DOWN; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_BREAK: PM8001_IO_DBG(pm8001_ha, @@ -1992,6 +1996,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->stat = SAS_OPEN_REJECT; /* Force the midlayer to retry */ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_PHY_NOT_READY: PM8001_IO_DBG(pm8001_ha, @@ -1999,6 +2005,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_INVALID_SSP_RSP_FRAME: PM8001_IO_DBG(pm8001_ha, @@ -2006,6 +2014,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: PM8001_IO_DBG(pm8001_ha, @@ -2013,6 +2023,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_EPROTO; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: PM8001_IO_DBG(pm8001_ha, @@ -2020,6 +2032,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_BREAK: PM8001_IO_DBG(pm8001_ha, @@ -2027,6 +2041,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED: @@ -2050,6 +2066,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_BAD_DEST; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: PM8001_IO_DBG(pm8001_ha, pm8001_printk( @@ -2057,6 +2075,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_CONN_RATE; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: PM8001_IO_DBG(pm8001_ha, @@ -2064,6 +2084,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_WRONG_DEST; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_NAK_RECEIVED: PM8001_IO_DBG(pm8001_ha, @@ -2071,18 +2093,24 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_ACK_NAK_TIMEOUT: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_DMA: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_DMA\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_OPEN_RETRY_TIMEOUT: PM8001_IO_DBG(pm8001_ha, @@ -2090,18 +2118,24 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_OFFSET_MISMATCH: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_PORT_IN_RESET: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_PORT_IN_RESET\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_DS_NON_OPERATIONAL: PM8001_IO_DBG(pm8001_ha, @@ -2118,18 +2152,24 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) pm8001_printk("IO_DS_IN_RECOVERY\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_TM_TAG_NOT_FOUND: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_TM_TAG_NOT_FOUND\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_SSP_EXT_IU_ZERO_LEN_ERROR: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SSP_EXT_IU_ZERO_LEN_ERROR\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY: PM8001_IO_DBG(pm8001_ha, @@ -2137,6 +2177,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; default: PM8001_DEVIO_DBG(pm8001_ha, @@ -2144,6 +2186,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; } PM8001_IO_DBG(pm8001_ha, @@ -2203,7 +2247,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->stat = SAS_DATA_OVERRUN; ts->residual = 0; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_BREAK: PM8001_IO_DBG(pm8001_ha, @@ -2528,7 +2572,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk("response too large\n")); } if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_ABORTED: PM8001_IO_DBG(pm8001_ha, @@ -2536,7 +2580,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; /* following cases are to do cases */ case IO_UNDERFLOW: @@ -2547,19 +2591,23 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->stat = SAS_DATA_UNDERRUN; ts->residual = param; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_NO_DEVICE: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n")); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_PHY_DOWN; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_BREAK: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_BREAK\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_INTERRUPTED; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_PHY_NOT_READY: PM8001_IO_DBG(pm8001_ha, @@ -2567,6 +2615,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: PM8001_IO_DBG(pm8001_ha, pm8001_printk( @@ -2574,6 +2624,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_EPROTO; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: PM8001_IO_DBG(pm8001_ha, @@ -2581,6 +2633,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_BREAK: PM8001_IO_DBG(pm8001_ha, @@ -2588,6 +2642,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED: @@ -2631,6 +2687,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_CONN_RATE; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY: PM8001_IO_DBG(pm8001_ha, pm8001_printk( @@ -2653,48 +2711,64 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_WRONG_DEST; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_NAK_RECEIVED: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_ACK_NAK_TIMEOUT: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_DMA: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_DMA\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_SATA_LINK_TIMEOUT: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_SATA_LINK_TIMEOUT\n")); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_DEV_NO_RESPONSE; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_REJECTED_NCQ_MODE: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_UNDERRUN; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_OPEN_RETRY_TIMEOUT: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_PORT_IN_RESET: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_PORT_IN_RESET\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_DS_NON_OPERATIONAL: PM8001_IO_DBG(pm8001_ha, @@ -2715,6 +2789,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk("IO_DS_IN_RECOVERY\n")); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; case IO_DS_IN_ERROR: PM8001_IO_DBG(pm8001_ha, @@ -2736,6 +2812,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; default: PM8001_DEVIO_DBG(pm8001_ha, @@ -2743,6 +2821,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; + if (pm8001_dev) + atomic_dec(&pm8001_dev->running_req); break; } spin_lock_irqsave(&t->task_state_lock, flags); @@ -2820,7 +2900,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->stat = SAS_DATA_OVERRUN; ts->residual = 0; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_BREAK: PM8001_IO_DBG(pm8001_ha, @@ -3040,7 +3120,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAM_STAT_GOOD; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); if (pm8001_ha->smp_exp_mode == SMP_DIRECT) { PM8001_IO_DBG(pm8001_ha, pm8001_printk("DIRECT RESPONSE Length:%d\n", @@ -3063,7 +3143,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_OVERFLOW: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n")); @@ -3071,7 +3151,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->stat = SAS_DATA_OVERRUN; ts->residual = 0; if (pm8001_dev) - pm8001_dev->running_req--; + atomic_dec(&pm8001_dev->running_req); break; case IO_NO_DEVICE: PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n")); @@ -4809,6 +4889,7 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, flags); pm8001_ccb_task_free_done(pm8001_ha, task, ccb, tag); + atomic_dec(&pm8001_ha_dev->running_req); return 0; } } -- cgit v1.2.3 From 48cd6b38eb4f2874f091c4776ea1c26e7e4f967e Mon Sep 17 00:00:00 2001 From: akshatzen Date: Mon, 2 Nov 2020 22:25:27 +0530 Subject: scsi: pm80xx: Avoid busywait in FW ready check In function check_fw_ready() we busy wait using udelay. The CPU is not released and we see need_resched failures. Busy waiting is not necessary since we are in process context and we can sleep instead. Replace udelay with msleep of 20 ms intervals while waiting for firmware to become ready. It has been verified that check_fw_ready is not being used in interrupt context anywhere, hence it is safe to make this change. Link: https://lore.kernel.org/r/20201102165528.26510-4-Viswas.G@microchip.com.com Acked-by: Jack Wang Signed-off-by: akshatzen Signed-off-by: Viswas G Signed-off-by: Ruksar Devadi Signed-off-by: Radha Ramachandran Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm80xx_hwi.c | 21 +++++++++++---------- drivers/scsi/pm8001/pm80xx_hwi.h | 6 ++++++ 2 files changed, 17 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 1ba93fb76093..24a4f6b9e79d 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -1042,6 +1042,7 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha) /** * check_fw_ready - The LLDD check if the FW is ready, if not, return error. + * This function sleeps hence it must not be used in atomic context. * @pm8001_ha: our hba card information */ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha) @@ -1052,16 +1053,16 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha) int ret = 0; /* reset / PCIe ready */ - max_wait_time = max_wait_count = 100 * 1000; /* 100 milli sec */ + max_wait_time = max_wait_count = 5; /* 100 milli sec */ do { - udelay(1); + msleep(FW_READY_INTERVAL); value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); } while ((value == 0xFFFFFFFF) && (--max_wait_count)); /* check ila status */ - max_wait_time = max_wait_count = 1000 * 1000; /* 1000 milli sec */ + max_wait_time = max_wait_count = 50; /* 1000 milli sec */ do { - udelay(1); + msleep(FW_READY_INTERVAL); value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); } while (((value & SCRATCH_PAD_ILA_READY) != SCRATCH_PAD_ILA_READY) && (--max_wait_count)); @@ -1074,9 +1075,9 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha) } /* check RAAE status */ - max_wait_time = max_wait_count = 1800 * 1000; /* 1800 milli sec */ + max_wait_time = max_wait_count = 90; /* 1800 milli sec */ do { - udelay(1); + msleep(FW_READY_INTERVAL); value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); } while (((value & SCRATCH_PAD_RAAE_READY) != SCRATCH_PAD_RAAE_READY) && (--max_wait_count)); @@ -1089,9 +1090,9 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha) } /* check iop0 status */ - max_wait_time = max_wait_count = 600 * 1000; /* 600 milli sec */ + max_wait_time = max_wait_count = 30; /* 600 milli sec */ do { - udelay(1); + msleep(FW_READY_INTERVAL); value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); } while (((value & SCRATCH_PAD_IOP0_READY) != SCRATCH_PAD_IOP0_READY) && (--max_wait_count)); @@ -1107,9 +1108,9 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha) if ((pm8001_ha->chip_id != chip_8008) && (pm8001_ha->chip_id != chip_8009)) { /* 200 milli sec */ - max_wait_time = max_wait_count = 200 * 1000; + max_wait_time = max_wait_count = 10; do { - udelay(1); + msleep(FW_READY_INTERVAL); value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); } while (((value & SCRATCH_PAD_IOP1_READY) != SCRATCH_PAD_IOP1_READY) && (--max_wait_count)); diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h index 701951a0f715..ec48bc276de6 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.h +++ b/drivers/scsi/pm8001/pm80xx_hwi.h @@ -1639,3 +1639,9 @@ typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t; #define MEMBASE_II_SHIFT_REGISTER 0x1010 #endif + +/** + * As we know sleep (1~20) ms may result in sleep longer than ~20 ms, hence we + * choose 20 ms interval. + */ +#define FW_READY_INTERVAL 20 -- cgit v1.2.3 From 1f889b58716a5f5e3e4fe0e6742c1a4472f29ac1 Mon Sep 17 00:00:00 2001 From: yuuzheng Date: Mon, 2 Nov 2020 22:25:28 +0530 Subject: scsi: pm80xx: Fix pm8001_mpi_get_nvmd_resp() race condition A use-after-free or null-pointer error occurs when the 251-byte response data is copied from IOMB buffer to response message buffer in function pm8001_mpi_get_nvmd_resp(). After sending the command get_nvmd_data(), the caller begins to sleep by calling wait_for_complete() and waits for the wake-up from calling complete() in pm8001_mpi_get_nvmd_resp(). Due to unexpected events (e.g., interrupt), if response buffer gets freed before memcpy(), a use-after-free error will occur. To fix this, the complete() should be called after memcpy(). Link: https://lore.kernel.org/r/20201102165528.26510-5-Viswas.G@microchip.com.com Acked-by: Jack Wang Signed-off-by: yuuzheng Signed-off-by: Viswas G Signed-off-by: Ruksar Devadi Signed-off-by: Radha Ramachandran Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_hwi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 9e9a546da959..2054c2b03d92 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -3279,10 +3279,15 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_ha->memoryMap.region[NVMD].virt_ptr, fw_control_context->len); kfree(ccb->fw_control_context); + /* To avoid race condition, complete should be + * called after the message is copied to + * fw_control_context->usrAddr + */ + complete(pm8001_ha->nvmd_completion); + PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Set nvm data complete!\n")); ccb->task = NULL; ccb->ccb_tag = 0xFFFFFFFF; pm8001_tag_free(pm8001_ha, tag); - complete(pm8001_ha->nvmd_completion); } int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb) -- cgit v1.2.3 From fe1d4c2ebcae994dffe8673cc3cba10102d15d11 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 3 Nov 2020 16:14:02 +0200 Subject: scsi: ufs: Add DeepSleep feature DeepSleep is a UFS v3.1 feature that achieves the lowest power consumption of the device, apart from power off. In DeepSleep mode, no commands are accepted, and the only way to exit is using a hardware reset or power cycle. This patch assumes that if a power cycle was an option, then power off would be preferable, so only exit via a hardware reset is supported. Drivers that wish to support DeepSleep need to set a new capability flag UFSHCD_CAP_DEEPSLEEP and provide a hardware reset via the existing ->device_reset() callback. It is assumed that UFS devices with wspecversion >= 0x310 support DeepSleep. [mkp: dropped sysfs ABI doc due to conflicts] Link: https://lore.kernel.org/r/20201103141403.2142-2-adrian.hunter@intel.com Reviewed-by: Bean Huo Reviewed-by: Asutosh Das Reviewed-by: Stanley Chu Reviewed-by: Can Guo Acked-by: Jonathan Corbet Acked-by: Suzuki K Poulose Signed-off-by: Adrian Hunter Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-sysfs.c | 7 +++++++ drivers/scsi/ufs/ufs.h | 1 + drivers/scsi/ufs/ufshcd.c | 39 +++++++++++++++++++++++++++++++++++++-- drivers/scsi/ufs/ufshcd.h | 17 ++++++++++++++++- include/trace/events/ufs.h | 3 ++- 5 files changed, 63 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c index bdcd27faa054..08e72b7eef6a 100644 --- a/drivers/scsi/ufs/ufs-sysfs.c +++ b/drivers/scsi/ufs/ufs-sysfs.c @@ -28,6 +28,7 @@ static const char *ufschd_ufs_dev_pwr_mode_to_string( case UFS_ACTIVE_PWR_MODE: return "ACTIVE"; case UFS_SLEEP_PWR_MODE: return "SLEEP"; case UFS_POWERDOWN_PWR_MODE: return "POWERDOWN"; + case UFS_DEEPSLEEP_PWR_MODE: return "DEEPSLEEP"; default: return "UNKNOWN"; } } @@ -38,6 +39,7 @@ static inline ssize_t ufs_sysfs_pm_lvl_store(struct device *dev, bool rpm) { struct ufs_hba *hba = dev_get_drvdata(dev); + struct ufs_dev_info *dev_info = &hba->dev_info; unsigned long flags, value; if (kstrtoul(buf, 0, &value)) @@ -46,6 +48,11 @@ static inline ssize_t ufs_sysfs_pm_lvl_store(struct device *dev, if (value >= UFS_PM_LVL_MAX) return -EINVAL; + if (ufs_pm_lvl_states[value].dev_state == UFS_DEEPSLEEP_PWR_MODE && + (!(hba->caps & UFSHCD_CAP_DEEPSLEEP) || + !(dev_info->wspecversion >= 0x310))) + return -EINVAL; + spin_lock_irqsave(hba->host->host_lock, flags); if (rpm) hba->rpm_lvl = value; diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index f8ab16f30fdc..d593edb48767 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -442,6 +442,7 @@ enum ufs_dev_pwr_mode { UFS_ACTIVE_PWR_MODE = 1, UFS_SLEEP_PWR_MODE = 2, UFS_POWERDOWN_PWR_MODE = 3, + UFS_DEEPSLEEP_PWR_MODE = 4, }; #define UFS_WB_BUF_REMAIN_PERCENT(val) ((val) / 10) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 2309253d3101..ee083b96e405 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -163,6 +163,11 @@ struct ufs_pm_lvl_states ufs_pm_lvl_states[] = { {UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE}, {UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE}, {UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE}, + /* + * For DeepSleep, the link is first put in hibern8 and then off. + * Leaving the link in hibern8 is not supported. + */ + {UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE}, }; static inline enum ufs_dev_pwr_mode @@ -8297,7 +8302,8 @@ static int ufshcd_link_state_transition(struct ufs_hba *hba, } /* * If autobkops is enabled, link can't be turned off because - * turning off the link would also turn off the device. + * turning off the link would also turn off the device, except in the + * case of DeepSleep where the device is expected to remain powered. */ else if ((req_link_state == UIC_LINK_OFF_STATE) && (!check_for_bkops || !hba->auto_bkops_enabled)) { @@ -8307,6 +8313,9 @@ static int ufshcd_link_state_transition(struct ufs_hba *hba, * put the link in low power mode is to send the DME end point * to device and then send the DME reset command to local * unipro. But putting the link in hibern8 is much faster. + * + * Note also that putting the link in Hibern8 is a requirement + * for entering DeepSleep. */ ret = ufshcd_uic_hibern8_enter(hba); if (ret) { @@ -8439,6 +8448,7 @@ static void ufshcd_hba_vreg_set_hpm(struct ufs_hba *hba) static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) { int ret = 0; + int check_for_bkops; enum ufs_pm_level pm_lvl; enum ufs_dev_pwr_mode req_dev_pwr_mode; enum uic_link_state req_link_state; @@ -8524,7 +8534,13 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) } flush_work(&hba->eeh_work); - ret = ufshcd_link_state_transition(hba, req_link_state, 1); + + /* + * In the case of DeepSleep, the device is expected to remain powered + * with the link off, so do not check for bkops. + */ + check_for_bkops = !ufshcd_is_ufs_dev_deepsleep(hba); + ret = ufshcd_link_state_transition(hba, req_link_state, check_for_bkops); if (ret) goto set_dev_active; @@ -8565,11 +8581,25 @@ set_link_active: if (hba->clk_scaling.is_allowed) ufshcd_resume_clkscaling(hba); ufshcd_vreg_set_hpm(hba); + /* + * Device hardware reset is required to exit DeepSleep. Also, for + * DeepSleep, the link is off so host reset and restore will be done + * further below. + */ + if (ufshcd_is_ufs_dev_deepsleep(hba)) { + ufshcd_vops_device_reset(hba); + WARN_ON(!ufshcd_is_link_off(hba)); + } if (ufshcd_is_link_hibern8(hba) && !ufshcd_uic_hibern8_exit(hba)) ufshcd_set_link_active(hba); else if (ufshcd_is_link_off(hba)) ufshcd_host_reset_and_restore(hba); set_dev_active: + /* Can also get here needing to exit DeepSleep */ + if (ufshcd_is_ufs_dev_deepsleep(hba)) { + ufshcd_vops_device_reset(hba); + ufshcd_host_reset_and_restore(hba); + } if (!ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE)) ufshcd_disable_auto_bkops(hba); enable_gating: @@ -8631,6 +8661,9 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) if (ret) goto disable_vreg; + /* For DeepSleep, the only supported option is to have the link off */ + WARN_ON(ufshcd_is_ufs_dev_deepsleep(hba) && !ufshcd_is_link_off(hba)); + if (ufshcd_is_link_hibern8(hba)) { ret = ufshcd_uic_hibern8_exit(hba); if (!ret) { @@ -8644,6 +8677,8 @@ static int ufshcd_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) /* * A full initialization of the host and the device is * required since the link was put to off during suspend. + * Note, in the case of DeepSleep, the device will exit + * DeepSleep due to device reset. */ ret = ufshcd_reset_and_restore(hba); /* diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 0fbb735bb70c..213be0667b59 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -114,16 +114,22 @@ enum uic_link_state { ((h)->curr_dev_pwr_mode = UFS_SLEEP_PWR_MODE) #define ufshcd_set_ufs_dev_poweroff(h) \ ((h)->curr_dev_pwr_mode = UFS_POWERDOWN_PWR_MODE) +#define ufshcd_set_ufs_dev_deepsleep(h) \ + ((h)->curr_dev_pwr_mode = UFS_DEEPSLEEP_PWR_MODE) #define ufshcd_is_ufs_dev_active(h) \ ((h)->curr_dev_pwr_mode == UFS_ACTIVE_PWR_MODE) #define ufshcd_is_ufs_dev_sleep(h) \ ((h)->curr_dev_pwr_mode == UFS_SLEEP_PWR_MODE) #define ufshcd_is_ufs_dev_poweroff(h) \ ((h)->curr_dev_pwr_mode == UFS_POWERDOWN_PWR_MODE) +#define ufshcd_is_ufs_dev_deepsleep(h) \ + ((h)->curr_dev_pwr_mode == UFS_DEEPSLEEP_PWR_MODE) /* * UFS Power management levels. - * Each level is in increasing order of power savings. + * Each level is in increasing order of power savings, except DeepSleep + * which is lower than PowerDown with power on but not PowerDown with + * power off. */ enum ufs_pm_level { UFS_PM_LVL_0, /* UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE */ @@ -132,6 +138,7 @@ enum ufs_pm_level { UFS_PM_LVL_3, /* UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE */ UFS_PM_LVL_4, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE */ UFS_PM_LVL_5, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE */ + UFS_PM_LVL_6, /* UFS_DEEPSLEEP_PWR_MODE, UIC_LINK_OFF_STATE */ UFS_PM_LVL_MAX }; @@ -599,6 +606,14 @@ enum ufshcd_caps { * This would increase power savings. */ UFSHCD_CAP_AGGR_POWER_COLLAPSE = 1 << 9, + + /* + * This capability allows the host controller driver to use DeepSleep, + * if it is supported by the UFS device. The host controller driver must + * support device hardware reset via the hba->device_reset() callback, + * in order to exit DeepSleep state. + */ + UFSHCD_CAP_DEEPSLEEP = 1 << 10, }; struct ufs_hba_variant_params { diff --git a/include/trace/events/ufs.h b/include/trace/events/ufs.h index 84841b3a7ffd..2362244c2a9e 100644 --- a/include/trace/events/ufs.h +++ b/include/trace/events/ufs.h @@ -19,7 +19,8 @@ #define UFS_PWR_MODES \ EM(UFS_ACTIVE_PWR_MODE) \ EM(UFS_SLEEP_PWR_MODE) \ - EMe(UFS_POWERDOWN_PWR_MODE) + EM(UFS_POWERDOWN_PWR_MODE) \ + EMe(UFS_DEEPSLEEP_PWR_MODE) #define UFSCHD_CLK_GATING_STATES \ EM(CLKS_OFF) \ -- cgit v1.2.3 From 151f1b664ffbb847c7fbbce5a5b8580f1b9b1d98 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 3 Nov 2020 16:14:03 +0200 Subject: scsi: ufs: Allow an error return value from ->device_reset() It is simpler for drivers to provide a ->device_reset() callback irrespective of whether the GPIO, or firmware interface necessary to do the reset, is discovered during probe. Change ->device_reset() to return an error code. Drivers that provide the callback, but do not do the reset operation should return -EOPNOTSUPP. Link: https://lore.kernel.org/r/20201103141403.2142-3-adrian.hunter@intel.com Reviewed-by: Asutosh Das Reviewed-by: Stanley Chu Reviewed-by: Bean huo Reviewed-by: Can Guo Signed-off-by: Adrian Hunter Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek.c | 4 +++- drivers/scsi/ufs/ufs-qcom.c | 6 ++++-- drivers/scsi/ufs/ufshcd.h | 11 +++++++---- 3 files changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 8df73bc2f8cb..914a827a93ee 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -743,7 +743,7 @@ static int ufs_mtk_link_startup_notify(struct ufs_hba *hba, return ret; } -static void ufs_mtk_device_reset(struct ufs_hba *hba) +static int ufs_mtk_device_reset(struct ufs_hba *hba) { struct arm_smccc_res res; @@ -764,6 +764,8 @@ static void ufs_mtk_device_reset(struct ufs_hba *hba) usleep_range(10000, 15000); dev_info(hba->dev, "device reset done\n"); + + return 0; } static int ufs_mtk_link_set_hpm(struct ufs_hba *hba) diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 9a19c6d15d3b..357c3b49321d 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -1422,13 +1422,13 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba) * * Toggles the (optional) reset line to reset the attached device. */ -static void ufs_qcom_device_reset(struct ufs_hba *hba) +static int ufs_qcom_device_reset(struct ufs_hba *hba) { struct ufs_qcom_host *host = ufshcd_get_variant(hba); /* reset gpio is optional */ if (!host->device_reset) - return; + return -EOPNOTSUPP; /* * The UFS device shall detect reset pulses of 1us, sleep for 10us to @@ -1439,6 +1439,8 @@ static void ufs_qcom_device_reset(struct ufs_hba *hba) gpiod_set_value_cansleep(host->device_reset, 0); usleep_range(10, 15); + + return 0; } #if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND) diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 213be0667b59..5191d87f6263 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -323,7 +323,7 @@ struct ufs_hba_variant_ops { int (*resume)(struct ufs_hba *, enum ufs_pm_op); void (*dbg_register_dump)(struct ufs_hba *hba); int (*phy_initialization)(struct ufs_hba *); - void (*device_reset)(struct ufs_hba *hba); + int (*device_reset)(struct ufs_hba *hba); void (*config_scaling_param)(struct ufs_hba *hba, struct devfreq_dev_profile *profile, void *data); @@ -1207,9 +1207,12 @@ static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba) static inline void ufshcd_vops_device_reset(struct ufs_hba *hba) { if (hba->vops && hba->vops->device_reset) { - hba->vops->device_reset(hba); - ufshcd_set_ufs_dev_active(hba); - ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, 0); + int err = hba->vops->device_reset(hba); + + if (!err) + ufshcd_set_ufs_dev_active(hba); + if (err != -EOPNOTSUPP) + ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, err); } } -- cgit v1.2.3 From d2a2f3794cbcb2c6051f907fbe207ecf3c69702e Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 10:25:42 +0000 Subject: scsi: arcmsr: Stop __builtin_strncpy complaining about a lack of space for NUL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SCSI strings like inqdata are not NUL terminated. Fixes the following W=1 kernel build warning(s): In file included from include/linux/bitmap.h:9, from include/linux/nodemask.h:95, from include/linux/mmzone.h:17, from include/linux/gfp.h:6, from include/linux/umh.h:4, from include/linux/kmod.h:9, from include/linux/module.h:16, from drivers/scsi/arcmsr/arcmsr_hba.c:47: In function ‘strncpy’, inlined from ‘arcmsr_handle_virtual_command’ at drivers/scsi/arcmsr/arcmsr_hba.c:3055:3: include/linux/string.h:297:30: warning: ‘__builtin_strncpy’ output truncated before terminating nul copying 4 bytes from a string of the same length [-Wstringop-truncation] 297 | #define __underlying_strncpy __builtin_strncpy | ^ include/linux/string.h:307:9: note: in expansion of macro ‘__underlying_strncpy’ 307 | return __underlying_strncpy(p, q, size); | ^~~~~~~~~~~~~~~~~~~~ In function ‘strncpy’, inlined from ‘arcmsr_handle_virtual_command’ at drivers/scsi/arcmsr/arcmsr_hba.c:3053:3: include/linux/string.h:297:30: warning: ‘__builtin_strncpy’ output truncated before terminating nul copying 16 bytes from a string of the same length [-Wstringop-truncation] 297 | #define __underlying_strncpy __builtin_strncpy | ^ include/linux/string.h:307:9: note: in expansion of macro ‘__underlying_strncpy’ 307 | return __underlying_strncpy(p, q, size); | ^~~~~~~~~~~~~~~~~~~~ In function ‘strncpy’, inlined from ‘arcmsr_handle_virtual_command’ at drivers/scsi/arcmsr/arcmsr_hba.c:3051:3: include/linux/string.h:297:30: warning: ‘__builtin_strncpy’ output truncated before terminating nul copying 8 bytes from a string of the same length [-Wstringop-truncation] 297 | #define __underlying_strncpy __builtin_strncpy | ^ include/linux/string.h:307:9: note: in expansion of macro ‘__underlying_strncpy’ 307 | return __underlying_strncpy(p, q, size); | ^~~~~~~~~~~~~~~~~~~~ Link: https://lore.kernel.org/r/20201102102544.1018706-1-lee.jones@linaro.org Cc: support@areca.com.tw Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/arcmsr/arcmsr_hba.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 127fe50e6b12..f241ae15496a 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -3201,11 +3201,11 @@ static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, /* ISO, ECMA, & ANSI versions */ inqdata[4] = 31; /* length of additional data */ - strncpy(&inqdata[8], "Areca ", 8); + memcpy(&inqdata[8], "Areca ", 8); /* Vendor Identification */ - strncpy(&inqdata[16], "RAID controller ", 16); + memcpy(&inqdata[16], "RAID controller ", 16); /* Product Identification */ - strncpy(&inqdata[32], "R001", 4); /* Product Revision */ + memcpy(&inqdata[32], "R001", 4); /* Product Revision */ sg = scsi_sglist(cmd); buffer = kmap_atomic(sg_page(sg)) + sg->offset; -- cgit v1.2.3 From 412b51ffda3c8023cc017f951e864588f157a988 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 10:25:43 +0000 Subject: scsi: pm8001: pm8001_sas: Fix strncpy() warning when space is not left for NUL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This string is not NUL terminated. Fixes the following W=1 kernel build warning(s): from drivers/scsi/pm8001/pm8001_sas.c:41: In function ‘strncpy’, inlined from ‘pm8001_issue_ssp_tmf’ at drivers/scsi/pm8001/pm8001_sas.c:919:2: include/linux/string.h:297:30: warning: ‘__builtin_strncpy’ specified bound 8 equals destination size [-Wstringop-truncation] 297 | #define __underlying_strncpy __builtin_strncpy | ^ include/linux/string.h:307:9: note: in expansion of macro ‘__underlying_strncpy’ 307 | return __underlying_strncpy(p, q, size); | ^~~~~~~~~~~~~~~~~~~~ Link: https://lore.kernel.org/r/20201102102544.1018706-2-lee.jones@linaro.org Cc: Jack Wang Acked-by: Jack Wang Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_sas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index d6e0bc588698..e91497847620 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -919,7 +919,7 @@ static int pm8001_issue_ssp_tmf(struct domain_device *dev, if (!(dev->tproto & SAS_PROTOCOL_SSP)) return TMF_RESP_FUNC_ESUPP; - strncpy((u8 *)&ssp_task.LUN, lun, 8); + memcpy((u8 *)&ssp_task.LUN, lun, 8); return pm8001_exec_internal_tmf_task(dev, &ssp_task, sizeof(ssp_task), tmf); } -- cgit v1.2.3 From b2ed1babfefb072fac732d10553d290126175911 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:41 +0000 Subject: scsi: aic7xxx: aic79xx_osm: Remove unused variable 'saved_scsiid' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following W=1 kernel build warning(s): drivers/scsi/aic7xxx/aic79xx_osm.c: In function ‘ahd_linux_queue_abort_cmd’: drivers/scsi/aic7xxx/aic79xx_osm.c:2143:9: warning: variable ‘saved_scsiid’ set but not used [-Wunused-but-set-variable] Link: https://lore.kernel.org/r/20201102142359.561122-2-lee.jones@linaro.org Cc: Hannes Reinecke Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/aic7xxx/aic79xx_osm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index f32398939f74..d413b1c5fdc5 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -2140,7 +2140,6 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) u_int saved_scbptr; u_int active_scbptr; u_int last_phase; - u_int saved_scsiid; u_int cdb_byte; int retval = SUCCESS; int was_paused; @@ -2254,7 +2253,7 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) * passed in command. That command is currently active on the * bus or is in the disconnected state. */ - saved_scsiid = ahd_inb(ahd, SAVED_SCSIID); + ahd_inb(ahd, SAVED_SCSIID); if (last_phase != P_BUSFREE && SCB_GET_TAG(pending_scb) == active_scbptr) { -- cgit v1.2.3 From e330c96968680b2b72f73636f00321886792eb71 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:42 +0000 Subject: scsi: mpt3sas: mpt3sas_scsih: Fix function documentation formatting Fixes the following W=1 kernel build warning(s): drivers/scsi/mpt3sas/mpt3sas_scsih.c:2778: warning: Function parameter or member 'ioc' not described in 'scsih_tm_cmd_map_status' drivers/scsi/mpt3sas/mpt3sas_scsih.c:2778: warning: Function parameter or member 'channel' not described in 'scsih_tm_cmd_map_status' drivers/scsi/mpt3sas/mpt3sas_scsih.c:2829: warning: Function parameter or member 'ioc' not described in 'scsih_tm_post_processing' drivers/scsi/mpt3sas/mpt3sas_scsih.c:2829: warning: Function parameter or member 'channel' not described in 'scsih_tm_post_processing' Link: https://lore.kernel.org/r/20201102142359.561122-3-lee.jones@linaro.org Cc: Sathya Prakash Cc: Sreekanth Reddy Cc: Suganath Prabu Subramani Cc: MPT-FusionLinux.pdl@avagotech.com Cc: MPT-FusionLinux.pdl@broadcom.com Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 005268aa0515..f081adb85add 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -2922,8 +2922,8 @@ mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle) /** * scsih_tm_cmd_map_status - map the target reset & LUN reset TM status - * @ioc - per adapter object - * @channel - the channel assigned by the OS + * @ioc: per adapter object + * @channel: the channel assigned by the OS * @id: the id assigned by the OS * @lun: lun number * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h) @@ -2968,9 +2968,9 @@ scsih_tm_cmd_map_status(struct MPT3SAS_ADAPTER *ioc, uint channel, /** * scsih_tm_post_processing - post processing of target & LUN reset - * @ioc - per adapter object + * @ioc: per adapter object * @handle: device handle - * @channel - the channel assigned by the OS + * @channel: the channel assigned by the OS * @id: the id assigned by the OS * @lun: lun number * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h) -- cgit v1.2.3 From eceee00e41565523a0010c8828a2330d04f64878 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:43 +0000 Subject: scsi: lpfc: lpfc_scsi: Fix a whole host of kernel-doc issues Fixes the following W=1 kernel build warning(s): drivers/scsi/lpfc/lpfc_scsi.c:331: warning: Function parameter or member 'num_to_alloc' not described in 'lpfc_new_scsi_buf_s3' drivers/scsi/lpfc/lpfc_scsi.c:331: warning: Excess function parameter 'num_to_allocate' description in 'lpfc_new_scsi_buf_s3' drivers/scsi/lpfc/lpfc_scsi.c:507: warning: Function parameter or member 'idx' not described in 'lpfc_sli4_io_xri_aborted' drivers/scsi/lpfc/lpfc_scsi.c:593: warning: Function parameter or member 'ndlp' not described in 'lpfc_get_scsi_buf_s3' drivers/scsi/lpfc/lpfc_scsi.c:593: warning: Function parameter or member 'cmnd' not described in 'lpfc_get_scsi_buf_s3' drivers/scsi/lpfc/lpfc_scsi.c:632: warning: Function parameter or member 'ndlp' not described in 'lpfc_get_scsi_buf_s4' drivers/scsi/lpfc/lpfc_scsi.c:632: warning: Function parameter or member 'cmnd' not described in 'lpfc_get_scsi_buf_s4' drivers/scsi/lpfc/lpfc_scsi.c:744: warning: Function parameter or member 'ndlp' not described in 'lpfc_get_scsi_buf' drivers/scsi/lpfc/lpfc_scsi.c:744: warning: Function parameter or member 'cmnd' not described in 'lpfc_get_scsi_buf' drivers/scsi/lpfc/lpfc_scsi.c:986: warning: Function parameter or member 'new_guard' not described in 'lpfc_bg_err_inject' drivers/scsi/lpfc/lpfc_scsi.c:1393: warning: Function parameter or member 'txop' not described in 'lpfc_sc_to_bg_opcodes' drivers/scsi/lpfc/lpfc_scsi.c:1393: warning: Function parameter or member 'rxop' not described in 'lpfc_sc_to_bg_opcodes' drivers/scsi/lpfc/lpfc_scsi.c:1393: warning: Excess function parameter 'txopt' description in 'lpfc_sc_to_bg_opcodes' drivers/scsi/lpfc/lpfc_scsi.c:1393: warning: Excess function parameter 'rxopt' description in 'lpfc_sc_to_bg_opcodes' drivers/scsi/lpfc/lpfc_scsi.c:1473: warning: Function parameter or member 'txop' not described in 'lpfc_bg_err_opcodes' drivers/scsi/lpfc/lpfc_scsi.c:1473: warning: Function parameter or member 'rxop' not described in 'lpfc_bg_err_opcodes' drivers/scsi/lpfc/lpfc_scsi.c:1473: warning: Excess function parameter 'txopt' description in 'lpfc_bg_err_opcodes' drivers/scsi/lpfc/lpfc_scsi.c:1473: warning: Excess function parameter 'rxopt' description in 'lpfc_bg_err_opcodes' drivers/scsi/lpfc/lpfc_scsi.c:1565: warning: Function parameter or member 'datasegcnt' not described in 'lpfc_bg_setup_bpl' drivers/scsi/lpfc/lpfc_scsi.c:1565: warning: Excess function parameter 'datacnt' description in 'lpfc_bg_setup_bpl' drivers/scsi/lpfc/lpfc_scsi.c:1951: warning: Function parameter or member 'datasegcnt' not described in 'lpfc_bg_setup_sgl' drivers/scsi/lpfc/lpfc_scsi.c:1951: warning: Function parameter or member 'lpfc_cmd' not described in 'lpfc_bg_setup_sgl' drivers/scsi/lpfc/lpfc_scsi.c:1951: warning: Excess function parameter 'datacnt' description in 'lpfc_bg_setup_sgl' drivers/scsi/lpfc/lpfc_scsi.c:2131: warning: Function parameter or member 'lpfc_cmd' not described in 'lpfc_bg_setup_sgl_prot' drivers/scsi/lpfc/lpfc_scsi.c:4476: warning: Function parameter or member 't' not described in 'lpfc_poll_timeout' drivers/scsi/lpfc/lpfc_scsi.c:4476: warning: Excess function parameter 'ptr' description in 'lpfc_poll_timeout' drivers/scsi/lpfc/lpfc_scsi.c:4503: warning: Function parameter or member 'shost' not described in 'lpfc_queuecommand' drivers/scsi/lpfc/lpfc_scsi.c:4503: warning: Excess function parameter 'done' description in 'lpfc_queuecommand' drivers/scsi/lpfc/lpfc_scsi.c:5035: warning: Function parameter or member 'cmnd' not described in 'lpfc_send_taskmgmt' drivers/scsi/lpfc/lpfc_scsi.c:5035: warning: Excess function parameter 'rdata' description in 'lpfc_send_taskmgmt' drivers/scsi/lpfc/lpfc_scsi.c:5688: warning: Function parameter or member 'phba' not described in 'lpfc_create_device_data' drivers/scsi/lpfc/lpfc_scsi.c:5688: warning: Function parameter or member 'pri' not described in 'lpfc_create_device_data' drivers/scsi/lpfc/lpfc_scsi.c:5688: warning: Excess function parameter 'pha' description in 'lpfc_create_device_data' drivers/scsi/lpfc/lpfc_scsi.c:5730: warning: Function parameter or member 'phba' not described in 'lpfc_delete_device_data' drivers/scsi/lpfc/lpfc_scsi.c:5730: warning: Excess function parameter 'pha' description in 'lpfc_delete_device_data' drivers/scsi/lpfc/lpfc_scsi.c:5762: warning: Function parameter or member 'phba' not described in '__lpfc_get_device_data' drivers/scsi/lpfc/lpfc_scsi.c:5762: warning: Excess function parameter 'pha' description in '__lpfc_get_device_data' drivers/scsi/lpfc/lpfc_scsi.c:5818: warning: Function parameter or member 'phba' not described in 'lpfc_find_next_oas_lun' drivers/scsi/lpfc/lpfc_scsi.c:5818: warning: Function parameter or member 'found_lun_pri' not described in 'lpfc_find_next_oas_lun' drivers/scsi/lpfc/lpfc_scsi.c:5818: warning: Excess function parameter 'pha' description in 'lpfc_find_next_oas_lun' drivers/scsi/lpfc/lpfc_scsi.c:5909: warning: Function parameter or member 'phba' not described in 'lpfc_enable_oas_lun' drivers/scsi/lpfc/lpfc_scsi.c:5909: warning: Function parameter or member 'pri' not described in 'lpfc_enable_oas_lun' drivers/scsi/lpfc/lpfc_scsi.c:5909: warning: Excess function parameter 'pha' description in 'lpfc_enable_oas_lun' drivers/scsi/lpfc/lpfc_scsi.c:5968: warning: Function parameter or member 'phba' not described in 'lpfc_disable_oas_lun' drivers/scsi/lpfc/lpfc_scsi.c:5968: warning: Function parameter or member 'pri' not described in 'lpfc_disable_oas_lun' drivers/scsi/lpfc/lpfc_scsi.c:5968: warning: Excess function parameter 'pha' description in 'lpfc_disable_oas_lun' Link: https://lore.kernel.org/r/20201102142359.561122-4-lee.jones@linaro.org Cc: James Smart Cc: Dick Kennedy Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_scsi.c | 48 +++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 4ffdfd2c8604..0f0ab86cf192 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -313,7 +313,7 @@ lpfc_scsi_dev_block(struct lpfc_hba *phba) /** * lpfc_new_scsi_buf_s3 - Scsi buffer allocator for HBA with SLI3 IF spec * @vport: The virtual port for which this call being executed. - * @num_to_allocate: The requested number of buffers to allocate. + * @num_to_alloc: The requested number of buffers to allocate. * * This routine allocates a scsi buffer for device with SLI-3 interface spec, * the scsi buffer contains all the necessary information needed to initiate @@ -497,6 +497,7 @@ lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport) * lpfc_sli4_io_xri_aborted - Fast-path process of fcp xri abort * @phba: pointer to lpfc hba data structure. * @axri: pointer to the fcp xri abort wcqe structure. + * @idx: index into hdwq * * This routine is invoked by the worker thread to process a SLI4 fast-path * FCP or NVME aborted xri. @@ -579,6 +580,8 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba, /** * lpfc_get_scsi_buf_s3 - Get a scsi buffer from lpfc_scsi_buf_list of the HBA * @phba: The HBA for which this call is being executed. + * @ndlp: pointer to a node-list data structure. + * @cmnd: Pointer to scsi_cmnd data structure. * * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list * and returns to caller. @@ -618,6 +621,8 @@ lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, /** * lpfc_get_scsi_buf_s4 - Get a scsi buffer from io_buf_list of the HBA * @phba: The HBA for which this call is being executed. + * @ndlp: pointer to a node-list data structure. + * @cmnd: Pointer to scsi_cmnd data structure. * * This routine removes a scsi buffer from head of @hdwq io_buf_list * and returns to caller. @@ -730,6 +735,8 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, /** * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA * @phba: The HBA for which this call is being executed. + * @ndlp: pointer to a node-list data structure. + * @cmnd: Pointer to scsi_cmnd data structure. * * This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list * and returns to caller. @@ -976,7 +983,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) * @sc: The SCSI command to examine * @reftag: (out) BlockGuard reference tag for transmitted data * @apptag: (out) BlockGuard application tag for transmitted data - * @new_guard (in) Value to replace CRC with if needed + * @new_guard: (in) Value to replace CRC with if needed * * Returns BG_ERR_* bit mask or 0 if request ignored **/ @@ -1381,8 +1388,8 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, * the specified SCSI command. * @phba: The Hba for which this call is being executed. * @sc: The SCSI command to examine - * @txopt: (out) BlockGuard operation for transmitted data - * @rxopt: (out) BlockGuard operation for received data + * @txop: (out) BlockGuard operation for transmitted data + * @rxop: (out) BlockGuard operation for received data * * Returns: zero on success; non-zero if tx and/or rx op cannot be determined * @@ -1461,8 +1468,8 @@ lpfc_sc_to_bg_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc, * the specified SCSI command in order to force a guard tag error. * @phba: The Hba for which this call is being executed. * @sc: The SCSI command to examine - * @txopt: (out) BlockGuard operation for transmitted data - * @rxopt: (out) BlockGuard operation for received data + * @txop: (out) BlockGuard operation for transmitted data + * @rxop: (out) BlockGuard operation for received data * * Returns: zero on success; non-zero if tx and/or rx op cannot be determined * @@ -1533,7 +1540,7 @@ lpfc_bg_err_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc, * @phba: The Hba for which this call is being executed. * @sc: pointer to scsi command we're working on * @bpl: pointer to buffer list for protection groups - * @datacnt: number of segments of data that have been dma mapped + * @datasegcnt: number of segments of data that have been dma mapped * * This function sets up BPL buffer list for protection groups of * type LPFC_PG_TYPE_NO_DIF @@ -1920,7 +1927,8 @@ out: * @phba: The Hba for which this call is being executed. * @sc: pointer to scsi command we're working on * @sgl: pointer to buffer list for protection groups - * @datacnt: number of segments of data that have been dma mapped + * @datasegcnt: number of segments of data that have been dma mapped + * @lpfc_cmd: lpfc scsi command object pointer. * * This function sets up SGL buffer list for protection groups of * type LPFC_PG_TYPE_NO_DIF @@ -2094,6 +2102,7 @@ out: * @sgl: pointer to buffer list for protection groups * @datacnt: number of segments of data that have been dma mapped * @protcnt: number of segment of protection data that have been dma mapped + * @lpfc_cmd: lpfc scsi command object pointer. * * This function sets up SGL buffer list for protection groups of * type LPFC_PG_TYPE_DIF @@ -4465,12 +4474,11 @@ void lpfc_poll_start_timer(struct lpfc_hba * phba) /** * lpfc_poll_timeout - Restart polling timer - * @ptr: Map to lpfc_hba data structure pointer. + * @t: Timer construct where lpfc_hba data structure pointer is obtained. * * This routine restarts fcp_poll timer, when FCP ring polling is enable * and FCP Ring interrupt is disable. **/ - void lpfc_poll_timeout(struct timer_list *t) { struct lpfc_hba *phba = from_timer(phba, t, fcp_poll_timer); @@ -4486,8 +4494,8 @@ void lpfc_poll_timeout(struct timer_list *t) /** * lpfc_queuecommand - scsi_host_template queuecommand entry point + * @shost: kernel scsi host pointer. * @cmnd: Pointer to scsi_cmnd data structure. - * @done: Pointer to done routine. * * Driver registers this routine to scsi midlayer to submit a @cmd to process. * This routine prepares an IOCB from scsi command and provides to firmware. @@ -5015,7 +5023,7 @@ lpfc_check_fcp_rsp(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd) /** * lpfc_send_taskmgmt - Generic SCSI Task Mgmt Handler * @vport: The virtual port for which this call is being executed. - * @rdata: Pointer to remote port local data + * @cmnd: Pointer to scsi_cmnd data structure. * @tgt_id: Target ID of remote device. * @lun_id: Lun number for the TMF * @task_mgmt_cmd: type of TMF to send @@ -5664,10 +5672,11 @@ lpfc_slave_destroy(struct scsi_device *sdev) /** * lpfc_create_device_data - creates and initializes device data structure for OAS - * @pha: Pointer to host bus adapter structure. + * @phba: Pointer to host bus adapter structure. * @vport_wwpn: Pointer to vport's wwpn information * @target_wwpn: Pointer to target's wwpn information * @lun: Lun on target + * @pri: Priority * @atomic_create: Flag to indicate if memory should be allocated using the * GFP_ATOMIC flag or not. * @@ -5717,7 +5726,7 @@ lpfc_create_device_data(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, /** * lpfc_delete_device_data - frees a device data structure for OAS - * @pha: Pointer to host bus adapter structure. + * @phba: Pointer to host bus adapter structure. * @lun_info: Pointer to device data structure to free. * * This routine frees the previously allocated device data structure passed. @@ -5740,7 +5749,7 @@ lpfc_delete_device_data(struct lpfc_hba *phba, /** * __lpfc_get_device_data - returns the device data for the specified lun - * @pha: Pointer to host bus adapter structure. + * @phba: Pointer to host bus adapter structure. * @list: Point to list to search. * @vport_wwpn: Pointer to vport's wwpn information * @target_wwpn: Pointer to target's wwpn information @@ -5782,7 +5791,7 @@ __lpfc_get_device_data(struct lpfc_hba *phba, struct list_head *list, /** * lpfc_find_next_oas_lun - searches for the next oas lun - * @pha: Pointer to host bus adapter structure. + * @phba: Pointer to host bus adapter structure. * @vport_wwpn: Pointer to vport's wwpn information * @target_wwpn: Pointer to target's wwpn information * @starting_lun: Pointer to the lun to start searching for @@ -5790,6 +5799,7 @@ __lpfc_get_device_data(struct lpfc_hba *phba, struct list_head *list, * @found_target_wwpn: Pointer to the found lun's target wwpn information * @found_lun: Pointer to the found lun. * @found_lun_status: Pointer to status of the found lun. + * @found_lun_pri: Pointer to priority of the found lun. * * This routine searches the luns list for the specified lun * or the first lun for the vport/target. If the vport wwpn contains @@ -5884,10 +5894,11 @@ lpfc_find_next_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, /** * lpfc_enable_oas_lun - enables a lun for OAS operations - * @pha: Pointer to host bus adapter structure. + * @phba: Pointer to host bus adapter structure. * @vport_wwpn: Pointer to vport's wwpn information * @target_wwpn: Pointer to target's wwpn information * @lun: Lun + * @pri: Priority * * This routine enables a lun for oas operations. The routines does so by * doing the following : @@ -5944,10 +5955,11 @@ lpfc_enable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, /** * lpfc_disable_oas_lun - disables a lun for OAS operations - * @pha: Pointer to host bus adapter structure. + * @phba: Pointer to host bus adapter structure. * @vport_wwpn: Pointer to vport's wwpn information * @target_wwpn: Pointer to target's wwpn information * @lun: Lun + * @pri: Priority * * This routine disables a lun for oas operations. The routines does so by * doing the following : -- cgit v1.2.3 From 9176ad27acac13c3254ef45581ffd4a41795a9b5 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:44 +0000 Subject: scsi: lpfc: lpfc_attr: Demote kernel-doc format for redefined functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kernel-doc does not understand this use-case. Fixes the following W=1 kernel build warning(s): from drivers/scsi/lpfc/lpfc_attr.c:26: inlined from ‘lpfc_stat_data_ctrl_store’ at drivers/scsi/lpfc/lpfc_attr.c:4164:3: drivers/scsi/lpfc/lpfc_attr.c:2315: warning: Excess function parameter 'dev' description in 'lpfc_param_show' drivers/scsi/lpfc/lpfc_attr.c:2315: warning: Excess function parameter 'buf' description in 'lpfc_param_show' drivers/scsi/lpfc/lpfc_attr.c:2343: warning: Excess function parameter 'dev' description in 'lpfc_param_hex_show' drivers/scsi/lpfc/lpfc_attr.c:2343: warning: Excess function parameter 'buf' description in 'lpfc_param_hex_show' drivers/scsi/lpfc/lpfc_attr.c:2377: warning: Function parameter or member 'attr' not described in 'lpfc_param_init' drivers/scsi/lpfc/lpfc_attr.c:2377: warning: Function parameter or member 'default' not described in 'lpfc_param_init' drivers/scsi/lpfc/lpfc_attr.c:2377: warning: Function parameter or member 'minval' not described in 'lpfc_param_init' drivers/scsi/lpfc/lpfc_attr.c:2377: warning: Function parameter or member 'maxval' not described in 'lpfc_param_init' drivers/scsi/lpfc/lpfc_attr.c:2377: warning: Excess function parameter 'phba' description in 'lpfc_param_init' drivers/scsi/lpfc/lpfc_attr.c:2377: warning: Excess function parameter 'val' description in 'lpfc_param_init' drivers/scsi/lpfc/lpfc_attr.c:2414: warning: Function parameter or member 'attr' not described in 'lpfc_param_set' drivers/scsi/lpfc/lpfc_attr.c:2414: warning: Function parameter or member 'default' not described in 'lpfc_param_set' drivers/scsi/lpfc/lpfc_attr.c:2414: warning: Function parameter or member 'minval' not described in 'lpfc_param_set' drivers/scsi/lpfc/lpfc_attr.c:2414: warning: Function parameter or member 'maxval' not described in 'lpfc_param_set' drivers/scsi/lpfc/lpfc_attr.c:2414: warning: Excess function parameter 'phba' description in 'lpfc_param_set' drivers/scsi/lpfc/lpfc_attr.c:2414: warning: Excess function parameter 'val' description in 'lpfc_param_set' drivers/scsi/lpfc/lpfc_attr.c:2454: warning: Excess function parameter 'dev' description in 'lpfc_param_store' drivers/scsi/lpfc/lpfc_attr.c:2454: warning: Excess function parameter 'buf' description in 'lpfc_param_store' drivers/scsi/lpfc/lpfc_attr.c:2454: warning: Excess function parameter 'count' description in 'lpfc_param_store' drivers/scsi/lpfc/lpfc_attr.c:2478: warning: Excess function parameter 'dev' description in 'lpfc_vport_param_show' drivers/scsi/lpfc/lpfc_attr.c:2478: warning: Excess function parameter 'buf' description in 'lpfc_vport_param_show' drivers/scsi/lpfc/lpfc_attr.c:2503: warning: Excess function parameter 'dev' description in 'lpfc_vport_param_hex_show' drivers/scsi/lpfc/lpfc_attr.c:2503: warning: Excess function parameter 'buf' description in 'lpfc_vport_param_hex_show' drivers/scsi/lpfc/lpfc_attr.c:2536: warning: Function parameter or member 'attr' not described in 'lpfc_vport_param_init' drivers/scsi/lpfc/lpfc_attr.c:2536: warning: Function parameter or member 'default' not described in 'lpfc_vport_param_init' drivers/scsi/lpfc/lpfc_attr.c:2536: warning: Function parameter or member 'minval' not described in 'lpfc_vport_param_init' drivers/scsi/lpfc/lpfc_attr.c:2536: warning: Function parameter or member 'maxval' not described in 'lpfc_vport_param_init' drivers/scsi/lpfc/lpfc_attr.c:2536: warning: Excess function parameter 'phba' description in 'lpfc_vport_param_init' drivers/scsi/lpfc/lpfc_attr.c:2536: warning: Excess function parameter 'val' description in 'lpfc_vport_param_init' drivers/scsi/lpfc/lpfc_attr.c:2572: warning: Function parameter or member 'attr' not described in 'lpfc_vport_param_set' drivers/scsi/lpfc/lpfc_attr.c:2572: warning: Function parameter or member 'default' not described in 'lpfc_vport_param_set' drivers/scsi/lpfc/lpfc_attr.c:2572: warning: Function parameter or member 'minval' not described in 'lpfc_vport_param_set' drivers/scsi/lpfc/lpfc_attr.c:2572: warning: Function parameter or member 'maxval' not described in 'lpfc_vport_param_set' drivers/scsi/lpfc/lpfc_attr.c:2572: warning: Excess function parameter 'phba' description in 'lpfc_vport_param_set' drivers/scsi/lpfc/lpfc_attr.c:2572: warning: Excess function parameter 'val' description in 'lpfc_vport_param_set' drivers/scsi/lpfc/lpfc_attr.c:2607: warning: Function parameter or member 'attr' not described in 'lpfc_vport_param_store' drivers/scsi/lpfc/lpfc_attr.c:2607: warning: Excess function parameter 'cdev' description in 'lpfc_vport_param_store' drivers/scsi/lpfc/lpfc_attr.c:2607: warning: Excess function parameter 'buf' description in 'lpfc_vport_param_store' drivers/scsi/lpfc/lpfc_attr.c:2607: warning: Excess function parameter 'count' description in 'lpfc_vport_param_store' drivers/scsi/lpfc/lpfc_attr.c:7081: warning: Function parameter or member 'field' not described in 'lpfc_rport_show_function' drivers/scsi/lpfc/lpfc_attr.c:7081: warning: Function parameter or member 'format_string' not described in 'lpfc_rport_show_function' drivers/scsi/lpfc/lpfc_attr.c:7081: warning: Function parameter or member 'sz' not described in 'lpfc_rport_show_function' drivers/scsi/lpfc/lpfc_attr.c:7081: warning: Function parameter or member 'cast' not described in 'lpfc_rport_show_function' drivers/scsi/lpfc/lpfc_attr.c:7081: warning: Excess function parameter 'cdev' description in 'lpfc_rport_show_function' drivers/scsi/lpfc/lpfc_attr.c:7081: warning: Excess function parameter 'buf' description in 'lpfc_rport_show_function' Link: https://lore.kernel.org/r/20201102142359.561122-5-lee.jones@linaro.org Cc: James Smart Cc: Dick Kennedy Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 0673d944c2a8..6a33f0607cc8 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1501,6 +1501,7 @@ lpfc_sli4_pdev_status_reg_wait(struct lpfc_hba *phba) /** * lpfc_sli4_pdev_reg_request - Request physical dev to perform a register acc * @phba: lpfc_hba pointer. + * @opcode: The sli4 config command opcode. * * Description: * Request SLI4 interface type-2 device to perform a physical register set @@ -2284,7 +2285,7 @@ lpfc_enable_bbcr_set(struct lpfc_hba *phba, uint val) return -EINVAL; } -/** +/* * lpfc_param_show - Return a cfg attribute value in decimal * * Description: @@ -2310,7 +2311,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ phba->cfg_##attr);\ } -/** +/* * lpfc_param_hex_show - Return a cfg attribute value in hex * * Description: @@ -2338,7 +2339,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ phba->cfg_##attr);\ } -/** +/* * lpfc_param_init - Initializes a cfg attribute * * Description: @@ -2372,7 +2373,7 @@ lpfc_##attr##_init(struct lpfc_hba *phba, uint val) \ return -EINVAL;\ } -/** +/* * lpfc_param_set - Set a cfg attribute value * * Description: @@ -2409,7 +2410,7 @@ lpfc_##attr##_set(struct lpfc_hba *phba, uint val) \ return -EINVAL;\ } -/** +/* * lpfc_param_store - Set a vport attribute value * * Description: @@ -2449,7 +2450,7 @@ lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \ return -EINVAL;\ } -/** +/* * lpfc_vport_param_show - Return decimal formatted cfg attribute value * * Description: @@ -2473,7 +2474,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ return scnprintf(buf, PAGE_SIZE, "%d\n", vport->cfg_##attr);\ } -/** +/* * lpfc_vport_param_hex_show - Return hex formatted attribute value * * Description: @@ -2498,7 +2499,7 @@ lpfc_##attr##_show(struct device *dev, struct device_attribute *attr, \ return scnprintf(buf, PAGE_SIZE, "%#x\n", vport->cfg_##attr);\ } -/** +/* * lpfc_vport_param_init - Initialize a vport cfg attribute * * Description: @@ -2531,7 +2532,7 @@ lpfc_##attr##_init(struct lpfc_vport *vport, uint val) \ return -EINVAL;\ } -/** +/* * lpfc_vport_param_set - Set a vport cfg attribute * * Description: @@ -2567,7 +2568,7 @@ lpfc_##attr##_set(struct lpfc_vport *vport, uint val) \ return -EINVAL;\ } -/** +/* * lpfc_vport_param_store - Set a vport attribute * * Description: @@ -7061,7 +7062,7 @@ lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) #endif } -/** +/* * lpfc_rport_show_function - Return rport target information * * Description: -- cgit v1.2.3 From a738bd9bbe53c1a9b5134845af16e0fedf9ab2f8 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:45 +0000 Subject: scsi: lpfc: lpfc_attr: Fix-up a bunch of kernel-doc misdemeanours MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following W=1 kernel build warning(s): from drivers/scsi/lpfc/lpfc_attr.c:26: inlined from ‘lpfc_stat_data_ctrl_store’ at drivers/scsi/lpfc/lpfc_attr.c:4165:3: drivers/scsi/lpfc/lpfc_attr.c:2537: warning: Function parameter or member 'attr' not described in 'lpfc_vport_param_init' drivers/scsi/lpfc/lpfc_attr.c:2537: warning: Function parameter or member 'default' not described in 'lpfc_vport_param_init' drivers/scsi/lpfc/lpfc_attr.c:2537: warning: Function parameter or member 'minval' not described in 'lpfc_vport_param_init' drivers/scsi/lpfc/lpfc_attr.c:2537: warning: Function parameter or member 'maxval' not described in 'lpfc_vport_param_init' drivers/scsi/lpfc/lpfc_attr.c:2537: warning: Excess function parameter 'phba' description in 'lpfc_vport_param_init' drivers/scsi/lpfc/lpfc_attr.c:2537: warning: Excess function parameter 'val' description in 'lpfc_vport_param_init' drivers/scsi/lpfc/lpfc_attr.c:2792: warning: Function parameter or member 'dev' not described in 'lpfc_soft_wwpn_store' drivers/scsi/lpfc/lpfc_attr.c:2886: warning: Function parameter or member 'dev' not described in 'lpfc_soft_wwnn_store' drivers/scsi/lpfc/lpfc_attr.c:2886: warning: Function parameter or member 'attr' not described in 'lpfc_soft_wwnn_store' drivers/scsi/lpfc/lpfc_attr.c:2886: warning: Excess function parameter 'cdev' description in 'lpfc_soft_wwnn_store' drivers/scsi/lpfc/lpfc_attr.c:3224: warning: Function parameter or member 'vpt_wwpn' not described in 'lpfc_oas_lun_state_set' drivers/scsi/lpfc/lpfc_attr.c:3224: warning: Function parameter or member 'tgt_wwpn' not described in 'lpfc_oas_lun_state_set' drivers/scsi/lpfc/lpfc_attr.c:3224: warning: Function parameter or member 'pri' not described in 'lpfc_oas_lun_state_set' drivers/scsi/lpfc/lpfc_attr.c:3224: warning: Excess function parameter 'ndlp' description in 'lpfc_oas_lun_state_set' drivers/scsi/lpfc/lpfc_attr.c:3264: warning: Function parameter or member 'lun_pri' not described in 'lpfc_oas_lun_get_next' drivers/scsi/lpfc/lpfc_attr.c:3302: warning: Function parameter or member 'pri' not described in 'lpfc_oas_lun_state_change' drivers/scsi/lpfc/lpfc_attr.c:3376: warning: Function parameter or member 'count' not described in 'lpfc_oas_lun_store' drivers/scsi/lpfc/lpfc_attr.c:3835: warning: Function parameter or member 'vport' not described in 'lpfc_tgt_queue_depth_set' drivers/scsi/lpfc/lpfc_attr.c:3835: warning: Excess function parameter 'phba' description in 'lpfc_tgt_queue_depth_set' drivers/scsi/lpfc/lpfc_attr.c:4026: warning: Function parameter or member 'dev' not described in 'lpfc_topology_store' drivers/scsi/lpfc/lpfc_attr.c:4026: warning: Function parameter or member 'attr' not described in 'lpfc_topology_store' drivers/scsi/lpfc/lpfc_attr.c:4026: warning: Function parameter or member 'buf' not described in 'lpfc_topology_store' drivers/scsi/lpfc/lpfc_attr.c:4026: warning: Function parameter or member 'count' not described in 'lpfc_topology_store' drivers/scsi/lpfc/lpfc_attr.c:4026: warning: Excess function parameter 'phba' description in 'lpfc_topology_store' drivers/scsi/lpfc/lpfc_attr.c:4026: warning: Excess function parameter 'val' description in 'lpfc_topology_store' drivers/scsi/lpfc/lpfc_attr.c:4148: warning: Function parameter or member 'attr' not described in 'lpfc_stat_data_ctrl_store' drivers/scsi/lpfc/lpfc_attr.c:4302: warning: Function parameter or member 'attr' not described in 'lpfc_stat_data_ctrl_show' drivers/scsi/lpfc/lpfc_attr.c:4383: warning: Function parameter or member 'buf' not described in 'sysfs_drvr_stat_data_read' drivers/scsi/lpfc/lpfc_attr.c:4383: warning: Excess function parameter 'buff' description in 'sysfs_drvr_stat_data_read' drivers/scsi/lpfc/lpfc_attr.c:4476: warning: Function parameter or member 'dev' not described in 'lpfc_link_speed_store' drivers/scsi/lpfc/lpfc_attr.c:4476: warning: Function parameter or member 'attr' not described in 'lpfc_link_speed_store' drivers/scsi/lpfc/lpfc_attr.c:4476: warning: Function parameter or member 'buf' not described in 'lpfc_link_speed_store' drivers/scsi/lpfc/lpfc_attr.c:4476: warning: Function parameter or member 'count' not described in 'lpfc_link_speed_store' drivers/scsi/lpfc/lpfc_attr.c:4476: warning: Excess function parameter 'phba' description in 'lpfc_link_speed_store' drivers/scsi/lpfc/lpfc_attr.c:4476: warning: Excess function parameter 'val' description in 'lpfc_link_speed_store' drivers/scsi/lpfc/lpfc_attr.c:7117: warning: Function parameter or member 'verbose' not described in 'lpfc_hba_log_verbose_init' Link: https://lore.kernel.org/r/20201102142359.561122-6-lee.jones@linaro.org Cc: James Smart Cc: Dick Kennedy Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 6a33f0607cc8..ada231d4f0c6 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -2771,7 +2771,7 @@ lpfc_soft_wwpn_show(struct device *dev, struct device_attribute *attr, /** * lpfc_soft_wwpn_store - Set the ww port name of the adapter - * @dev class device that is converted into a Scsi_host. + * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: contains the wwpn in hexadecimal. * @count: number of wwpn bytes in buf @@ -2868,7 +2868,8 @@ lpfc_soft_wwnn_show(struct device *dev, struct device_attribute *attr, /** * lpfc_soft_wwnn_store - sets the ww node name of the adapter - * @cdev: class device that is converted into a Scsi_host. + * @dev: class device that is converted into a Scsi_host. + * @attr: device attribute, not used. * @buf: contains the ww node name in hexadecimal. * @count: number of wwnn bytes in buf. * @@ -3204,9 +3205,11 @@ static DEVICE_ATTR(lpfc_xlane_lun_status, S_IRUGO, * lpfc_oas_lun_state_set - enable or disable a lun for Optimized Access Storage * (OAS) operations. * @phba: lpfc_hba pointer. - * @ndlp: pointer to fcp target node. + * @vpt_wwpn: wwpn of the vport associated with the returned lun + * @tgt_wwpn: wwpn of the target associated with the returned lun * @lun: the fc lun for setting oas state. * @oas_state: the oas state to be set to the lun. + * @pri: priority * * Returns: * SUCCESS : 0 @@ -3244,6 +3247,7 @@ lpfc_oas_lun_state_set(struct lpfc_hba *phba, uint8_t vpt_wwpn[], * @vpt_wwpn: wwpn of the vport associated with the returned lun * @tgt_wwpn: wwpn of the target associated with the returned lun * @lun_status: status of the lun returned lun + * @lun_pri: priority of the lun returned lun * * Returns the first or next lun enabled for OAS operations for the vport/target * specified. If a lun is found, its vport wwpn, target wwpn and status is @@ -3282,6 +3286,7 @@ lpfc_oas_lun_get_next(struct lpfc_hba *phba, uint8_t vpt_wwpn[], * @tgt_wwpn: target wwpn by reference. * @lun: the fc lun for setting oas state. * @oas_state: the oas state to be set to the oas_lun. + * @pri: priority * * This routine enables (OAS_LUN_ENABLE) or disables (OAS_LUN_DISABLE) * a lun for OAS operations. @@ -3356,6 +3361,7 @@ lpfc_oas_lun_show(struct device *dev, struct device_attribute *attr, * @dev: class device that is converted into a Scsi_host. * @attr: device attribute, not used. * @buf: buffer for passing information. + * @count: size of the formatting string * * This function sets the OAS state for lun. Before this function is called, * the vport wwpn, target wwpn, and oas state need to be set. @@ -3817,7 +3823,7 @@ lpfc_vport_param_init(tgt_queue_depth, LPFC_MAX_TGT_QDEPTH, /** * lpfc_tgt_queue_depth_store: Sets an attribute value. - * @phba: pointer the the adapter structure. + * @vport: lpfc vport structure pointer. * @val: integer attribute value. * * Description: Sets the parameter to the new value. @@ -4002,8 +4008,10 @@ LPFC_ATTR(topology, 0, 0, 6, /** * lpfc_topology_set - Set the adapters topology field - * @phba: lpfc_hba pointer. - * @val: topology value. + * @dev: class device that is converted into a scsi_host. + * @attr:device attribute, not used. + * @buf: buffer for passing information. + * @count: size of the data buffer. * * Description: * If val is in a valid range then set the adapter's topology field and @@ -4122,6 +4130,7 @@ static DEVICE_ATTR_RO(lpfc_static_vport); /** * lpfc_stat_data_ctrl_store - write call back for lpfc_stat_data_ctrl sysfs file * @dev: Pointer to class device. + * @attr: Unused. * @buf: Data buffer. * @count: Size of the data buffer. * @@ -4285,7 +4294,8 @@ lpfc_stat_data_ctrl_store(struct device *dev, struct device_attribute *attr, /** * lpfc_stat_data_ctrl_show - Read function for lpfc_stat_data_ctrl sysfs file - * @dev: Pointer to class device object. + * @dev: Pointer to class device. + * @attr: Unused. * @buf: Data buffer. * * This function is the read call back function for @@ -4364,7 +4374,7 @@ static DEVICE_ATTR_RW(lpfc_stat_data_ctrl); * @filp: sysfs file * @kobj: Pointer to the kernel object * @bin_attr: Attribute object - * @buff: Buffer pointer + * @buf: Buffer pointer * @off: File offset * @count: Buffer size * @@ -4451,8 +4461,10 @@ static struct bin_attribute sysfs_drvr_stat_data_attr = { */ /** * lpfc_link_speed_set - Set the adapters link speed - * @phba: lpfc_hba pointer. - * @val: link speed value. + * @dev: Pointer to class device. + * @attr: Unused. + * @buf: Data buffer. + * @count: Size of the data buffer. * * Description: * If val is in a valid range then set the adapter's link speed field and @@ -7111,6 +7123,7 @@ lpfc_set_vport_symbolic_name(struct fc_vport *fc_vport) /** * lpfc_hba_log_verbose_init - Set hba's log verbose level * @phba: Pointer to lpfc_hba struct. + * @verbose: Verbose level to set. * * This function is called by the lpfc_get_cfgparam() routine to set the * module lpfc_log_verbose into the @phba cfg_log_verbose for use with -- cgit v1.2.3 From e61e07409cf7dbdc532aeb39706f4de04f0aee2e Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:46 +0000 Subject: scsi: lpfc: lpfc_debugfs: Fix a couple of function documentation issues Fixes the following W=1 kernel build warning(s): drivers/scsi/lpfc/lpfc_debugfs.c:4204: warning: Function parameter or member 'len' not described in 'lpfc_idiag_queacc_read_qe' drivers/scsi/lpfc/lpfc_debugfs.c:4781: warning: Function parameter or member 'ctlregid' not described in 'lpfc_idiag_ctlacc_read_reg' drivers/scsi/lpfc/lpfc_debugfs.c:4781: warning: Excess function parameter 'drbregid' description in 'lpfc_idiag_ctlacc_read_reg' Link: https://lore.kernel.org/r/20201102142359.561122-7-lee.jones@linaro.org Cc: James Smart Cc: Dick Kennedy Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_debugfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 325081ac6553..5a354abcbafc 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -4186,6 +4186,7 @@ lpfc_idiag_que_param_check(struct lpfc_queue *q, int index, int count) /** * lpfc_idiag_queacc_read_qe - read a single entry from the given queue index * @pbuffer: The pointer to buffer to copy the read data into. + * @len: Length of the buffer. * @pque: The pointer to the queue to be read. * @index: The index into the queue entry. * @@ -4762,7 +4763,7 @@ error_out: * @phba: The pointer to hba structure. * @pbuffer: The pointer to the buffer to copy the data to. * @len: The length of bytes to copied. - * @drbregid: The id to doorbell registers. + * @ctlregid: The id to doorbell registers. * * Description: * This routine reads a control register and copies its content to the -- cgit v1.2.3 From ea085dab6b9f220f0455f27e64af00deed102976 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:47 +0000 Subject: scsi: lpfc: lpfc_bsg: Provide correct documentation for a bunch of functions Fixes the following W=1 kernel build warning(s): drivers/scsi/lpfc/lpfc_bsg.c:917: warning: Function parameter or member 'phba' not described in 'lpfc_bsg_ct_unsol_event' drivers/scsi/lpfc/lpfc_bsg.c:917: warning: Function parameter or member 'pring' not described in 'lpfc_bsg_ct_unsol_event' drivers/scsi/lpfc/lpfc_bsg.c:1484: warning: Function parameter or member 'cmp' not described in 'lpfc_issue_ct_rsp' drivers/scsi/lpfc/lpfc_bsg.c:3900: warning: Function parameter or member 'job' not described in 'lpfc_bsg_sli_cfg_read_cmd_ext' drivers/scsi/lpfc/lpfc_bsg.c:3900: warning: Function parameter or member 'dmabuf' not described in 'lpfc_bsg_sli_cfg_read_cmd_ext' drivers/scsi/lpfc/lpfc_bsg.c:3900: warning: Excess function parameter 'mb' description in 'lpfc_bsg_sli_cfg_read_cmd_ext' drivers/scsi/lpfc/lpfc_bsg.c:3900: warning: Excess function parameter 'dmabuff' description in 'lpfc_bsg_sli_cfg_read_cmd_ext' drivers/scsi/lpfc/lpfc_bsg.c:4088: warning: Function parameter or member 'job' not described in 'lpfc_bsg_sli_cfg_write_cmd_ext' drivers/scsi/lpfc/lpfc_bsg.c:4088: warning: Function parameter or member 'nemb_tp' not described in 'lpfc_bsg_sli_cfg_write_cmd_ext' drivers/scsi/lpfc/lpfc_bsg.c:4088: warning: Function parameter or member 'dmabuf' not described in 'lpfc_bsg_sli_cfg_write_cmd_ext' drivers/scsi/lpfc/lpfc_bsg.c:4088: warning: Excess function parameter 'mb' description in 'lpfc_bsg_sli_cfg_write_cmd_ext' drivers/scsi/lpfc/lpfc_bsg.c:4088: warning: Excess function parameter 'dmabuff' description in 'lpfc_bsg_sli_cfg_write_cmd_ext' drivers/scsi/lpfc/lpfc_bsg.c:4254: warning: Function parameter or member 'job' not described in 'lpfc_bsg_handle_sli_cfg_mbox' drivers/scsi/lpfc/lpfc_bsg.c:4254: warning: Function parameter or member 'dmabuf' not described in 'lpfc_bsg_handle_sli_cfg_mbox' drivers/scsi/lpfc/lpfc_bsg.c:4254: warning: Excess function parameter 'mb' description in 'lpfc_bsg_handle_sli_cfg_mbox' drivers/scsi/lpfc/lpfc_bsg.c:4254: warning: Excess function parameter 'dmabuff' description in 'lpfc_bsg_handle_sli_cfg_mbox' drivers/scsi/lpfc/lpfc_bsg.c:4403: warning: Function parameter or member 'job' not described in 'lpfc_bsg_read_ebuf_get' drivers/scsi/lpfc/lpfc_bsg.c:4403: warning: Excess function parameter 'dmabuf' description in 'lpfc_bsg_read_ebuf_get' drivers/scsi/lpfc/lpfc_bsg.c:4474: warning: Function parameter or member 'job' not described in 'lpfc_bsg_write_ebuf_set' drivers/scsi/lpfc/lpfc_bsg.c:4600: warning: Function parameter or member 'job' not described in 'lpfc_bsg_handle_sli_cfg_ebuf' drivers/scsi/lpfc/lpfc_bsg.c:4600: warning: Function parameter or member 'dmabuf' not described in 'lpfc_bsg_handle_sli_cfg_ebuf' drivers/scsi/lpfc/lpfc_bsg.c:4600: warning: Excess function parameter 'mb' description in 'lpfc_bsg_handle_sli_cfg_ebuf' drivers/scsi/lpfc/lpfc_bsg.c:4600: warning: Excess function parameter 'dmabuff' description in 'lpfc_bsg_handle_sli_cfg_ebuf' drivers/scsi/lpfc/lpfc_bsg.c:4645: warning: Function parameter or member 'job' not described in 'lpfc_bsg_handle_sli_cfg_ext' drivers/scsi/lpfc/lpfc_bsg.c:4645: warning: Function parameter or member 'dmabuf' not described in 'lpfc_bsg_handle_sli_cfg_ext' drivers/scsi/lpfc/lpfc_bsg.c:4645: warning: Excess function parameter 'mb' description in 'lpfc_bsg_handle_sli_cfg_ext' drivers/scsi/lpfc/lpfc_bsg.c:4645: warning: Excess function parameter 'dmabuff' description in 'lpfc_bsg_handle_sli_cfg_ext' drivers/scsi/lpfc/lpfc_bsg.c:4723: warning: Function parameter or member 'job' not described in 'lpfc_bsg_issue_mbox' drivers/scsi/lpfc/lpfc_bsg.c:4723: warning: Excess function parameter 'mb' description in 'lpfc_bsg_issue_mbox' Link: https://lore.kernel.org/r/20201102142359.561122-8-lee.jones@linaro.org Cc: James Smart Cc: Dick Kennedy Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_bsg.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 5b66b8ea8363..abe7c53f8caa 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -902,11 +902,8 @@ diag_cmd_data_free(struct lpfc_hba *phba, struct lpfc_dmabufext *mlist) return 0; } -/** +/* * lpfc_bsg_ct_unsol_event - process an unsolicited CT command - * @phba: - * @pring: - * @piocbq: * * This function is called when an unsolicited CT command is received. It * forwards the event to any processes registered to receive CT events. @@ -1455,7 +1452,8 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba, * @phba: Pointer to HBA context object. * @job: Pointer to the job object. * @tag: tag index value into the ports context exchange array. - * @bmp: Pointer to a dma buffer descriptor. + * @cmp: Pointer to a cmp dma buffer descriptor. + * @bmp: Pointer to a bmp dma buffer descriptor. * @num_entry: Number of enties in the bde. **/ static int @@ -3867,9 +3865,9 @@ lpfc_bsg_sli_cfg_dma_desc_setup(struct lpfc_hba *phba, enum nemb_type nemb_tp, /** * lpfc_bsg_sli_cfg_mse_read_cmd_ext - sli_config non-embedded mailbox cmd read * @phba: Pointer to HBA context object. - * @mb: Pointer to a BSG mailbox object. + * @job: Pointer to the job object. * @nemb_tp: Enumerate of non-embedded mailbox command type. - * @dmabuff: Pointer to a DMA buffer descriptor. + * @dmabuf: Pointer to a DMA buffer descriptor. * * This routine performs SLI_CONFIG (0x9B) read mailbox command operation with * non-embedded external bufffers. @@ -4056,8 +4054,9 @@ job_error: /** * lpfc_bsg_sli_cfg_write_cmd_ext - sli_config non-embedded mailbox cmd write * @phba: Pointer to HBA context object. - * @mb: Pointer to a BSG mailbox object. - * @dmabuff: Pointer to a DMA buffer descriptor. + * @job: Pointer to the job object. + * @nemb_tp: Enumerate of non-embedded mailbox command type. + * @dmabuf: Pointer to a DMA buffer descriptor. * * This routine performs SLI_CONFIG (0x9B) write mailbox command operation with * non-embedded external bufffers. @@ -4222,8 +4221,8 @@ job_error: /** * lpfc_bsg_handle_sli_cfg_mbox - handle sli-cfg mailbox cmd with ext buffer * @phba: Pointer to HBA context object. - * @mb: Pointer to a BSG mailbox object. - * @dmabuff: Pointer to a DMA buffer descriptor. + * @job: Pointer to the job object. + * @dmabuf: Pointer to a DMA buffer descriptor. * * This routine handles SLI_CONFIG (0x9B) mailbox command with non-embedded * external bufffers, including both 0x9B with non-embedded MSEs and 0x9B @@ -4374,7 +4373,7 @@ lpfc_bsg_mbox_ext_abort(struct lpfc_hba *phba) /** * lpfc_bsg_read_ebuf_get - get the next mailbox read external buffer * @phba: Pointer to HBA context object. - * @dmabuf: Pointer to a DMA buffer descriptor. + * @job: Pointer to the job object. * * This routine extracts the next mailbox read external buffer back to * user space through BSG. @@ -4444,6 +4443,7 @@ lpfc_bsg_read_ebuf_get(struct lpfc_hba *phba, struct bsg_job *job) /** * lpfc_bsg_write_ebuf_set - set the next mailbox write external buffer * @phba: Pointer to HBA context object. + * @job: Pointer to the job object. * @dmabuf: Pointer to a DMA buffer descriptor. * * This routine sets up the next mailbox read external buffer obtained @@ -4569,8 +4569,8 @@ job_error: /** * lpfc_bsg_handle_sli_cfg_ebuf - handle ext buffer with sli-cfg mailbox cmd * @phba: Pointer to HBA context object. - * @mb: Pointer to a BSG mailbox object. - * @dmabuff: Pointer to a DMA buffer descriptor. + * @job: Pointer to the job object. + * @dmabuf: Pointer to a DMA buffer descriptor. * * This routine handles the external buffer with SLI_CONFIG (0x9B) mailbox * command with multiple non-embedded external buffers. @@ -4614,8 +4614,8 @@ lpfc_bsg_handle_sli_cfg_ebuf(struct lpfc_hba *phba, struct bsg_job *job, /** * lpfc_bsg_handle_sli_cfg_ext - handle sli-cfg mailbox with external buffer * @phba: Pointer to HBA context object. - * @mb: Pointer to a BSG mailbox object. - * @dmabuff: Pointer to a DMA buffer descriptor. + * @job: Pointer to the job object. + * @dmabuf: Pointer to a DMA buffer descriptor. * * This routine checkes and handles non-embedded multi-buffer SLI_CONFIG * (0x9B) mailbox commands and external buffers. @@ -4688,7 +4688,7 @@ sli_cfg_ext_error: /** * lpfc_bsg_issue_mbox - issues a mailbox command on behalf of an app * @phba: Pointer to HBA context object. - * @mb: Pointer to a mailbox object. + * @job: Pointer to the job object. * @vport: Pointer to a vport object. * * Allocate a tracking object, mailbox command memory, get a mailbox -- cgit v1.2.3 From 9a5cf98d7ee69e7705705b40b5d947a252c134ac Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:48 +0000 Subject: scsi: esas2r: esas2r_disc: Place brackets around a potentially empty if() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following W=1 kernel build warning(s): drivers/scsi/esas2r/esas2r_disc.c: In function ‘esas2r_disc_get_phys_addr’: drivers/scsi/esas2r/esas2r_disc.c:1035:17: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] Link: https://lore.kernel.org/r/20201102142359.561122-9-lee.jones@linaro.org Cc: Bradley Grove Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/esas2r/esas2r_disc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/esas2r/esas2r_disc.c b/drivers/scsi/esas2r/esas2r_disc.c index 1c079f4300a5..ba42536d1e87 100644 --- a/drivers/scsi/esas2r/esas2r_disc.c +++ b/drivers/scsi/esas2r/esas2r_disc.c @@ -1031,8 +1031,9 @@ static u32 esas2r_disc_get_phys_addr(struct esas2r_sg_context *sgc, u64 *addr) { struct esas2r_adapter *a = sgc->adapter; - if (sgc->length > ESAS2R_DISC_BUF_LEN) + if (sgc->length > ESAS2R_DISC_BUF_LEN) { esas2r_bugon(); + } *addr = a->uncached_phys + (u64)((u8 *)a->disc_buffer - a->uncached); -- cgit v1.2.3 From 433e07e08c638827e99923192e91c9be8912b5e0 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:49 +0000 Subject: scsi: esas2r: esas2r_init: Place brackets around a potentially empty if() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following W=1 kernel build warning(s): drivers/scsi/esas2r/esas2r_init.c: In function ‘esas2r_init_adapter’: drivers/scsi/esas2r/esas2r_init.c:418:41: warning: suggest braces around empty body in an ‘else’ statement [-Wempty-body] Link: https://lore.kernel.org/r/20201102142359.561122-10-lee.jones@linaro.org Cc: Bradley Grove Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/esas2r/esas2r_init.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/esas2r/esas2r_init.c b/drivers/scsi/esas2r/esas2r_init.c index 09c5c24bf391..4b91db7ba919 100644 --- a/drivers/scsi/esas2r/esas2r_init.c +++ b/drivers/scsi/esas2r/esas2r_init.c @@ -412,10 +412,11 @@ int esas2r_init_adapter(struct Scsi_Host *host, struct pci_dev *pcid, esas2r_disable_chip_interrupts(a); esas2r_check_adapter(a); - if (!esas2r_init_adapter_hw(a, true)) + if (!esas2r_init_adapter_hw(a, true)) { esas2r_log(ESAS2R_LOG_CRIT, "failed to initialize hardware!"); - else + } else { esas2r_debug("esas2r_init_adapter ok"); + } esas2r_claim_interrupts(a); -- cgit v1.2.3 From 74d1f928162a217f5dc034b98deff78490300479 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:50 +0000 Subject: scsi: lpfc: lpfc_nvme: Remove unused variable 'phba' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following W=1 kernel build warning(s): drivers/scsi/lpfc/lpfc_nvme.c: In function ‘lpfc_nvme_ls_abort’: drivers/scsi/lpfc/lpfc_nvme.c:943:19: warning: variable ‘phba’ set but not used [-Wunused-but-set-variable] Link: https://lore.kernel.org/r/20201102142359.561122-11-lee.jones@linaro.org Cc: James Smart Cc: Dick Kennedy Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvme.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 69f1a0457f51..33d007ca5c8e 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -940,7 +940,6 @@ lpfc_nvme_ls_abort(struct nvme_fc_local_port *pnvme_lport, { struct lpfc_nvme_lport *lport; struct lpfc_vport *vport; - struct lpfc_hba *phba; struct lpfc_nodelist *ndlp; int ret; @@ -948,7 +947,6 @@ lpfc_nvme_ls_abort(struct nvme_fc_local_port *pnvme_lport, if (unlikely(!lport)) return; vport = lport->vport; - phba = vport->phba; if (vport->load_flag & FC_UNLOADING) return; -- cgit v1.2.3 From d23ec0b610e5cdf55853472157768d4412b3d13b Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:51 +0000 Subject: scsi: ufs: ufshcd: Fix some function doc-rot Fixes the following W=1 kernel build warning(s): drivers/scsi/ufs/ufshcd.c:6603: warning: Function parameter or member 'hba' not described in 'ufshcd_try_to_abort_task' drivers/scsi/ufs/ufshcd.c:6603: warning: Function parameter or member 'tag' not described in 'ufshcd_try_to_abort_task' drivers/scsi/ufs/ufshcd.c:6603: warning: Excess function parameter 'cmd' description in 'ufshcd_try_to_abort_task' Link: https://lore.kernel.org/r/20201102142359.561122-12-lee.jones@linaro.org Cc: Alim Akhtar Cc: Avri Altman Cc: Santosh Yaraganavi Cc: Vinayak Holikatti Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index ee083b96e405..8001bbfec5c0 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6599,7 +6599,8 @@ static void ufshcd_set_req_abort_skip(struct ufs_hba *hba, unsigned long bitmap) /** * ufshcd_try_to_abort_task - abort a specific task - * @cmd: SCSI command pointer + * @hba: Pointer to adapter instance + * @tag: Task tag/index to be aborted * * Abort the pending command in device by sending UFS_ABORT_TASK task management * command, and in host controller by clearing the door-bell register. There can -- cgit v1.2.3 From 3e7491701a3323659d2579f785cda5240351d6f3 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:52 +0000 Subject: scsi: lpfc: lpfc_nvme: Fix some kernel-doc related issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following W=1 kernel build warning(s): drivers/scsi/lpfc/lpfc_nvme.c: In function ‘lpfc_nvme_ls_abort’: drivers/scsi/lpfc/lpfc_nvme.c:943:19: warning: variable ‘phba’ set but not used [-Wunused-but-set-variable] drivers/scsi/lpfc/lpfc_nvme.c:256: warning: Excess function parameter 'lpfc_pnvme' description in 'lpfc_nvme_create_queue' drivers/scsi/lpfc/lpfc_nvme.c:804: warning: Function parameter or member 'pnvme_rport' not described in 'lpfc_nvme_ls_req' drivers/scsi/lpfc/lpfc_nvme.c:804: warning: Excess function parameter 'nvme_rport' description in 'lpfc_nvme_ls_req' drivers/scsi/lpfc/lpfc_nvme.c:1312: warning: Function parameter or member 'lpfc_ncmd' not described in 'lpfc_nvme_prep_io_cmd' drivers/scsi/lpfc/lpfc_nvme.c:1312: warning: Excess function parameter 'lpfcn_cmd' description in 'lpfc_nvme_prep_io_cmd' drivers/scsi/lpfc/lpfc_nvme.c:1416: warning: Function parameter or member 'lpfc_ncmd' not described in 'lpfc_nvme_prep_io_dma' drivers/scsi/lpfc/lpfc_nvme.c:1416: warning: Excess function parameter 'lpfcn_cmd' description in 'lpfc_nvme_prep_io_dma' drivers/scsi/lpfc/lpfc_nvme.c:1594: warning: bad line: indicated in @lpfc_nvme_rport. drivers/scsi/lpfc/lpfc_nvme.c:1605: warning: Function parameter or member 'pnvme_lport' not described in 'lpfc_nvme_fcp_io_submit' drivers/scsi/lpfc/lpfc_nvme.c:1605: warning: Function parameter or member 'pnvme_rport' not described in 'lpfc_nvme_fcp_io_submit' drivers/scsi/lpfc/lpfc_nvme.c:1605: warning: Function parameter or member 'pnvme_fcreq' not described in 'lpfc_nvme_fcp_io_submit' drivers/scsi/lpfc/lpfc_nvme.c:1605: warning: Excess function parameter 'lpfc_pnvme' description in 'lpfc_nvme_fcp_io_submit' drivers/scsi/lpfc/lpfc_nvme.c:1605: warning: Excess function parameter 'lpfc_nvme_lport' description in 'lpfc_nvme_fcp_io_submit' drivers/scsi/lpfc/lpfc_nvme.c:1605: warning: Excess function parameter 'lpfc_nvme_rport' description in 'lpfc_nvme_fcp_io_submit' drivers/scsi/lpfc/lpfc_nvme.c:1605: warning: Excess function parameter 'lpfc_nvme_fcreq' description in 'lpfc_nvme_fcp_io_submit' drivers/scsi/lpfc/lpfc_nvme.c:1852: warning: Function parameter or member 'abts_cmpl' not described in 'lpfc_nvme_abort_fcreq_cmpl' drivers/scsi/lpfc/lpfc_nvme.c:1852: warning: Excess function parameter 'rspiocb' description in 'lpfc_nvme_abort_fcreq_cmpl' drivers/scsi/lpfc/lpfc_nvme.c:1888: warning: Function parameter or member 'pnvme_lport' not described in 'lpfc_nvme_fcp_abort' drivers/scsi/lpfc/lpfc_nvme.c:1888: warning: Function parameter or member 'pnvme_rport' not described in 'lpfc_nvme_fcp_abort' drivers/scsi/lpfc/lpfc_nvme.c:1888: warning: Function parameter or member 'pnvme_fcreq' not described in 'lpfc_nvme_fcp_abort' drivers/scsi/lpfc/lpfc_nvme.c:1888: warning: Excess function parameter 'lpfc_pnvme' description in 'lpfc_nvme_fcp_abort' drivers/scsi/lpfc/lpfc_nvme.c:1888: warning: Excess function parameter 'lpfc_nvme_lport' description in 'lpfc_nvme_fcp_abort' drivers/scsi/lpfc/lpfc_nvme.c:1888: warning: Excess function parameter 'lpfc_nvme_rport' description in 'lpfc_nvme_fcp_abort' drivers/scsi/lpfc/lpfc_nvme.c:1888: warning: Excess function parameter 'lpfc_nvme_fcreq' description in 'lpfc_nvme_fcp_abort' drivers/scsi/lpfc/lpfc_nvme.c:2089: warning: Function parameter or member 'ndlp' not described in 'lpfc_get_nvme_buf' drivers/scsi/lpfc/lpfc_nvme.c:2089: warning: Function parameter or member 'idx' not described in 'lpfc_get_nvme_buf' drivers/scsi/lpfc/lpfc_nvme.c:2089: warning: Function parameter or member 'expedite' not described in 'lpfc_get_nvme_buf' drivers/scsi/lpfc/lpfc_nvme.c:2193: warning: Function parameter or member 'vport' not described in 'lpfc_nvme_create_localport' drivers/scsi/lpfc/lpfc_nvme.c:2326: warning: Function parameter or member 'vport' not described in 'lpfc_nvme_destroy_localport' drivers/scsi/lpfc/lpfc_nvme.c:2326: warning: Excess function parameter 'pnvme' description in 'lpfc_nvme_destroy_localport' drivers/scsi/lpfc/lpfc_nvme.c:2544: warning: Function parameter or member 'vport' not described in 'lpfc_nvme_rescan_port' drivers/scsi/lpfc/lpfc_nvme.c:2544: warning: Function parameter or member 'ndlp' not described in 'lpfc_nvme_rescan_port' Link: https://lore.kernel.org/r/20201102142359.561122-13-lee.jones@linaro.org Cc: James Smart Cc: Dick Kennedy Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvme.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 33d007ca5c8e..42eb144fed0d 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -235,7 +235,6 @@ lpfc_nvme_prep_abort_wqe(struct lpfc_iocbq *pwqeq, u16 xritag, u8 opt) /** * lpfc_nvme_create_queue - * @pnvme_lport: Transport localport that LS is to be issued from - * @lpfc_pnvme: Pointer to the driver's nvme instance data * @qidx: An cpu index used to affinitize IO queues and MSIX vectors. * @qsize: Size of the queue in bytes * @handle: An opaque driver handle used in follow-up calls. @@ -787,7 +786,7 @@ __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /** * lpfc_nvme_ls_req - Issue an NVME Link Service request * @pnvme_lport: Transport localport that LS is to be issued from. - * @nvme_rport: Transport remoteport that LS is to be sent to. + * @pnvme_rport: Transport remoteport that LS is to be sent to. * @pnvme_lsreq: the transport nvme_ls_req structure for the LS * * Driver registers this routine to handle any link service request @@ -1290,7 +1289,7 @@ out_err: /** * lpfc_nvme_prep_io_cmd - Issue an NVME-over-FCP IO * @vport: pointer to a host virtual N_Port data structure - * @lpfcn_cmd: Pointer to lpfc scsi command + * @lpfc_ncmd: Pointer to lpfc scsi command * @pnode: pointer to a node-list data structure * @cstat: pointer to the control status structure * @@ -1398,7 +1397,7 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport, /** * lpfc_nvme_prep_io_dma - Issue an NVME-over-FCP IO * @vport: pointer to a host virtual N_Port data structure - * @lpfcn_cmd: Pointer to lpfc scsi command + * @lpfc_ncmd: Pointer to lpfc scsi command * * Driver registers this routine as it io request handler. This * routine issues an fcp WQE with data from the @lpfc_nvme_fcpreq @@ -1580,16 +1579,14 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, /** * lpfc_nvme_fcp_io_submit - Issue an NVME-over-FCP IO - * @lpfc_pnvme: Pointer to the driver's nvme instance data - * @lpfc_nvme_lport: Pointer to the driver's local port data - * @lpfc_nvme_rport: Pointer to the rport getting the @lpfc_nvme_ereq - * @lpfc_nvme_fcreq: IO request from nvme fc to driver. + * @pnvme_lport: Pointer to the driver's local port data + * @pnvme_rport: Pointer to the rport getting the @lpfc_nvme_ereq * @hw_queue_handle: Driver-returned handle in lpfc_nvme_create_queue + * @pnvme_fcreq: IO request from nvme fc to driver. * * Driver registers this routine as it io request handler. This * routine issues an fcp WQE with data from the @lpfc_nvme_fcpreq - * data structure to the rport - indicated in @lpfc_nvme_rport. + * data structure to the rport indicated in @lpfc_nvme_rport. * * Return value : * 0 - Success @@ -1837,7 +1834,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport, * lpfc_nvme_abort_fcreq_cmpl - Complete an NVME FCP abort request. * @phba: Pointer to HBA context object * @cmdiocb: Pointer to command iocb object. - * @rspiocb: Pointer to response iocb object. + * @abts_cmpl: Pointer to wcqe complete object. * * This is the callback function for any NVME FCP IO that was aborted. * @@ -1863,11 +1860,10 @@ lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /** * lpfc_nvme_fcp_abort - Issue an NVME-over-FCP ABTS - * @lpfc_pnvme: Pointer to the driver's nvme instance data - * @lpfc_nvme_lport: Pointer to the driver's local port data - * @lpfc_nvme_rport: Pointer to the rport getting the @lpfc_nvme_ereq - * @lpfc_nvme_fcreq: IO request from nvme fc to driver. + * @pnvme_lport: Pointer to the driver's local port data + * @pnvme_rport: Pointer to the rport getting the @lpfc_nvme_ereq * @hw_queue_handle: Driver-returned handle in lpfc_nvme_create_queue + * @pnvme_fcreq: IO request from nvme fc to driver. * * Driver registers this routine as its nvme request io abort handler. This * routine issues an fcp Abort WQE with data from the @lpfc_nvme_fcpreq @@ -2070,9 +2066,8 @@ static struct nvme_fc_port_template lpfc_nvme_template = { .fcprqst_priv_sz = sizeof(struct lpfc_nvme_fcpreq_priv), }; -/** +/* * lpfc_get_nvme_buf - Get a nvme buffer from io_buf_list of the HBA - * @phba: The HBA for which this call is being executed. * * This routine removes a nvme buffer from head of @hdwq io_buf_list * and returns to caller. @@ -2172,7 +2167,7 @@ lpfc_release_nvme_buf(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_ncmd) /** * lpfc_nvme_create_localport - Create/Bind an nvme localport instance. - * @pvport - the lpfc_vport instance requesting a localport. + * @vport - the lpfc_vport instance requesting a localport. * * This routine is invoked to create an nvme localport instance to bind * to the nvme_fc_transport. It is called once during driver load @@ -2319,7 +2314,7 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport, /** * lpfc_nvme_destroy_localport - Destroy lpfc_nvme bound to nvme transport. - * @pnvme: pointer to lpfc nvme data structure. + * @vport: pointer to a host virtual N_Port data structure * * This routine is invoked to destroy all lports bound to the phba. * The lport memory was allocated by the nvme fc transport and is @@ -2538,7 +2533,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) #endif } -/** +/* * lpfc_nvme_rescan_port - Check to see if we should rescan this remoteport * * If the ndlp represents an NVME Target, that we are logged into, -- cgit v1.2.3 From 6abf98de6f8ad4f078f4845589e8d7f024a851bf Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:53 +0000 Subject: scsi: esas2r: esas2r_int: Add brackets around potentially empty if()s MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following W=1 kernel build warning(s): drivers/scsi/esas2r/esas2r_int.c: In function ‘esas2r_doorbell_interrupt’: drivers/scsi/esas2r/esas2r_int.c:692:22: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body] drivers/scsi/esas2r/esas2r_int.c: In function ‘esas2r_send_reset_ae’: drivers/scsi/esas2r/esas2r_int.c:868:44: warning: suggest braces around empty body in an ‘else’ statement [-Wempty-body] Link: https://lore.kernel.org/r/20201102142359.561122-14-lee.jones@linaro.org Cc: Bradley Grove Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/esas2r/esas2r_int.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/esas2r/esas2r_int.c b/drivers/scsi/esas2r/esas2r_int.c index f16d6bcf9bb6..5281d9356327 100644 --- a/drivers/scsi/esas2r/esas2r_int.c +++ b/drivers/scsi/esas2r/esas2r_int.c @@ -688,8 +688,9 @@ static void esas2r_doorbell_interrupt(struct esas2r_adapter *a, u32 doorbell) esas2r_local_reset_adapter(a); } - if (!(doorbell & DRBL_FORCE_INT)) + if (!(doorbell & DRBL_FORCE_INT)) { esas2r_trace_exit(); + } } void esas2r_force_interrupt(struct esas2r_adapter *a) @@ -862,10 +863,11 @@ void esas2r_send_reset_ae(struct esas2r_adapter *a, bool pwr_mgt) ae.byflags = 0; ae.bylength = (u8)sizeof(struct atto_vda_ae_hdr); - if (pwr_mgt) + if (pwr_mgt) { esas2r_hdebug("*** sending power management AE ***"); - else + } else { esas2r_hdebug("*** sending reset AE ***"); + } esas2r_queue_fw_event(a, fw_event_vda_ae, &ae, sizeof(union atto_vda_ae)); -- cgit v1.2.3 From d3cb79fcf943040394073de14d989a3547974d7f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:54 +0000 Subject: scsi: lpfc: lpfc_nvmet: Fix-up some formatting and doc-rot issues Fixes the following W=1 kernel build warning(s): drivers/scsi/lpfc/lpfc_nvmet.c:386: warning: Function parameter or member 'ctx_buf' not described in 'lpfc_nvmet_ctxbuf_post' drivers/scsi/lpfc/lpfc_nvmet.c:386: warning: Excess function parameter 'ctxp' description in 'lpfc_nvmet_ctxbuf_post' drivers/scsi/lpfc/lpfc_nvmet.c:386: warning: Excess function parameter 'mp' description in 'lpfc_nvmet_ctxbuf_post' drivers/scsi/lpfc/lpfc_nvmet.c:1310: warning: Function parameter or member 'targetport' not described in 'lpfc_nvmet_ls_req' drivers/scsi/lpfc/lpfc_nvmet.c:1310: warning: Function parameter or member 'hosthandle' not described in 'lpfc_nvmet_ls_req' drivers/scsi/lpfc/lpfc_nvmet.c:1310: warning: Function parameter or member 'pnvme_lsreq' not described in 'lpfc_nvmet_ls_req' drivers/scsi/lpfc/lpfc_nvmet.c:1350: warning: Function parameter or member 'hosthandle' not described in 'lpfc_nvmet_ls_abort' drivers/scsi/lpfc/lpfc_nvmet.c:1350: warning: Function parameter or member 'pnvme_lsreq' not described in 'lpfc_nvmet_ls_abort' drivers/scsi/lpfc/lpfc_nvmet.c:3607: warning: Function parameter or member 'phba' not described in 'lpfc_nvmet_invalidate_host' drivers/scsi/lpfc/lpfc_nvmet.c:3607: warning: Function parameter or member 'ndlp' not described in 'lpfc_nvmet_invalidate_host' Link: https://lore.kernel.org/r/20201102142359.561122-15-lee.jones@linaro.org Cc: James Smart Cc: Dick Kennedy Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvmet.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index d4ade7cdb93a..675253093e87 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -371,8 +371,7 @@ finish: /** * lpfc_nvmet_ctxbuf_post - Repost a NVMET RQ DMA buffer and clean up context * @phba: HBA buffer is associated with - * @ctxp: context to clean up - * @mp: Buffer to free + * @ctx_buf: ctx buffer context * * Description: Frees the given DMA buffer in the appropriate way given by * reposting it to its associated RQ so it can be reused. @@ -1291,10 +1290,10 @@ lpfc_nvmet_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, /** * lpfc_nvmet_ls_req - Issue an Link Service request - * @targetport - pointer to target instance registered with nvmet transport. - * @hosthandle - hosthandle set by the driver in a prior ls_rqst_rcv. + * @targetport: pointer to target instance registered with nvmet transport. + * @hosthandle: hosthandle set by the driver in a prior ls_rqst_rcv. * Driver sets this value to the ndlp pointer. - * @pnvme_lsreq - the transport nvme_ls_req structure for the LS + * @pnvme_lsreq: the transport nvme_ls_req structure for the LS * * Driver registers this routine to handle any link service request * from the nvme_fc transport to a remote nvme-aware port. @@ -1336,9 +1335,9 @@ lpfc_nvmet_ls_req(struct nvmet_fc_target_port *targetport, /** * lpfc_nvmet_ls_abort - Abort a prior NVME LS request * @targetport: Transport targetport, that LS was issued from. - * @hosthandle - hosthandle set by the driver in a prior ls_rqst_rcv. + * @hosthandle: hosthandle set by the driver in a prior ls_rqst_rcv. * Driver sets this value to the ndlp pointer. - * @pnvme_lsreq - the transport nvme_ls_req structure for LS to be aborted + * @pnvme_lsreq: the transport nvme_ls_req structure for LS to be aborted * * Driver registers this routine to abort an NVME LS request that is * in progress (from the transports perspective). @@ -3596,8 +3595,8 @@ out: /** * lpfc_nvmet_invalidate_host * - * @phba - pointer to the driver instance bound to an adapter port. - * @ndlp - pointer to an lpfc_nodelist type + * @phba: pointer to the driver instance bound to an adapter port. + * @ndlp: pointer to an lpfc_nodelist type * * This routine upcalls the nvmet transport to invalidate an NVME * host to which this target instance had active connections. -- cgit v1.2.3 From bf7e38aa0ee1f06130fb3019f42d59b767da73a9 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:55 +0000 Subject: scsi: esas2r: esas2r_main: Demote non-conformant kernel-doc header Fixes the following W=1 kernel build warning(s): drivers/scsi/esas2r/esas2r_main.c:911: warning: Function parameter or member 'a' not described in 'esas2r_check_active_queue' drivers/scsi/esas2r/esas2r_main.c:911: warning: Function parameter or member 'abort_request' not described in 'esas2r_check_active_queue' drivers/scsi/esas2r/esas2r_main.c:911: warning: Function parameter or member 'cmd' not described in 'esas2r_check_active_queue' drivers/scsi/esas2r/esas2r_main.c:911: warning: Function parameter or member 'queue' not described in 'esas2r_check_active_queue' Link: https://lore.kernel.org/r/20201102142359.561122-16-lee.jones@linaro.org Cc: Bradley Grove Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/esas2r/esas2r_main.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c index 7b49e2e9fcde..923e6e5ddbf9 100644 --- a/drivers/scsi/esas2r/esas2r_main.c +++ b/drivers/scsi/esas2r/esas2r_main.c @@ -894,15 +894,11 @@ static void complete_task_management_request(struct esas2r_adapter *a, esas2r_free_request(a, rq); } -/** +/* * Searches the specified queue for the specified queue for the command * to abort. * - * @param [in] a - * @param [in] abort_request - * @param [in] cmd - * t - * @return 0 on failure, 1 if command was not found, 2 if command was found + * Return 0 on failure, 1 if command was not found, 2 if command was found */ static int esas2r_check_active_queue(struct esas2r_adapter *a, struct esas2r_request **abort_request, -- cgit v1.2.3 From 90ab11234d7995530dfa2a2b072150fd6e5fc1d2 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:56 +0000 Subject: scsi: advansys: Relocate or remove unused variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following W=1 kernel build warning(s): drivers/scsi/advansys.c: In function ‘asc_prt_asc_board_eeprom’: drivers/scsi/advansys.c:2879:15: warning: variable ‘asc_dvc_varp’ set but not used [-Wunused-but-set-variable] drivers/scsi/advansys.c: In function ‘asc_prt_driver_conf’: drivers/scsi/advansys.c:3174:6: warning: variable ‘chip_scsi_id’ set but not used [-Wunused-but-set-variable] drivers/scsi/advansys.c: In function ‘AdvISR’: drivers/scsi/advansys.c:6114:9: warning: variable ‘target_bit’ set but not used [-Wunused-but-set-variable] Link: https://lore.kernel.org/r/20201102142359.561122-17-lee.jones@linaro.org Cc: Matthew Wilcox Cc: Hannes Reinecke Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/advansys.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index c2c7850ff7b4..79830e77afa9 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -2876,15 +2876,15 @@ static int asc_get_eeprom_string(ushort *serialnum, uchar *cp) static void asc_prt_asc_board_eeprom(struct seq_file *m, struct Scsi_Host *shost) { struct asc_board *boardp = shost_priv(shost); - ASC_DVC_VAR *asc_dvc_varp; ASCEEP_CONFIG *ep; int i; + uchar serialstr[13]; #ifdef CONFIG_ISA + ASC_DVC_VAR *asc_dvc_varp; int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 }; -#endif /* CONFIG_ISA */ - uchar serialstr[13]; asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; +#endif /* CONFIG_ISA */ ep = &boardp->eep_config.asc_eep; seq_printf(m, @@ -3171,7 +3171,6 @@ static void asc_prt_adv_board_eeprom(struct seq_file *m, struct Scsi_Host *shost static void asc_prt_driver_conf(struct seq_file *m, struct Scsi_Host *shost) { struct asc_board *boardp = shost_priv(shost); - int chip_scsi_id; seq_printf(m, "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n", @@ -3197,12 +3196,6 @@ static void asc_prt_driver_conf(struct seq_file *m, struct Scsi_Host *shost) boardp->asc_n_io_port); seq_printf(m, " io_port 0x%lx\n", shost->io_port); - - if (ASC_NARROW_BOARD(boardp)) { - chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; - } else { - chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; - } } /* @@ -6111,7 +6104,6 @@ static int AdvISR(ADV_DVC_VAR *asc_dvc) { AdvPortAddr iop_base; uchar int_stat; - ushort target_bit; ADV_CARR_T *free_carrp; __le32 irq_next_vpa; ADV_SCSI_REQ_Q *scsiq; @@ -6198,8 +6190,6 @@ static int AdvISR(ADV_DVC_VAR *asc_dvc) asc_dvc->carr_freelist = free_carrp; asc_dvc->carr_pending_cnt--; - target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id); - /* * Clear request microcode control flag. */ -- cgit v1.2.3 From 67056d90f13547558a3d7661fd69acd1463146de Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:57 +0000 Subject: scsi: dc395x: Remove a few unused variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following W=1 kernel build warning(s): drivers/scsi/dc395x.c: In function ‘data_io_transfer’: drivers/scsi/dc395x.c:2400:16: warning: variable ‘data2’ set but not used [-Wunused-but-set-variable] drivers/scsi/dc395x.c:2400:6: warning: variable ‘data’ set but not used [-Wunused-but-set-variable] drivers/scsi/dc395x.c: In function ‘reselect’: drivers/scsi/dc395x.c:2992:5: warning: variable ‘arblostflag’ set but not used [-Wunused-but-set-variable] drivers/scsi/dc395x.c: In function ‘doing_srb_done’: drivers/scsi/dc395x.c:3393:28: warning: variable ‘dir’ set but not used [-Wunused-but-set-variable] Link: https://lore.kernel.org/r/20201102142359.561122-18-lee.jones@linaro.org Cc: Oliver Neukum Cc: Ali Akcaagac Cc: Jamie Lenehan Cc: "C.L. Huang" Cc: Erich Chen Cc: Kurt Garloff Cc: dc395x@twibble.org Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/dc395x.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index fa16894d8758..f838fe8d7457 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -2397,7 +2397,6 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, } #endif /* DC395x_LASTPIO */ else { /* xfer pad */ - u8 data = 0, data2 = 0; if (srb->sg_count) { srb->adapter_status = H_OVER_UNDER_RUN; srb->status |= OVER_RUN; @@ -2412,8 +2411,8 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, CFG2_WIDEFIFO); if (io_dir & DMACMD_DIR) { - data = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); - data2 = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); + DC395x_read8(acb, TRM_S1040_SCSI_FIFO); + DC395x_read8(acb, TRM_S1040_SCSI_FIFO); } else { /* Danger, Robinson: If you find KGs * scattered over the wide disk, the driver @@ -2427,7 +2426,7 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, /* Danger, Robinson: If you find a collection of Ks on your disk * something broke :-( */ if (io_dir & DMACMD_DIR) - data = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); + DC395x_read8(acb, TRM_S1040_SCSI_FIFO); else DC395x_write8(acb, TRM_S1040_SCSI_FIFO, 'K'); } @@ -2989,7 +2988,6 @@ static void reselect(struct AdapterCtlBlk *acb) struct ScsiReqBlk *srb = NULL; u16 rsel_tar_lun_id; u8 id, lun; - u8 arblostflag = 0; dprintkdbg(DBG_0, "reselect: acb=%p\n", acb); clear_fifo(acb, "reselect"); @@ -3011,7 +3009,6 @@ static void reselect(struct AdapterCtlBlk *acb) srb->cmd, dcb->target_id, dcb->target_lun, rsel_tar_lun_id, DC395x_read16(acb, TRM_S1040_SCSI_STATUS)); - arblostflag = 1; /*srb->state |= SRB_DISCONNECT; */ srb->state = SRB_READY; @@ -3042,7 +3039,7 @@ static void reselect(struct AdapterCtlBlk *acb) "disconnection? <%02i-%i>\n", dcb->target_id, dcb->target_lun); - if (dcb->sync_mode & EN_TAG_QUEUEING /*&& !arblostflag */) { + if (dcb->sync_mode & EN_TAG_QUEUEING) { srb = acb->tmp_srb; dcb->active_srb = srb; } else { @@ -3390,11 +3387,9 @@ static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, struct scsi_cmnd *p; list_for_each_entry_safe(srb, tmp, &dcb->srb_going_list, list) { - enum dma_data_direction dir; int result; p = srb->cmd; - dir = p->sc_data_direction; result = MK_RES(0, did_flag, 0, 0); printk("G:%p(%02i-%i) ", p, p->device->id, (u8)p->device->lun); -- cgit v1.2.3 From 6c22079e9f369e513d8195f96db99a4fbb1525a8 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 2 Nov 2020 14:23:58 +0000 Subject: scsi: dc395x: Mark 's_stat2' as __maybe_unused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's only utilised when debugging is enabled. Fixes the following W=1 kernel build warning(s): drivers/scsi/dc395x.c: In function ‘start_scsi’: drivers/scsi/dc395x.c:1359:6: warning: variable ‘s_stat2’ set but not used [-Wunused-but-set-variable] Link: https://lore.kernel.org/r/20201102142359.561122-19-lee.jones@linaro.org Cc: Oliver Neukum Cc: Ali Akcaagac Cc: Jamie Lenehan Cc: "C.L. Huang" Cc: Erich Chen Cc: Kurt Garloff Cc: dc395x@twibble.org Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/dc395x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index f838fe8d7457..7b522ff345d5 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -1356,7 +1356,7 @@ void selection_timeout_missed(unsigned long ptr) static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, struct ScsiReqBlk* srb) { - u16 s_stat2, return_code; + u16 __maybe_unused s_stat2, return_code; u8 s_stat, scsicommand, i, identify_message; u8 *ptr; dprintkdbg(DBG_0, "start_scsi: (0x%p) <%02i-%i> srb=%p\n", -- cgit v1.2.3 From 268940b80fa4096397fd0a28e6ad807e64120215 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 30 Sep 2020 10:02:54 +0200 Subject: scsi: scsi_dh_alua: Return BLK_STS_AGAIN for ALUA transitioning state When the ALUA state indicates transitioning we should not retry the command immediately, but rather complete the command with BLK_STS_AGAIN to signal the completion handler that it might be retried. This allows multipathing to redirect the command to another path if possible, and avoid stalls during lengthy transitioning times. Link: https://lore.kernel.org/r/20200930080256.90964-3-hare@suse.de Reviewed-by: Ewan D. Milne Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/device_handler/scsi_dh_alua.c | 2 +- drivers/scsi/scsi_lib.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index f32da0ca529e..9e8d32d01d91 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -1091,7 +1091,7 @@ static blk_status_t alua_prep_fn(struct scsi_device *sdev, struct request *req) case SCSI_ACCESS_STATE_LBA: return BLK_STS_OK; case SCSI_ACCESS_STATE_TRANSITIONING: - return BLK_STS_RESOURCE; + return BLK_STS_AGAIN; default: req->rq_flags |= RQF_QUIET; return BLK_STS_IOERR; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 20a357563d3d..7691196f288c 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1707,6 +1707,11 @@ out_put_budget: scsi_device_blocked(sdev)) ret = BLK_STS_DEV_RESOURCE; break; + case BLK_STS_AGAIN: + scsi_req(req)->result = DID_BUS_BUSY << 16; + if (req->rq_flags & RQF_DONTPREP) + scsi_mq_uninit_cmd(cmd); + break; default: if (unlikely(!scsi_device_online(sdev))) scsi_req(req)->result = DID_NO_CONNECT << 16; -- cgit v1.2.3 From fb908850ece3bc93a9d276f6dd8505d824b2789c Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 30 Sep 2020 10:02:55 +0200 Subject: scsi: scsi_dh_alua: Set 'transitioning' state on Unit Attention We should be setting the 'transitioning' ALUA state once we get a Unit Attention indicating the array is in transitioning. There are arrays which cannot respond to an RTPG while in transitioning, and others have issues correctly reporting the state. So better to set the state during Unit Attention handling and wait for TUR / RTPG to run its course. Link: https://lore.kernel.org/r/20200930080256.90964-4-hare@suse.de Reviewed-by: Ewan D. Milne Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/device_handler/scsi_dh_alua.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 9e8d32d01d91..92b592e9ebcb 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -408,12 +408,20 @@ static char print_alua_state(unsigned char state) static int alua_check_sense(struct scsi_device *sdev, struct scsi_sense_hdr *sense_hdr) { + struct alua_dh_data *h = sdev->handler_data; + struct alua_port_group *pg; + switch (sense_hdr->sense_key) { case NOT_READY: if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0a) { /* * LUN Not Accessible - ALUA state transition */ + rcu_read_lock(); + pg = rcu_dereference(h->pg); + if (pg) + pg->state = SCSI_ACCESS_STATE_TRANSITIONING; + rcu_read_unlock(); alua_check(sdev, false); return NEEDS_RETRY; } -- cgit v1.2.3 From 0d88232010d5f40a8a31ff7b454e3f2594fd047f Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 30 Sep 2020 10:02:56 +0200 Subject: scsi: core: Return BLK_STS_AGAIN for ALUA transitioning Whenever we encounter a sense code of ALUA transitioning in scsi_io_completion() it means that the SCSI midlayer ran out of retries trying to wait for ALUA transitioning. In these cases we should be passing up the error, but signalling that the I/O might be retried, preferably on another path. So return BLK_STS_AGAIN in these cases. [mkp: typo + fallthrough] Link: https://lore.kernel.org/r/20200930080256.90964-5-hare@suse.de Reviewed-by: Ewan D. Milne Signed-off-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 7691196f288c..855e48c7514f 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -766,6 +766,9 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result) case 0x24: /* depopulation in progress */ action = ACTION_DELAYED_RETRY; break; + case 0x0a: /* ALUA state transition */ + blk_stat = BLK_STS_AGAIN; + fallthrough; default: action = ACTION_FAIL; break; -- cgit v1.2.3 From a004147a33199c660bbb203f11a82703459bf9f9 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Thu, 29 Oct 2020 19:57:45 +0800 Subject: scsi: ufs-mediatek: Assign arguments with correct type In ufs_mtk_unipro_set_lpm(), use specific unsigned values as the argument to invoke ufshcd_dme_set(). At the same time, change the name of ufs_mtk_unipro_set_pm() to ufs_mtk_unipro_set_lpm() to align the naming convention in MediaTek UFS driver. Link: https://lore.kernel.org/r/20201029115750.24391-2-stanley.chu@mediatek.com Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 914a827a93ee..5924ca04c201 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -639,14 +639,14 @@ static int ufs_mtk_pwr_change_notify(struct ufs_hba *hba, return ret; } -static int ufs_mtk_unipro_set_pm(struct ufs_hba *hba, bool lpm) +static int ufs_mtk_unipro_set_lpm(struct ufs_hba *hba, bool lpm) { int ret; struct ufs_mtk_host *host = ufshcd_get_variant(hba); ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(VS_UNIPROPOWERDOWNCONTROL, 0), - lpm); + lpm ? 1 : 0); if (!ret || !lpm) { /* * Forcibly set as non-LPM mode if UIC commands is failed @@ -664,7 +664,7 @@ static int ufs_mtk_pre_link(struct ufs_hba *hba) int ret; u32 tmp; - ret = ufs_mtk_unipro_set_pm(hba, false); + ret = ufs_mtk_unipro_set_lpm(hba, false); if (ret) return ret; @@ -776,7 +776,7 @@ static int ufs_mtk_link_set_hpm(struct ufs_hba *hba) if (err) return err; - err = ufs_mtk_unipro_set_pm(hba, false); + err = ufs_mtk_unipro_set_lpm(hba, false); if (err) return err; @@ -797,10 +797,10 @@ static int ufs_mtk_link_set_lpm(struct ufs_hba *hba) { int err; - err = ufs_mtk_unipro_set_pm(hba, true); + err = ufs_mtk_unipro_set_lpm(hba, true); if (err) { /* Resume UniPro state for following error recovery */ - ufs_mtk_unipro_set_pm(hba, false); + ufs_mtk_unipro_set_lpm(hba, false); return err; } -- cgit v1.2.3 From cf137b3ea49a04e0c843b12674afa4b1d23e827f Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Thu, 29 Oct 2020 19:57:46 +0800 Subject: scsi: ufs-mediatek: Support VA09 regulator operations Some MediaTek UFS platforms need to control VA09 power specifically. Provide such control according to the device tree binding. Link: https://lore.kernel.org/r/20201029115750.24391-3-stanley.chu@mediatek.com Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek.c | 137 ++++++++++++++++++++++++++++++---------- drivers/scsi/ufs/ufs-mediatek.h | 3 + 2 files changed, 108 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 5924ca04c201..0915389f3df8 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -28,6 +28,9 @@ arm_smccc_smc(MTK_SIP_UFS_CONTROL, \ cmd, val, 0, 0, 0, 0, 0, &(res)) +#define ufs_mtk_va09_pwr_ctrl(res, on) \ + ufs_mtk_smc(UFS_MTK_SIP_VA09_PWR_CTRL, on, res) + #define ufs_mtk_crypto_ctrl(res, enable) \ ufs_mtk_smc(UFS_MTK_SIP_CRYPTO_CTRL, enable, res) @@ -45,6 +48,10 @@ static struct ufs_dev_fix ufs_mtk_dev_fixups[] = { END_FIX }; +static const struct ufs_mtk_host_cfg ufs_mtk_mt8183_cfg = { + .caps = UFS_MTK_CAP_VA09_PWR_CTRL, +}; + static const struct ufs_mtk_host_cfg ufs_mtk_mt8192_cfg = { .caps = UFS_MTK_CAP_BOOST_CRYPT_ENGINE, }; @@ -52,6 +59,7 @@ static const struct ufs_mtk_host_cfg ufs_mtk_mt8192_cfg = { static const struct of_device_id ufs_mtk_of_match[] = { { .compatible = "mediatek,mt8183-ufshci", + .data = &ufs_mtk_mt8183_cfg }, { .compatible = "mediatek,mt8192-ufshci", @@ -67,6 +75,13 @@ static bool ufs_mtk_is_boost_crypt_enabled(struct ufs_hba *hba) return (host->caps & UFS_MTK_CAP_BOOST_CRYPT_ENGINE); } +static bool ufs_mtk_is_va09_supported(struct ufs_hba *hba) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + + return (host->caps & UFS_MTK_CAP_VA09_PWR_CTRL); +} + static void ufs_mtk_cfg_unipro_cg(struct ufs_hba *hba, bool enable) { u32 tmp; @@ -300,21 +315,46 @@ static int ufs_mtk_wait_link_state(struct ufs_hba *hba, u32 state, return -ETIMEDOUT; } -static void ufs_mtk_mphy_power_on(struct ufs_hba *hba, bool on) +static int ufs_mtk_mphy_power_on(struct ufs_hba *hba, bool on) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); struct phy *mphy = host->mphy; + struct arm_smccc_res res; + int ret = 0; - if (!mphy) - return; + if (!mphy || !(on ^ host->mphy_powered_on)) + return 0; - if (on && !host->mphy_powered_on) + if (on) { + if (host->reg_va09) { + ret = regulator_enable(host->reg_va09); + if (ret < 0) + goto out; + /* wait 200 us to stablize VA09 */ + usleep_range(200, 210); + ufs_mtk_va09_pwr_ctrl(res, 1); + } phy_power_on(mphy); - else if (!on && host->mphy_powered_on) + } else { phy_power_off(mphy); - else - return; - host->mphy_powered_on = on; + if (host->reg_va09) { + ufs_mtk_va09_pwr_ctrl(res, 0); + ret = regulator_disable(host->reg_va09); + if (ret < 0) + goto out; + } + } +out: + if (ret) { + dev_info(hba->dev, + "failed to %s va09: %d\n", + on ? "enable" : "disable", + ret); + } else { + host->mphy_powered_on = on; + } + + return ret; } static int ufs_mtk_get_host_clk(struct device *dev, const char *name, @@ -402,7 +442,7 @@ static int ufs_mtk_init_host_clk(struct ufs_hba *hba, const char *name, return ret; } -static void ufs_mtk_init_host_caps(struct ufs_hba *hba) +static void ufs_mtk_init_boost_crypt(struct ufs_hba *hba) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); struct ufs_mtk_crypt_cfg *cfg; @@ -410,11 +450,6 @@ static void ufs_mtk_init_host_caps(struct ufs_hba *hba) struct regulator *reg; u32 volt; - host->caps = host->cfg->caps; - - if (!ufs_mtk_is_boost_crypt_enabled(hba)) - return; - host->crypt = devm_kzalloc(dev, sizeof(*(host->crypt)), GFP_KERNEL); if (!host->crypt) @@ -448,13 +483,38 @@ static void ufs_mtk_init_host_caps(struct ufs_hba *hba) cfg->reg_vcore = reg; cfg->vcore_volt = volt; - dev_info(dev, "caps: boost-crypt"); return; disable_caps: host->caps &= ~UFS_MTK_CAP_BOOST_CRYPT_ENGINE; } +static void ufs_mtk_init_va09_pwr_ctrl(struct ufs_hba *hba) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + + host->reg_va09 = regulator_get(hba->dev, "va09"); + if (!host->reg_va09) { + dev_info(hba->dev, "failed to get va09"); + host->caps &= ~UFS_MTK_CAP_VA09_PWR_CTRL; + } +} + +static void ufs_mtk_init_host_caps(struct ufs_hba *hba) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + + host->caps = host->cfg->caps; + + if (ufs_mtk_is_boost_crypt_enabled(hba)) + ufs_mtk_init_boost_crypt(hba); + + if (ufs_mtk_is_va09_supported(hba)) + ufs_mtk_init_va09_pwr_ctrl(hba); + + dev_info(hba->dev, "caps: 0x%x", host->caps); +} + /** * ufs_mtk_setup_clocks - enables/disable clocks * @hba: host controller instance @@ -467,8 +527,8 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, enum ufs_notify_change_status status) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); - int ret = 0; bool clk_pwr_off = false; + int ret = 0; /* * In case ufs_mtk_init() is not yet done, simply ignore. @@ -499,10 +559,10 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, if (clk_pwr_off) { ufs_mtk_boost_crypt(hba, on); ufs_mtk_setup_ref_clk(hba, on); - ufs_mtk_mphy_power_on(hba, on); + phy_power_off(host->mphy); } } else if (on && status == POST_CHANGE) { - ufs_mtk_mphy_power_on(hba, on); + phy_power_on(host->mphy); ufs_mtk_setup_ref_clk(hba, on); ufs_mtk_boost_crypt(hba, on); } @@ -575,6 +635,7 @@ static int ufs_mtk_init(struct ufs_hba *hba) * * Enable phy clocks specifically here. */ + ufs_mtk_mphy_power_on(hba, true); ufs_mtk_setup_clocks(hba, true, POST_CHANGE); goto out; @@ -826,40 +887,52 @@ static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) if (ufshcd_is_link_hibern8(hba)) { err = ufs_mtk_link_set_lpm(hba); - if (err) { - /* - * Set link as off state enforcedly to trigger - * ufshcd_host_reset_and_restore() in ufshcd_suspend() - * for completed host reset. - */ - ufshcd_set_link_off(hba); - return -EAGAIN; - } + if (err) + goto fail; + } + + if (!ufshcd_is_link_active(hba)) { /* * Make sure no error will be returned to prevent * ufshcd_suspend() re-enabling regulators while vreg is still * in low-power mode. */ ufs_mtk_vreg_set_lpm(hba, true); + err = ufs_mtk_mphy_power_on(hba, false); + if (err) + goto fail; } return 0; +fail: + /* + * Set link as off state enforcedly to trigger + * ufshcd_host_reset_and_restore() in ufshcd_suspend() + * for completed host reset. + */ + ufshcd_set_link_off(hba); + return -EAGAIN; } static int ufs_mtk_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) { int err; + err = ufs_mtk_mphy_power_on(hba, true); + if (err) + goto fail; + + ufs_mtk_vreg_set_lpm(hba, false); + if (ufshcd_is_link_hibern8(hba)) { - ufs_mtk_vreg_set_lpm(hba, false); err = ufs_mtk_link_set_hpm(hba); - if (err) { - err = ufshcd_link_recovery(hba); - return err; - } + if (err) + goto fail; } return 0; +fail: + return ufshcd_link_recovery(hba); } static void ufs_mtk_dbg_register_dump(struct ufs_hba *hba) diff --git a/drivers/scsi/ufs/ufs-mediatek.h b/drivers/scsi/ufs/ufs-mediatek.h index 2b6a1312c9bc..f668241d37f8 100644 --- a/drivers/scsi/ufs/ufs-mediatek.h +++ b/drivers/scsi/ufs/ufs-mediatek.h @@ -69,6 +69,7 @@ enum { * SiP commands */ #define MTK_SIP_UFS_CONTROL MTK_SIP_SMC_CMD(0x276) +#define UFS_MTK_SIP_VA09_PWR_CTRL BIT(0) #define UFS_MTK_SIP_DEVICE_RESET BIT(1) #define UFS_MTK_SIP_CRYPTO_CTRL BIT(2) #define UFS_MTK_SIP_REF_CLK_NOTIFICATION BIT(3) @@ -94,6 +95,7 @@ enum { */ enum ufs_mtk_host_caps { UFS_MTK_CAP_BOOST_CRYPT_ENGINE = 1 << 0, + UFS_MTK_CAP_VA09_PWR_CTRL = 1 << 1, }; struct ufs_mtk_crypt_cfg { @@ -113,6 +115,7 @@ struct ufs_mtk_host { struct phy *mphy; struct ufs_mtk_host_cfg *cfg; struct ufs_mtk_crypt_cfg *crypt; + struct regulator *reg_va09; enum ufs_mtk_host_caps caps; struct reset_control *hci_reset; struct reset_control *unipro_reset; -- cgit v1.2.3 From ac8c2459091cd0e2bf226278d7b332e81c4c855a Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Thu, 29 Oct 2020 19:57:47 +0800 Subject: scsi: ufs-mediatek: Decouple features from platform bindings UFS proprietary features (including features introduced later) in MediaTek UFS platforms have complicated combinations among different platforms. To ease code readability and maintenance, decouple all proprietary features from platform bindings. Each feature would be enabled only if specific property string is defined in device tree node. Link: https://lore.kernel.org/r/20201029115750.24391-4-stanley.chu@mediatek.com Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek.c | 49 +++++++++++++---------------------------- drivers/scsi/ufs/ufs-mediatek.h | 11 +++------ 2 files changed, 18 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 0915389f3df8..bff613f1d126 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -48,23 +48,8 @@ static struct ufs_dev_fix ufs_mtk_dev_fixups[] = { END_FIX }; -static const struct ufs_mtk_host_cfg ufs_mtk_mt8183_cfg = { - .caps = UFS_MTK_CAP_VA09_PWR_CTRL, -}; - -static const struct ufs_mtk_host_cfg ufs_mtk_mt8192_cfg = { - .caps = UFS_MTK_CAP_BOOST_CRYPT_ENGINE, -}; - static const struct of_device_id ufs_mtk_of_match[] = { - { - .compatible = "mediatek,mt8183-ufshci", - .data = &ufs_mtk_mt8183_cfg - }, - { - .compatible = "mediatek,mt8192-ufshci", - .data = &ufs_mtk_mt8192_cfg - }, + { .compatible = "mediatek,mt8183-ufshci" }, {}, }; @@ -72,14 +57,14 @@ static bool ufs_mtk_is_boost_crypt_enabled(struct ufs_hba *hba) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); - return (host->caps & UFS_MTK_CAP_BOOST_CRYPT_ENGINE); + return !!(host->caps & UFS_MTK_CAP_BOOST_CRYPT_ENGINE); } static bool ufs_mtk_is_va09_supported(struct ufs_hba *hba) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); - return (host->caps & UFS_MTK_CAP_VA09_PWR_CTRL); + return !!(host->caps & UFS_MTK_CAP_VA09_PWR_CTRL); } static void ufs_mtk_cfg_unipro_cg(struct ufs_hba *hba, bool enable) @@ -326,7 +311,7 @@ static int ufs_mtk_mphy_power_on(struct ufs_hba *hba, bool on) return 0; if (on) { - if (host->reg_va09) { + if (ufs_mtk_is_va09_supported(hba)) { ret = regulator_enable(host->reg_va09); if (ret < 0) goto out; @@ -337,7 +322,7 @@ static int ufs_mtk_mphy_power_on(struct ufs_hba *hba, bool on) phy_power_on(mphy); } else { phy_power_off(mphy); - if (host->reg_va09) { + if (ufs_mtk_is_va09_supported(hba)) { ufs_mtk_va09_pwr_ctrl(res, 0); ret = regulator_disable(host->reg_va09); if (ret < 0) @@ -483,10 +468,10 @@ static void ufs_mtk_init_boost_crypt(struct ufs_hba *hba) cfg->reg_vcore = reg; cfg->vcore_volt = volt; - return; + host->caps |= UFS_MTK_CAP_BOOST_CRYPT_ENGINE; disable_caps: - host->caps &= ~UFS_MTK_CAP_BOOST_CRYPT_ENGINE; + return; } static void ufs_mtk_init_va09_pwr_ctrl(struct ufs_hba *hba) @@ -494,22 +479,21 @@ static void ufs_mtk_init_va09_pwr_ctrl(struct ufs_hba *hba) struct ufs_mtk_host *host = ufshcd_get_variant(hba); host->reg_va09 = regulator_get(hba->dev, "va09"); - if (!host->reg_va09) { + if (!host->reg_va09) dev_info(hba->dev, "failed to get va09"); - host->caps &= ~UFS_MTK_CAP_VA09_PWR_CTRL; - } + else + host->caps |= UFS_MTK_CAP_VA09_PWR_CTRL; } static void ufs_mtk_init_host_caps(struct ufs_hba *hba) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); + struct device_node *np = hba->dev->of_node; - host->caps = host->cfg->caps; - - if (ufs_mtk_is_boost_crypt_enabled(hba)) + if (of_property_read_bool(np, "mediatek,ufs-boost-crypt")) ufs_mtk_init_boost_crypt(hba); - if (ufs_mtk_is_va09_supported(hba)) + if (of_property_read_bool(np, "mediatek,ufs-support-va09")) ufs_mtk_init_va09_pwr_ctrl(hba); dev_info(hba->dev, "caps: 0x%x", host->caps); @@ -597,17 +581,14 @@ static int ufs_mtk_init(struct ufs_hba *hba) host->hba = hba; ufshcd_set_variant(hba, host); - /* Get host capability and platform data */ id = of_match_device(ufs_mtk_of_match, dev); if (!id) { err = -EINVAL; goto out; } - if (id->data) { - host->cfg = (struct ufs_mtk_host_cfg *)id->data; - ufs_mtk_init_host_caps(hba); - } + /* Initialize host capability */ + ufs_mtk_init_host_caps(hba); err = ufs_mtk_bind_mphy(hba); if (err) diff --git a/drivers/scsi/ufs/ufs-mediatek.h b/drivers/scsi/ufs/ufs-mediatek.h index f668241d37f8..0e76429f69d6 100644 --- a/drivers/scsi/ufs/ufs-mediatek.h +++ b/drivers/scsi/ufs/ufs-mediatek.h @@ -106,20 +106,15 @@ struct ufs_mtk_crypt_cfg { int vcore_volt; }; -struct ufs_mtk_host_cfg { - enum ufs_mtk_host_caps caps; -}; - struct ufs_mtk_host { - struct ufs_hba *hba; struct phy *mphy; - struct ufs_mtk_host_cfg *cfg; - struct ufs_mtk_crypt_cfg *crypt; struct regulator *reg_va09; - enum ufs_mtk_host_caps caps; struct reset_control *hci_reset; struct reset_control *unipro_reset; struct reset_control *crypto_reset; + struct ufs_hba *hba; + struct ufs_mtk_crypt_cfg *crypt; + enum ufs_mtk_host_caps caps; bool mphy_powered_on; bool unipro_lpm; bool ref_clk_enabled; -- cgit v1.2.3 From bf8fab86ab791cd24572eaf05f23af9b99dad43c Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Thu, 29 Oct 2020 19:57:48 +0800 Subject: scsi: ufs-mediatek: Support option to disable auto-hibern8 Support an option to allow users to disable auto-hibern8 feature. Instead, enable hibern8-during-clk-gating feature to keep similar power consumption. Link: https://lore.kernel.org/r/20201029115750.24391-5-stanley.chu@mediatek.com Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek.c | 18 ++++++++++++++++++ drivers/scsi/ufs/ufs-mediatek.h | 1 + 2 files changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index bff613f1d126..478774801196 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -158,6 +158,7 @@ static int ufs_mtk_hce_enable_notify(struct ufs_hba *hba, enum ufs_notify_change_status status) { struct ufs_mtk_host *host = ufshcd_get_variant(hba); + unsigned long flags; if (status == PRE_CHANGE) { if (host->unipro_lpm) { @@ -169,6 +170,17 @@ static int ufs_mtk_hce_enable_notify(struct ufs_hba *hba, if (hba->caps & UFSHCD_CAP_CRYPTO) ufs_mtk_crypto_enable(hba); + + if (host->caps & UFS_MTK_CAP_DISABLE_AH8) { + spin_lock_irqsave(hba->host->host_lock, flags); + ufshcd_writel(hba, 0, + REG_AUTO_HIBERNATE_IDLE_TIMER); + spin_unlock_irqrestore(hba->host->host_lock, + flags); + + hba->capabilities &= ~MASK_AUTO_HIBERN8_SUPPORT; + hba->ahit = 0; + } } return 0; @@ -496,6 +508,9 @@ static void ufs_mtk_init_host_caps(struct ufs_hba *hba) if (of_property_read_bool(np, "mediatek,ufs-support-va09")) ufs_mtk_init_va09_pwr_ctrl(hba); + if (of_property_read_bool(np, "mediatek,ufs-disable-ah8")) + host->caps |= UFS_MTK_CAP_DISABLE_AH8; + dev_info(hba->dev, "caps: 0x%x", host->caps); } @@ -609,6 +624,9 @@ static int ufs_mtk_init(struct ufs_hba *hba) hba->caps |= UFSHCD_CAP_WB_EN; hba->vps->wb_flush_threshold = UFS_WB_BUF_REMAIN_PERCENT(80); + if (host->caps & UFS_MTK_CAP_DISABLE_AH8) + hba->caps |= UFSHCD_CAP_HIBERN8_WITH_CLK_GATING; + /* * ufshcd_vops_init() is invoked after * ufshcd_setup_clock(true) in ufshcd_hba_init() thus diff --git a/drivers/scsi/ufs/ufs-mediatek.h b/drivers/scsi/ufs/ufs-mediatek.h index 0e76429f69d6..30f45dfce04c 100644 --- a/drivers/scsi/ufs/ufs-mediatek.h +++ b/drivers/scsi/ufs/ufs-mediatek.h @@ -96,6 +96,7 @@ enum { enum ufs_mtk_host_caps { UFS_MTK_CAP_BOOST_CRYPT_ENGINE = 1 << 0, UFS_MTK_CAP_VA09_PWR_CTRL = 1 << 1, + UFS_MTK_CAP_DISABLE_AH8 = 1 << 2, }; struct ufs_mtk_crypt_cfg { -- cgit v1.2.3 From 801909ac97530062c3de6bfdb1d7e08f3c7de8ce Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Thu, 29 Oct 2020 19:57:49 +0800 Subject: scsi: ufs: Add enums for UniPro version higher than 1.6 Some vendors need newer UniPro version to decide if some features can be enabled or not. Simply add missing enums for the latest UniPro versions. Link: https://lore.kernel.org/r/20201029115750.24391-6-stanley.chu@mediatek.com Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/unipro.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h index f6b52ce36de6..8e9e486a4f7b 100644 --- a/drivers/scsi/ufs/unipro.h +++ b/drivers/scsi/ufs/unipro.h @@ -237,8 +237,10 @@ enum ufs_unipro_ver { UFS_UNIPRO_VER_RESERVED = 0, UFS_UNIPRO_VER_1_40 = 1, /* UniPro version 1.40 */ UFS_UNIPRO_VER_1_41 = 2, /* UniPro version 1.41 */ - UFS_UNIPRO_VER_1_6 = 3, /* UniPro version 1.6 */ - UFS_UNIPRO_VER_MAX = 4, /* UniPro unsupported version */ + UFS_UNIPRO_VER_1_6 = 3, /* UniPro version 1.6 */ + UFS_UNIPRO_VER_1_61 = 4, /* UniPro version 1.61 */ + UFS_UNIPRO_VER_1_8 = 5, /* UniPro version 1.8 */ + UFS_UNIPRO_VER_MAX = 6, /* UniPro unsupported version */ /* UniPro version field mask in PA_LOCALVERINFO */ UFS_UNIPRO_VER_MASK = 0xF, }; -- cgit v1.2.3 From 638e6271cac2d6eba8d5d6cfd6a6ae77715a8cf6 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Thu, 29 Oct 2020 19:57:50 +0800 Subject: scsi: ufs-mediatek: Add HS-G4 support Provide HS-G4 support in MediaTek UFS platforms. To support HS-G4, introduce mechanism to get the MediaTek UFS controller version. With such information, driver can make right decision to apply different configurations in different controllers. Link: https://lore.kernel.org/r/20201029115750.24391-7-stanley.chu@mediatek.com Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek.c | 32 ++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufs-mediatek.h | 11 +++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 478774801196..7fed7630d36c 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -569,6 +569,24 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, return ret; } +static void ufs_mtk_get_controller_version(struct ufs_hba *hba) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + int ret, ver = 0; + + if (host->hw_ver.major) + return; + + /* Set default (minimum) version anyway */ + host->hw_ver.major = 2; + + ret = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_LOCALVERINFO), &ver); + if (!ret) { + if (ver >= UFS_UNIPRO_VER_1_8) + host->hw_ver.major = 3; + } +} + /** * ufs_mtk_init - find other essential mmio bases * @hba: host controller instance @@ -649,7 +667,9 @@ static int ufs_mtk_pre_pwr_change(struct ufs_hba *hba, struct ufs_pa_layer_attr *dev_max_params, struct ufs_pa_layer_attr *dev_req_params) { + struct ufs_mtk_host *host = ufshcd_get_variant(hba); struct ufs_dev_params host_cap; + u32 adapt_val; int ret; host_cap.tx_lanes = UFS_MTK_LIMIT_NUM_LANES_TX; @@ -674,6 +694,16 @@ static int ufs_mtk_pre_pwr_change(struct ufs_hba *hba, __func__); } + if (host->hw_ver.major >= 3) { + if (dev_req_params->gear_tx == UFS_HS_G4) + adapt_val = PA_INITIAL_ADAPT; + else + adapt_val = PA_NO_ADAPT; + ufshcd_dme_set(hba, + UIC_ARG_MIB(PA_TXHSADAPTTYPE), + adapt_val); + } + return ret; } @@ -724,6 +754,8 @@ static int ufs_mtk_pre_link(struct ufs_hba *hba) int ret; u32 tmp; + ufs_mtk_get_controller_version(hba); + ret = ufs_mtk_unipro_set_lpm(hba, false); if (ret) return ret; diff --git a/drivers/scsi/ufs/ufs-mediatek.h b/drivers/scsi/ufs/ufs-mediatek.h index 30f45dfce04c..ac37b11803fb 100644 --- a/drivers/scsi/ufs/ufs-mediatek.h +++ b/drivers/scsi/ufs/ufs-mediatek.h @@ -35,8 +35,8 @@ */ #define UFS_MTK_LIMIT_NUM_LANES_RX 2 #define UFS_MTK_LIMIT_NUM_LANES_TX 2 -#define UFS_MTK_LIMIT_HSGEAR_RX UFS_HS_G3 -#define UFS_MTK_LIMIT_HSGEAR_TX UFS_HS_G3 +#define UFS_MTK_LIMIT_HSGEAR_RX UFS_HS_G4 +#define UFS_MTK_LIMIT_HSGEAR_TX UFS_HS_G4 #define UFS_MTK_LIMIT_PWMGEAR_RX UFS_PWM_G4 #define UFS_MTK_LIMIT_PWMGEAR_TX UFS_PWM_G4 #define UFS_MTK_LIMIT_RX_PWR_PWM SLOW_MODE @@ -107,6 +107,12 @@ struct ufs_mtk_crypt_cfg { int vcore_volt; }; +struct ufs_mtk_hw_ver { + u8 step; + u8 minor; + u8 major; +}; + struct ufs_mtk_host { struct phy *mphy; struct regulator *reg_va09; @@ -115,6 +121,7 @@ struct ufs_mtk_host { struct reset_control *crypto_reset; struct ufs_hba *hba; struct ufs_mtk_crypt_cfg *crypt; + struct ufs_mtk_hw_ver hw_ver; enum ufs_mtk_host_caps caps; bool mphy_powered_on; bool unipro_lpm; -- cgit v1.2.3 From 44ff81f2995794982daf7b89a923c6335d57c469 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Sat, 7 Nov 2020 15:34:19 +0530 Subject: scsi: isci: Don't use PCI helper functions PCI helper functions such as pci_enable/disable_device(), pci_save/restore_state(), pci_set_power_state(), etc. were used by the legacy framework to perform standard operations related to PCI PM. This driver is using the generic framework and thus calls for those functions should be dropped as those tasks are now performed by the PCI core. Link: https://lore.kernel.org/r/20201107100420.149521-1-vaibhavgupta40@gmail.com Acked-by: Artur Paszkiewicz Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/isci/init.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 93bc9019667f..c452849e7bb4 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -715,10 +715,6 @@ static int isci_suspend(struct device *dev) isci_host_deinit(ihost); } - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - return 0; } @@ -726,19 +722,7 @@ static int isci_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct isci_host *ihost; - int rc, i; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - rc = pcim_enable_device(pdev); - if (rc) { - dev_err(&pdev->dev, - "enabling device failure after resume(%d)\n", rc); - return rc; - } - - pci_set_master(pdev); + int i; for_each_isci_host(i, ihost, pdev) { sas_prep_resume_ha(&ihost->sas_ha); -- cgit v1.2.3 From cb2b4e8f5ea69b6dc0a37ace8c6ffb1854c1f9e5 Mon Sep 17 00:00:00 2001 From: Kaixu Xia Date: Sun, 8 Nov 2020 00:52:00 +0800 Subject: scsi: bnx2fc: Fix comparison to bool warning Fix the following coccicheck warning: ./drivers/scsi/bnx2fc/bnx2fc_fcoe.c:2089:5-23: WARNING: Comparison to bool ./drivers/scsi/bnx2fc/bnx2fc_fcoe.c:2187:5-23: WARNING: Comparison to bool Link: https://lore.kernel.org/r/1604767920-8361-1-git-send-email-kaixuxia@tencent.com Reported-by: Tosk Robot Acked-by: Saurav Kashyap Signed-off-by: Kaixu Xia Signed-off-by: Martin K. Petersen --- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index a436adb6092d..52bd0db643b0 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -2086,7 +2086,7 @@ static int __bnx2fc_disable(struct fcoe_ctlr *ctlr) { struct bnx2fc_interface *interface = fcoe_ctlr_priv(ctlr); - if (interface->enabled == true) { + if (interface->enabled) { if (!ctlr->lp) { pr_err(PFX "__bnx2fc_disable: lport not found\n"); return -ENODEV; @@ -2184,7 +2184,7 @@ static int __bnx2fc_enable(struct fcoe_ctlr *ctlr) struct cnic_fc_npiv_tbl *npiv_tbl; struct fc_lport *lport; - if (interface->enabled == false) { + if (!interface->enabled) { if (!ctlr->lp) { pr_err(PFX "__bnx2fc_enable: lport not found\n"); return -ENODEV; -- cgit v1.2.3 From 2e4209b3806cda9b89c30fd5e7bfecb7044ec78b Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 29 Oct 2020 18:08:45 +0100 Subject: scsi: core: Fix VPD LUN ID designator priorities The current implementation of scsi_vpd_lun_id() uses the designator length as an implicit measure of priority. This works most of the time, but not always. For example, some Hitachi storage arrays return this in VPD 0x83: VPD INQUIRY: Device Identification page Designation descriptor number 1, descriptor length: 24 designator_type: T10 vendor identification, code_set: ASCII associated with the Addressed logical unit vendor id: HITACHI vendor specific: 5030C3502025 Designation descriptor number 2, descriptor length: 6 designator_type: vendor specific [0x0], code_set: Binary associated with the Target port vendor specific: 08 03 Designation descriptor number 3, descriptor length: 20 designator_type: NAA, code_set: Binary associated with the Addressed logical unit NAA 6, IEEE Company_id: 0x60e8 Vendor Specific Identifier: 0x7c35000 Vendor Specific Identifier Extension: 0x30c35000002025 [0x60060e8007c350000030c35000002025] The current code would use the first descriptor because it's longer than the NAA descriptor. But this is wrong, the kernel is supposed to prefer NAA descriptors over T10 vendor ID. Designator length should only be used to compare designators of the same type. This patch addresses the issue by separating designator priority and length. Link: https://lore.kernel.org/r/20201029170846.14786-1-mwilck@suse.com Fixes: 9983bed3907c ("scsi: Add scsi_vpd_lun_id()") Reviewed-by: Hannes Reinecke Signed-off-by: Martin Wilck Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 126 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 86 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 855e48c7514f..5f963df0906a 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -2957,6 +2957,78 @@ void sdev_enable_disk_events(struct scsi_device *sdev) } EXPORT_SYMBOL(sdev_enable_disk_events); +static unsigned char designator_prio(const unsigned char *d) +{ + if (d[1] & 0x30) + /* not associated with LUN */ + return 0; + + if (d[3] == 0) + /* invalid length */ + return 0; + + /* + * Order of preference for lun descriptor: + * - SCSI name string + * - NAA IEEE Registered Extended + * - EUI-64 based 16-byte + * - EUI-64 based 12-byte + * - NAA IEEE Registered + * - NAA IEEE Extended + * - EUI-64 based 8-byte + * - SCSI name string (truncated) + * - T10 Vendor ID + * as longer descriptors reduce the likelyhood + * of identification clashes. + */ + + switch (d[1] & 0xf) { + case 8: + /* SCSI name string, variable-length UTF-8 */ + return 9; + case 3: + switch (d[4] >> 4) { + case 6: + /* NAA registered extended */ + return 8; + case 5: + /* NAA registered */ + return 5; + case 4: + /* NAA extended */ + return 4; + case 3: + /* NAA locally assigned */ + return 1; + default: + break; + } + break; + case 2: + switch (d[3]) { + case 16: + /* EUI64-based, 16 byte */ + return 7; + case 12: + /* EUI64-based, 12 byte */ + return 6; + case 8: + /* EUI64-based, 8 byte */ + return 3; + default: + break; + } + break; + case 1: + /* T10 vendor ID */ + return 1; + default: + break; + } + + return 0; +} + /** * scsi_vpd_lun_id - return a unique device identification * @sdev: SCSI device @@ -2973,7 +3045,7 @@ EXPORT_SYMBOL(sdev_enable_disk_events); */ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) { - u8 cur_id_type = 0xff; + u8 cur_id_prio = 0; u8 cur_id_size = 0; const unsigned char *d, *cur_id_str; const struct scsi_vpd *vpd_pg83; @@ -2986,20 +3058,6 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) return -ENXIO; } - /* - * Look for the correct descriptor. - * Order of preference for lun descriptor: - * - SCSI name string - * - NAA IEEE Registered Extended - * - EUI-64 based 16-byte - * - EUI-64 based 12-byte - * - NAA IEEE Registered - * - NAA IEEE Extended - * - T10 Vendor ID - * as longer descriptors reduce the likelyhood - * of identification clashes. - */ - /* The id string must be at least 20 bytes + terminating NULL byte */ if (id_len < 21) { rcu_read_unlock(); @@ -3009,8 +3067,9 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) memset(id, 0, id_len); d = vpd_pg83->data + 4; while (d < vpd_pg83->data + vpd_pg83->len) { - /* Skip designators not referring to the LUN */ - if ((d[1] & 0x30) != 0x00) + u8 prio = designator_prio(d); + + if (prio == 0 || cur_id_prio > prio) goto next_desig; switch (d[1] & 0xf) { @@ -3018,28 +3077,19 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) /* T10 Vendor ID */ if (cur_id_size > d[3]) break; - /* Prefer anything */ - if (cur_id_type > 0x01 && cur_id_type != 0xff) - break; + cur_id_prio = prio; cur_id_size = d[3]; if (cur_id_size + 4 > id_len) cur_id_size = id_len - 4; cur_id_str = d + 4; - cur_id_type = d[1] & 0xf; id_size = snprintf(id, id_len, "t10.%*pE", cur_id_size, cur_id_str); break; case 0x2: /* EUI-64 */ - if (cur_id_size > d[3]) - break; - /* Prefer NAA IEEE Registered Extended */ - if (cur_id_type == 0x3 && - cur_id_size == d[3]) - break; + cur_id_prio = prio; cur_id_size = d[3]; cur_id_str = d + 4; - cur_id_type = d[1] & 0xf; switch (cur_id_size) { case 8: id_size = snprintf(id, id_len, @@ -3057,17 +3107,14 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) cur_id_str); break; default: - cur_id_size = 0; break; } break; case 0x3: /* NAA */ - if (cur_id_size > d[3]) - break; + cur_id_prio = prio; cur_id_size = d[3]; cur_id_str = d + 4; - cur_id_type = d[1] & 0xf; switch (cur_id_size) { case 8: id_size = snprintf(id, id_len, @@ -3080,26 +3127,25 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) cur_id_str); break; default: - cur_id_size = 0; break; } break; case 0x8: /* SCSI name string */ - if (cur_id_size + 4 > d[3]) + if (cur_id_size > d[3]) break; /* Prefer others for truncated descriptor */ - if (cur_id_size && d[3] > id_len) - break; + if (d[3] > id_len) { + prio = 2; + if (cur_id_prio > prio) + break; + } + cur_id_prio = prio; cur_id_size = id_size = d[3]; cur_id_str = d + 4; - cur_id_type = d[1] & 0xf; if (cur_id_size >= id_len) cur_id_size = id_len - 1; memcpy(id, cur_id_str, cur_id_size); - /* Decrease priority for truncated descriptor */ - if (cur_id_size != id_size) - cur_id_size = 6; break; default: break; -- cgit v1.2.3 From 16d6317ea438b10c5747f5d4a972ea0e68d1a6ae Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 29 Oct 2020 18:08:46 +0100 Subject: scsi: core: Replace while-loop by for-loop in scsi_vpd_lun_id() This makes the code slightly more readable. Link: https://lore.kernel.org/r/20201029170846.14786-2-mwilck@suse.com Reviewed-by: Hannes Reinecke Signed-off-by: Martin Wilck Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 5f963df0906a..b7ac14571415 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -3065,12 +3065,13 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) } memset(id, 0, id_len); - d = vpd_pg83->data + 4; - while (d < vpd_pg83->data + vpd_pg83->len) { + for (d = vpd_pg83->data + 4; + d < vpd_pg83->data + vpd_pg83->len; + d += d[3] + 4) { u8 prio = designator_prio(d); if (prio == 0 || cur_id_prio > prio) - goto next_desig; + continue; switch (d[1] & 0xf) { case 0x1: @@ -3150,8 +3151,6 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) default: break; } -next_desig: - d += d[3] + 4; } rcu_read_unlock(); -- cgit v1.2.3 From 883928201b00928df0b2000be37ee7a8e975be26 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Sat, 7 Nov 2020 00:11:32 -0800 Subject: scsi: core: Fix -Wformat for scsi_host Clang is more aggressive about -Wformat warnings when the format flag specifies a type smaller than the parameter. Turns out, struct Scsi_Host's member can_queue is actually an int. Fixes: [-Wformat] shost_rd_attr(can_queue, "%hd\n"); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %d Link: https://github.com/ClangBuiltLinux/linux/issues/378 Link: https://lore.kernel.org/r/20201107081132.2629071-1-ndesaulniers@google.com Reviewed-by: Nathan Chancellor Signed-off-by: Nick Desaulniers Signed-off-by: Martin K. Petersen warning: format specifies type 'short' but the argument has type 'int' --- drivers/scsi/scsi_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index d6e344fa33ad..b6378c8ca783 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -370,7 +370,7 @@ static DEVICE_ATTR(eh_deadline, S_IRUGO | S_IWUSR, show_shost_eh_deadline, store shost_rd_attr(unique_id, "%u\n"); shost_rd_attr(cmd_per_lun, "%hd\n"); -shost_rd_attr(can_queue, "%hd\n"); +shost_rd_attr(can_queue, "%d\n"); shost_rd_attr(sg_tablesize, "%hu\n"); shost_rd_attr(sg_prot_tablesize, "%hu\n"); shost_rd_attr(unchecked_isa_dma, "%d\n"); -- cgit v1.2.3 From a364a3ea32da6de55a9a7c75db311bd908fcfbb4 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Mon, 16 Nov 2020 10:41:19 +0000 Subject: scsi: pm8001: Remove unused variable 'value' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hasn't been used since 2009. Fixes the following W=1 kernel build warning(s): drivers/scsi/pm8001/pm8001_hwi.c: In function ‘mpi_set_phys_g3_with_ssc’: drivers/scsi/pm8001/pm8001_hwi.c:415:6: warning: variable ‘value’ set but not used [-Wunused-but-set-variable] Link: https://lore.kernel.org/r/20201116104119.816527-1-lee.jones@linaro.org Cc: Jack Wang Acked-by: Jack Wang Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_hwi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 2054c2b03d92..0a1e09b1cd58 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -416,7 +416,7 @@ int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue) static void mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit) { - u32 value, offset, i; + u32 offset, i; unsigned long flags; #define SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR 0x00030000 @@ -467,7 +467,7 @@ static void mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, so that the written value will be 0x8090c016. This will ensure only down-spreading SSC is enabled on the SPC. *************************************************************/ - value = pm8001_cr32(pm8001_ha, 2, 0xd8); + pm8001_cr32(pm8001_ha, 2, 0xd8); pm8001_cw32(pm8001_ha, 2, 0xd8, 0x8000C016); /*set the shifted destination address to 0x0 to avoid error operation */ -- cgit v1.2.3 From 1bdf6e9343877030640336d93da08321719bca43 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 11 Nov 2020 14:24:39 -0600 Subject: scsi: smartpqi: Correct driver removal with HBA disks Correct rmmod hangs when using HBA disks with write cache enabled. Do not set controller flag "in_shutdown" during rmmod. SCSI SYNCHRONIZE CACHE(10) and SCSI SYNCHRONIZE CACHE(16) requests were blocked with SCSI_MLQUEUE_HOST_BUSY. Link: https://lore.kernel.org/r/160512627928.2359.10698615071827614781.stgit@brunhilda Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi_init.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 9d0229656681..531f10853f03 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -345,10 +345,9 @@ static inline void pqi_device_remove_start(struct pqi_scsi_dev *device) device->in_remove = true; } -static inline bool pqi_device_in_remove(struct pqi_ctrl_info *ctrl_info, - struct pqi_scsi_dev *device) +static inline bool pqi_device_in_remove(struct pqi_scsi_dev *device) { - return device->in_remove && !ctrl_info->in_shutdown; + return device->in_remove; } static inline void pqi_ctrl_shutdown_start(struct pqi_ctrl_info *ctrl_info) @@ -5347,8 +5346,7 @@ static int pqi_scsi_queue_command(struct Scsi_Host *shost, atomic_inc(&device->scsi_cmds_outstanding); - if (pqi_ctrl_offline(ctrl_info) || pqi_device_in_remove(ctrl_info, - device)) { + if (pqi_ctrl_offline(ctrl_info) || pqi_device_in_remove(device)) { set_host_byte(scmd, DID_NO_CONNECT); pqi_scsi_done(scmd); return 0; @@ -8031,8 +8029,6 @@ static void pqi_pci_remove(struct pci_dev *pci_dev) if (!ctrl_info) return; - ctrl_info->in_shutdown = true; - pqi_remove_ctrl(ctrl_info); } -- cgit v1.2.3 From 408bdd7e5845d8f3e0dac0dcc18f358835175801 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 11 Nov 2020 14:24:45 -0600 Subject: scsi: smartpqi: Correct pqi_sas_smp_handler busy condition Remove unbalanced call to pqi_ctrl_unbusy. Link: https://lore.kernel.org/r/160512628513.2359.17193493825283879603.stgit@brunhilda Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi_sas_transport.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/smartpqi/smartpqi_sas_transport.c b/drivers/scsi/smartpqi/smartpqi_sas_transport.c index 999870eb9ed8..c9b00b3368d7 100644 --- a/drivers/scsi/smartpqi/smartpqi_sas_transport.c +++ b/drivers/scsi/smartpqi/smartpqi_sas_transport.c @@ -549,7 +549,6 @@ void pqi_sas_smp_handler(struct bsg_job *job, struct Scsi_Host *shost, reslen = pqi_build_sas_smp_handler_reply(smp_buf, job, &error_info); out: bsg_job_done(job, rc, reslen); - pqi_ctrl_unbusy(ctrl_info); } struct sas_function_template pqi_sas_transport_functions = { .get_linkerrors = pqi_sas_get_linkerrors, -- cgit v1.2.3 From 5443bdc4cc777f3629f02e934fef418e9d921809 Mon Sep 17 00:00:00 2001 From: Don Brace Date: Wed, 11 Nov 2020 14:24:50 -0600 Subject: scsi: smartpqi: Update version to 1.2.16-012 Link: https://lore.kernel.org/r/160512629093.2359.13675060282143622110.stgit@brunhilda Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Gerry Morong Signed-off-by: Don Brace Signed-off-by: Martin K. Petersen --- drivers/scsi/smartpqi/smartpqi_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 531f10853f03..c53f456fbd09 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -33,11 +33,11 @@ #define BUILD_TIMESTAMP #endif -#define DRIVER_VERSION "1.2.16-010" +#define DRIVER_VERSION "1.2.16-012" #define DRIVER_MAJOR 1 #define DRIVER_MINOR 2 #define DRIVER_RELEASE 16 -#define DRIVER_REVISION 10 +#define DRIVER_REVISION 12 #define DRIVER_NAME "Microsemi PQI Driver (v" \ DRIVER_VERSION BUILD_TIMESTAMP ")" -- cgit v1.2.3 From 6081b12ceb7d6e58346ce359282cdc1ed8282b76 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Thu, 12 Nov 2020 13:45:37 +0800 Subject: scsi: ufs: Add retry flow for failed HBA enabling Once HBA enabling has failed, add retry mechanism and allow vendors to apply specific tweaks before the next retry. For example, vendors can do vendor-specific host reset flow in variant function "ufshcd_vops_hce_enable_notify()". Link: https://lore.kernel.org/r/20201112054537.22494-1-stanley.chu@mediatek.com Reviewed-by: Can Guo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 8001bbfec5c0..9186ee01379a 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -4328,8 +4328,10 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba) */ static int ufshcd_hba_execute_hce(struct ufs_hba *hba) { - int retry; + int retry_outer = 3; + int retry_inner; +start: if (!ufshcd_is_hba_active(hba)) /* change controller state to "reset state" */ ufshcd_hba_stop(hba); @@ -4355,13 +4357,17 @@ static int ufshcd_hba_execute_hce(struct ufs_hba *hba) ufshcd_delay_us(hba->vps->hba_enable_delay_us, 100); /* wait for the host controller to complete initialization */ - retry = 50; + retry_inner = 50; while (ufshcd_is_hba_active(hba)) { - if (retry) { - retry--; + if (retry_inner) { + retry_inner--; } else { dev_err(hba->dev, "Controller enable failed\n"); + if (retry_outer) { + retry_outer--; + goto start; + } return -EIO; } usleep_range(1000, 1100); -- cgit v1.2.3 From 1fc6591951308c9923311913811717d46400100d Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 12 Nov 2020 10:19:29 +0000 Subject: scsi: hpsa: Strip out a bunch of set but unused variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following W=1 kernel build warning(s): drivers/scsi/hpsa.c: In function ‘hpsa_volume_offline’: drivers/scsi/hpsa.c:3885:5: warning: variable ‘scsi_status’ set but not used [-Wunused-but-set-variable] drivers/scsi/hpsa.c:3884:6: warning: variable ‘cmd_status’ set but not used [-Wunused-but-set-variable] drivers/scsi/hpsa.c: In function ‘hpsa_update_scsi_devices’: drivers/scsi/hpsa.c:4354:9: warning: variable ‘n_ext_target_devs’ set but not used [-Wunused-but-set-variable] drivers/scsi/hpsa.c: In function ‘hpsa_scatter_gather’: drivers/scsi/hpsa.c:4583:36: warning: variable ‘last_sg’ set but not used [-Wunused-but-set-variable] drivers/scsi/hpsa.c: In function ‘hpsa_init_one’: drivers/scsi/hpsa.c:8639:6: warning: variable ‘dac’ set but not used [-Wunused-but-set-variable] drivers/scsi/hpsa.c: In function ‘hpsa_enter_performant_mode’: drivers/scsi/hpsa.c:9300:7: warning: variable ‘rc’ set but not used [-Wunused-but-set-variable] Link: https://lore.kernel.org/r/20201112101929.GC1997862@dell Cc: Don Brace Cc: Bugfixes to Cc: storagedev@microchip.com Signed-off-by: Lee Jones Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 45136e3a4efc..f10489e4f804 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3881,8 +3881,6 @@ static unsigned char hpsa_volume_offline(struct ctlr_info *h, u8 sense_key, asc, ascq; int sense_len; int rc, ldstat = 0; - u16 cmd_status; - u8 scsi_status; #define ASC_LUN_NOT_READY 0x04 #define ASCQ_LUN_NOT_READY_FORMAT_IN_PROGRESS 0x04 #define ASCQ_LUN_NOT_READY_INITIALIZING_CMD_REQ 0x02 @@ -3902,8 +3900,6 @@ static unsigned char hpsa_volume_offline(struct ctlr_info *h, else sense_len = c->err_info->SenseLen; decode_sense_data(sense, sense_len, &sense_key, &asc, &ascq); - cmd_status = c->err_info->CommandStatus; - scsi_status = c->err_info->ScsiStatus; cmd_free(h, c); /* Determine the reason for not ready state */ @@ -4351,7 +4347,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) u32 ndev_allocated = 0; struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice; int ncurrent = 0; - int i, n_ext_target_devs, ndevs_to_allocate; + int i, ndevs_to_allocate; int raid_ctlr_position; bool physical_device; DECLARE_BITMAP(lunzerobits, MAX_EXT_TARGETS); @@ -4416,7 +4412,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) raid_ctlr_position = nphysicals + nlogicals; /* adjust our table of devices */ - n_ext_target_devs = 0; for (i = 0; i < nphysicals + nlogicals + 1; i++) { u8 *lunaddrbytes, is_OBDR = 0; int rc = 0; @@ -4580,7 +4575,7 @@ static int hpsa_scatter_gather(struct ctlr_info *h, struct scsi_cmnd *cmd) { struct scatterlist *sg; - int use_sg, i, sg_limit, chained, last_sg; + int use_sg, i, sg_limit, chained; struct SGDescriptor *curr_sg; BUG_ON(scsi_sg_count(cmd) > h->maxsgentries); @@ -4602,7 +4597,6 @@ static int hpsa_scatter_gather(struct ctlr_info *h, curr_sg = cp->SG; chained = use_sg > h->max_cmd_sg_entries; sg_limit = chained ? h->max_cmd_sg_entries - 1 : use_sg; - last_sg = scsi_sg_count(cmd) - 1; scsi_for_each_sg(cmd, sg, sg_limit, i) { hpsa_set_sg_descriptor(curr_sg, sg); curr_sg++; @@ -8635,7 +8629,7 @@ static struct ctlr_info *hpda_alloc_ctlr_info(void) static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - int dac, rc; + int rc; struct ctlr_info *h; int try_soft_reset = 0; unsigned long flags; @@ -8711,13 +8705,9 @@ reinit_after_soft_reset: /* configure PCI DMA stuff */ rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); - if (rc == 0) { - dac = 1; - } else { + if (rc != 0) { rc = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (rc == 0) { - dac = 0; - } else { + if (rc != 0) { dev_err(&pdev->dev, "no suitable DMA available\n"); goto clean3; /* shost, pci, lu, aer/h */ } @@ -9296,10 +9286,9 @@ static int hpsa_enter_performant_mode(struct ctlr_info *h, u32 trans_support) } else if (trans_support & CFGTBL_Trans_io_accel2) { u64 cfg_offset, cfg_base_addr_index; u32 bft2_offset, cfg_base_addr; - int rc; - rc = hpsa_find_cfg_addrs(h->pdev, h->vaddr, &cfg_base_addr, - &cfg_base_addr_index, &cfg_offset); + hpsa_find_cfg_addrs(h->pdev, h->vaddr, &cfg_base_addr, + &cfg_base_addr_index, &cfg_offset); BUILD_BUG_ON(offsetof(struct io_accel2_cmd, sg) != 64); bft2[15] = h->ioaccel_maxsg + HPSA_IOACCEL2_HEADER_SZ; calc_bucket_map(bft2, ARRAY_SIZE(bft2), h->ioaccel_maxsg, -- cgit v1.2.3 From 6ac63216a7af03e8281758d7cd32a09718531eb2 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 13 Nov 2020 16:47:54 -0800 Subject: scsi: ufs-qcom: Only select QCOM_SCM if SCSI_UFS_CRYPTO QCOM_SCM is only needed to make the qcom_scm_*() calls in ufs-qcom-ice.c, which is only compiled when SCSI_UFS_CRYPTO=y. So don't unnecessarily enable QCOM_SCM when SCSI_UFS_CRYPTO=n. Link: https://lore.kernel.org/r/20201114004754.235378-1-ebiggers@kernel.org Signed-off-by: Eric Biggers Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index dcdb4eb1f90b..3f6dfed4fe84 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig @@ -99,7 +99,7 @@ config SCSI_UFS_DWC_TC_PLATFORM config SCSI_UFS_QCOM tristate "QCOM specific hooks to UFS controller platform driver" depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM - select QCOM_SCM + select QCOM_SCM if SCSI_UFS_CRYPTO select RESET_CONTROLLER help This selects the QCOM specific additions to UFSHCD platform driver. -- cgit v1.2.3 From 4ab2990a5ce15e6a689f349ba6ab1e6e23df57df Mon Sep 17 00:00:00 2001 From: Zou Wei Date: Sat, 14 Nov 2020 15:37:54 +0800 Subject: scsi: be2iscsi: Mark beiscsi_attrs with static keyword Fix the following sparse warning: ./be_main.c:167:25: warning: symbol 'beiscsi_attrs' was not declared. Should it be static? Link: https://lore.kernel.org/r/1605339474-22329-1-git-send-email-zou_wei@huawei.com Signed-off-by: Zou Wei Signed-off-by: Martin K. Petersen --- drivers/scsi/be2iscsi/be_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 202ba925c494..50e464224d47 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -164,7 +164,7 @@ DEVICE_ATTR(beiscsi_active_session_count, S_IRUGO, beiscsi_active_session_disp, NULL); DEVICE_ATTR(beiscsi_free_session_count, S_IRUGO, beiscsi_free_session_disp, NULL); -struct device_attribute *beiscsi_attrs[] = { +static struct device_attribute *beiscsi_attrs[] = { &dev_attr_beiscsi_log_enable, &dev_attr_beiscsi_drvr_ver, &dev_attr_beiscsi_adapter_family, -- cgit v1.2.3 From 307e338097dc320afb9f62493a325c7b9208d574 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:30 -0800 Subject: scsi: lpfc: Rework remote port ref counting and node freeing When a remote port is disconnected and disappears, its node structure (ndlp) stays allocated and on a vport node list. While on the list it can be matched, thus requires validation checks on state to be added in numerous code paths. If the node comes back, its possible for there to be multiple node structures for the same device on the vport node list. There is no reason to keep the node structure around after it is no longer in existence, and the current implementation creates problems for itself (multiple nodes) and lots of unnecessary code for state validation. Additionally, the reference taking on the node structure didn't follow the normal model used by the kernel kref api. It included lots of odd logic to match state with reference count. The combination of this odd logic plus the way it was implicitly used in the discovery engine made its reference taking implementation suspect and extremely hard to follow. Change the driver such that the reference taking routines are now normal ref increments/decrements and callout on refcount=0. With this in place, the rework can be done such that the node structure is fully removed and deallocated when the remote port no longer exists and all references are removed. This removal logic, and the basic ref counting are intrically tied, thus in a single patch. Link: https://lore.kernel.org/r/20201115192646.12977-2-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_attr.c | 11 +- drivers/scsi/lpfc/lpfc_bsg.c | 2 +- drivers/scsi/lpfc/lpfc_crtn.h | 2 - drivers/scsi/lpfc/lpfc_ct.c | 15 +- drivers/scsi/lpfc/lpfc_debugfs.c | 2 - drivers/scsi/lpfc/lpfc_disc.h | 33 +--- drivers/scsi/lpfc/lpfc_els.c | 210 ++++++------------------ drivers/scsi/lpfc/lpfc_hbadisc.c | 321 ++++++------------------------------- drivers/scsi/lpfc/lpfc_init.c | 63 ++------ drivers/scsi/lpfc/lpfc_nportdisc.c | 2 +- drivers/scsi/lpfc/lpfc_nvme.c | 12 +- drivers/scsi/lpfc/lpfc_nvmet.c | 10 +- drivers/scsi/lpfc/lpfc_scsi.c | 28 ++-- drivers/scsi/lpfc/lpfc_sli.c | 32 ++-- drivers/scsi/lpfc/lpfc_vport.c | 57 +------ 15 files changed, 170 insertions(+), 630 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index ada231d4f0c6..1987554dcd8f 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -3634,8 +3634,6 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport) shost = lpfc_shost_from_vport(vport); spin_lock_irq(shost->host_lock); list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp)) - continue; if (ndlp->rport) ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo; #if (IS_ENABLED(CONFIG_NVME_FC)) @@ -4404,7 +4402,7 @@ sysfs_drvr_stat_data_read(struct file *filp, struct kobject *kobj, spin_lock_irq(shost->host_lock); list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp) || !ndlp->lat_data) + if (!ndlp->lat_data) continue; if (nport_index > 0) { @@ -5472,8 +5470,6 @@ lpfc_max_scsicmpl_time_set(struct lpfc_vport *vport, int val) spin_lock_irq(shost->host_lock); list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp)) - continue; if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) continue; ndlp->cmd_qdepth = vport->cfg_tgt_queue_depth; @@ -6982,8 +6978,7 @@ lpfc_get_node_by_target(struct scsi_target *starget) spin_lock_irq(shost->host_lock); /* Search for this, mapped, target ID */ list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { - if (NLP_CHK_NODE_ACT(ndlp) && - ndlp->nlp_state == NLP_STE_MAPPED_NODE && + if (ndlp->nlp_state == NLP_STE_MAPPED_NODE && starget->id == ndlp->nlp_sid) { spin_unlock_irq(shost->host_lock); return ndlp; @@ -7058,7 +7053,7 @@ lpfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) else rport->dev_loss_tmo = 1; - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { + if (!ndlp) { dev_info(&rport->dev, "Cannot find remote node to " "set rport dev loss tmo, port_id x%x\n", rport->port_id); diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index abe7c53f8caa..bb15787c8f20 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -1520,7 +1520,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag, } /* Check if the ndlp is active */ - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { + if (!ndlp) { rc = IOCB_ERROR; goto issue_ct_rsp_exit; } diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 782f6f76f18a..903151aa6f02 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -88,8 +88,6 @@ void lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_unregister_vfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_enqueue_node(struct lpfc_vport *, struct lpfc_nodelist *); void lpfc_dequeue_node(struct lpfc_vport *, struct lpfc_nodelist *); -struct lpfc_nodelist *lpfc_enable_node(struct lpfc_vport *, - struct lpfc_nodelist *, int); void lpfc_nlp_set_state(struct lpfc_vport *, struct lpfc_nodelist *, int); void lpfc_drop_node(struct lpfc_vport *, struct lpfc_nodelist *); void lpfc_set_disctmo(struct lpfc_vport *); diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index b963e234d77d..32f5d8951b8f 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -740,7 +740,7 @@ lpfc_prep_node_fc4type(struct lpfc_vport *vport, uint32_t Did, uint8_t fc4_type) ndlp = lpfc_setup_disc_node(vport, Did); - if (ndlp && NLP_CHK_NODE_ACT(ndlp)) { + if (ndlp) { lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, "Parse GID_FTrsp: did:x%x flg:x%x x%x", Did, ndlp->nlp_flag, vport->fc_flag); @@ -791,7 +791,7 @@ lpfc_prep_node_fc4type(struct lpfc_vport *vport, uint32_t Did, uint8_t fc4_type) * Don't even bother to send GFF_ID. */ ndlp = lpfc_findnode_did(vport, Did); - if (ndlp && NLP_CHK_NODE_ACT(ndlp) && + if (ndlp && (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET))) { if (fc4_type == FC_TYPE_FCP) @@ -1437,7 +1437,7 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* This is a target port, unregistered port, or the GFF_ID failed */ ndlp = lpfc_setup_disc_node(vport, did); - if (ndlp && NLP_CHK_NODE_ACT(ndlp)) { + if (ndlp) { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "0242 Process x%x GFF " "NameServer Rsp Data: x%x x%x x%x\n", @@ -1872,8 +1872,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, int rc = 0; ndlp = lpfc_findnode_did(vport, NameServer_DID); - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) - || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) { + if (!ndlp || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) { rc=1; goto ns_cmd_exit; } @@ -2204,7 +2203,7 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_ct_free_iocb(phba, cmdiocb); ndlp = lpfc_findnode_did(vport, FDMI_DID); - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) + if (!ndlp) return; /* Check for a CT LS_RJT response */ @@ -2343,7 +2342,7 @@ lpfc_fdmi_change_check(struct lpfc_vport *vport) return; ndlp = lpfc_findnode_did(vport, FDMI_DID); - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) + if (!ndlp) return; /* Check if system hostname changed */ @@ -3389,7 +3388,7 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, struct lpfc_iocbq *); - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) + if (!ndlp) return 0; cmpl = lpfc_cmpl_ct_disc_fdmi; /* called from discovery */ diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 5a354abcbafc..af1e15cf9c12 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -895,8 +895,6 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) if (ndlp->nlp_type & NLP_NVME_INITIATOR) len += scnprintf(buf + len, size - len, "NVME_INITIATOR "); - len += scnprintf(buf+len, size-len, "usgmap:%x ", - ndlp->nlp_usg_map); len += scnprintf(buf+len, size-len, "refcnt:%x", kref_read(&ndlp->kref)); if (iocnt) { diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 1437e44ade80..f8ab001e4f0d 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h @@ -116,12 +116,6 @@ struct lpfc_nodelist { u8 nlp_nvme_info; /* NVME NSLER Support */ #define NLP_NVME_NSLER 0x1 /* NVME NSLER device */ - uint16_t nlp_usg_map; /* ndlp management usage bitmap */ -#define NLP_USG_NODE_ACT_BIT 0x1 /* Indicate ndlp is actively used */ -#define NLP_USG_IACT_REQ_BIT 0x2 /* Request to inactivate ndlp */ -#define NLP_USG_FREE_REQ_BIT 0x4 /* Request to invoke ndlp memory free */ -#define NLP_USG_FREE_ACK_BIT 0x8 /* Indicate ndlp memory free invoked */ - struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */ struct lpfc_hba *phba; struct fc_rport *rport; /* scsi_transport_fc port structure */ @@ -173,6 +167,7 @@ struct lpfc_node_rrq { #define NLP_FCP_PRLI_RJT 0x00002000 /* Rport does not support FCP PRLI. */ #define NLP_UNREG_INP 0x00008000 /* UNREG_RPI cmd is in progress */ #define NLP_DEFER_RM 0x00010000 /* Remove this ndlp if no longer used */ +#define NLP_DROPPED 0x00000008 /* Init ref count has been dropped */ #define NLP_DELAY_TMO 0x00020000 /* delay timeout is running for node */ #define NLP_NPR_2B_DISC 0x00040000 /* node is included in num_disc_nodes */ #define NLP_RCV_PLOGI 0x00080000 /* Rcv'ed PLOGI from remote system */ @@ -191,32 +186,6 @@ struct lpfc_node_rrq { #define NLP_FIRSTBURST 0x40000000 /* Target supports FirstBurst */ #define NLP_RPI_REGISTERED 0x80000000 /* nlp_rpi is valid */ - -/* ndlp usage management macros */ -#define NLP_CHK_NODE_ACT(ndlp) (((ndlp)->nlp_usg_map \ - & NLP_USG_NODE_ACT_BIT) \ - && \ - !((ndlp)->nlp_usg_map \ - & NLP_USG_FREE_ACK_BIT)) -#define NLP_SET_NODE_ACT(ndlp) ((ndlp)->nlp_usg_map \ - |= NLP_USG_NODE_ACT_BIT) -#define NLP_INT_NODE_ACT(ndlp) ((ndlp)->nlp_usg_map \ - = NLP_USG_NODE_ACT_BIT) -#define NLP_CLR_NODE_ACT(ndlp) ((ndlp)->nlp_usg_map \ - &= ~NLP_USG_NODE_ACT_BIT) -#define NLP_CHK_IACT_REQ(ndlp) ((ndlp)->nlp_usg_map \ - & NLP_USG_IACT_REQ_BIT) -#define NLP_SET_IACT_REQ(ndlp) ((ndlp)->nlp_usg_map \ - |= NLP_USG_IACT_REQ_BIT) -#define NLP_CHK_FREE_REQ(ndlp) ((ndlp)->nlp_usg_map \ - & NLP_USG_FREE_REQ_BIT) -#define NLP_SET_FREE_REQ(ndlp) ((ndlp)->nlp_usg_map \ - |= NLP_USG_FREE_REQ_BIT) -#define NLP_CHK_FREE_ACK(ndlp) ((ndlp)->nlp_usg_map \ - & NLP_USG_FREE_ACK_BIT) -#define NLP_SET_FREE_ACK(ndlp) ((ndlp)->nlp_usg_map \ - |= NLP_USG_FREE_ACK_BIT) - /* There are 4 different double linked lists nodelist entries can reside on. * The Port Login (PLOGI) list and Address Discovery (ADISC) list are used * when Link Up discovery or Registered State Change Notification (RSCN) diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index de3a59f2e3df..9cf0e9d55cdf 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -378,7 +378,7 @@ lpfc_issue_fabric_reglogin(struct lpfc_vport *vport) sp = &phba->fc_fabparam; ndlp = lpfc_findnode_did(vport, Fabric_DID); - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { + if (!ndlp) { err = 1; goto fail; } @@ -471,7 +471,7 @@ lpfc_issue_reg_vfi(struct lpfc_vport *vport) !(phba->link_flag & LS_LOOPBACK_MODE) && !(vport->fc_flag & FC_PT2PT)) { ndlp = lpfc_findnode_did(vport, Fabric_DID); - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { + if (!ndlp) { rc = -ENODEV; goto fail; } @@ -765,8 +765,6 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, */ list_for_each_entry_safe(np, next_np, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(np)) - continue; if ((np->nlp_state != NLP_STE_NPR_NODE) || !(np->nlp_flag & NLP_NPR_ADISC)) continue; @@ -908,11 +906,6 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ndlp = lpfc_nlp_init(vport, PT2PT_RemoteID); if (!ndlp) goto fail; - } else if (!NLP_CHK_NODE_ACT(ndlp)) { - ndlp = lpfc_enable_node(vport, ndlp, - NLP_STE_UNUSED_NODE); - if(!ndlp) - goto fail; } memcpy(&ndlp->nlp_portname, &sp->portName, @@ -1421,8 +1414,7 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba) icmd = &iocb->iocb; if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) { ndlp = (struct lpfc_nodelist *)(iocb->context1); - if (ndlp && NLP_CHK_NODE_ACT(ndlp) && - (ndlp->nlp_DID == Fabric_DID)) + if (ndlp && (ndlp->nlp_DID == Fabric_DID)) lpfc_sli_issue_abort_iotag(phba, pring, iocb); } } @@ -1464,13 +1456,9 @@ lpfc_initial_flogi(struct lpfc_vport *vport) return 0; /* Set the node type */ ndlp->nlp_type |= NLP_FABRIC; + /* Put ndlp onto node list */ lpfc_enqueue_node(vport, ndlp); - } else if (!NLP_CHK_NODE_ACT(ndlp)) { - /* re-setup ndlp without removing from node list */ - ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); - if (!ndlp) - return 0; } if (lpfc_issue_els_flogi(vport, ndlp, 0)) { @@ -1513,11 +1501,6 @@ lpfc_initial_fdisc(struct lpfc_vport *vport) return 0; /* Put ndlp onto node list */ lpfc_enqueue_node(vport, ndlp); - } else if (!NLP_CHK_NODE_ACT(ndlp)) { - /* re-setup ndlp without removing from node list */ - ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); - if (!ndlp) - return 0; } if (lpfc_issue_els_fdisc(vport, ndlp, 0)) { @@ -1627,7 +1610,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, new_ndlp = lpfc_findnode_wwpn(vport, &sp->portName); /* return immediately if the WWPN matches ndlp */ - if (new_ndlp == ndlp && NLP_CHK_NODE_ACT(new_ndlp)) + if (new_ndlp == ndlp) return ndlp; if (phba->sli_rev == LPFC_SLI_REV4) { @@ -1662,28 +1645,6 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, phba->active_rrq_pool); return ndlp; } - } else if (!NLP_CHK_NODE_ACT(new_ndlp)) { - rc = memcmp(&ndlp->nlp_portname, name, - sizeof(struct lpfc_name)); - if (!rc) { - if (active_rrqs_xri_bitmap) - mempool_free(active_rrqs_xri_bitmap, - phba->active_rrq_pool); - return ndlp; - } - new_ndlp = lpfc_enable_node(vport, new_ndlp, - NLP_STE_UNUSED_NODE); - if (!new_ndlp) { - if (active_rrqs_xri_bitmap) - mempool_free(active_rrqs_xri_bitmap, - phba->active_rrq_pool); - return ndlp; - } - keepDID = new_ndlp->nlp_DID; - if ((phba->sli_rev == LPFC_SLI_REV4) && active_rrqs_xri_bitmap) - memcpy(active_rrqs_xri_bitmap, - new_ndlp->active_rrqs_xri_bitmap, - phba->cfg_rrq_xri_bitmap_sz); } else { keepDID = new_ndlp->nlp_DID; if (phba->sli_rev == LPFC_SLI_REV4 && @@ -1781,16 +1742,6 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, lpfc_nlp_put(ndlp); } - /* We shall actually free the ndlp with both nlp_DID and - * nlp_portname fields equals 0 to avoid any ndlp on the - * nodelist never to be used. - */ - if (ndlp->nlp_DID == 0) { - spin_lock_irq(&phba->ndlp_lock); - NLP_SET_FREE_REQ(ndlp); - spin_unlock_irq(&phba->ndlp_lock); - } - /* Two ndlps cannot have the same did on the nodelist. * Note: for this case, ndlp has a NULL WWPN so setting * the nlp_fc4_type isn't required. @@ -1803,10 +1754,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, active_rrqs_xri_bitmap, phba->cfg_rrq_xri_bitmap_sz); - if (!NLP_CHK_NODE_ACT(ndlp)) - lpfc_drop_node(vport, ndlp); - } - else { + } else { lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "3180 PLOGI confirm SWAP: %x %x\n", new_ndlp->nlp_DID, keepDID); @@ -1856,6 +1804,14 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, put_device(&rport->dev); } } + + /* + * If ndlp is not associated with any rport we can drop it here else + * let dev_loss_tmo_callbk trigger DEVICE_RM event + */ + if (!ndlp->rport && (ndlp->nlp_state == NLP_STE_NPR_NODE)) + lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); + if (phba->sli_rev == LPFC_SLI_REV4 && active_rrqs_xri_bitmap) mempool_free(active_rrqs_xri_bitmap, @@ -1933,7 +1889,7 @@ lpfc_cmpl_els_rrq(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, irsp->un.elsreq64.remoteID); ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || ndlp != rrq->ndlp) { + if (!ndlp || ndlp != rrq->ndlp) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "2882 RRQ completes to NPort x%x " "with no ndlp. Data: x%x x%x x%x\n", @@ -2010,7 +1966,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, irsp->un.elsreq64.remoteID); ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { + if (!ndlp) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0136 PLOGI completes to NPort x%x " "with no ndlp. Data: x%x x%x x%x\n", @@ -2151,8 +2107,6 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) ndlp->nlp_defer_did = did; return 0; } - if (!NLP_CHK_NODE_ACT(ndlp)) - ndlp = NULL; } /* If ndlp is not NULL, we will bump the reference count on it */ @@ -3184,10 +3138,6 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry) if (!ndlp) return 1; lpfc_enqueue_node(vport, ndlp); - } else if (!NLP_CHK_NODE_ACT(ndlp)) { - ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); - if (!ndlp) - return 1; } elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, @@ -3287,11 +3237,6 @@ lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry) if (!ndlp) return 1; lpfc_enqueue_node(vport, ndlp); - } else if (!NLP_CHK_NODE_ACT(ndlp)) { - ndlp = lpfc_enable_node(vport, ndlp, - NLP_STE_UNUSED_NODE); - if (!ndlp) - return 1; } } @@ -3392,10 +3337,6 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) if (!ndlp) return 1; lpfc_enqueue_node(vport, ndlp); - } else if (!NLP_CHK_NODE_ACT(ndlp)) { - ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); - if (!ndlp) - return 1; } elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, @@ -3425,7 +3366,7 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) memcpy(&fp->RportName, &vport->fc_portname, sizeof(struct lpfc_name)); memcpy(&fp->RnodeName, &vport->fc_nodename, sizeof(struct lpfc_name)); ondlp = lpfc_findnode_did(vport, nportid); - if (ondlp && NLP_CHK_NODE_ACT(ondlp)) { + if (ondlp) { memcpy(&fp->OportName, &ondlp->nlp_portname, sizeof(struct lpfc_name)); memcpy(&fp->OnodeName, &ondlp->nlp_nodename, @@ -3489,10 +3430,6 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry) if (!ndlp) return -ENODEV; lpfc_enqueue_node(vport, ndlp); - } else if (!NLP_CHK_NODE_ACT(ndlp)) { - ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); - if (!ndlp) - return -ENODEV; } /* RDF ELS is not required on an NPIV VN_Port. */ @@ -3828,14 +3765,13 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, cmd = *elscmd++; } - if (ndlp && NLP_CHK_NODE_ACT(ndlp)) + if (ndlp) did = ndlp->nlp_DID; else { /* We should only hit this case for retrying PLOGI */ did = irsp->un.elsreq64.remoteID; ndlp = lpfc_findnode_did(vport, did); - if ((!ndlp || !NLP_CHK_NODE_ACT(ndlp)) - && (cmd != ELS_CMD_PLOGI)) + if (!ndlp && (cmd != ELS_CMD_PLOGI)) return 1; } @@ -4163,7 +4099,7 @@ out_retry: } phba->fc_stat.elsXmitRetry++; - if (ndlp && NLP_CHK_NODE_ACT(ndlp) && delay) { + if (ndlp && delay) { phba->fc_stat.elsDelayRetry++; ndlp->nlp_retry = cmdiocb->retry; @@ -4194,7 +4130,7 @@ out_retry: lpfc_issue_els_fdisc(vport, ndlp, cmdiocb->retry); return 1; case ELS_CMD_PLOGI: - if (ndlp && NLP_CHK_NODE_ACT(ndlp)) { + if (ndlp) { ndlp->nlp_prev_state = ndlp->nlp_state; lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); @@ -4469,20 +4405,16 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) mempool_free(pmb, phba->mbox_mem_pool); if (ndlp) { lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, - "0006 rpi%x DID:%x flg:%x %d map:%x x%px\n", + "0006 rpi%x DID:%x flg:%x %d x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref), - ndlp->nlp_usg_map, ndlp); - if (NLP_CHK_NODE_ACT(ndlp)) { - lpfc_nlp_put(ndlp); - /* This is the end of the default RPI cleanup logic for - * this ndlp. If no other discovery threads are using - * this ndlp, free all resources associated with it. - */ - lpfc_nlp_not_used(ndlp); - } else { - lpfc_drop_node(ndlp->vport, ndlp); - } + ndlp); + lpfc_nlp_put(ndlp); + /* This is the end of the default RPI cleanup logic for + * this ndlp. If no other discovery threads are using + * this ndlp, free all resources associated with it. + */ + lpfc_nlp_not_used(ndlp); } return; @@ -4531,8 +4463,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * function can have cmdiocb->contest1 (ndlp) field set to NULL. */ pcmd = (uint8_t *) (((struct lpfc_dmabuf *) cmdiocb->context2)->virt); - if (ndlp && NLP_CHK_NODE_ACT(ndlp) && - (*((uint32_t *) (pcmd)) == ELS_CMD_LS_RJT)) { + if (ndlp && (*((uint32_t *) (pcmd)) == ELS_CMD_LS_RJT)) { /* A LS_RJT associated with Default RPI cleanup has its own * separate code path. */ @@ -4541,7 +4472,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } /* Check to see if link went down during discovery */ - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || lpfc_els_chk_latt(vport)) { + if (!ndlp || lpfc_els_chk_latt(vport)) { if (mbox) { mp = (struct lpfc_dmabuf *)mbox->ctx_buf; if (mp) { @@ -4550,8 +4481,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } mempool_free(mbox, phba->mbox_mem_pool); } - if (ndlp && NLP_CHK_NODE_ACT(ndlp) && - (ndlp->nlp_flag & NLP_RM_DFLT_RPI)) + if (ndlp && (ndlp->nlp_flag & NLP_RM_DFLT_RPI)) if (lpfc_nlp_not_used(ndlp)) { ndlp = NULL; /* Indicate the node has already released, @@ -4663,7 +4593,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, mempool_free(mbox, phba->mbox_mem_pool); } out: - if (ndlp && NLP_CHK_NODE_ACT(ndlp) && shost) { + if (ndlp && shost) { spin_lock_irq(shost->host_lock); if (mbox) ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN; @@ -5417,8 +5347,6 @@ lpfc_els_disc_adisc(struct lpfc_vport *vport) /* go thru NPR nodes and issue any remaining ELS ADISCs */ list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp)) - continue; if (ndlp->nlp_state == NLP_STE_NPR_NODE && (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && (ndlp->nlp_flag & NLP_NPR_ADISC) != 0) { @@ -5475,8 +5403,6 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport) /* go thru NPR nodes and issue any remaining ELS PLOGIs */ list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp)) - continue; if (ndlp->nlp_state == NLP_STE_NPR_NODE && (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && (ndlp->nlp_flag & NLP_DELAY_TMO) == 0 && @@ -6584,8 +6510,7 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport) /* Move all affected nodes by pending RSCNs to NPR state. */ list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp) || - (ndlp->nlp_state == NLP_STE_UNUSED_NODE) || + if ((ndlp->nlp_state == NLP_STE_UNUSED_NODE) || !lpfc_rscn_payload_check(vport, ndlp->nlp_DID)) continue; @@ -6920,8 +6845,7 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport) vport->num_disc_nodes = 0; ndlp = lpfc_findnode_did(vport, NameServer_DID); - if (ndlp && NLP_CHK_NODE_ACT(ndlp) - && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { + if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { /* Good ndlp, issue CT Request to NameServer. Need to * know how many gidfts were issued. If none, then just * flush the RSCN. Otherwise, the outstanding requests @@ -6939,13 +6863,8 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport) } else { /* Nameserver login in question. Revalidate. */ if (ndlp) { - ndlp = lpfc_enable_node(vport, ndlp, - NLP_STE_PLOGI_ISSUE); - if (!ndlp) { - lpfc_els_flush_rscn(vport); - return 0; - } ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE; + lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); } else { ndlp = lpfc_nlp_init(vport, NameServer_DID); if (!ndlp) { @@ -7529,7 +7448,7 @@ lpfc_issue_els_rrq(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (ndlp != rrq->ndlp) ndlp = rrq->ndlp; - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) + if (!ndlp) return 1; /* If ndlp is not NULL, we will bump the reference count on it */ @@ -8000,7 +7919,7 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) else { struct lpfc_nodelist *ndlp; ndlp = __lpfc_findnode_rpi(vport, cmd->ulpContext); - if (ndlp && NLP_CHK_NODE_ACT(ndlp)) + if (ndlp) remote_ID = ndlp->nlp_DID; } list_add_tail(&piocb->dlist, &abort_list); @@ -8227,7 +8146,7 @@ lpfc_send_els_failure_event(struct lpfc_hba *phba, uint32_t *pcmd; ndlp = cmdiocbp->context1; - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) + if (!ndlp) return; if (rspiocbp->iocb.ulpStatus == IOSTAT_LS_RJT) { @@ -8503,20 +8422,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, newnode = 1; if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) ndlp->nlp_type |= NLP_FABRIC; - } else if (!NLP_CHK_NODE_ACT(ndlp)) { - ndlp = lpfc_enable_node(vport, ndlp, - NLP_STE_UNUSED_NODE); - if (!ndlp) - goto dropit; - lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); - newnode = 1; - if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) - ndlp->nlp_type |= NLP_FABRIC; } else if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) { - /* This is similar to the new node path */ - ndlp = lpfc_nlp_get(ndlp); - if (!ndlp) - goto dropit; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); newnode = 1; } @@ -8993,13 +8899,9 @@ lpfc_start_fdmi(struct lpfc_vport *vport) return; } } - if (!NLP_CHK_NODE_ACT(ndlp)) - ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_NPR_NODE); - if (ndlp) { - lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); - lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); - } + lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); + lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); } /** @@ -9051,19 +8953,8 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) "0251 NameServer login: no memory\n"); return; } - } else if (!NLP_CHK_NODE_ACT(ndlp)) { - ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); - if (!ndlp) { - if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { - lpfc_disc_start(vport); - return; - } - lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, - "0348 NameServer login: node freed\n"); - return; - } } + ndlp->nlp_type |= NLP_FABRIC; lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); @@ -9425,8 +9316,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, */ list_for_each_entry_safe(np, next_np, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp) || - (np->nlp_state != NLP_STE_NPR_NODE) || + if ((np->nlp_state != NLP_STE_NPR_NODE) || !(np->nlp_flag & NLP_NPR_ADISC)) continue; spin_lock_irq(shost->host_lock); @@ -10052,8 +9942,10 @@ lpfc_sli4_vport_delete_els_xri_aborted(struct lpfc_vport *vport) spin_lock(&phba->sli4_hba.sgl_list_lock); list_for_each_entry_safe(sglq_entry, sglq_next, &phba->sli4_hba.lpfc_abts_els_sgl_list, list) { - if (sglq_entry->ndlp && sglq_entry->ndlp->vport == vport) + if (sglq_entry->ndlp && sglq_entry->ndlp->vport == vport) { + lpfc_nlp_put(sglq_entry->ndlp); sglq_entry->ndlp = NULL; + } } spin_unlock(&phba->sli4_hba.sgl_list_lock); spin_unlock_irqrestore(&phba->hbalock, iflag); @@ -10096,9 +9988,13 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba, sglq_entry->state = SGL_FREED; spin_unlock(&phba->sli4_hba.sgl_list_lock); spin_unlock_irqrestore(&phba->hbalock, iflag); - lpfc_set_rrq_active(phba, ndlp, - sglq_entry->sli4_lxritag, - rxid, 1); + + if (ndlp) { + lpfc_set_rrq_active(phba, ndlp, + sglq_entry->sli4_lxritag, + rxid, 1); + lpfc_nlp_put(ndlp); + } /* Check if TXQ queue needs to be serviced */ if (pring && !list_empty(&pring->txq)) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index c61eb6032500..47d26917e10f 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -83,7 +83,7 @@ lpfc_terminate_rport_io(struct fc_rport *rport) rdata = rport->dd_data; ndlp = rdata->pnode; - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { + if (!ndlp) { if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) printk(KERN_ERR "Cannot find remote node" " to terminate I/O Data x%x\n", @@ -122,7 +122,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) rdata = rport->dd_data; ndlp = rdata->pnode; - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) + if (!ndlp) return; vport = ndlp->vport; @@ -820,8 +820,7 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove) struct lpfc_nodelist *ndlp, *next_ndlp; list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp)) - continue; + if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) continue; if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) || @@ -992,8 +991,7 @@ lpfc_linkup_cleanup_nodes(struct lpfc_vport *vport) list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME); - if (!NLP_CHK_NODE_ACT(ndlp)) - continue; + if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) continue; if (ndlp->nlp_type & NLP_FABRIC) { @@ -3594,10 +3592,10 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) pmb->ctx_ndlp = NULL; lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, - "0002 rpi:%x DID:%x flg:%x %d map:%x x%px\n", + "0002 rpi:%x DID:%x flg:%x %d x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref), - ndlp->nlp_usg_map, ndlp); + ndlp); if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND) ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; @@ -4109,10 +4107,10 @@ out: ndlp->nlp_type |= NLP_FABRIC; lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_DISCOVERY, - "0003 rpi:%x DID:%x flg:%x %d map%x x%px\n", + "0003 rpi:%x DID:%x flg:%x %d x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref), - ndlp->nlp_usg_map, ndlp); + ndlp); if (vport->port_state < LPFC_VPORT_READY) { /* Link up discovery requires Fabric registration. */ @@ -4437,6 +4435,7 @@ lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, { struct Scsi_Host *shost = lpfc_shost_from_vport(vport); int old_state = ndlp->nlp_state; + int node_dropped = ndlp->nlp_flag & NLP_DROPPED; char name1[16], name2[16]; lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, @@ -4449,6 +4448,12 @@ lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, "node statechg did:x%x old:%d ste:%d", ndlp->nlp_DID, old_state, state); + if (node_dropped && old_state == NLP_STE_UNUSED_NODE && + state != NLP_STE_UNUSED_NODE) { + ndlp->nlp_flag &= ~NLP_DROPPED; + lpfc_nlp_get(ndlp); + } + if (old_state == NLP_STE_NPR_NODE && state != NLP_STE_NPR_NODE) lpfc_cancel_retry_delay_tmo(vport, ndlp); @@ -4496,15 +4501,6 @@ lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) NLP_STE_UNUSED_NODE); } -static void -lpfc_disable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) -{ - lpfc_cancel_retry_delay_tmo(vport, ndlp); - if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) - lpfc_nlp_counters(vport, ndlp->nlp_state, -1); - lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state, - NLP_STE_UNUSED_NODE); -} /** * lpfc_initialize_node - Initialize all fields of node object * @vport: Pointer to Virtual Port object. @@ -4534,122 +4530,11 @@ lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ndlp->nlp_sid = NLP_NO_SID; ndlp->nlp_fc4_type = NLP_FC4_NONE; kref_init(&ndlp->kref); - NLP_INT_NODE_ACT(ndlp); atomic_set(&ndlp->cmd_pending, 0); ndlp->cmd_qdepth = vport->cfg_tgt_queue_depth; ndlp->nlp_defer_did = NLP_EVT_NOTHING_PENDING; } -struct lpfc_nodelist * -lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, - int state) -{ - struct lpfc_hba *phba = vport->phba; - uint32_t did, flag; - unsigned long flags; - unsigned long *active_rrqs_xri_bitmap = NULL; - int rpi = LPFC_RPI_ALLOC_ERROR; - uint32_t defer_did = 0; - - if (!ndlp) - return NULL; - - if (phba->sli_rev == LPFC_SLI_REV4) { - if (ndlp->nlp_rpi == LPFC_RPI_ALLOC_ERROR) - rpi = lpfc_sli4_alloc_rpi(vport->phba); - else - rpi = ndlp->nlp_rpi; - - if (rpi == LPFC_RPI_ALLOC_ERROR) { - lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE, - "0359 %s: ndlp:x%px " - "usgmap:x%x refcnt:%d FAILED RPI " - " ALLOC\n", - __func__, - (void *)ndlp, ndlp->nlp_usg_map, - kref_read(&ndlp->kref)); - return NULL; - } - } - - spin_lock_irqsave(&phba->ndlp_lock, flags); - /* The ndlp should not be in memory free mode */ - if (NLP_CHK_FREE_REQ(ndlp)) { - spin_unlock_irqrestore(&phba->ndlp_lock, flags); - lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE, - "0277 %s: ndlp:x%px " - "usgmap:x%x refcnt:%d\n", - __func__, (void *)ndlp, ndlp->nlp_usg_map, - kref_read(&ndlp->kref)); - goto free_rpi; - } - /* The ndlp should not already be in active mode */ - if (NLP_CHK_NODE_ACT(ndlp)) { - spin_unlock_irqrestore(&phba->ndlp_lock, flags); - lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE, - "0278 %s: ndlp:x%px " - "usgmap:x%x refcnt:%d\n", - __func__, (void *)ndlp, ndlp->nlp_usg_map, - kref_read(&ndlp->kref)); - goto free_rpi; - } - - /* First preserve the orginal DID, xri_bitmap and some flags */ - did = ndlp->nlp_DID; - flag = (ndlp->nlp_flag & NLP_UNREG_INP); - if (flag & NLP_UNREG_INP) - defer_did = ndlp->nlp_defer_did; - if (phba->sli_rev == LPFC_SLI_REV4) - active_rrqs_xri_bitmap = ndlp->active_rrqs_xri_bitmap; - - /* Zero ndlp except of ndlp linked list pointer */ - memset((((char *)ndlp) + sizeof (struct list_head)), 0, - sizeof (struct lpfc_nodelist) - sizeof (struct list_head)); - - /* Next reinitialize and restore saved objects */ - lpfc_initialize_node(vport, ndlp, did); - ndlp->nlp_flag |= flag; - if (flag & NLP_UNREG_INP) - ndlp->nlp_defer_did = defer_did; - if (phba->sli_rev == LPFC_SLI_REV4) - ndlp->active_rrqs_xri_bitmap = active_rrqs_xri_bitmap; - - spin_unlock_irqrestore(&phba->ndlp_lock, flags); - if (vport->phba->sli_rev == LPFC_SLI_REV4) { - ndlp->nlp_rpi = rpi; - lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, - "0008 rpi:%x DID:%x flg:%x refcnt:%d " - "map:%x x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, - ndlp->nlp_flag, - kref_read(&ndlp->kref), - ndlp->nlp_usg_map, ndlp); - } - - - if (state != NLP_STE_UNUSED_NODE) - lpfc_nlp_set_state(vport, ndlp, state); - else - lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, - "0013 rpi:%x DID:%x flg:%x refcnt:%d " - "map:%x x%px STATE=UNUSED\n", - ndlp->nlp_rpi, ndlp->nlp_DID, - ndlp->nlp_flag, - kref_read(&ndlp->kref), - ndlp->nlp_usg_map, ndlp); - - lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE, - "node enable: did:x%x", - ndlp->nlp_DID, 0, 0); - return ndlp; - -free_rpi: - if (phba->sli_rev == LPFC_SLI_REV4) { - lpfc_sli4_free_rpi(vport->phba, rpi); - ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR; - } - return NULL; -} - void lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) { @@ -4663,6 +4548,7 @@ lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) return; lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); + ndlp->nlp_flag |= NLP_DROPPED; if (vport->phba->sli_rev == LPFC_SLI_REV4) { lpfc_cleanup_vports_rrqs(vport, ndlp); lpfc_unreg_rpi(vport, ndlp); @@ -5179,22 +5065,7 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) "Data: x%x x%x x%x\n", ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); - if (NLP_CHK_FREE_REQ(ndlp)) { - lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE, - "0280 %s: ndlp:x%px " - "usgmap:x%x refcnt:%d\n", - __func__, (void *)ndlp, ndlp->nlp_usg_map, - kref_read(&ndlp->kref)); - lpfc_dequeue_node(vport, ndlp); - } else { - lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE, - "0281 %s: ndlp:x%px " - "usgmap:x%x refcnt:%d\n", - __func__, (void *)ndlp, ndlp->nlp_usg_map, - kref_read(&ndlp->kref)); - lpfc_disable_node(vport, ndlp); - } - + lpfc_dequeue_node(vport, ndlp); /* Don't need to clean up REG_LOGIN64 cmds for Default RPI cleanup */ @@ -5296,10 +5167,10 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_DISCOVERY, "0005 Cleanup Default rpi:x%x DID:x%x flg:x%x " - "ref %d map:x%x ndlp x%px\n", + "ref %d ndlp x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref), - ndlp->nlp_usg_map, ndlp); + ndlp); if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) != NULL) { rc = lpfc_reg_rpi(phba, vport->vpi, ndlp->nlp_DID, @@ -5410,8 +5281,8 @@ __lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did) if (lpfc_matchdid(vport, ndlp, did)) { data1 = (((uint32_t)ndlp->nlp_state << 24) | ((uint32_t)ndlp->nlp_xri << 16) | - ((uint32_t)ndlp->nlp_type << 8) | - ((uint32_t)ndlp->nlp_usg_map & 0xff)); + ((uint32_t)ndlp->nlp_type << 8) + ); lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, "0929 FIND node DID " "Data: x%px x%x x%x x%x x%x x%px\n", @@ -5500,25 +5371,6 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, vport->fc_flag); - spin_lock_irq(shost->host_lock); - ndlp->nlp_flag |= NLP_NPR_2B_DISC; - spin_unlock_irq(shost->host_lock); - return ndlp; - } else if (!NLP_CHK_NODE_ACT(ndlp)) { - if (vport->phba->nvmet_support) - return NULL; - ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_NPR_NODE); - if (!ndlp) { - lpfc_printf_vlog(vport, KERN_WARNING, LOG_SLI, - "0014 Could not enable ndlp\n"); - return NULL; - } - lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, - "6454 Setup Enabled Node 2B_DISC x%x " - "Data:x%x x%x x%x\n", - ndlp->nlp_DID, ndlp->nlp_flag, - ndlp->nlp_state, vport->fc_flag); - spin_lock_irq(shost->host_lock); ndlp->nlp_flag |= NLP_NPR_2B_DISC; spin_unlock_irq(shost->host_lock); @@ -5858,8 +5710,6 @@ lpfc_disc_flush_list(struct lpfc_vport *vport) if (vport->fc_plogi_cnt || vport->fc_adisc_cnt) { list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp)) - continue; if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE || ndlp->nlp_state == NLP_STE_ADISC_ISSUE) { lpfc_free_tx(phba, ndlp); @@ -5947,8 +5797,6 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) /* Start discovery by sending FLOGI, clean up old rpis */ list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp)) - continue; if (ndlp->nlp_state != NLP_STE_NPR_NODE) continue; if (ndlp->nlp_type & NLP_FABRIC) { @@ -6000,7 +5848,7 @@ lpfc_disc_timeout_handler(struct lpfc_vport *vport) "NameServer login\n"); /* Next look for NameServer ndlp */ ndlp = lpfc_findnode_did(vport, NameServer_DID); - if (ndlp && NLP_CHK_NODE_ACT(ndlp)) + if (ndlp) lpfc_els_abort(phba, ndlp); /* ReStart discovery */ @@ -6173,10 +6021,10 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ndlp->nlp_type |= NLP_FABRIC; lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_DISCOVERY, - "0004 rpi:%x DID:%x flg:%x %d map:%x x%px\n", + "0004 rpi:%x DID:%x flg:%x %d x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref), - ndlp->nlp_usg_map, ndlp); + ndlp); /* * Start issuing Fabric-Device Management Interface (FDMI) command to * 0xfffffa (FDMI well known port). @@ -6205,10 +6053,6 @@ lpfc_filter_by_rpi(struct lpfc_nodelist *ndlp, void *param) { uint16_t *rpi = param; - /* check for active node */ - if (!NLP_CHK_NODE_ACT(ndlp)) - return 0; - return ndlp->nlp_rpi == *rpi; } @@ -6363,10 +6207,9 @@ lpfc_nlp_init(struct lpfc_vport *vport, uint32_t did) ndlp->nlp_rpi = rpi; lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_DISCOVERY, "0007 Init New ndlp x%px, rpi:x%x DID:%x " - "flg:x%x refcnt:%d map:x%x\n", + "flg:x%x refcnt:%d\n", ndlp, ndlp->nlp_rpi, ndlp->nlp_DID, - ndlp->nlp_flag, kref_read(&ndlp->kref), - ndlp->nlp_usg_map); + ndlp->nlp_flag, kref_read(&ndlp->kref)); ndlp->active_rrqs_xri_bitmap = mempool_alloc(vport->phba->active_rrq_pool, @@ -6391,8 +6234,6 @@ lpfc_nlp_init(struct lpfc_vport *vport, uint32_t did) static void lpfc_nlp_release(struct kref *kref) { - struct lpfc_hba *phba; - unsigned long flags; struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist, kref); @@ -6401,29 +6242,19 @@ lpfc_nlp_release(struct kref *kref) ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, - "0279 %s: ndlp:x%px did %x " - "usgmap:x%x refcnt:%d rpi:%x\n", - __func__, - (void *)ndlp, ndlp->nlp_DID, ndlp->nlp_usg_map, + "0279 %s: ndlp:x%px did %x refcnt:%d rpi:%x\n", + __func__, (void *)ndlp, ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp->nlp_rpi); /* remove ndlp from action. */ lpfc_nlp_remove(ndlp->vport, ndlp); - /* clear the ndlp active flag for all release cases */ - phba = ndlp->phba; - spin_lock_irqsave(&phba->ndlp_lock, flags); - NLP_CLR_NODE_ACT(ndlp); - spin_unlock_irqrestore(&phba->ndlp_lock, flags); - /* free ndlp memory for final ndlp release */ - if (NLP_CHK_FREE_REQ(ndlp)) { - kfree(ndlp->lat_data); - if (phba->sli_rev == LPFC_SLI_REV4) - mempool_free(ndlp->active_rrqs_xri_bitmap, - ndlp->phba->active_rrq_pool); - mempool_free(ndlp, ndlp->phba->nlp_mem_pool); - } + kfree(ndlp->lat_data); + if (ndlp->phba->sli_rev == LPFC_SLI_REV4) + mempool_free(ndlp->active_rrqs_xri_bitmap, + ndlp->phba->active_rrq_pool); + mempool_free(ndlp, ndlp->phba->nlp_mem_pool); } /* This routine bumps the reference count for a ndlp structure to ensure @@ -6441,94 +6272,44 @@ lpfc_nlp_get(struct lpfc_nodelist *ndlp) "node get: did:x%x flg:x%x refcnt:x%x", ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); + /* The check of ndlp usage to prevent incrementing the * ndlp reference count that is in the process of being * released. */ phba = ndlp->phba; spin_lock_irqsave(&phba->ndlp_lock, flags); - if (!NLP_CHK_NODE_ACT(ndlp) || NLP_CHK_FREE_ACK(ndlp)) { + if (!kref_get_unless_zero(&ndlp->kref)) { spin_unlock_irqrestore(&phba->ndlp_lock, flags); lpfc_printf_vlog(ndlp->vport, KERN_WARNING, LOG_NODE, - "0276 %s: ndlp:x%px " - "usgmap:x%x refcnt:%d\n", - __func__, (void *)ndlp, ndlp->nlp_usg_map, - kref_read(&ndlp->kref)); + "0276 %s: ndlp:x%px refcnt:%d\n", + __func__, (void *)ndlp, kref_read(&ndlp->kref)); return NULL; - } else - kref_get(&ndlp->kref); + } spin_unlock_irqrestore(&phba->ndlp_lock, flags); + } else { + WARN_ONCE(!ndlp, "**** %s, get ref on NULL ndlp!", __func__); } + return ndlp; } /* This routine decrements the reference count for a ndlp structure. If the - * count goes to 0, this indicates the the associated nodelist should be - * freed. Returning 1 indicates the ndlp resource has been released; on the - * other hand, returning 0 indicates the ndlp resource has not been released - * yet. + * count goes to 0, this indicates the associated nodelist should be freed. */ int lpfc_nlp_put(struct lpfc_nodelist *ndlp) { - struct lpfc_hba *phba; - unsigned long flags; - - if (!ndlp) - return 1; - - lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, - "node put: did:x%x flg:x%x refcnt:x%x", - ndlp->nlp_DID, ndlp->nlp_flag, - kref_read(&ndlp->kref)); - phba = ndlp->phba; - spin_lock_irqsave(&phba->ndlp_lock, flags); - /* Check the ndlp memory free acknowledge flag to avoid the - * possible race condition that kref_put got invoked again - * after previous one has done ndlp memory free. - */ - if (NLP_CHK_FREE_ACK(ndlp)) { - spin_unlock_irqrestore(&phba->ndlp_lock, flags); - lpfc_printf_vlog(ndlp->vport, KERN_WARNING, LOG_NODE, - "0274 %s: ndlp:x%px " - "usgmap:x%x refcnt:%d\n", - __func__, (void *)ndlp, ndlp->nlp_usg_map, - kref_read(&ndlp->kref)); - return 1; - } - /* Check the ndlp inactivate log flag to avoid the possible - * race condition that kref_put got invoked again after ndlp - * is already in inactivating state. - */ - if (NLP_CHK_IACT_REQ(ndlp)) { - spin_unlock_irqrestore(&phba->ndlp_lock, flags); - lpfc_printf_vlog(ndlp->vport, KERN_WARNING, LOG_NODE, - "0275 %s: ndlp:x%px " - "usgmap:x%x refcnt:%d\n", - __func__, (void *)ndlp, ndlp->nlp_usg_map, + if (ndlp) { + lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, + "node put: did:x%x flg:x%x refcnt:x%x", + ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); - return 1; + } else { + WARN_ONCE(!ndlp, "**** %s, put ref on NULL ndlp!", __func__); } - /* For last put, mark the ndlp usage flags to make sure no - * other kref_get and kref_put on the same ndlp shall get - * in between the process when the final kref_put has been - * invoked on this ndlp. - */ - if (kref_read(&ndlp->kref) == 1) { - /* Indicate ndlp is put to inactive state. */ - NLP_SET_IACT_REQ(ndlp); - /* Acknowledge ndlp memory free has been seen. */ - if (NLP_CHK_FREE_REQ(ndlp)) - NLP_SET_FREE_ACK(ndlp); - } - spin_unlock_irqrestore(&phba->ndlp_lock, flags); - /* Note, the kref_put returns 1 when decrementing a reference - * count that was 1, it invokes the release callback function, - * but it still left the reference count as 1 (not actually - * performs the last decrementation). Otherwise, it actually - * decrements the reference count and returns 0. - */ - return kref_put(&ndlp->kref, lpfc_nlp_release); + + return ndlp ? kref_put(&ndlp->kref, lpfc_nlp_release) : 0; } /* This routine free's the specified nodelist if it is not in use @@ -6588,7 +6369,7 @@ lpfc_fcf_inuse(struct lpfc_hba *phba) goto out; } list_for_each_entry(ndlp, &vports[i]->fc_nodes, nlp_listp) { - if (NLP_CHK_NODE_ACT(ndlp) && ndlp->rport && + if (ndlp->rport && (ndlp->rport->roles & FC_RPORT_ROLE_FCP_TARGET)) { ret = 1; spin_unlock_irq(shost->host_lock); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index aa7931a1750f..add2eb0d729b 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -2844,28 +2844,6 @@ lpfc_cleanup(struct lpfc_vport *vport) lpfc_port_link_failure(vport); list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp)) { - ndlp = lpfc_enable_node(vport, ndlp, - NLP_STE_UNUSED_NODE); - if (!ndlp) - continue; - spin_lock_irq(&phba->ndlp_lock); - NLP_SET_FREE_REQ(ndlp); - spin_unlock_irq(&phba->ndlp_lock); - /* Trigger the release of the ndlp memory */ - lpfc_nlp_put(ndlp); - continue; - } - spin_lock_irq(&phba->ndlp_lock); - if (NLP_CHK_FREE_REQ(ndlp)) { - /* The ndlp should not be in memory free mode already */ - spin_unlock_irq(&phba->ndlp_lock); - continue; - } else - /* Indicate request for freeing ndlp memory */ - NLP_SET_FREE_REQ(ndlp); - spin_unlock_irq(&phba->ndlp_lock); - if (vport->port_type != LPFC_PHYSICAL_PORT && ndlp->nlp_DID == Fabric_DID) { /* Just free up ndlp with Fabric_DID for vports */ @@ -2903,9 +2881,8 @@ lpfc_cleanup(struct lpfc_vport *vport) lpfc_printf_vlog(ndlp->vport, KERN_ERR, LOG_TRACE_EVENT, "0282 did:x%x ndlp:x%px " - "usgmap:x%x refcnt:%d\n", + "refcnt:%d\n", ndlp->nlp_DID, (void *)ndlp, - ndlp->nlp_usg_map, kref_read(&ndlp->kref)); } break; @@ -3080,7 +3057,6 @@ lpfc_sli4_node_prep(struct lpfc_hba *phba) struct lpfc_nodelist *ndlp, *next_ndlp; struct lpfc_vport **vports; int i, rpi; - unsigned long flags; if (phba->sli_rev != LPFC_SLI_REV4) return; @@ -3096,22 +3072,18 @@ lpfc_sli4_node_prep(struct lpfc_hba *phba) list_for_each_entry_safe(ndlp, next_ndlp, &vports[i]->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp)) - continue; rpi = lpfc_sli4_alloc_rpi(phba); if (rpi == LPFC_RPI_ALLOC_ERROR) { - spin_lock_irqsave(&phba->ndlp_lock, flags); - NLP_CLR_NODE_ACT(ndlp); - spin_unlock_irqrestore(&phba->ndlp_lock, flags); + /* TODO print log? */ continue; } ndlp->nlp_rpi = rpi; lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE | LOG_DISCOVERY, "0009 Assign RPI x%x to ndlp x%px " - "DID:x%06x flg:x%x map:x%x\n", + "DID:x%06x flg:x%x\n", ndlp->nlp_rpi, ndlp, ndlp->nlp_DID, - ndlp->nlp_flag, ndlp->nlp_usg_map); + ndlp->nlp_flag); } } lpfc_destroy_vport_work_array(phba, vports); @@ -3510,8 +3482,7 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) list_for_each_entry_safe(ndlp, next_ndlp, &vports[i]->fc_nodes, nlp_listp) { - if ((!NLP_CHK_NODE_ACT(ndlp)) || - ndlp->nlp_state == NLP_STE_UNUSED_NODE) { + if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) { /* Driver must assume RPI is invalid for * any unused or inactive node. */ @@ -3519,12 +3490,6 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) continue; } - if (ndlp->nlp_type & NLP_FABRIC) { - lpfc_disc_state_machine(vports[i], ndlp, - NULL, NLP_EVT_DEVICE_RECOVERY); - lpfc_disc_state_machine(vports[i], ndlp, - NULL, NLP_EVT_DEVICE_RM); - } spin_lock_irq(shost->host_lock); ndlp->nlp_flag &= ~NLP_NPR_ADISC; spin_unlock_irq(shost->host_lock); @@ -3537,15 +3502,20 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE | LOG_DISCOVERY, "0011 Free RPI x%x on " - "ndlp:x%px did x%x " - "usgmap:x%x\n", + "ndlp:x%px did x%x\n", ndlp->nlp_rpi, ndlp, - ndlp->nlp_DID, - ndlp->nlp_usg_map); + ndlp->nlp_DID); lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi); ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR; } lpfc_unreg_rpi(vports[i], ndlp); + + if (ndlp->nlp_type & NLP_FABRIC) { + lpfc_disc_state_machine(vports[i], ndlp, + NULL, NLP_EVT_DEVICE_RECOVERY); + lpfc_disc_state_machine(vports[i], ndlp, + NULL, NLP_EVT_DEVICE_RM); + } } } } @@ -5604,11 +5574,6 @@ lpfc_sli4_perform_vport_cvl(struct lpfc_vport *vport) ndlp->nlp_type |= NLP_FABRIC; /* Put ndlp onto node list */ lpfc_enqueue_node(vport, ndlp); - } else if (!NLP_CHK_NODE_ACT(ndlp)) { - /* re-setup ndlp without removing from node list */ - ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); - if (!ndlp) - return 0; } if ((phba->pport->port_state < LPFC_FLOGI) && (phba->pport->port_state != LPFC_VPORT_FAILED)) diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 92d6e7b98770..16a37c2153ae 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -1907,7 +1907,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport, /* software abort if any GID_FT is outstanding */ if (vport->cfg_enable_fc4_type != LPFC_ENABLE_FCP) { ns_ndlp = lpfc_findnode_did(vport, NameServer_DID); - if (ns_ndlp && NLP_CHK_NODE_ACT(ns_ndlp)) + if (ns_ndlp) lpfc_els_abort(phba, ns_ndlp); } diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 42eb144fed0d..042a3b9bfc80 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -694,7 +694,7 @@ __lpfc_nvme_ls_req(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int ret; uint16_t ntype, nstate; - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { + if (!ndlp) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6051 NVMEx LS REQ: Bad NDLP x%px, Failing " "LS Req\n", @@ -1131,7 +1131,7 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, * transport is still transitioning. */ ndlp = lpfc_ncmd->ndlp; - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { + if (!ndlp) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6062 Ignoring NVME cmpl. No ndlp\n"); goto out_err; @@ -1313,9 +1313,6 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport, union lpfc_wqe128 *wqe = &pwqeq->wqe; uint32_t req_len; - if (!NLP_CHK_NODE_ACT(pnode)) - return -EINVAL; - /* * There are three possibilities here - use scatter-gather segment, use * the single mapping, or neither. @@ -1665,7 +1662,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport, * transport is still transitioning. */ ndlp = rport->ndlp; - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { + if (!ndlp) { lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_NVME_IOERR, "6053 Busy IO, ndlp not ready: rport x%px " "ndlp x%px, DID x%06x\n", @@ -2496,8 +2493,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) * reference would cause a premature cleanup. */ if (prev_ndlp && prev_ndlp != ndlp) { - if ((!NLP_CHK_NODE_ACT(prev_ndlp)) || - (!prev_ndlp->nrport)) + if (!prev_ndlp->nrport) lpfc_nlp_put(prev_ndlp); } } diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 675253093e87..78b934b021aa 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -1806,7 +1806,7 @@ lpfc_sli4_nvmet_xri_aborted(struct lpfc_hba *phba, rrq_empty = list_empty(&phba->active_rrq_list); spin_unlock_irqrestore(&phba->hbalock, iflag); ndlp = lpfc_findnode_did(phba->pport, ctxp->sid); - if (ndlp && NLP_CHK_NODE_ACT(ndlp) && + if (ndlp && (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE || ndlp->nlp_state == NLP_STE_MAPPED_NODE)) { lpfc_set_rrq_active(phba, ndlp, @@ -2596,7 +2596,7 @@ lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *phba, } ndlp = lpfc_findnode_did(phba->pport, ctxp->sid); - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || + if (!ndlp || ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && (ndlp->nlp_state != NLP_STE_MAPPED_NODE))) { lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, @@ -2716,7 +2716,7 @@ lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba, } ndlp = lpfc_findnode_did(phba->pport, ctxp->sid); - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || + if (!ndlp || ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && (ndlp->nlp_state != NLP_STE_MAPPED_NODE))) { lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, @@ -3248,7 +3248,7 @@ lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba, tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private; ndlp = lpfc_findnode_did(phba->pport, sid); - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || + if (!ndlp || ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && (ndlp->nlp_state != NLP_STE_MAPPED_NODE))) { if (tgtp) @@ -3346,7 +3346,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba, } ndlp = lpfc_findnode_did(phba->pport, sid); - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || + if (!ndlp || ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && (ndlp->nlp_state != NLP_STE_MAPPED_NODE))) { atomic_inc(&tgtp->xmt_abort_rsp_error); diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 0f0ab86cf192..d22ede4b9d74 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -3505,7 +3505,7 @@ lpfc_send_scsi_error_event(struct lpfc_hba *phba, struct lpfc_vport *vport, struct lpfc_nodelist *pnode = lpfc_cmd->rdata->pnode; unsigned long flags; - if (!pnode || !NLP_CHK_NODE_ACT(pnode)) + if (!pnode) return; /* If there is queuefull or busy condition send a scsi event */ @@ -3925,7 +3925,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, fast_path_evt->un.fabric_evt.subcategory = (lpfc_cmd->status == IOSTAT_NPORT_BSY) ? LPFC_EVENT_PORT_BUSY : LPFC_EVENT_FABRIC_BUSY; - if (pnode && NLP_CHK_NODE_ACT(pnode)) { + if (pnode) { memcpy(&fast_path_evt->un.fabric_evt.wwpn, &pnode->nlp_portname, sizeof(struct lpfc_name)); @@ -3980,7 +3980,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, } if ((lpfc_cmd->status == IOSTAT_REMOTE_STOP) && (phba->sli_rev == LPFC_SLI_REV4) - && (pnode && NLP_CHK_NODE_ACT(pnode))) { + && pnode) { /* This IO was aborted by the target, we don't * know the rxid and because we did not send the * ABTS we cannot generate and RRQ. @@ -3995,8 +3995,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, break; } - if (!pnode || !NLP_CHK_NODE_ACT(pnode) - || (pnode->nlp_state != NLP_STE_MAPPED_NODE)) + if (!pnode || (pnode->nlp_state != NLP_STE_MAPPED_NODE)) cmd->result = DID_TRANSPORT_DISRUPTED << 16 | SAM_STAT_BUSY; } else @@ -4018,7 +4017,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, time_after(jiffies, lpfc_cmd->start_time + msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) { spin_lock_irqsave(shost->host_lock, flags); - if (pnode && NLP_CHK_NODE_ACT(pnode)) { + if (pnode) { if (pnode->cmd_qdepth > atomic_read(&pnode->cmd_pending) && (atomic_read(&pnode->cmd_pending) > @@ -4104,7 +4103,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, bool sli4; uint32_t fcpdl; - if (!pnode || !NLP_CHK_NODE_ACT(pnode)) + if (!pnode) return; lpfc_cmd->fcp_rsp->rspSnsLen = 0; @@ -4215,8 +4214,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, struct lpfc_rport_data *rdata = lpfc_cmd->rdata; struct lpfc_nodelist *ndlp = rdata->pnode; - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || - ndlp->nlp_state != NLP_STE_MAPPED_NODE) + if (!ndlp || ndlp->nlp_state != NLP_STE_MAPPED_NODE) return 0; piocbq = &(lpfc_cmd->cur_iocbq); @@ -4551,7 +4549,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) * Catch race where our node has transitioned, but the * transport is still transitioning. */ - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) + if (!ndlp) goto out_tgt_busy; if (lpfc_ndlp_check_qdepth(phba, ndlp)) { if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) { @@ -5050,7 +5048,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct scsi_cmnd *cmnd, int status; rdata = lpfc_rport_data_from_scsi_device(cmnd->device); - if (!rdata || !rdata->pnode || !NLP_CHK_NODE_ACT(rdata->pnode)) + if (!rdata || !rdata->pnode) return FAILED; pnode = rdata->pnode; @@ -5154,7 +5152,7 @@ lpfc_chk_tgt_mapped(struct lpfc_vport *vport, struct scsi_cmnd *cmnd) */ later = msecs_to_jiffies(2 * vport->cfg_devloss_tmo * 1000) + jiffies; while (time_after(later, jiffies)) { - if (!pnode || !NLP_CHK_NODE_ACT(pnode)) + if (!pnode) return FAILED; if (pnode->nlp_state == NLP_STE_MAPPED_NODE) return SUCCESS; @@ -5164,8 +5162,7 @@ lpfc_chk_tgt_mapped(struct lpfc_vport *vport, struct scsi_cmnd *cmnd) return FAILED; pnode = rdata->pnode; } - if (!pnode || !NLP_CHK_NODE_ACT(pnode) || - (pnode->nlp_state != NLP_STE_MAPPED_NODE)) + if (!pnode || (pnode->nlp_state != NLP_STE_MAPPED_NODE)) return FAILED; return SUCCESS; } @@ -5409,8 +5406,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd) match = 0; spin_lock_irq(shost->host_lock); list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp)) - continue; + if (vport->phba->cfg_fcp2_no_tgt_reset && (ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE)) continue; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index eaa5fb5ea079..4974bf671063 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -860,7 +860,7 @@ lpfc_clr_rrq_active(struct lpfc_hba *phba, { struct lpfc_nodelist *ndlp = NULL; - if ((rrq->vport) && NLP_CHK_NODE_ACT(rrq->ndlp)) + if (rrq->vport) ndlp = lpfc_findnode_did(rrq->vport, rrq->nlp_DID); /* The target DID could have been swapped (cable swap) @@ -1061,12 +1061,6 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, goto out; } - /* - * set the active bit even if there is no mem available. - */ - if (NLP_CHK_FREE_REQ(ndlp)) - goto out; - if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING)) goto out; @@ -1289,6 +1283,11 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) (sglq->state != SGL_XRI_ABORTED)) { spin_lock_irqsave(&phba->sli4_hba.sgl_list_lock, iflag); + + /* Check if we can get a reference on ndlp */ + if (sglq->ndlp && !lpfc_nlp_get(sglq->ndlp)) + sglq->ndlp = NULL; + list_add(&sglq->list, &phba->sli4_hba.lpfc_abts_els_sgl_list); spin_unlock_irqrestore( @@ -2589,11 +2588,11 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) vport, KERN_INFO, LOG_MBOX | LOG_SLI, "0010 UNREG_LOGIN vpi:%x " "rpi:%x DID:%x defer x%x flg x%x " - "map:%x %px\n", + "%px\n", vport->vpi, ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_defer_did, ndlp->nlp_flag, - ndlp->nlp_usg_map, ndlp); + ndlp); ndlp->nlp_flag &= ~NLP_LOGO_ACC; lpfc_nlp_put(ndlp); @@ -2852,7 +2851,7 @@ lpfc_nvme_unsol_ls_handler(struct lpfc_hba *phba, struct lpfc_iocbq *piocb) /* validate the source of the LS is logged in */ ndlp = lpfc_findnode_did(phba->pport, sid); - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || + if (!ndlp || ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && (ndlp->nlp_state != NLP_STE_MAPPED_NODE))) { lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC, @@ -10426,7 +10425,7 @@ lpfc_sli_abts_err_handler(struct lpfc_hba *phba, if (!vport) goto err_exit; ndlp = lpfc_findnode_rpi(vport, rpi); - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) + if (!ndlp) goto err_exit; if (iocbq->iocb.ulpStatus == IOSTAT_LOCAL_REJECT) @@ -10459,7 +10458,7 @@ lpfc_sli4_abts_err_handler(struct lpfc_hba *phba, struct lpfc_vport *vport; uint32_t ext_status = 0; - if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { + if (!ndlp) { lpfc_printf_log(phba, KERN_INFO, LOG_SLI, "3115 Node Context not found, driver " "ignoring abts err event\n"); @@ -17901,15 +17900,6 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport, } /* Put ndlp onto pport node list */ lpfc_enqueue_node(vport, ndlp); - } else if (!NLP_CHK_NODE_ACT(ndlp)) { - /* re-setup ndlp without removing from node list */ - ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); - if (!ndlp) { - lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, - "3275 Failed to active ndlp found " - "for oxid:x%x SID:x%x\n", oxid, sid); - return; - } } /* Allocate buffer for rsp iocb */ diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index aa4e451d5dc1..6ab78131b94d 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -462,7 +462,7 @@ lpfc_vport_create(struct fc_vport *fc_vport, bool disable) * up and ready to FDISC. */ ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); - if (ndlp && NLP_CHK_NODE_ACT(ndlp) && + if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) { lpfc_set_disctmo(vport); @@ -495,8 +495,7 @@ disable_vport(struct fc_vport *fc_vport) struct Scsi_Host *shost = lpfc_shost_from_vport(vport); ndlp = lpfc_findnode_did(vport, Fabric_DID); - if (ndlp && NLP_CHK_NODE_ACT(ndlp) - && phba->link_state >= LPFC_LINK_UP) { + if (ndlp && phba->link_state >= LPFC_LINK_UP) { vport->unreg_vpi_cmpl = VPORT_INVAL; timeout = msecs_to_jiffies(phba->fc_ratov * 2000); if (!lpfc_issue_els_npiv_logo(vport, ndlp)) @@ -510,8 +509,6 @@ disable_vport(struct fc_vport *fc_vport) * calling lpfc_cleanup_rpis(vport, 1) */ list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp)) - continue; if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) continue; lpfc_disc_state_machine(vport, ndlp, NULL, @@ -568,8 +565,7 @@ enable_vport(struct fc_vport *fc_vport) * up and ready to FDISC. */ ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); - if (ndlp && NLP_CHK_NODE_ACT(ndlp) - && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { + if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) { lpfc_set_disctmo(vport); lpfc_initial_fdisc(vport); @@ -663,7 +659,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport) * being released. */ ndlp = lpfc_findnode_did(vport, NameServer_DID); - if (ndlp && NLP_CHK_NODE_ACT(ndlp)) { + if (ndlp) { lpfc_nlp_get(ndlp); ns_ndlp_referenced = true; } @@ -679,26 +675,16 @@ lpfc_vport_delete(struct fc_vport *fc_vport) * can safely skip the fabric logo. */ if (phba->pport->load_flag & FC_UNLOADING) { - if (ndlp && NLP_CHK_NODE_ACT(ndlp) && - ndlp->nlp_state == NLP_STE_UNMAPPED_NODE && + if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE && phba->link_state >= LPFC_LINK_UP) { /* First look for the Fabric ndlp */ ndlp = lpfc_findnode_did(vport, Fabric_DID); if (!ndlp) goto skip_logo; - else if (!NLP_CHK_NODE_ACT(ndlp)) { - ndlp = lpfc_enable_node(vport, ndlp, - NLP_STE_UNUSED_NODE); - if (!ndlp) - goto skip_logo; - } + /* Remove ndlp from vport npld list */ lpfc_dequeue_node(vport, ndlp); - /* Indicate free memory when release */ - spin_lock_irq(&phba->ndlp_lock); - NLP_SET_FREE_REQ(ndlp); - spin_unlock_irq(&phba->ndlp_lock); /* Kick off release ndlp when it can be safely done */ lpfc_nlp_put(ndlp); } @@ -706,8 +692,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport) } /* Otherwise, we will perform fabric logo as needed */ - if (ndlp && NLP_CHK_NODE_ACT(ndlp) && - ndlp->nlp_state == NLP_STE_UNMAPPED_NODE && + if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE && phba->link_state >= LPFC_LINK_UP && phba->fc_topology != LPFC_TOPOLOGY_LOOP) { if (vport->cfg_enable_da_id) { @@ -728,28 +713,6 @@ lpfc_vport_delete(struct fc_vport *fc_vport) ndlp = lpfc_nlp_init(vport, Fabric_DID); if (!ndlp) goto skip_logo; - /* Indicate free memory when release */ - NLP_SET_FREE_REQ(ndlp); - } else { - if (!NLP_CHK_NODE_ACT(ndlp)) { - ndlp = lpfc_enable_node(vport, ndlp, - NLP_STE_UNUSED_NODE); - if (!ndlp) - goto skip_logo; - } - - /* Remove ndlp from vport list */ - lpfc_dequeue_node(vport, ndlp); - spin_lock_irq(&phba->ndlp_lock); - if (!NLP_CHK_FREE_REQ(ndlp)) - /* Indicate free memory when release */ - NLP_SET_FREE_REQ(ndlp); - else { - /* Skip this if ndlp is already in free mode */ - spin_unlock_irq(&phba->ndlp_lock); - goto skip_logo; - } - spin_unlock_irq(&phba->ndlp_lock); } /* @@ -865,8 +828,6 @@ lpfc_vport_reset_stat_data(struct lpfc_vport *vport) struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL; list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp)) - continue; if (ndlp->lat_data) memset(ndlp->lat_data, 0, LPFC_MAX_BUCKET_COUNT * sizeof(struct lpfc_scsicmd_bkt)); @@ -887,8 +848,6 @@ lpfc_alloc_bucket(struct lpfc_vport *vport) struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL; list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp)) - continue; kfree(ndlp->lat_data); ndlp->lat_data = NULL; @@ -921,8 +880,6 @@ lpfc_free_bucket(struct lpfc_vport *vport) struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL; list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { - if (!NLP_CHK_NODE_ACT(ndlp)) - continue; kfree(ndlp->lat_data); ndlp->lat_data = NULL; -- cgit v1.2.3 From 4430f7fd09ecb037570119e0aacbf0c17b8f98b2 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:31 -0800 Subject: scsi: lpfc: Rework locations of ndlp reference taking Now that the driver has gone to a normal ref interface (with no odd logic) the discovery logic needs to be updated to reworked so that it properly takes references when it should and give them up when it should. Rework the driver for the following get/put model: - Move gets to just before an I/O is issued. Add gets for places where an I/O was issued without one. - Ensure that failures from lpfc_nlp_get() are handled by the driver. - Check and fix the placement of lpfc_nlp_puts relative to io completions. Note: some of these paths may not release the reference on the exact io completion as the reference is held as the code takes another step in the discovery thread and which may cause another io to be issued. - Rearrange some code for error processing and calling lpfc_nlp_put. - Fix some places of incorrect reference freeing that was causing the premature releasing of the structure. - Nvmet plogi handling performs unreg_rpi's. The reference counts were unbalanced resulting in premature node removal. In some cases this caused loss of node discovery. Corrected the reftaking around nvmet plogis. Nodes that experience devloss now get released from the node list now that there is a proper reference taking. Link: https://lore.kernel.org/r/20201115192646.12977-3-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_bsg.c | 71 ++-- drivers/scsi/lpfc/lpfc_ct.c | 56 +-- drivers/scsi/lpfc/lpfc_disc.h | 3 +- drivers/scsi/lpfc/lpfc_els.c | 693 ++++++++++++++++++++++++------------- drivers/scsi/lpfc/lpfc_hbadisc.c | 12 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 28 +- drivers/scsi/lpfc/lpfc_nvme.c | 13 +- drivers/scsi/lpfc/lpfc_sli.c | 9 +- 8 files changed, 569 insertions(+), 316 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index bb15787c8f20..6bbdfaf6ddfe 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -329,7 +329,7 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, spin_unlock_irqrestore(&phba->hbalock, flags); iocb = &dd_data->context_un.iocb; - ndlp = iocb->ndlp; + ndlp = iocb->cmdiocbq->context_un.ndlp; rmp = iocb->rmp; cmp = cmdiocbq->context2; bmp = cmdiocbq->context3; @@ -366,8 +366,8 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba, lpfc_free_bsg_buffers(phba, rmp); lpfc_mbuf_free(phba, bmp->virt, bmp->phys); kfree(bmp); - lpfc_sli_release_iocbq(phba, cmdiocbq); lpfc_nlp_put(ndlp); + lpfc_sli_release_iocbq(phba, cmdiocbq); kfree(dd_data); /* Complete the job if the job is still active */ @@ -408,6 +408,9 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job) /* in case no data is transferred */ bsg_reply->reply_payload_rcv_len = 0; + if (ndlp->nlp_flag & NLP_ELS_SND_MASK) + return -ENODEV; + /* allocate our bsg tracking structure */ dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); if (!dd_data) { @@ -417,20 +420,10 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job) goto no_dd_data; } - if (!lpfc_nlp_get(ndlp)) { - rc = -ENODEV; - goto no_ndlp; - } - - if (ndlp->nlp_flag & NLP_ELS_SND_MASK) { - rc = -ENODEV; - goto free_ndlp; - } - cmdiocbq = lpfc_sli_get_iocbq(phba); if (!cmdiocbq) { rc = -ENOMEM; - goto free_ndlp; + goto free_dd; } cmd = &cmdiocbq->iocb; @@ -496,11 +489,10 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job) cmdiocbq->context1 = dd_data; cmdiocbq->context2 = cmp; cmdiocbq->context3 = bmp; - cmdiocbq->context_un.ndlp = ndlp; + dd_data->type = TYPE_IOCB; dd_data->set_job = job; dd_data->context_un.iocb.cmdiocbq = cmdiocbq; - dd_data->context_un.iocb.ndlp = ndlp; dd_data->context_un.iocb.rmp = rmp; job->dd_data = dd_data; @@ -514,8 +506,13 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job) readl(phba->HCregaddr); /* flush */ } - iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0); + cmdiocbq->context_un.ndlp = lpfc_nlp_get(ndlp); + if (!cmdiocbq->context_un.ndlp) { + rc = -ENODEV; + goto free_rmp; + } + iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0); if (iocb_stat == IOCB_SUCCESS) { spin_lock_irqsave(&phba->hbalock, flags); /* make sure the I/O had not been completed yet */ @@ -532,7 +529,7 @@ lpfc_bsg_send_mgmt_cmd(struct bsg_job *job) } /* iocb failed so cleanup */ - job->dd_data = NULL; + lpfc_nlp_put(ndlp); free_rmp: lpfc_free_bsg_buffers(phba, rmp); @@ -544,9 +541,7 @@ free_bmp: kfree(bmp); free_cmdiocbq: lpfc_sli_release_iocbq(phba, cmdiocbq); -free_ndlp: - lpfc_nlp_put(ndlp); -no_ndlp: +free_dd: kfree(dd_data); no_dd_data: /* make error code available to userspace */ @@ -640,8 +635,9 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba, } } - lpfc_nlp_put(ndlp); lpfc_els_free_iocb(phba, cmdiocbq); + + lpfc_nlp_put(ndlp); kfree(dd_data); /* Complete the job if the job is still active */ @@ -718,15 +714,14 @@ lpfc_bsg_rport_els(struct bsg_job *job) goto release_ndlp; } - rpi = ndlp->nlp_rpi; - /* Transfer the request payload to allocated command dma buffer */ - sg_copy_to_buffer(job->request_payload.sg_list, job->request_payload.sg_cnt, ((struct lpfc_dmabuf *)cmdiocbq->context2)->virt, cmdsize); + rpi = ndlp->nlp_rpi; + if (phba->sli_rev == LPFC_SLI_REV4) cmdiocbq->iocb.ulpContext = phba->sli4_hba.rpi_ids[rpi]; else @@ -752,8 +747,13 @@ lpfc_bsg_rport_els(struct bsg_job *job) readl(phba->HCregaddr); /* flush */ } - rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0); + cmdiocbq->context1 = lpfc_nlp_get(ndlp); + if (!cmdiocbq->context1) { + rc = -EIO; + goto linkdown_err; + } + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0); if (rc == IOCB_SUCCESS) { spin_lock_irqsave(&phba->hbalock, flags); /* make sure the I/O had not been completed/released */ @@ -769,11 +769,9 @@ lpfc_bsg_rport_els(struct bsg_job *job) rc = -EIO; } - /* iocb failed so cleanup */ - job->dd_data = NULL; + /* I/O issue failed. Cleanup resources. */ linkdown_err: - cmdiocbq->context1 = ndlp; lpfc_els_free_iocb(phba, cmdiocbq); release_ndlp: @@ -1469,6 +1467,15 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag, unsigned long flags; uint32_t creg_val; + ndlp = lpfc_findnode_did(phba->pport, phba->ct_ctx[tag].SID); + if (!ndlp) { + lpfc_printf_log(phba, KERN_WARNING, LOG_ELS, + "2721 ndlp null for oxid %x SID %x\n", + phba->ct_ctx[tag].rxid, + phba->ct_ctx[tag].SID); + return IOCB_ERROR; + } + /* allocate our bsg tracking structure */ dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL); if (!dd_data) { @@ -1559,7 +1566,11 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag, dd_data->type = TYPE_IOCB; dd_data->set_job = job; dd_data->context_un.iocb.cmdiocbq = ctiocb; - dd_data->context_un.iocb.ndlp = ndlp; + dd_data->context_un.iocb.ndlp = lpfc_nlp_get(ndlp); + if (!dd_data->context_un.iocb.ndlp) { + rc = -IOCB_ERROR; + goto issue_ct_rsp_exit; + } dd_data->context_un.iocb.rmp = NULL; job->dd_data = dd_data; @@ -1574,7 +1585,6 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag, } rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0); - if (rc == IOCB_SUCCESS) { spin_lock_irqsave(&phba->hbalock, flags); /* make sure the I/O had not been completed/released */ @@ -1588,6 +1598,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag, /* iocb failed so cleanup */ job->dd_data = NULL; + lpfc_nlp_put(ndlp); issue_ct_rsp_exit: lpfc_sli_release_iocbq(phba, ctiocb); diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 32f5d8951b8f..9a492aa284f9 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -548,10 +548,8 @@ lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb) { struct lpfc_dmabuf *buf_ptr; - if (ctiocb->context_un.ndlp) { - lpfc_nlp_put(ctiocb->context_un.ndlp); - ctiocb->context_un.ndlp = NULL; - } + /* I/O job is complete so context is now invalid*/ + ctiocb->context_un.ndlp = NULL; if (ctiocb->context1) { buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1; lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys); @@ -618,7 +616,6 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, /* Save for completion so we can release these resources */ geniocb->context1 = (uint8_t *) inp; geniocb->context2 = (uint8_t *) outp; - geniocb->context_un.ndlp = lpfc_nlp_get(ndlp); /* Fill in payload, bp points to frame payload */ icmd->ulpCommand = CMD_GEN_REQUEST64_CR; @@ -657,16 +654,21 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT; geniocb->vport = vport; geniocb->retry = retry; + geniocb->context_un.ndlp = lpfc_nlp_get(ndlp); + if (!geniocb->context_un.ndlp) + goto out; rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, geniocb, 0); if (rc == IOCB_ERROR) { geniocb->context_un.ndlp = NULL; lpfc_nlp_put(ndlp); - lpfc_sli_release_iocbq(phba, geniocb); - return 1; + goto out; } return 0; +out: + lpfc_sli_release_iocbq(phba, geniocb); + return 1; } /* @@ -1134,8 +1136,8 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_disc_start(vport); } out: - cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */ lpfc_ct_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); return; } @@ -1341,8 +1343,8 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_disc_start(vport); } out: - cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */ lpfc_ct_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); } static void @@ -1357,7 +1359,7 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_sli_ct_request *CTrsp; int did, rc, retry; uint8_t fbits; - struct lpfc_nodelist *ndlp; + struct lpfc_nodelist *ndlp = NULL, *free_ndlp = NULL; did = ((struct lpfc_sli_ct_request *) inp->virt)->un.gff.PortId; did = be32_to_cpu(did); @@ -1423,7 +1425,9 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, cmdiocb->retry, did); if (rc == 0) { /* success */ + free_ndlp = cmdiocb->context_un.ndlp; lpfc_ct_free_iocb(phba, cmdiocb); + lpfc_nlp_put(free_ndlp); return; } } @@ -1476,7 +1480,10 @@ out: } lpfc_disc_start(vport); } + + free_ndlp = cmdiocb->context_un.ndlp; lpfc_ct_free_iocb(phba, cmdiocb); + lpfc_nlp_put(free_ndlp); return; } @@ -1490,7 +1497,8 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *)cmdiocb->context2; struct lpfc_sli_ct_request *CTrsp; int did; - struct lpfc_nodelist *ndlp; + struct lpfc_nodelist *ndlp = NULL; + struct lpfc_nodelist *ns_ndlp = NULL; uint32_t fc4_data_0, fc4_data_1; did = ((struct lpfc_sli_ct_request *)inp->virt)->un.gft.PortId; @@ -1500,6 +1508,9 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "GFT_ID cmpl: status:x%x/x%x did:x%x", irsp->ulpStatus, irsp->un.ulpWord[4], did); + /* Preserve the nameserver node to release the reference. */ + ns_ndlp = cmdiocb->context_un.ndlp; + if (irsp->ulpStatus == IOSTAT_SUCCESS) { /* Good status, continue checking */ CTrsp = (struct lpfc_sli_ct_request *)outp->virt; @@ -1515,6 +1526,10 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, (fc4_data_1 & LPFC_FC4_TYPE_BITMASK) ? "NVME" : " "); + /* Lookup the NPort_ID queried in the GFT_ID and find the + * driver's local node. It's an error if the driver + * doesn't have one. + */ ndlp = lpfc_findnode_did(vport, did); if (ndlp) { /* The bitmask value for FCP and NVME FCP types is @@ -1560,6 +1575,7 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "3065 GFT_ID failed x%08x\n", irsp->ulpStatus); lpfc_ct_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ns_ndlp); } static void @@ -1629,8 +1645,8 @@ lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } out: - cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */ lpfc_ct_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); return; } @@ -2113,11 +2129,6 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, } rc=6; - /* Decrement ndlp reference count to release ndlp reference held - * for the failed command's callback function. - */ - lpfc_nlp_put(ndlp); - ns_cmd_free_bmpvirt: lpfc_mbuf_free(phba, bmp->virt, bmp->phys); ns_cmd_free_bmp: @@ -2154,7 +2165,7 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp; uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp; IOCB_t *irsp = &rspiocb->iocb; - struct lpfc_nodelist *ndlp; + struct lpfc_nodelist *ndlp, *free_ndlp = NULL; uint32_t latt, cmd, err; latt = lpfc_els_chk_latt(vport); @@ -2200,7 +2211,10 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, be16_to_cpu(fdmi_cmd), latt, irsp->ulpStatus, irsp->un.ulpWord[4]); } + + free_ndlp = cmdiocb->context_un.ndlp; lpfc_ct_free_iocb(phba, cmdiocb); + lpfc_nlp_put(free_ndlp); ndlp = lpfc_findnode_did(vport, FDMI_DID); if (!ndlp) @@ -3582,12 +3596,6 @@ port_out: if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, 0)) return 0; - /* - * Decrement ndlp reference count to release ndlp reference held - * for the failed command's callback function. - */ - lpfc_nlp_put(ndlp); - fdmi_cmd_free_bmpvirt: lpfc_mbuf_free(phba, bmp->virt, bmp->phys); fdmi_cmd_free_bmp: diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index f8ab001e4f0d..09d4ec2a20db 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h @@ -166,8 +166,7 @@ struct lpfc_node_rrq { #define NLP_NVMET_RECOV 0x00001000 /* NVMET auditing node for recovery. */ #define NLP_FCP_PRLI_RJT 0x00002000 /* Rport does not support FCP PRLI. */ #define NLP_UNREG_INP 0x00008000 /* UNREG_RPI cmd is in progress */ -#define NLP_DEFER_RM 0x00010000 /* Remove this ndlp if no longer used */ -#define NLP_DROPPED 0x00000008 /* Init ref count has been dropped */ +#define NLP_DROPPED 0x00010000 /* Init ref count has been dropped */ #define NLP_DELAY_TMO 0x00020000 /* delay timeout is running for node */ #define NLP_NPR_2B_DISC 0x00040000 /* node is included in num_disc_nodes */ #define NLP_RCV_PLOGI 0x00080000 /* Rcv'ed PLOGI from remote system */ diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 9cf0e9d55cdf..44e99e7872f3 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -300,10 +300,6 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, bpl->tus.w = le32_to_cpu(bpl->tus.w); } - /* prevent preparing iocb with NULL ndlp reference */ - elsiocb->context1 = lpfc_nlp_get(ndlp); - if (!elsiocb->context1) - goto els_iocb_free_pbuf_exit; elsiocb->context2 = pcmd; elsiocb->context3 = pbuflist; elsiocb->retry = retry; @@ -418,10 +414,14 @@ lpfc_issue_fabric_reglogin(struct lpfc_vport *vport) * for the callback routine. */ mbox->ctx_ndlp = lpfc_nlp_get(ndlp); + if (!mbox->ctx_ndlp) { + err = 6; + goto fail_no_ndlp; + } rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); if (rc == MBX_NOT_FINISHED) { - err = 6; + err = 7; goto fail_issue_reg_login; } @@ -432,6 +432,7 @@ fail_issue_reg_login: * for the failed mbox command. */ lpfc_nlp_put(ndlp); +fail_no_ndlp: mp = (struct lpfc_dmabuf *)mbox->ctx_buf; lpfc_mbuf_free(phba, mp->virt, mp->phys); kfree(mp); @@ -1088,6 +1089,7 @@ stop_rr_fcf_flogi: /* Do not register VFI if the driver aborted FLOGI */ if (!lpfc_error_lost_link(irsp)) lpfc_issue_reg_vfi(vport); + lpfc_nlp_put(ndlp); goto out; } @@ -1149,6 +1151,7 @@ stop_rr_fcf_flogi: phba->fcf.current_rec.fabric_name[5], phba->fcf.current_rec.fabric_name[6], phba->fcf.current_rec.fabric_name[7]); + lpfc_nlp_put(ndlp); spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag &= ~FCF_DISCOVERY; @@ -1180,7 +1183,6 @@ flogifail: spin_unlock_irq(&phba->hbalock); lpfc_nlp_put(ndlp); - if (!lpfc_error_lost_link(irsp)) { /* FLOGI failed, so just use loop map to make discovery list */ lpfc_disc_list_loopmap(vport); @@ -1198,6 +1200,7 @@ flogifail: } out: lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); } /** @@ -1337,7 +1340,13 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, "Issue FLOGI: opt:x%x", phba->sli3_options, 0, 0); + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto out; + rc = lpfc_issue_fabric_iocb(phba, elsiocb); + if (rc == IOCB_ERROR) + lpfc_nlp_put(ndlp); phba->hba_flag |= HBA_FLOGI_ISSUED; @@ -1367,11 +1376,11 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, vport->fc_myDID = did; } - if (rc == IOCB_ERROR) { - lpfc_els_free_iocb(phba, elsiocb); - return 1; - } - return 0; + if (!rc) + return 0; + out: + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -1922,7 +1931,9 @@ lpfc_cmpl_els_rrq(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, out: if (rrq) lpfc_clr_rrq_active(phba, rrq->xritag, rrq); + lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); return; } /** @@ -1952,7 +1963,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_vport *vport = cmdiocb->vport; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); IOCB_t *irsp; - struct lpfc_nodelist *ndlp; + struct lpfc_nodelist *ndlp, *free_ndlp; struct lpfc_dmabuf *prsp; int disc; @@ -2049,7 +2060,15 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } out: + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_NODE, + "PLOGI Cmpl PUT: did:x%x refcnt %d", + ndlp->nlp_DID, kref_read(&ndlp->kref), 0); + + /* Release the reference on the original I/O request. */ + free_ndlp = (struct lpfc_nodelist *)cmdiocb->context1; + lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(free_ndlp); return; } @@ -2161,13 +2180,24 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) phba->fc_stat.elsXmitPLOGI++; elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi; - ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); - if (ret == IOCB_ERROR) { - lpfc_els_free_iocb(phba, elsiocb); - return 1; + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "Issue PLOGI: did:x%x refcnt %d", + did, kref_read(&ndlp->kref), 0); + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto io_err; + + ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (ret) { + lpfc_nlp_put(ndlp); + goto io_err; } return 0; + + io_err: + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -2267,6 +2297,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, out: lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); return; } @@ -2295,6 +2326,7 @@ int lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, uint8_t retry) { + int rc = 0; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; PRLI *npr; @@ -2430,10 +2462,6 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, local_nlp_type &= ~NLP_FC4_NVME; } - lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, - "Issue PRLI: did:x%x", - ndlp->nlp_DID, 0, 0); - phba->fc_stat.elsXmitPRLI++; elsiocb->iocb_cmpl = lpfc_cmpl_els_prli; spin_lock_irq(shost->host_lock); @@ -2446,14 +2474,17 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, vport->fc_prli_sent++; ndlp->fc4_prli_sent++; spin_unlock_irq(shost->host_lock); - if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == - IOCB_ERROR) { - spin_lock_irq(shost->host_lock); - ndlp->nlp_flag &= ~NLP_PRLI_SND; - spin_unlock_irq(shost->host_lock); - lpfc_els_free_iocb(phba, elsiocb); - return 1; - } + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "Issue PRLI: did:x%x refcnt %d", + ndlp->nlp_DID, kref_read(&ndlp->kref), 0); + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto io_err; + + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (rc == IOCB_ERROR) + goto node_err; /* The driver supports 2 FC4 types. Make sure @@ -2462,8 +2493,17 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (phba->sli_rev == LPFC_SLI_REV4 && local_nlp_type & (NLP_FC4_FCP | NLP_FC4_NVME)) goto send_next_prli; + else + return 0; - return 0; + node_err: + lpfc_nlp_put(ndlp); + io_err: + spin_lock_irq(shost->host_lock); + ndlp->nlp_flag &= ~NLP_PRLI_SND; + spin_unlock_irq(shost->host_lock); + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -2672,6 +2712,7 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_more_adisc(vport); out: lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); return; } @@ -2699,6 +2740,7 @@ int lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, uint8_t retry) { + int rc = 0; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; ADISC *ap; @@ -2725,24 +2767,31 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name)); ap->DID = be32_to_cpu(vport->fc_myDID); - lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, - "Issue ADISC: did:x%x", - ndlp->nlp_DID, 0, 0); - phba->fc_stat.elsXmitADISC++; elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc; spin_lock_irq(shost->host_lock); ndlp->nlp_flag |= NLP_ADISC_SND; spin_unlock_irq(shost->host_lock); - if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == - IOCB_ERROR) { - spin_lock_irq(shost->host_lock); - ndlp->nlp_flag &= ~NLP_ADISC_SND; - spin_unlock_irq(shost->host_lock); - lpfc_els_free_iocb(phba, elsiocb); - return 1; - } + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "Issue ADISC: did:x%x refcnt %d", + ndlp->nlp_DID, kref_read(&ndlp->kref), 0); + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (rc == IOCB_ERROR) + goto io_err; return 0; + + io_err: + lpfc_nlp_put(ndlp); + node_err: + spin_lock_irq(shost->host_lock); + ndlp->nlp_flag &= ~NLP_ADISC_SND; + spin_unlock_irq(shost->host_lock); + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -2827,7 +2876,10 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO); out: + /* Driver is done with the IO. */ lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); + /* If we are in pt2pt mode, we could rcv new S_ID on PLOGI */ if ((vport->fc_flag & FC_PT2PT) && !(vport->fc_flag & FC_PT2PT_PLOGI)) { @@ -2932,30 +2984,37 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, pcmd += sizeof(uint32_t); memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name)); - lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, - "Issue LOGO: did:x%x", - ndlp->nlp_DID, 0, 0); - phba->fc_stat.elsXmitLOGO++; elsiocb->iocb_cmpl = lpfc_cmpl_els_logo; spin_lock_irq(shost->host_lock); ndlp->nlp_flag |= NLP_LOGO_SND; ndlp->nlp_flag &= ~NLP_ISSUE_LOGO; spin_unlock_irq(shost->host_lock); + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "Issue LOGO: did:x%x refcnt %d", + ndlp->nlp_DID, kref_read(&ndlp->kref), 0); rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); - if (rc == IOCB_ERROR) { - spin_lock_irq(shost->host_lock); - ndlp->nlp_flag &= ~NLP_LOGO_SND; - spin_unlock_irq(shost->host_lock); - lpfc_els_free_iocb(phba, elsiocb); - return 1; - } + if (rc == IOCB_ERROR) + goto io_err; spin_lock_irq(shost->host_lock); ndlp->nlp_prev_state = ndlp->nlp_state; spin_unlock_irq(shost->host_lock); lpfc_nlp_set_state(vport, ndlp, NLP_STE_LOGO_ISSUE); return 0; + + io_err: + lpfc_nlp_put(ndlp); + node_err: + spin_lock_irq(shost->host_lock); + ndlp->nlp_flag &= ~NLP_LOGO_SND; + spin_unlock_irq(shost->host_lock); + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -2978,6 +3037,7 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { struct lpfc_vport *vport = cmdiocb->vport; + struct lpfc_nodelist *free_ndlp; IOCB_t *irsp; irsp = &rspiocb->iocb; @@ -2995,7 +3055,11 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* Check to see if link went down during discovery */ lpfc_els_chk_latt(vport); + + free_ndlp = (struct lpfc_nodelist *)cmdiocb->context1; + lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(free_ndlp); } /** @@ -3019,6 +3083,7 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_dmabuf *pcmd, *prsp; u32 *pdata; u32 cmd; + struct lpfc_nodelist *ndlp = cmdiocb->context1; irsp = &rspiocb->iocb; @@ -3097,6 +3162,7 @@ out: /* Check to see if link went down during discovery */ lpfc_els_chk_latt(vport); lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); return; } @@ -3124,6 +3190,7 @@ out: int lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry) { + int rc = 0; struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *elsiocb; uint8_t *pcmd; @@ -3143,13 +3210,8 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry) elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, ndlp->nlp_DID, ELS_CMD_SCR); - if (!elsiocb) { - /* This will trigger the release of the node just - * allocated - */ - lpfc_nlp_put(ndlp); + if (!elsiocb) return 1; - } pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); @@ -3166,22 +3228,26 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry) phba->fc_stat.elsXmitSCR++; elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; - if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == - IOCB_ERROR) { - /* The additional lpfc_nlp_put will cause the following - * lpfc_els_free_iocb routine to trigger the rlease of - * the node. - */ - lpfc_nlp_put(ndlp); - lpfc_els_free_iocb(phba, elsiocb); - return 1; - } - /* This will cause the callback-function lpfc_cmpl_els_cmd to - * trigger the release of node. - */ - if (!(vport->fc_flag & FC_PT2PT)) - lpfc_nlp_put(ndlp); + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; + + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "Issue SCR: did:x%x refcnt %d", + ndlp->nlp_DID, kref_read(&ndlp->kref), 0); + + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (rc == IOCB_ERROR) + goto io_err; + + /* Keep the ndlp just in case RDF is being sent */ return 0; + + io_err: + lpfc_nlp_put(ndlp); + node_err: + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -3207,6 +3273,7 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry) int lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry) { + int rc = 0; struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *elsiocb; struct lpfc_nodelist *ndlp; @@ -3243,13 +3310,8 @@ lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry) elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, ndlp->nlp_DID, ELS_CMD_RSCN_XMT); - if (!elsiocb) { - /* This will trigger the release of the node just - * allocated - */ - lpfc_nlp_put(ndlp); + if (!elsiocb) return 1; - } event = ((struct lpfc_dmabuf *)elsiocb->context2)->virt; @@ -3264,35 +3326,31 @@ lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry) event->portid.rscn_fid[1] = (nportid & 0x0000FF00) >> 8; event->portid.rscn_fid[2] = nportid & 0x000000FF; + phba->fc_stat.elsXmitRSCN++; + elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "Issue RSCN: did:x%x", ndlp->nlp_DID, 0, 0); - phba->fc_stat.elsXmitRSCN++; - elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; - if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == - IOCB_ERROR) { - /* The additional lpfc_nlp_put will cause the following - * lpfc_els_free_iocb routine to trigger the rlease of - * the node. - */ - lpfc_nlp_put(ndlp); - lpfc_els_free_iocb(phba, elsiocb); - return 1; - } - - /* Only keep the ndlp if RDF is being sent */ - if (!phba->cfg_enable_mi || - phba->sli4_hba.pc_sli4_params.mi_ver < LPFC_MIB3_SUPPORT) - return 0; + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (rc == IOCB_ERROR) + goto io_err; /* This will cause the callback-function lpfc_cmpl_els_cmd to * trigger the release of node. */ if (!(vport->fc_flag & FC_PT2PT)) lpfc_nlp_put(ndlp); - return 0; +io_err: + lpfc_nlp_put(ndlp); +node_err: + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -3320,6 +3378,7 @@ lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry) static int lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) { + int rc = 0; struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *elsiocb; FARP *fp; @@ -3341,13 +3400,8 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, ndlp->nlp_DID, ELS_CMD_RNID); - if (!elsiocb) { - /* This will trigger the release of the node just - * allocated - */ - lpfc_nlp_put(ndlp); + if (!elsiocb) return 1; - } pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); @@ -3379,8 +3433,14 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) phba->fc_stat.elsXmitFARPR++; elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; - if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == - IOCB_ERROR) { + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); + return 1; + } + + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (rc == IOCB_ERROR) { /* The additional lpfc_nlp_put will cause the following * lpfc_els_free_iocb routine to trigger the release of * the node. @@ -3421,6 +3481,7 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry) struct lpfc_els_rdf_req *prdf; struct lpfc_nodelist *ndlp; uint16_t cmdsize; + int rc; cmdsize = sizeof(*prdf); @@ -3440,13 +3501,8 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry) elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, ndlp->nlp_DID, ELS_CMD_RDF); - if (!elsiocb) { - /* This will trigger the release of the node just - * allocated - */ - lpfc_nlp_put(ndlp); + if (!elsiocb) return -ENOMEM; - } /* Configure the payload for the supported FPIN events. */ prdf = (struct lpfc_els_rdf_req *) @@ -3464,31 +3520,29 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry) prdf->reg_d1.desc_tags[2] = cpu_to_be32(ELS_DTAG_PEER_CONGEST); prdf->reg_d1.desc_tags[3] = cpu_to_be32(ELS_DTAG_CONGESTION); - lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, - "Issue RDF: did:x%x", - ndlp->nlp_DID, 0, 0); - lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "6444 Xmit RDF to remote NPORT x%x\n", ndlp->nlp_DID); elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; - if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == - IOCB_ERROR) { - /* The additional lpfc_nlp_put will cause the following - * lpfc_els_free_iocb routine to trigger the rlease of - * the node. - */ - lpfc_nlp_put(ndlp); - lpfc_els_free_iocb(phba, elsiocb); - return -EIO; - } + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; - /* An RDF was issued - this put ensures the ndlp is cleaned up - * when the RDF completes. - */ - lpfc_nlp_put(ndlp); + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, + "Issue RDF: did:x%x refcnt %d", + ndlp->nlp_DID, kref_read(&ndlp->kref), 0); + + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (rc == IOCB_ERROR) + goto io_err; return 0; + + io_err: + lpfc_nlp_put(ndlp); + node_err: + lpfc_els_free_iocb(phba, elsiocb); + return -EIO; } /** @@ -4256,27 +4310,10 @@ int lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) { struct lpfc_dmabuf *buf_ptr, *buf_ptr1; - struct lpfc_nodelist *ndlp; - ndlp = (struct lpfc_nodelist *)elsiocb->context1; - if (ndlp) { - if (ndlp->nlp_flag & NLP_DEFER_RM) { - lpfc_nlp_put(ndlp); + /* The I/O job is complete. Clear the context1 data. */ + elsiocb->context1 = NULL; - /* If the ndlp is not being used by another discovery - * thread, free it. - */ - if (!lpfc_nlp_not_used(ndlp)) { - /* If ndlp is being used by another discovery - * thread, just clear NLP_DEFER_RM - */ - ndlp->nlp_flag &= ~NLP_DEFER_RM; - } - } - else - lpfc_nlp_put(ndlp); - elsiocb->context1 = NULL; - } /* context2 = cmd, context2->next = rsp, context3 = bpl */ if (elsiocb->context2) { if (elsiocb->iocb_flag & LPFC_DELAY_MEM_FREE) { @@ -4376,6 +4413,7 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * At this point, the driver is done so release the IOCB */ lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); } /** @@ -4506,32 +4544,38 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); if (mbox) { - if ((rspiocb->iocb.ulpStatus == 0) - && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { + if ((rspiocb->iocb.ulpStatus == 0) && + (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { if (!lpfc_unreg_rpi(vport, ndlp) && - (!(vport->fc_flag & FC_PT2PT)) && - (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE || - ndlp->nlp_state == NLP_STE_REG_LOGIN_ISSUE)) { - lpfc_printf_vlog(vport, KERN_INFO, - LOG_DISCOVERY, - "0314 PLOGI recov DID x%x " - "Data: x%x x%x x%x\n", - ndlp->nlp_DID, ndlp->nlp_state, - ndlp->nlp_rpi, ndlp->nlp_flag); - mp = mbox->ctx_buf; - if (mp) { - lpfc_mbuf_free(phba, mp->virt, - mp->phys); - kfree(mp); + (!(vport->fc_flag & FC_PT2PT))) { + if (ndlp->nlp_state == NLP_STE_REG_LOGIN_ISSUE) { + lpfc_printf_vlog(vport, KERN_INFO, + LOG_DISCOVERY, + "0314 PLOGI recov " + "DID x%x " + "Data: x%x x%x x%x\n", + ndlp->nlp_DID, + ndlp->nlp_state, + ndlp->nlp_rpi, + ndlp->nlp_flag); + mp = mbox->ctx_buf; + if (mp) { + lpfc_mbuf_free(phba, mp->virt, + mp->phys); + kfree(mp); + } + mempool_free(mbox, phba->mbox_mem_pool); + goto out; } - mempool_free(mbox, phba->mbox_mem_pool); - goto out; } /* Increment reference count to ndlp to hold the * reference to ndlp for the callback function. */ mbox->ctx_ndlp = lpfc_nlp_get(ndlp); + if (!mbox->ctx_ndlp) + goto out; + mbox->vport = vport; if (ndlp->nlp_flag & NLP_RM_DFLT_RPI) { mbox->mbox_flag |= LPFC_MBX_IMED_UNREG; @@ -4615,7 +4659,9 @@ out: } + /* Release the originating I/O reference. */ lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); return; } @@ -4785,12 +4831,29 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, } phba->fc_stat.elsXmitACC++; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); - if (rc == IOCB_ERROR) { - lpfc_els_free_iocb(phba, elsiocb); - return 1; - } + if (rc == IOCB_ERROR) + goto io_err; + + /* Xmit ELS ACC response tag */ + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "0128 Xmit ELS ACC response Status: x%x, IoTag: x%x, " + "XRI: x%x, DID: x%x, nlp_flag: x%x nlp_state: x%x " + "RPI: x%x, fc_flag x%x\n", + rc, elsiocb->iotag, elsiocb->sli4_xritag, + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, + ndlp->nlp_rpi, vport->fc_flag); return 0; + +io_err: + lpfc_nlp_put(ndlp); +node_err: + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -4820,13 +4883,13 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp, LPFC_MBOXQ_t *mbox) { + int rc; struct lpfc_hba *phba = vport->phba; IOCB_t *icmd; IOCB_t *oldcmd; struct lpfc_iocbq *elsiocb; uint8_t *pcmd; uint16_t cmdsize; - int rc; cmdsize = 2 * sizeof(uint32_t); elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, @@ -4861,13 +4924,21 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError, phba->fc_stat.elsXmitLSRJT++; elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (rc == IOCB_ERROR) + goto io_err; - if (rc == IOCB_ERROR) { - lpfc_els_free_iocb(phba, elsiocb); - return 1; - } return 0; + + io_err: + lpfc_nlp_put(ndlp); + node_err: + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -4931,16 +5002,18 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, ap->DID = be32_to_cpu(vport->fc_myDID); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, - "Issue ACC ADISC: did:x%x flg:x%x", - ndlp->nlp_DID, ndlp->nlp_flag, 0); + "Issue ACC ADISC: did:x%x flg:x%x refcnt %d", + ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); phba->fc_stat.elsXmitACC++; elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); - if (rc == IOCB_ERROR) { - lpfc_els_free_iocb(phba, elsiocb); - return 1; - } + if (rc == IOCB_ERROR) + goto io_err; /* Xmit ELS ACC response tag */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, @@ -4951,6 +5024,12 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi, vport->fc_flag); return 0; + +io_err: + lpfc_nlp_put(ndlp); +node_err: + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -5098,18 +5177,25 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, ndlp->nlp_DID); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, - "Issue ACC PRLI: did:x%x flg:x%x", - ndlp->nlp_DID, ndlp->nlp_flag, 0); + "Issue ACC PRLI: did:x%x flg:x%x", + ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); phba->fc_stat.elsXmitACC++; elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); - if (rc == IOCB_ERROR) { - lpfc_els_free_iocb(phba, elsiocb); - return 1; - } + if (rc == IOCB_ERROR) + goto io_err; return 0; + + io_err: + lpfc_nlp_put(ndlp); + node_err: + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -5198,18 +5284,26 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format, } lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, - "Issue ACC RNID: did:x%x flg:x%x", - ndlp->nlp_DID, ndlp->nlp_flag, 0); + "Issue ACC RNID: did:x%x flg:x%x refcnt %d", + ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); phba->fc_stat.elsXmitACC++; elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); - if (rc == IOCB_ERROR) { - lpfc_els_free_iocb(phba, elsiocb); - return 1; - } + if (rc == IOCB_ERROR) + goto io_err; + return 0; + + io_err: + lpfc_nlp_put(ndlp); + node_err: + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -5305,18 +5399,25 @@ lpfc_els_rsp_echo_acc(struct lpfc_vport *vport, uint8_t *data, memcpy(pcmd, data, cmdsize - sizeof(uint32_t)); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP, - "Issue ACC ECHO: did:x%x flg:x%x", - ndlp->nlp_DID, ndlp->nlp_flag, 0); + "Issue ACC ECHO: did:x%x flg:x%x refcnt %d", + ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref)); phba->fc_stat.elsXmitACC++; elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); - if (rc == IOCB_ERROR) { - lpfc_els_free_iocb(phba, elsiocb); - return 1; - } + if (rc == IOCB_ERROR) + goto io_err; return 0; + + io_err: + lpfc_nlp_put(ndlp); + node_err: + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -5879,7 +5980,6 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context, elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, lpfc_max_els_tries, rdp_context->ndlp, rdp_context->ndlp->nlp_DID, ELS_CMD_ACC); - lpfc_nlp_put(ndlp); if (!elsiocb) goto free_rdp_context; @@ -5953,18 +6053,24 @@ lpfc_els_rdp_cmpl(struct lpfc_hba *phba, struct lpfc_rdp_context *rdp_context, bpl->tus.w = le32_to_cpu(bpl->tus.w); phba->fc_stat.elsXmitACC++; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); + goto free_rdp_context; + } + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); - if (rc == IOCB_ERROR) + if (rc == IOCB_ERROR) { + lpfc_nlp_put(ndlp); lpfc_els_free_iocb(phba, elsiocb); + } - kfree(rdp_context); + goto free_rdp_context; - return; error: cmdsize = 2 * sizeof(uint32_t); elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, lpfc_max_els_tries, ndlp, ndlp->nlp_DID, ELS_CMD_LS_RJT); - lpfc_nlp_put(ndlp); if (!elsiocb) goto free_rdp_context; @@ -5979,11 +6085,23 @@ error: phba->fc_stat.elsXmitLSRJT++; elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; - rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); + goto free_rdp_context; + } - if (rc == IOCB_ERROR) + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (rc == IOCB_ERROR) { + lpfc_nlp_put(ndlp); lpfc_els_free_iocb(phba, elsiocb); + } + free_rdp_context: + /* This reference put is for the original unsolicited RDP. If the + * iocb prep failed, there is no reference to remove. + */ + lpfc_nlp_put(ndlp); kfree(rdp_context); } @@ -6087,6 +6205,11 @@ lpfc_els_rcv_rdp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, cmd = &cmdiocb->iocb; rdp_context->ndlp = lpfc_nlp_get(ndlp); + if (!rdp_context->ndlp) { + kfree(rdp_context); + rjt_err = LSRJT_UNABLE_TPC; + goto error; + } rdp_context->ox_id = cmd->unsli3.rcvsli3.ox_id; rdp_context->rx_id = cmd->ulpContext; rdp_context->cmpl = lpfc_els_rdp_cmpl; @@ -6181,10 +6304,19 @@ lpfc_els_lcb_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lcb_res->lcb_duration = lcb_context->duration; elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitACC++; + + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); - if (rc == IOCB_ERROR) - lpfc_els_free_iocb(phba, elsiocb); + if (!rc) + goto out; + lpfc_nlp_put(ndlp); + node_err: + lpfc_els_free_iocb(phba, elsiocb); + out: kfree(lcb_context); return; @@ -6211,9 +6343,17 @@ error: elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitLSRJT++; + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); + goto free_lcb_context; + } + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); - if (rc == IOCB_ERROR) + if (rc == IOCB_ERROR) { + lpfc_nlp_put(ndlp); lpfc_els_free_iocb(phba, elsiocb); + } free_lcb_context: kfree(lcb_context); } @@ -6313,7 +6453,7 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, uint8_t *lp; struct fc_lcb_request_frame *beacon; struct lpfc_lcb_context *lcb_context; - uint8_t state, rjt_err; + u8 state, rjt_err = 0; struct ls_rjt stat; pcmd = (struct lpfc_dmabuf *)cmdiocb->context2; @@ -6359,6 +6499,11 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lcb_context->ox_id = cmdiocb->iocb.unsli3.rcvsli3.ox_id; lcb_context->rx_id = cmdiocb->iocb.ulpContext; lcb_context->ndlp = lpfc_nlp_get(ndlp); + if (!lcb_context->ndlp) { + rjt_err = LSRJT_UNABLE_TPC; + goto rjt; + } + if (lpfc_sli4_set_beacon(vport, lcb_context, state)) { lpfc_printf_vlog(ndlp->vport, KERN_ERR, LOG_TRACE_EVENT, "0193 failed to send mail box"); @@ -7208,6 +7353,7 @@ lpfc_els_rcv_rrq(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, static void lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) { + int rc = 0; MAILBOX_t *mb; IOCB_t *icmd; struct RLS_RSP *rls_rsp; @@ -7269,8 +7415,19 @@ lpfc_els_rsp_rls_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ndlp->nlp_rpi); elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitACC++; - if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == IOCB_ERROR) - lpfc_els_free_iocb(phba, elsiocb); + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; + + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (rc == IOCB_ERROR) + goto io_err; + return; + + io_err: + lpfc_nlp_put(ndlp); + node_err: + lpfc_els_free_iocb(phba, elsiocb); } /** @@ -7311,6 +7468,8 @@ lpfc_els_rcv_rls(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, ((cmdiocb->iocb.unsli3.rcvsli3.ox_id << 16) | cmdiocb->iocb.ulpContext)); /* rx_id */ mbox->ctx_ndlp = lpfc_nlp_get(ndlp); + if (!mbox->ctx_ndlp) + goto node_err; mbox->vport = vport; mbox->mbox_cmpl = lpfc_els_rsp_rls_acc; if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) @@ -7321,6 +7480,7 @@ lpfc_els_rcv_rls(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, * command. */ lpfc_nlp_put(ndlp); +node_err: mempool_free(mbox, phba->mbox_mem_pool); } reject_out: @@ -7358,6 +7518,7 @@ static int lpfc_els_rcv_rtv(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, struct lpfc_nodelist *ndlp) { + int rc = 0; struct lpfc_hba *phba = vport->phba; struct ls_rjt stat; struct RTV_RSP *rtv_rsp; @@ -7407,8 +7568,17 @@ lpfc_els_rcv_rtv(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, rtv_rsp->ratov, rtv_rsp->edtov, rtv_rsp->qtov); elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitACC++; - if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == IOCB_ERROR) + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) { + lpfc_els_free_iocb(phba, elsiocb); + return 0; + } + + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (rc == IOCB_ERROR) { + lpfc_nlp_put(ndlp); lpfc_els_free_iocb(phba, elsiocb); + } return 0; reject_out: @@ -7477,13 +7647,20 @@ lpfc_issue_els_rrq(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, did, rrq->xritag, rrq->rxid); elsiocb->context_un.rrq = rrq; elsiocb->iocb_cmpl = lpfc_cmpl_els_rrq; - ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; - if (ret == IOCB_ERROR) { - lpfc_els_free_iocb(phba, elsiocb); - return 1; - } + ret = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (ret == IOCB_ERROR) + goto io_err; return 0; + + io_err: + lpfc_nlp_put(ndlp); + node_err: + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -7536,6 +7713,7 @@ static int lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize, struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp) { + int rc = 0; struct lpfc_hba *phba = vport->phba; IOCB_t *icmd, *oldcmd; RPL_RSP rpl_rsp; @@ -7577,12 +7755,20 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize, ndlp->nlp_rpi); elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; phba->fc_stat.elsXmitACC++; - if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == - IOCB_ERROR) { - lpfc_els_free_iocb(phba, elsiocb); - return 1; - } + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; + + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (rc == IOCB_ERROR) + goto io_err; return 0; + + io_err: + lpfc_nlp_put(ndlp); + node_err: + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -8444,6 +8630,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, spin_unlock_irq(shost->host_lock); elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto dropit; elsiocb->vport = vport; if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) { @@ -8755,7 +8943,10 @@ lsrjt: stat.un.b.lsRjtRsnCode = rjt_err; stat.un.b.lsRjtRsnCodeExp = rjt_exp; lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp, - NULL); + NULL); + /* Remove the reference from above for new nodes. */ + if (newnode) + lpfc_nlp_put(ndlp); } lpfc_nlp_put(elsiocb->context1); @@ -9108,6 +9299,11 @@ lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport, lpfc_reg_vpi(vport, mbox); mbox->vport = vport; mbox->ctx_ndlp = lpfc_nlp_get(ndlp); + if (!mbox->ctx_ndlp) { + mempool_free(mbox, phba->mbox_mem_pool); + goto mbox_err_exit; + } + mbox->mbox_cmpl = lpfc_cmpl_reg_new_vport; if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) == MBX_NOT_FINISHED) { @@ -9360,9 +9556,9 @@ fdisc_failed: lpfc_vport_set_state(vport, FC_VPORT_FAILED); /* Cancel discovery timer */ lpfc_can_disctmo(vport); - lpfc_nlp_put(ndlp); out: lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); } /** @@ -9455,16 +9651,25 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, "Issue FDISC: did:x%x", did, 0, 0); + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto err_out; + rc = lpfc_issue_fabric_iocb(phba, elsiocb); if (rc == IOCB_ERROR) { - lpfc_els_free_iocb(phba, elsiocb); - lpfc_vport_set_state(vport, FC_VPORT_FAILED); - lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, - "0256 Issue FDISC: Cannot send IOCB\n"); - return 1; + lpfc_nlp_put(ndlp); + goto err_out; } + lpfc_vport_set_state(vport, FC_VPORT_INITIALIZING); return 0; + + err_out: + lpfc_els_free_iocb(phba, elsiocb); + lpfc_vport_set_state(vport, FC_VPORT_FAILED); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "0256 Issue FDISC: Cannot send IOCB\n"); + return 1; } /** @@ -9496,6 +9701,7 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "LOGO npiv cmpl: status:x%x/x%x did:x%x", irsp->ulpStatus, irsp->un.ulpWord[4], irsp->un.rcvels.remoteID); + lpfc_nlp_put(ndlp); lpfc_els_free_iocb(phba, cmdiocb); vport->unreg_vpi_cmpl = VPORT_ERROR; @@ -9516,6 +9722,7 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, spin_unlock_irq(shost->host_lock); lpfc_can_disctmo(vport); } + lpfc_nlp_put(ndlp); } /** @@ -9537,6 +9744,7 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, int lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) { + int rc = 0; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *elsiocb; @@ -9566,15 +9774,22 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) spin_lock_irq(shost->host_lock); ndlp->nlp_flag |= NLP_LOGO_SND; spin_unlock_irq(shost->host_lock); - if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == - IOCB_ERROR) { - spin_lock_irq(shost->host_lock); - ndlp->nlp_flag &= ~NLP_LOGO_SND; - spin_unlock_irq(shost->host_lock); - lpfc_els_free_iocb(phba, elsiocb); - return 1; - } + elsiocb->context1 = lpfc_nlp_get(ndlp); + if (!elsiocb->context1) + goto node_err; + rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0); + if (rc == IOCB_ERROR) + goto io_err; return 0; + + io_err: + lpfc_nlp_put(ndlp); + node_err: + spin_lock_irq(shost->host_lock); + ndlp->nlp_flag &= ~NLP_LOGO_SND; + spin_unlock_irq(shost->host_lock); + lpfc_els_free_iocb(phba, elsiocb); + return 1; } /** @@ -9660,8 +9875,6 @@ repeat: goto repeat; } } - - return; } /** diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 47d26917e10f..9d387fbf65a3 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -178,7 +178,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) /* We need to hold the node by incrementing the reference * count until this queued work is done */ - evtp->evt_arg1 = lpfc_nlp_get(ndlp); + evtp->evt_arg1 = lpfc_nlp_get(ndlp); spin_lock_irqsave(&phba->hbalock, iflags); if (evtp->evt_arg1) { @@ -4214,6 +4214,13 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) rport->supported_classes = ndlp->nlp_class_sup; rdata = rport->dd_data; rdata->pnode = lpfc_nlp_get(ndlp); + if (!rdata->pnode) { + dev_warn(&phba->pcidev->dev, + "Warning - node ref failed. Unreg rport\n"); + fc_remote_port_delete(rport); + ndlp->rport = NULL; + return; + } if (ndlp->nlp_type & NLP_FCP_TARGET) rport_ids.roles |= FC_PORT_ROLE_FCP_TARGET; @@ -5157,8 +5164,7 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) int rc; lpfc_cancel_retry_delay_tmo(vport, ndlp); - if ((ndlp->nlp_flag & NLP_DEFER_RM) && - !(ndlp->nlp_flag & NLP_REG_LOGIN_SEND) && + if (!(ndlp->nlp_flag & NLP_REG_LOGIN_SEND) && !(ndlp->nlp_flag & NLP_RPI_REGISTERED) && phba->sli_rev != LPFC_SLI_REV4) { /* For this case we need to cleanup the default rpi diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 16a37c2153ae..5c57aeb1fb0b 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -357,7 +357,6 @@ lpfc_defer_acc_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) * Complete the unreg rpi mbx request, and update flags. * This will also restart any deferred events. */ - lpfc_nlp_get(ndlp); lpfc_sli4_unreg_rpi_cmpl_clr(phba, pmb); if (!piocb) { @@ -365,7 +364,7 @@ lpfc_defer_acc_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) "4578 PLOGI ACC fail\n"); if (mbox) mempool_free(mbox, phba->mbox_mem_pool); - goto out; + return; } rc = lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, piocb, ndlp, mbox); @@ -376,8 +375,6 @@ lpfc_defer_acc_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) mempool_free(mbox, phba->mbox_mem_pool); } kfree(piocb); -out: - lpfc_nlp_put(ndlp); } static int @@ -588,7 +585,10 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, rpi = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; lpfc_unreg_login(phba, vport->vpi, rpi, link_mbox); link_mbox->vport = vport; - link_mbox->ctx_ndlp = ndlp; + link_mbox->ctx_ndlp = lpfc_nlp_get(ndlp); + if (!link_mbox->ctx_ndlp) + goto out; + link_mbox->mbox_cmpl = lpfc_defer_acc_rsp; if (((ndlp->nlp_DID & Fabric_DID_MASK) != Fabric_DID_MASK) && @@ -1104,7 +1104,11 @@ lpfc_release_rpi(struct lpfc_hba *phba, struct lpfc_vport *vport, lpfc_unreg_login(phba, vport->vpi, rpi, pmb); pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; pmb->vport = vport; - pmb->ctx_ndlp = ndlp; + pmb->ctx_ndlp = lpfc_nlp_get(ndlp); + if (!pmb->ctx_ndlp) { + mempool_free(pmb, phba->mbox_mem_pool); + return; + } if (((ndlp->nlp_DID & Fabric_DID_MASK) != Fabric_DID_MASK) && (!(vport->fc_flag & FC_OFFLINE_MODE))) @@ -1342,7 +1346,6 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, uint32_t evt) { struct lpfc_hba *phba = vport->phba; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_iocbq *cmdiocb, *rspiocb; struct lpfc_dmabuf *pcmd, *prsp, *mp; uint32_t *lp; @@ -1488,7 +1491,11 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport, ndlp->nlp_flag |= NLP_REG_LOGIN_SEND; mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login; } + mbox->ctx_ndlp = lpfc_nlp_get(ndlp); + if (!mbox->ctx_ndlp) + goto out; + mbox->vport = vport; if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) != MBX_NOT_FINISHED) { @@ -1537,9 +1544,6 @@ out: ndlp->nlp_prev_state = ndlp->nlp_state; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); - spin_lock_irq(shost->host_lock); - ndlp->nlp_flag |= NLP_DEFER_RM; - spin_unlock_irq(shost->host_lock); return NLP_STE_FREED_NODE; } @@ -2797,16 +2801,12 @@ lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, { struct lpfc_iocbq *cmdiocb, *rspiocb; IOCB_t *irsp; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); cmdiocb = (struct lpfc_iocbq *) arg; rspiocb = cmdiocb->context_un.rsp_iocb; irsp = &rspiocb->iocb; if (irsp->ulpStatus) { - spin_lock_irq(shost->host_lock); - ndlp->nlp_flag |= NLP_DEFER_RM; - spin_unlock_irq(shost->host_lock); return NLP_STE_FREED_NODE; } return ndlp->nlp_state; diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 042a3b9bfc80..3513e1ea609c 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -566,6 +566,13 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, /* Save for completion so we can release these resources */ genwqe->context1 = lpfc_nlp_get(ndlp); + if (!genwqe->context1) { + dev_warn(&phba->pcidev->dev, + "Warning: Failed node ref, not sending LS_REQ\n"); + lpfc_sli_release_iocbq(phba, genwqe); + return 1; + } + genwqe->context2 = (uint8_t *)pnvme_lsreq; /* Fill in payload, bp points to frame payload */ @@ -2459,7 +2466,11 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) spin_unlock_irq(&vport->phba->hbalock); } else { spin_unlock_irq(&vport->phba->hbalock); - lpfc_nlp_get(ndlp); + if (!lpfc_nlp_get(ndlp)) { + dev_warn(&vport->phba->pcidev->dev, + "Warning - No node ref - exit register\n"); + return 0; + } } ret = nvme_fc_register_remoteport(localport, &rpinfo, &remote_port); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 4974bf671063..1232fad17d1e 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2594,7 +2594,6 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ndlp->nlp_flag, ndlp); ndlp->nlp_flag &= ~NLP_LOGO_ACC; - lpfc_nlp_put(ndlp); /* Check to see if there are any deferred * events to process @@ -2617,6 +2616,8 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } else { __lpfc_sli_rpi_release(vport, ndlp); } + + lpfc_nlp_put(ndlp); } } } @@ -11352,11 +11353,11 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "x%x x%x x%x\n", irsp->ulpIoTag, irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout); + lpfc_nlp_put((struct lpfc_nodelist *)cmdiocb->context1); if (cmdiocb->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) lpfc_ct_free_iocb(phba, cmdiocb); else lpfc_els_free_iocb(phba, cmdiocb); - return; } /** @@ -17924,6 +17925,10 @@ lpfc_sli4_seq_abort_rsp(struct lpfc_vport *vport, icmd->ulpClass = CLASS3; icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi]; ctiocb->context1 = lpfc_nlp_get(ndlp); + if (!ctiocb->context1) { + lpfc_sli_release_iocbq(phba, ctiocb); + return; + } ctiocb->vport = phba->pport; ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_rsp_cmpl; -- cgit v1.2.3 From 95f0ef8a8368b2195ca9b8b4eca9a3ec8d132a75 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:32 -0800 Subject: scsi: lpfc: Fix removal of SCSI transport device get and put on dev structure The lpfc driver is calling get_device and put_device on scsi_fc_transport device structure. When this code was removed, the driver triggered an oops in "scsi_is_host_dev" when the first SCSI target was unregistered from the transport. The reason the calls were necessary is that the driver is calling scsi_remove_host too early, before the target rports are unregistered and the scsi devices disconnected from the scsi_host. The fc_host was torn down during fc_remove_host. Fix by moving the lpfc_pci_remove_one_s3/s4 calls to scsi_remove_host to after the nodes are cleaned up. Remove the get_device and put_device calls and the supporting code. Link: https://lore.kernel.org/r/20201115192646.12977-4-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 4 ---- drivers/scsi/lpfc/lpfc_hbadisc.c | 12 ++---------- drivers/scsi/lpfc/lpfc_init.c | 14 +++++++++----- drivers/scsi/lpfc/lpfc_vport.c | 6 ++++-- 4 files changed, 15 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 44e99e7872f3..c778e48e85d8 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1601,7 +1601,6 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, u32 keep_nlp_fc4_type = 0; struct lpfc_nvme_rport *keep_nrport = NULL; int put_node; - int put_rport; unsigned long *active_rrqs_xri_bitmap = NULL; /* Fabric nodes can have the same WWPN so we don't bother searching @@ -1804,13 +1803,10 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, if (rport) { rdata = rport->dd_data; put_node = rdata->pnode != NULL; - put_rport = ndlp->rport != NULL; rdata->pnode = NULL; ndlp->rport = NULL; if (put_node) lpfc_nlp_put(ndlp); - if (put_rport) - put_device(&rport->dev); } } diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 9d387fbf65a3..71ef50c65dcf 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -117,7 +117,6 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) struct lpfc_hba *phba; struct lpfc_work_evt *evtp; int put_node; - int put_rport; unsigned long iflags; rdata = rport->dd_data; @@ -142,13 +141,10 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) */ if (vport->load_flag & FC_UNLOADING) { put_node = rdata->pnode != NULL; - put_rport = ndlp->rport != NULL; rdata->pnode = NULL; ndlp->rport = NULL; if (put_node) lpfc_nlp_put(ndlp); - if (put_rport) - put_device(&rport->dev); return; } @@ -263,7 +259,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ndlp->rport = NULL; if (put_node) lpfc_nlp_put(ndlp); - put_device(&rport->dev); return fcf_inuse; } @@ -284,7 +279,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ndlp->rport = NULL; if (put_node) lpfc_nlp_put(ndlp); - put_device(&rport->dev); if (ndlp->nlp_type & NLP_FABRIC) return fcf_inuse; @@ -4190,8 +4184,6 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) lpfc_nlp_put(ndlp); rdata->pnode = NULL; } - /* drop reference for earlier registeration */ - put_device(&rport->dev); } lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, @@ -4203,7 +4195,7 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) return; ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids); - if (!rport || !get_device(&rport->dev)) { + if (!rport) { dev_printk(KERN_WARNING, &phba->pcidev->dev, "Warning: fc_remote_port_add failed\n"); return; @@ -4244,6 +4236,7 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) (rport->scsi_target_id < LPFC_MAX_TARGET)) { ndlp->nlp_sid = rport->scsi_target_id; } + return; } @@ -5217,7 +5210,6 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) rdata = rport->dd_data; rdata->pnode = NULL; ndlp->rport = NULL; - put_device(&rport->dev); } } diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index add2eb0d729b..72448287a3d1 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -12499,12 +12499,15 @@ lpfc_pci_remove_one_s3(struct pci_dev *pdev) } lpfc_destroy_vport_work_array(phba, vports); - /* Remove FC host and then SCSI host with the physical port */ + /* Remove FC host with the physical port */ fc_remove_host(shost); - scsi_remove_host(shost); + /* Clean up all nodes, mailboxes and IOs. */ lpfc_cleanup(vport); + /* Remove the shost now that the devices connections are lost. */ + scsi_remove_host(shost); + /* * Bring down the SLI Layer. This step disable all interrupts, * clears the rings, discards all mailbox commands, and resets @@ -13342,7 +13345,6 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev) vport->load_flag |= FC_UNLOADING; spin_unlock_irq(&phba->hbalock); - /* Free the HBA sysfs attributes */ lpfc_free_sysfs_attr(vport); /* Release all the vports against this physical port */ @@ -13355,9 +13357,8 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev) } lpfc_destroy_vport_work_array(phba, vports); - /* Remove FC host and then SCSI host with the physical port */ + /* Remove FC host with the physical port */ fc_remove_host(shost); - scsi_remove_host(shost); /* Perform ndlp cleanup on the physical port. The nvme and nvmet * localports are destroyed after to cleanup all transport memory. @@ -13370,6 +13371,9 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev) if (phba->cfg_xri_rebalancing) lpfc_destroy_multixri_pools(phba); + /* Remove the shost now that the devices connections are lost. */ + scsi_remove_host(shost); + /* * Bring down the SLI Layer. This step disables all interrupts, * clears the rings, discards all mailbox commands, and resets diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 6ab78131b94d..0261495b44d3 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -664,9 +664,8 @@ lpfc_vport_delete(struct fc_vport *fc_vport) ns_ndlp_referenced = true; } - /* Remove FC host and then SCSI host with the vport */ + /* Remove FC host to break driver binding. */ fc_remove_host(shost); - scsi_remove_host(shost); ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); @@ -747,6 +746,9 @@ skip_logo: } lpfc_cleanup(vport); + + /* Remove scsi host now. The nodes are cleaned up. */ + scsi_remove_host(shost); lpfc_sli_host_down(vport); lpfc_stop_vport_timers(vport); -- cgit v1.2.3 From e9b1108316b9b5beee03f731c7c9c7c874e537fa Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:33 -0800 Subject: scsi: lpfc: Fix refcounting around SCSI and NVMe transport APIs Due to bug history and code review, the node reference counting approach in the driver isn't implemented consistently with how the scsi and nvme transport perform registrations and unregistrations and their callbacks. This resulted in many bad/stale node pointers. Reword the driver so that reference handling is performed as follows: - The initial node reference is taken on structure allocation - Take a reference on any add/register call to the transport - Remove a reference on any delete/unregister call to the transport - After the node has fully removed from both the SCSI and NVMEe transports (dev_loss_callbacks have called back) call the discovery engine DEVICE_RM event which will remove the final reference and release the node structure. - Alter dev_loss handling when a vport or base port is unloading. - Remove the put_node handling - no longer needed. - Rewrite the vport_delete handling on reference counts. Part of this effort was driven from the FDISC not registering with the transport and disrupting the model for node reference counting. - Deleted lpfc_nlp_remove. Pushed it's remaining ops into lpfc_nlp_release. - Several other small code cleanups. Link: https://lore.kernel.org/r/20201115192646.12977-5-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_disc.h | 6 ++- drivers/scsi/lpfc/lpfc_els.c | 89 ++++++++++++++---------------------------- drivers/scsi/lpfc/lpfc_init.c | 49 ++++++++++++++--------- drivers/scsi/lpfc/lpfc_nvme.c | 62 +++++++++++++++++++---------- drivers/scsi/lpfc/lpfc_nvme.h | 2 +- drivers/scsi/lpfc/lpfc_sli.c | 13 ++++-- drivers/scsi/lpfc/lpfc_vport.c | 73 ++++++---------------------------- 7 files changed, 130 insertions(+), 164 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 09d4ec2a20db..b831f10a686c 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h @@ -131,13 +131,17 @@ struct lpfc_nodelist { unsigned long *active_rrqs_xri_bitmap; struct lpfc_scsicmd_bkt *lat_data; /* Latency data */ uint32_t fc4_prli_sent; - uint32_t upcall_flags; + uint32_t fc4_xpt_flags; #define NLP_WAIT_FOR_UNREG 0x1 +#define SCSI_XPT_REGD 0x2 +#define NVME_XPT_REGD 0x4 + uint32_t nvme_fb_size; /* NVME target's supported byte cnt */ #define NVME_FB_BIT_SHIFT 9 /* PRLI Rsp first burst in 512B units. */ uint32_t nlp_defer_did; }; + struct lpfc_node_rrq { struct list_head list; uint16_t xritag; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index c778e48e85d8..c3e3a6afd91e 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1554,7 +1554,7 @@ lpfc_more_plogi(struct lpfc_vport *vport) } /** - * lpfc_plogi_confirm_nport - Confirm pologi wwpn matches stored ndlp + * lpfc_plogi_confirm_nport - Confirm plogi wwpn matches stored ndlp * @phba: pointer to lpfc hba data structure. * @prsp: pointer to response IOCB payload. * @ndlp: pointer to a node-list data structure. @@ -1591,8 +1591,6 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, struct lpfc_vport *vport = ndlp->vport; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_nodelist *new_ndlp; - struct lpfc_rport_data *rdata; - struct fc_rport *rport; struct serv_parm *sp; uint8_t name[sizeof(struct lpfc_name)]; uint32_t rc, keepDID = 0, keep_nlp_flag = 0; @@ -1600,7 +1598,6 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, uint16_t keep_nlp_state; u32 keep_nlp_fc4_type = 0; struct lpfc_nvme_rport *keep_nrport = NULL; - int put_node; unsigned long *active_rrqs_xri_bitmap = NULL; /* Fabric nodes can have the same WWPN so we don't bother searching @@ -1730,26 +1727,6 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, "3179 PLOGI confirm NEW: %x %x\n", new_ndlp->nlp_DID, keepDID); - /* Fix up the rport accordingly */ - rport = ndlp->rport; - if (rport) { - rdata = rport->dd_data; - if (rdata->pnode == ndlp) { - /* break the link before dropping the ref */ - ndlp->rport = NULL; - lpfc_nlp_put(ndlp); - rdata->pnode = lpfc_nlp_get(new_ndlp); - new_ndlp->rport = rport; - } - new_ndlp->nlp_type = ndlp->nlp_type; - } - - /* Fix up the nvme rport */ - if (ndlp->nrport) { - ndlp->nrport = NULL; - lpfc_nlp_put(ndlp); - } - /* Two ndlps cannot have the same did on the nodelist. * Note: for this case, ndlp has a NULL WWPN so setting * the nlp_fc4_type isn't required. @@ -1789,25 +1766,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, (ndlp->nlp_state == NLP_STE_MAPPED_NODE)) keep_nlp_state = NLP_STE_NPR_NODE; lpfc_nlp_set_state(vport, ndlp, keep_nlp_state); - - /* Previous ndlp no longer active with nvme host transport. - * Remove reference from earlier registration unless the - * nvme host took care of it. - */ - if (ndlp->nrport) - lpfc_nlp_put(ndlp); ndlp->nrport = keep_nrport; - - /* Fix up the rport accordingly */ - rport = ndlp->rport; - if (rport) { - rdata = rport->dd_data; - put_node = rdata->pnode != NULL; - rdata->pnode = NULL; - ndlp->rport = NULL; - if (put_node) - lpfc_nlp_put(ndlp); - } } /* @@ -2027,10 +1986,12 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "2753 PLOGI failure DID:%06X Status:x%x/x%x\n", ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4]); - /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ + /* Do not call DSM for lpfc_els_abort'ed ELS cmds. Just execute + * the final node put to free it to the pool. + */ if (!lpfc_error_lost_link(irsp)) lpfc_disc_state_machine(vport, ndlp, cmdiocb, - NLP_EVT_CMPL_PLOGI); + NLP_EVT_DEVICE_RM); } else { /* Good status, call state machine */ prsp = list_entry(((struct lpfc_dmabuf *) @@ -2038,7 +1999,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_dmabuf, list); ndlp = lpfc_plogi_confirm_nport(phba, prsp->virt, ndlp); lpfc_disc_state_machine(vport, ndlp, cmdiocb, - NLP_EVT_CMPL_PLOGI); + NLP_EVT_CMPL_PLOGI); } if (disc && vport->num_disc_nodes) { @@ -4439,15 +4400,16 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) mempool_free(pmb, phba->mbox_mem_pool); if (ndlp) { lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, - "0006 rpi%x DID:%x flg:%x %d x%px\n", + "0006 rpi x%x DID:%x flg:%x %d x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref), ndlp); - lpfc_nlp_put(ndlp); /* This is the end of the default RPI cleanup logic for - * this ndlp. If no other discovery threads are using - * this ndlp, free all resources associated with it. + * this ndlp and it could get released. Clear the nlp_flags to + * prevent any further processing. */ + ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; + lpfc_nlp_put(ndlp); lpfc_nlp_not_used(ndlp); } @@ -4652,7 +4614,6 @@ out: * the routine lpfc_els_free_iocb. */ cmdiocb->context1 = NULL; - } /* Release the originating I/O reference. */ @@ -8945,6 +8906,7 @@ lsrjt: lpfc_nlp_put(ndlp); } + /* Release the reference on this elsiocb, not the ndlp. */ lpfc_nlp_put(elsiocb->context1); elsiocb->context1 = NULL; @@ -9261,8 +9223,9 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_start_fdiscs(phba); lpfc_do_scr_ns_plogi(phba, vport); } - } else + } else { lpfc_do_scr_ns_plogi(phba, vport); + } } mbox_err_exit: /* Now, we decrement the ndlp reference count held for this @@ -9536,6 +9499,7 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, * to update the MAC address. */ lpfc_register_new_vport(phba, vport, ndlp); + lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); goto out; } @@ -9545,7 +9509,13 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, lpfc_register_new_vport(phba, vport, ndlp); else lpfc_do_scr_ns_plogi(phba, vport); + + /* The FDISC completed successfully. Move the fabric ndlp to + * UNMAPPED state and register with the transport. + */ + lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); goto out; + fdisc_failed: if (vport->fc_vport && (vport->fc_vport->vport_state != FC_VPORT_NO_FABRIC_RSCS)) @@ -9697,19 +9667,14 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "LOGO npiv cmpl: status:x%x/x%x did:x%x", irsp->ulpStatus, irsp->un.ulpWord[4], irsp->un.rcvels.remoteID); - lpfc_nlp_put(ndlp); - lpfc_els_free_iocb(phba, cmdiocb); - vport->unreg_vpi_cmpl = VPORT_ERROR; - - /* Trigger the release of the ndlp after logo */ - lpfc_nlp_put(ndlp); - /* NPIV LOGO completes to NPort */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "2928 NPIV LOGO completes to NPort x%x " - "Data: x%x x%x x%x x%x\n", + "Data: x%x x%x x%x x%x x%x x%x x%x\n", ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], - irsp->ulpTimeout, vport->num_disc_nodes); + irsp->ulpTimeout, vport->num_disc_nodes, + kref_read(&ndlp->kref), ndlp->nlp_flag, + ndlp->fc4_xpt_flags); if (irsp->ulpStatus == IOSTAT_SUCCESS) { spin_lock_irq(shost->host_lock); @@ -9718,7 +9683,11 @@ lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, spin_unlock_irq(shost->host_lock); lpfc_can_disctmo(vport); } + + /* Safe to release resources now. */ + lpfc_els_free_iocb(phba, cmdiocb); lpfc_nlp_put(ndlp); + vport->unreg_vpi_cmpl = VPORT_ERROR; } /** diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 72448287a3d1..65b9e4e06b9f 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -2859,12 +2859,17 @@ lpfc_cleanup(struct lpfc_vport *vport) continue; } - if (ndlp->nlp_type & NLP_FABRIC) + /* Fabric Ports not in UNMAPPED state are cleaned up in the + * DEVICE_RM event. + */ + if (ndlp->nlp_type & NLP_FABRIC && + ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RECOVERY); - lpfc_disc_state_machine(vport, ndlp, NULL, - NLP_EVT_DEVICE_RM); + if (!(ndlp->fc4_xpt_flags & (NVME_XPT_REGD|SCSI_XPT_REGD))) + lpfc_disc_state_machine(vport, ndlp, NULL, + NLP_EVT_DEVICE_RM); } /* At this point, ALL ndlp's should be gone @@ -2879,11 +2884,13 @@ lpfc_cleanup(struct lpfc_vport *vport) list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { lpfc_printf_vlog(ndlp->vport, KERN_ERR, - LOG_TRACE_EVENT, - "0282 did:x%x ndlp:x%px " - "refcnt:%d\n", - ndlp->nlp_DID, (void *)ndlp, - kref_read(&ndlp->kref)); + LOG_TRACE_EVENT, + "0282 did:x%x ndlp:x%px " + "refcnt:%d xflags x%x nflag x%x\n", + ndlp->nlp_DID, (void *)ndlp, + kref_read(&ndlp->kref), + ndlp->fc4_xpt_flags, + ndlp->nlp_flag); } break; } @@ -3499,10 +3506,10 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) * comes back online. */ if (phba->sli_rev == LPFC_SLI_REV4) { - lpfc_printf_vlog(ndlp->vport, KERN_INFO, + lpfc_printf_vlog(vports[i], KERN_INFO, LOG_NODE | LOG_DISCOVERY, "0011 Free RPI x%x on " - "ndlp:x%px did x%x\n", + "ndlp: %p did x%x\n", ndlp->nlp_rpi, ndlp, ndlp->nlp_DID); lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi); @@ -3513,8 +3520,18 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) if (ndlp->nlp_type & NLP_FABRIC) { lpfc_disc_state_machine(vports[i], ndlp, NULL, NLP_EVT_DEVICE_RECOVERY); - lpfc_disc_state_machine(vports[i], ndlp, - NULL, NLP_EVT_DEVICE_RM); + + /* Don't remove the node unless the + * has been unregistered with the + * transport. If so, let dev_loss + * take care of the node. + */ + if (!(ndlp->fc4_xpt_flags & + (NVME_XPT_REGD | SCSI_XPT_REGD))) + lpfc_disc_state_machine + (vports[i], ndlp, + NULL, + NLP_EVT_DEVICE_RM); } } } @@ -12501,13 +12518,11 @@ lpfc_pci_remove_one_s3(struct pci_dev *pdev) /* Remove FC host with the physical port */ fc_remove_host(shost); + scsi_remove_host(shost); /* Clean up all nodes, mailboxes and IOs. */ lpfc_cleanup(vport); - /* Remove the shost now that the devices connections are lost. */ - scsi_remove_host(shost); - /* * Bring down the SLI Layer. This step disable all interrupts, * clears the rings, discards all mailbox commands, and resets @@ -13359,6 +13374,7 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev) /* Remove FC host with the physical port */ fc_remove_host(shost); + scsi_remove_host(shost); /* Perform ndlp cleanup on the physical port. The nvme and nvmet * localports are destroyed after to cleanup all transport memory. @@ -13371,9 +13387,6 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev) if (phba->cfg_xri_rebalancing) lpfc_destroy_multixri_pools(phba); - /* Remove the shost now that the devices connections are lost. */ - scsi_remove_host(shost); - /* * Bring down the SLI Layer. This step disables all interrupts, * clears the rings, discards all mailbox commands, and resets diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 3513e1ea609c..defdde760dbc 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -356,39 +356,47 @@ lpfc_nvme_remoteport_delete(struct nvme_fc_remote_port *remoteport) struct lpfc_nvme_rport *rport = remoteport->private; struct lpfc_vport *vport; struct lpfc_nodelist *ndlp; + u32 fc4_xpt_flags; ndlp = rport->ndlp; - if (!ndlp) + if (!ndlp) { + pr_err("**** %s: NULL ndlp on rport %p remoteport %p\n", + __func__, rport, remoteport); goto rport_err; + } vport = ndlp->vport; - if (!vport) + if (!vport) { + pr_err("**** %s: Null vport on ndlp %p, ste x%x rport %p\n", + __func__, ndlp, ndlp->nlp_state, rport); goto rport_err; + } + + fc4_xpt_flags = NVME_XPT_REGD | SCSI_XPT_REGD; /* Remove this rport from the lport's list - memory is owned by the * transport. Remove the ndlp reference for the NVME transport before * calling state machine to remove the node. */ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, - "6146 remoteport delete of remoteport x%px\n", + "6146 remoteport delete of remoteport %p\n", remoteport); spin_lock_irq(&vport->phba->hbalock); /* The register rebind might have occurred before the delete * downcall. Guard against this race. */ - if (ndlp->upcall_flags & NLP_WAIT_FOR_UNREG) { - ndlp->nrport = NULL; - ndlp->upcall_flags &= ~NLP_WAIT_FOR_UNREG; - spin_unlock_irq(&vport->phba->hbalock); + if (ndlp->fc4_xpt_flags & NLP_WAIT_FOR_UNREG) + ndlp->fc4_xpt_flags &= ~(NLP_WAIT_FOR_UNREG | NVME_XPT_REGD); - /* Remove original register reference. The host transport - * won't reference this rport/remoteport any further. - */ - lpfc_nlp_put(ndlp); - } else { - spin_unlock_irq(&vport->phba->hbalock); - } + spin_unlock_irq(&vport->phba->hbalock); + + /* On a devloss timeout event, one more put is executed provided the + * NVME and SCSI rport unregister requests are complete. If the vport + * is unloading, this extra put is executed by lpfc_drop_node. + */ + if (!(ndlp->fc4_xpt_flags & fc4_xpt_flags)) + lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); rport_err: return; @@ -660,6 +668,7 @@ lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, "Data: x%x x%x rc x%x\n", ndlp->nlp_DID, genwqe->iotag, vport->port_state, rc); + lpfc_nlp_put(ndlp); lpfc_sli_release_iocbq(phba, genwqe); return 1; } @@ -1687,7 +1696,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport, "IO. State x%x, Type x%x Flg x%x\n", pnvme_rport->port_id, ndlp->nlp_state, ndlp->nlp_type, - ndlp->upcall_flags); + ndlp->fc4_xpt_flags); atomic_inc(&lport->xmt_fcp_bad_ndlp); ret = -EBUSY; goto out_fail; @@ -2483,7 +2492,8 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) * race that leaves the WAIT flag set. */ spin_lock_irq(&vport->phba->hbalock); - ndlp->upcall_flags &= ~NLP_WAIT_FOR_UNREG; + ndlp->fc4_xpt_flags &= ~NLP_WAIT_FOR_UNREG; + ndlp->fc4_xpt_flags |= NVME_XPT_REGD; spin_unlock_irq(&vport->phba->hbalock); rport = remote_port->private; if (oldrport) { @@ -2494,7 +2504,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) */ spin_lock_irq(&vport->phba->hbalock); ndlp->nrport = NULL; - ndlp->upcall_flags &= ~NLP_WAIT_FOR_UNREG; + ndlp->fc4_xpt_flags &= ~NLP_WAIT_FOR_UNREG; spin_unlock_irq(&vport->phba->hbalock); rport->ndlp = NULL; rport->remoteport = NULL; @@ -2631,10 +2641,11 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, "6033 Unreg nvme remoteport x%px, portname x%llx, " - "port_id x%06x, portstate x%x port type x%x\n", + "port_id x%06x, portstate x%x port type x%x " + "refcnt %d\n", remoteport, remoteport->port_name, remoteport->port_id, remoteport->port_state, - ndlp->nlp_type); + ndlp->nlp_type, kref_read(&ndlp->kref)); /* Sanity check ndlp type. Only call for NVME ports. Don't * clear any rport state until the transport calls back. @@ -2644,7 +2655,9 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) /* No concern about the role change on the nvme remoteport. * The transport will update it. */ - ndlp->upcall_flags |= NLP_WAIT_FOR_UNREG; + spin_lock_irq(&vport->phba->hbalock); + ndlp->fc4_xpt_flags |= NLP_WAIT_FOR_UNREG; + spin_unlock_irq(&vport->phba->hbalock); /* Don't let the host nvme transport keep sending keep-alives * on this remoteport. Vport is unloading, no recovery. The @@ -2655,8 +2668,15 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) (void)nvme_fc_set_remoteport_devloss(remoteport, 0); ret = nvme_fc_unregister_remoteport(remoteport); + + /* The driver no longer knows if the nrport memory is valid. + * because the controller teardown process has begun and + * is asynchronous. Break the binding in the ndlp. Also + * remove the register ndlp reference to setup node release. + */ + ndlp->nrport = NULL; + lpfc_nlp_put(ndlp); if (ret != 0) { - lpfc_nlp_put(ndlp); lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6167 NVME unregister failed %d " "port_state x%x\n", diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h index 4a4c3f780e1f..4e11ce8d5e31 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.h +++ b/drivers/scsi/lpfc/lpfc_nvme.h @@ -38,7 +38,7 @@ #define LPFC_NVME_INFO_MORE_STR "\nCould be more info...\n" #define lpfc_ndlp_get_nrport(ndlp) \ - ((!ndlp->nrport || (ndlp->upcall_flags & NLP_WAIT_FOR_UNREG)) \ + ((!ndlp->nrport || (ndlp->fc4_xpt_flags & NLP_WAIT_FOR_UNREG)) \ ? NULL : ndlp->nrport) struct lpfc_nvme_qhandle { diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 1232fad17d1e..1f020d2abfa0 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2528,9 +2528,10 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) vport, KERN_INFO, LOG_MBOX | LOG_DISCOVERY, "1438 UNREG cmpl deferred mbox x%x " - "on NPort x%x Data: x%x x%x %px\n", + "on NPort x%x Data: x%x x%x %px x%x x%x\n", ndlp->nlp_rpi, ndlp->nlp_DID, - ndlp->nlp_flag, ndlp->nlp_defer_did, ndlp); + ndlp->nlp_flag, ndlp->nlp_defer_did, + ndlp, vport->load_flag, kref_read(&ndlp->kref)); if ((ndlp->nlp_flag & NLP_UNREG_INP) && (ndlp->nlp_defer_did != NLP_EVT_NOTHING_PENDING)) { @@ -2585,7 +2586,7 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) LPFC_SLI_INTF_IF_TYPE_2)) { if (ndlp) { lpfc_printf_vlog( - vport, KERN_INFO, LOG_MBOX | LOG_SLI, + vport, KERN_INFO, LOG_MBOX | LOG_SLI, "0010 UNREG_LOGIN vpi:%x " "rpi:%x DID:%x defer x%x flg x%x " "%px\n", @@ -13415,6 +13416,12 @@ lpfc_sli4_sp_handle_mbox_event(struct lpfc_hba *phba, struct lpfc_mcqe *mcqe) pmbox->un.varWords[0], pmb); pmb->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi; pmb->ctx_buf = mp; + + /* No reference taken here. This is a default + * RPI reg/immediate unreg cycle. The reference was + * taken in the reg rpi path and is released when + * this mailbox completes. + */ pmb->ctx_ndlp = ndlp; pmb->vport = vport; rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 0261495b44d3..f590d18b3f06 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -593,16 +593,14 @@ lpfc_vport_disable(struct fc_vport *fc_vport, bool disable) return enable_vport(fc_vport); } - int lpfc_vport_delete(struct fc_vport *fc_vport) { struct lpfc_nodelist *ndlp = NULL; struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - struct lpfc_hba *phba = vport->phba; + struct lpfc_hba *phba = vport->phba; long timeout; - bool ns_ndlp_referenced = false; if (vport->port_type == LPFC_PHYSICAL_PORT) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, @@ -619,9 +617,11 @@ lpfc_vport_delete(struct fc_vport *fc_vport) "static vport.\n"); return VPORT_ERROR; } + spin_lock_irq(&phba->hbalock); vport->load_flag |= FC_UNLOADING; spin_unlock_irq(&phba->hbalock); + /* * If we are not unloading the driver then prevent the vport_delete * from happening until after this vport's discovery is finished. @@ -649,52 +649,22 @@ lpfc_vport_delete(struct fc_vport *fc_vport) return VPORT_INVAL; lpfc_free_sysfs_attr(vport); - lpfc_debugfs_terminate(vport); - /* - * The call to fc_remove_host might release the NameServer ndlp. Since - * we might need to use the ndlp to send the DA_ID CT command, - * increment the reference for the NameServer ndlp to prevent it from - * being released. - */ - ndlp = lpfc_findnode_did(vport, NameServer_DID); - if (ndlp) { - lpfc_nlp_get(ndlp); - ns_ndlp_referenced = true; - } - /* Remove FC host to break driver binding. */ fc_remove_host(shost); + scsi_remove_host(shost); - ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); - - /* In case of driver unload, we shall not perform fabric logo as the - * worker thread already stopped at this stage and, in this case, we - * can safely skip the fabric logo. - */ - if (phba->pport->load_flag & FC_UNLOADING) { - if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE && - phba->link_state >= LPFC_LINK_UP) { - /* First look for the Fabric ndlp */ - ndlp = lpfc_findnode_did(vport, Fabric_DID); - if (!ndlp) - goto skip_logo; - - /* Remove ndlp from vport npld list */ - lpfc_dequeue_node(vport, ndlp); - - /* Kick off release ndlp when it can be safely done */ - lpfc_nlp_put(ndlp); - } + /* Send the DA_ID and Fabric LOGO to cleanup Nameserver entries. */ + ndlp = lpfc_findnode_did(vport, Fabric_DID); + if (!ndlp) goto skip_logo; - } - /* Otherwise, we will perform fabric logo as needed */ if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE && phba->link_state >= LPFC_LINK_UP && phba->fc_topology != LPFC_TOPOLOGY_LOOP) { if (vport->cfg_enable_da_id) { + /* Send DA_ID and wait for a completion. */ timeout = msecs_to_jiffies(phba->fc_ratov * 2000); if (!lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0)) while (vport->ct_flags && timeout) @@ -705,25 +675,19 @@ lpfc_vport_delete(struct fc_vport *fc_vport) "1829 CT command failed to " "delete objects on fabric\n"); } - /* First look for the Fabric ndlp */ - ndlp = lpfc_findnode_did(vport, Fabric_DID); - if (!ndlp) { - /* Cannot find existing Fabric ndlp, allocate one */ - ndlp = lpfc_nlp_init(vport, Fabric_DID); - if (!ndlp) - goto skip_logo; - } /* * If the vpi is not registered, then a valid FDISC doesn't * exist and there is no need for a ELS LOGO. Just cleanup * the ndlp. */ - if (!(vport->vpi_state & LPFC_VPI_REGISTERED)) { - lpfc_nlp_put(ndlp); + if (!(vport->vpi_state & LPFC_VPI_REGISTERED)) goto skip_logo; - } + /* Issue a Fabric LOGO to cleanup fabric resources. */ + ndlp = lpfc_findnode_did(vport, Fabric_DID); + if (!ndlp) + goto skip_logo; vport->unreg_vpi_cmpl = VPORT_INVAL; timeout = msecs_to_jiffies(phba->fc_ratov * 2000); if (!lpfc_issue_els_npiv_logo(vport, ndlp)) @@ -736,21 +700,10 @@ lpfc_vport_delete(struct fc_vport *fc_vport) skip_logo: - /* - * If the NameServer ndlp has been incremented to allow the DA_ID CT - * command to be sent, decrement the ndlp now. - */ - if (ns_ndlp_referenced) { - ndlp = lpfc_findnode_did(vport, NameServer_DID); - lpfc_nlp_put(ndlp); - } - lpfc_cleanup(vport); /* Remove scsi host now. The nodes are cleaned up. */ - scsi_remove_host(shost); lpfc_sli_host_down(vport); - lpfc_stop_vport_timers(vport); if (!(phba->pport->load_flag & FC_UNLOADING)) { -- cgit v1.2.3 From c6adba150191762a7e58644f9e522d9d6d945e1c Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:34 -0800 Subject: scsi: lpfc: Rework remote port lock handling Currently the discovery layers within the driver use the SCSI midlayer host_lock to access node-specific structures. This can contend with the I/O path and is too coarse of a lock. Rework the driver so that it uses a lock specific to the remote port node structure when accessing the structure contents. A few of the changes brought out spots were some slightly reorganized routines worked better. Link: https://lore.kernel.org/r/20201115192646.12977-6-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 2 - drivers/scsi/lpfc/lpfc_attr.c | 8 +- drivers/scsi/lpfc/lpfc_ct.c | 10 +- drivers/scsi/lpfc/lpfc_debugfs.c | 4 +- drivers/scsi/lpfc/lpfc_disc.h | 3 + drivers/scsi/lpfc/lpfc_els.c | 168 ++++++++--------- drivers/scsi/lpfc/lpfc_hbadisc.c | 372 +++++++++++++++---------------------- drivers/scsi/lpfc/lpfc_init.c | 11 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 181 +++++++----------- drivers/scsi/lpfc/lpfc_nvme.c | 30 +-- drivers/scsi/lpfc/lpfc_scsi.c | 4 +- drivers/scsi/lpfc/lpfc_sli.c | 17 +- 12 files changed, 345 insertions(+), 465 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 3c77e02d36b0..2b92aa7a0762 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -1131,8 +1131,6 @@ struct lpfc_hba { uint8_t hb_outstanding; struct timer_list rrq_tmr; enum hba_temp_state over_temp_state; - /* ndlp reference management */ - spinlock_t ndlp_lock; /* * Following bit will be set for all buffer tags which are not * associated with any HBQ. diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 1987554dcd8f..4528166dee36 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -368,11 +368,11 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr, list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { nrport = NULL; - spin_lock(&vport->phba->hbalock); + spin_lock(&ndlp->lock); rport = lpfc_ndlp_get_nrport(ndlp); if (rport) nrport = rport->remoteport; - spin_unlock(&vport->phba->hbalock); + spin_unlock(&ndlp->lock); if (!nrport) continue; @@ -3637,11 +3637,11 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport) if (ndlp->rport) ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo; #if (IS_ENABLED(CONFIG_NVME_FC)) - spin_lock(&vport->phba->hbalock); + spin_lock(&ndlp->lock); rport = lpfc_ndlp_get_nrport(ndlp); if (rport) remoteport = rport->remoteport; - spin_unlock(&vport->phba->hbalock); + spin_unlock(&ndlp->lock); if (rport && remoteport) nvme_fc_set_remoteport_devloss(remoteport, vport->cfg_devloss_tmo); diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 9a492aa284f9..ef4b8620c0e8 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -825,7 +825,6 @@ lpfc_ns_rsp_audit_did(struct lpfc_vport *vport, uint32_t Did, uint8_t fc4_type) { struct lpfc_hba *phba = vport->phba; struct lpfc_nodelist *ndlp = NULL; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); char *str; if (phba->cfg_ns_query == LPFC_NS_QUERY_GID_FT) @@ -854,12 +853,12 @@ lpfc_ns_rsp_audit_did(struct lpfc_vport *vport, uint32_t Did, uint8_t fc4_type) if (ndlp->nlp_type != NLP_NVME_INITIATOR || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) continue; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); if (ndlp->nlp_DID == Did) ndlp->nlp_flag &= ~NLP_NVMET_RECOV; else ndlp->nlp_flag |= NLP_NVMET_RECOV; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); } } } @@ -875,7 +874,6 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint8_t fc4_type, uint32_t Did, CTentry; int Cnt; struct list_head head; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_nodelist *ndlp = NULL; lpfc_set_disctmo(vport); @@ -921,9 +919,9 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint8_t fc4_type, continue; lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RECOVERY); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_NVMET_RECOV; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); } } diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index af1e15cf9c12..9ecf8962b2a0 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -955,13 +955,13 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size) len += scnprintf(buf + len, size - len, "\tRport List:\n"); list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { /* local short-hand pointer. */ - spin_lock(&phba->hbalock); + spin_lock(&ndlp->lock); rport = lpfc_ndlp_get_nrport(ndlp); if (rport) nrport = rport->remoteport; else nrport = NULL; - spin_unlock(&phba->hbalock); + spin_unlock(&ndlp->lock); if (!nrport) continue; diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index b831f10a686c..7757175a5c37 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h @@ -81,6 +81,9 @@ struct lpfc_nodelist { struct list_head nlp_listp; struct lpfc_name nlp_portname; struct lpfc_name nlp_nodename; + + spinlock_t lock; /* Node management lock */ + uint32_t nlp_flag; /* entry flags */ uint32_t nlp_DID; /* FC D_ID of entry */ uint32_t nlp_last_elscmd; /* Last ELS cmd sent */ diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index c3e3a6afd91e..020300b97bd3 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -769,9 +769,9 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if ((np->nlp_state != NLP_STE_NPR_NODE) || !(np->nlp_flag & NLP_NPR_ADISC)) continue; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&np->lock); np->nlp_flag &= ~NLP_NPR_ADISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&np->lock); lpfc_unreg_rpi(vport, np); } lpfc_cleanup_pending_mbox(vport); @@ -915,9 +915,9 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, sizeof(struct lpfc_name)); /* Set state will put ndlp onto node list if not already done */ lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_NPR_2B_DISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!mbox) @@ -1589,7 +1589,6 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, struct lpfc_nodelist *ndlp) { struct lpfc_vport *vport = ndlp->vport; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_nodelist *new_ndlp; struct serv_parm *sp; uint8_t name[sizeof(struct lpfc_name)]; @@ -1677,7 +1676,9 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, ndlp->active_rrqs_xri_bitmap, phba->cfg_rrq_xri_bitmap_sz); - spin_lock_irq(shost->host_lock); + /* Lock both ndlps */ + spin_lock_irq(&ndlp->lock); + spin_lock_irq(&new_ndlp->lock); keep_new_nlp_flag = new_ndlp->nlp_flag; keep_nlp_flag = ndlp->nlp_flag; new_ndlp->nlp_flag = ndlp->nlp_flag; @@ -1708,7 +1709,8 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, else ndlp->nlp_flag &= ~NLP_RPI_REGISTERED; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&new_ndlp->lock); + spin_unlock_irq(&ndlp->lock); /* Set nlp_states accordingly */ keep_nlp_state = new_ndlp->nlp_state; @@ -1945,10 +1947,10 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* Since ndlp can be freed in the disc state machine, note if this node * is being used during discovery. */ - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); /* PLOGI completes to NPort */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, @@ -1960,9 +1962,9 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* Check to see if link went down during discovery */ if (lpfc_els_chk_latt(vport)) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_NPR_2B_DISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); goto out; } @@ -1971,9 +1973,9 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (lpfc_els_retry(phba, cmdiocb, rspiocb)) { /* ELS command is being retried */ if (disc) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_NPR_2B_DISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); } goto out; } @@ -2093,9 +2095,9 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) return 1; shost = lpfc_shost_from_vport(vport); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_FCP_PRLI_RJT; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); @@ -2175,7 +2177,6 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { struct lpfc_vport *vport = cmdiocb->vport; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); IOCB_t *irsp; struct lpfc_nodelist *ndlp; char *mode; @@ -2186,13 +2187,13 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, irsp = &(rspiocb->iocb); ndlp = (struct lpfc_nodelist *) cmdiocb->context1; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_PRLI_SND; /* Driver supports multiple FC4 types. Counters matter. */ vport->fc_prli_sent--; ndlp->fc4_prli_sent--; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "PRLI cmpl: status:x%x/x%x did:x%x", @@ -2284,7 +2285,6 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, uint8_t retry) { int rc = 0; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; PRLI *npr; struct lpfc_nvme_prli *npr_nvme; @@ -2421,7 +2421,7 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, phba->fc_stat.elsXmitPRLI++; elsiocb->iocb_cmpl = lpfc_cmpl_els_prli; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_PRLI_SND; /* The vport counters are used for lpfc_scan_finished, but @@ -2430,7 +2430,7 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, */ vport->fc_prli_sent++; ndlp->fc4_prli_sent++; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "Issue PRLI: did:x%x refcnt %d", @@ -2456,9 +2456,9 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, node_err: lpfc_nlp_put(ndlp); io_err: - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_PRLI_SND; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_els_free_iocb(phba, elsiocb); return 1; } @@ -2601,7 +2601,6 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { struct lpfc_vport *vport = cmdiocb->vport; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); IOCB_t *irsp; struct lpfc_nodelist *ndlp; int disc; @@ -2620,10 +2619,10 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* Since ndlp can be freed in the disc state machine, note if this node * is being used during discovery. */ - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); ndlp->nlp_flag &= ~(NLP_ADISC_SND | NLP_NPR_2B_DISC); - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); /* ADISC completes to NPort */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0104 ADISC completes to NPort x%x " @@ -2632,9 +2631,9 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, irsp->ulpTimeout, disc, vport->num_disc_nodes); /* Check to see if link went down during discovery */ if (lpfc_els_chk_latt(vport)) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_NPR_2B_DISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); goto out; } @@ -2643,9 +2642,9 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if (lpfc_els_retry(phba, cmdiocb, rspiocb)) { /* ELS command is being retried */ if (disc) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_NPR_2B_DISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_set_disctmo(vport); } goto out; @@ -2698,7 +2697,6 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, uint8_t retry) { int rc = 0; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; ADISC *ap; struct lpfc_iocbq *elsiocb; @@ -2726,9 +2724,9 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, phba->fc_stat.elsXmitADISC++; elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_ADISC_SND; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) goto node_err; @@ -2744,9 +2742,9 @@ lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, io_err: lpfc_nlp_put(ndlp); node_err: - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_ADISC_SND; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_els_free_iocb(phba, elsiocb); return 1; } @@ -2769,7 +2767,6 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, { struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; struct lpfc_vport *vport = ndlp->vport; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); IOCB_t *irsp; struct lpfcMboxq *mbox; unsigned long flags; @@ -2779,9 +2776,9 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, cmdiocb->context_un.rsp_iocb = rspiocb; irsp = &(rspiocb->iocb); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_LOGO_SND; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, "LOGO cmpl: status:x%x/x%x did:x%x", @@ -2871,9 +2868,9 @@ out: if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET) && skip_recovery == 0) { lpfc_cancel_retry_delay_tmo(vport, ndlp); - spin_lock_irqsave(shost->host_lock, flags); + spin_lock_irqsave(&ndlp->lock, flags); ndlp->nlp_flag |= NLP_NPR_2B_DISC; - spin_unlock_irqrestore(shost->host_lock, flags); + spin_unlock_irqrestore(&ndlp->lock, flags); lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "3187 LOGO completes to NPort x%x: Start " @@ -2912,19 +2909,18 @@ int lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, uint8_t retry) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *elsiocb; uint8_t *pcmd; uint16_t cmdsize; int rc; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); if (ndlp->nlp_flag & NLP_LOGO_SND) { - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); return 0; } - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); cmdsize = (2 * sizeof(uint32_t)) + sizeof(struct lpfc_name); elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, @@ -2943,10 +2939,10 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, phba->fc_stat.elsXmitLOGO++; elsiocb->iocb_cmpl = lpfc_cmpl_els_logo; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_LOGO_SND; ndlp->nlp_flag &= ~NLP_ISSUE_LOGO; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) goto node_err; @@ -2958,18 +2954,18 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (rc == IOCB_ERROR) goto io_err; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_prev_state = ndlp->nlp_state; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_nlp_set_state(vport, ndlp, NLP_STE_LOGO_ISSUE); return 0; io_err: lpfc_nlp_put(ndlp); node_err: - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_LOGO_SND; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_els_free_iocb(phba, elsiocb); return 1; } @@ -3522,9 +3518,9 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) if (!(nlp->nlp_flag & NLP_DELAY_TMO)) return; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&nlp->lock); nlp->nlp_flag &= ~NLP_DELAY_TMO; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&nlp->lock); del_timer_sync(&nlp->nlp_delayfunc); nlp->nlp_last_elscmd = 0; if (!list_empty(&nlp->els_retry_evt.evt_listp)) { @@ -3534,9 +3530,9 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) lpfc_nlp_put((struct lpfc_nodelist *)evtp->evt_arg1); } if (nlp->nlp_flag & NLP_NPR_2B_DISC) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&nlp->lock); nlp->nlp_flag &= ~NLP_NPR_2B_DISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&nlp->lock); if (vport->num_disc_nodes) { if (vport->port_state < LPFC_VPORT_READY) { /* Check if there are more ADISCs to be sent */ @@ -3612,20 +3608,19 @@ void lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp) { struct lpfc_vport *vport = ndlp->vport; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); uint32_t cmd, retry; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); cmd = ndlp->nlp_last_elscmd; ndlp->nlp_last_elscmd = 0; if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); return; } ndlp->nlp_flag &= ~NLP_DELAY_TMO; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); /* * If a discovery event readded nlp_delayfunc after timer * firing and before processing the timer, cancel the @@ -3754,7 +3749,6 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb) { struct lpfc_vport *vport = cmdiocb->vport; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); IOCB_t *irsp = &rspiocb->iocb; struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1; struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; @@ -4012,9 +4006,9 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, */ if (stat.un.b.lsRjtRsnCodeExp == LSEXP_REQ_UNSUPPORTED && cmd == ELS_CMD_PRLI) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_FCP_PRLI_RJT; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); retry = 0; goto out_retry; } @@ -4117,9 +4111,9 @@ out_retry: /* delay is specified in milliseconds */ mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(delay)); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_DELAY_TMO; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); ndlp->nlp_prev_state = ndlp->nlp_state; if ((cmd == ELS_CMD_PRLI) || @@ -4596,11 +4590,11 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } out: if (ndlp && shost) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); if (mbox) ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN; ndlp->nlp_flag &= ~NLP_RM_DFLT_RPI; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); /* If the node is not being used by another discovery thread, * and we are sending a reject, we are done with it. @@ -4652,7 +4646,6 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp, LPFC_MBOXQ_t *mbox) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; IOCB_t *icmd; IOCB_t *oldcmd; @@ -4671,9 +4664,9 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, ndlp->nlp_DID, ELS_CMD_ACC); if (!elsiocb) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_LOGO_ACC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); return 1; } @@ -4777,11 +4770,11 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag, return 1; } if (ndlp->nlp_flag & NLP_LOGO_ACC) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED || ndlp->nlp_flag & NLP_REG_LOGIN_SEND)) ndlp->nlp_flag &= ~NLP_LOGO_ACC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc; } else { elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; @@ -5408,9 +5401,9 @@ lpfc_els_disc_adisc(struct lpfc_vport *vport) if (ndlp->nlp_state == NLP_STE_NPR_NODE && (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 && (ndlp->nlp_flag & NLP_NPR_ADISC) != 0) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_NPR_ADISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); ndlp->nlp_prev_state = ndlp->nlp_state; lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE); lpfc_issue_els_adisc(vport, ndlp, 0); @@ -8577,14 +8570,14 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, * if the ndlp is in DEV_LOSS */ shost = lpfc_shost_from_vport(vport); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); if (ndlp->nlp_flag & NLP_IN_DEV_LOSS) { - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); if (newnode) lpfc_nlp_put(ndlp); goto dropit; } - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) @@ -8650,9 +8643,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, } } - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_TARGET_REMOVE; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PLOGI); @@ -9347,9 +9340,9 @@ lpfc_retry_pport_discovery(struct lpfc_hba *phba) shost = lpfc_shost_from_vport(phba->pport); mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000)); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_DELAY_TMO; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); ndlp->nlp_last_elscmd = ELS_CMD_FLOGI; phba->pport->port_state = LPFC_FLOGI; return; @@ -9474,9 +9467,9 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, if ((np->nlp_state != NLP_STE_NPR_NODE) || !(np->nlp_flag & NLP_NPR_ADISC)) continue; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); np->nlp_flag &= ~NLP_NPR_ADISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_unreg_rpi(vport, np); } lpfc_cleanup_pending_mbox(vport); @@ -9710,7 +9703,6 @@ int lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) { int rc = 0; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *elsiocb; uint8_t *pcmd; @@ -9736,9 +9728,9 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ndlp->nlp_DID, ndlp->nlp_flag, 0); elsiocb->iocb_cmpl = lpfc_cmpl_els_npiv_logo; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_LOGO_SND; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); elsiocb->context1 = lpfc_nlp_get(ndlp); if (!elsiocb->context1) goto node_err; @@ -9750,9 +9742,9 @@ lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) io_err: lpfc_nlp_put(ndlp); node_err: - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_LOGO_SND; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_els_free_iocb(phba, elsiocb); return 1; } @@ -10235,10 +10227,10 @@ lpfc_sli_abts_recover_port(struct lpfc_vport *vport, * The rport is not responding. Remove the FCP-2 flag to prevent * an ADISC in the follow-up recovery code. */ - spin_lock_irqsave(shost->host_lock, flags); + spin_lock_irqsave(&ndlp->lock, flags); ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; ndlp->nlp_flag |= NLP_ISSUE_LOGO; - spin_unlock_irqrestore(shost->host_lock, flags); + spin_unlock_irqrestore(&ndlp->lock, flags); lpfc_unreg_rpi(vport, ndlp); } diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 71ef50c65dcf..8c99e89c7685 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -73,34 +73,69 @@ static void lpfc_unregister_fcfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); static int lpfc_fcf_inuse(struct lpfc_hba *); static void lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *); -void -lpfc_terminate_rport_io(struct fc_rport *rport) +/* The source of a terminate rport I/O is either a dev_loss_tmo + * event or a call to fc_remove_host. While the rport should be + * valid during these downcalls, the transport can call twice + * in a single event. This routine provides somoe protection + * as the NDLP isn't really free, just released to the pool. + */ +static int +lpfc_rport_invalid(struct fc_rport *rport) { struct lpfc_rport_data *rdata; - struct lpfc_nodelist * ndlp; - struct lpfc_hba *phba; + struct lpfc_nodelist *ndlp; + struct lpfc_vport *vport; + + if (!rport) { + pr_err("**** %s: NULL rport, exit.\n", __func__); + return -EINVAL; + } rdata = rport->dd_data; + if (!rdata) { + pr_err("**** %s: NULL dd_data on rport %p SID x%x\n", + __func__, rport, rport->scsi_target_id); + return -EINVAL; + } + ndlp = rdata->pnode; + if (!rdata->pnode) { + pr_err("**** %s: NULL ndlp on rport %p SID x%x\n", + __func__, rport, rport->scsi_target_id); + return -EINVAL; + } - if (!ndlp) { - if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) - printk(KERN_ERR "Cannot find remote node" - " to terminate I/O Data x%x\n", - rport->port_id); - return; + vport = ndlp->vport; + if (!ndlp->vport) { + pr_err("**** %s: Null vport on ndlp %p, DID x%x rport %p " + "SID x%x\n", __func__, ndlp, ndlp->nlp_DID, rport, + rport->scsi_target_id); + return -EINVAL; } + return 0; +} - phba = ndlp->phba; +void +lpfc_terminate_rport_io(struct fc_rport *rport) +{ + struct lpfc_rport_data *rdata; + struct lpfc_nodelist *ndlp; + struct lpfc_vport *vport; - lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT, - "rport terminate: sid:x%x did:x%x flg:x%x", - ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); + if (lpfc_rport_invalid(rport)) + return; + + rdata = rport->dd_data; + ndlp = rdata->pnode; + vport = ndlp->vport; + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, + "rport terminate: sid:x%x did:x%x flg:x%x", + ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); if (ndlp->nlp_sid != NLP_NO_SID) { - lpfc_sli_abort_iocb(ndlp->vport, - &phba->sli.sli3_ring[LPFC_FCP_RING], - ndlp->nlp_sid, 0, LPFC_CTX_TGT); + lpfc_sli_abort_iocb(vport, + &vport->phba->sli.sli3_ring[LPFC_FCP_RING], + ndlp->nlp_sid, 0, LPFC_CTX_TGT); } } @@ -110,17 +145,13 @@ lpfc_terminate_rport_io(struct fc_rport *rport) void lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) { - struct lpfc_rport_data *rdata; - struct lpfc_nodelist * ndlp; + struct lpfc_nodelist *ndlp; struct lpfc_vport *vport; - struct Scsi_Host *shost; struct lpfc_hba *phba; struct lpfc_work_evt *evtp; - int put_node; unsigned long iflags; - rdata = rport->dd_data; - ndlp = rdata->pnode; + ndlp = ((struct lpfc_rport_data *)rport->dd_data)->pnode; if (!ndlp) return; @@ -132,19 +163,24 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag); lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, - "3181 dev_loss_callbk x%06x, rport x%px flg x%x\n", - ndlp->nlp_DID, ndlp->rport, ndlp->nlp_flag); + "3181 dev_loss_callbk x%06x, rport %p flg x%x " + "load_flag x%x refcnt %d\n", + ndlp->nlp_DID, ndlp->rport, ndlp->nlp_flag, + vport->load_flag, kref_read(&ndlp->kref)); - /* Don't defer this if we are in the process of deleting the vport - * or unloading the driver. The unload will cleanup the node - * appropriately we just need to cleanup the ndlp rport info here. + /* Don't schedule a worker thread event if the vport is going down. + * The teardown process cleans up the node via lpfc_drop_node. */ if (vport->load_flag & FC_UNLOADING) { - put_node = rdata->pnode != NULL; - rdata->pnode = NULL; + ((struct lpfc_rport_data *)rport->dd_data)->pnode = NULL; ndlp->rport = NULL; - if (put_node) - lpfc_nlp_put(ndlp); + + ndlp->fc4_xpt_flags &= ~SCSI_XPT_REGD; + + /* Remove the node reference from remote_port_add now. + * The driver will not call remote_port_delete. + */ + lpfc_nlp_put(ndlp); return; } @@ -161,15 +197,20 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) if (!list_empty(&evtp->evt_listp)) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, - "6790 rport name %llx dev_loss_evt pending", + "6790 rport name %llx dev_loss_evt pending\n", rport->port_name); return; } - shost = lpfc_shost_from_vport(vport); - spin_lock_irqsave(shost->host_lock, iflags); + spin_lock_irqsave(&ndlp->lock, iflags); ndlp->nlp_flag |= NLP_IN_DEV_LOSS; - spin_unlock_irqrestore(shost->host_lock, iflags); + /* + * The backend does not expect any more calls assoicated with this + * rport, Remove the association between rport and ndlp + */ + ((struct lpfc_rport_data *)rport->dd_data)->pnode = NULL; + ndlp->rport = NULL; + spin_unlock_irqrestore(&ndlp->lock, iflags); /* We need to hold the node by incrementing the reference * count until this queued work is done @@ -200,68 +241,35 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) static int lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) { - struct lpfc_rport_data *rdata; - struct fc_rport *rport; struct lpfc_vport *vport; struct lpfc_hba *phba; struct Scsi_Host *shost; uint8_t *name; - int put_node; int warn_on = 0; int fcf_inuse = 0; unsigned long iflags; + u32 fc4_xpt_flags; - rport = ndlp->rport; vport = ndlp->vport; shost = lpfc_shost_from_vport(vport); + name = (uint8_t *)&ndlp->nlp_portname; + phba = vport->phba; - spin_lock_irqsave(shost->host_lock, iflags); + spin_lock_irqsave(&ndlp->lock, iflags); ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS; - spin_unlock_irqrestore(shost->host_lock, iflags); - - if (!rport) - return fcf_inuse; - - name = (uint8_t *) &ndlp->nlp_portname; - phba = vport->phba; + spin_unlock_irqrestore(&ndlp->lock, iflags); if (phba->sli_rev == LPFC_SLI_REV4) fcf_inuse = lpfc_fcf_inuse(phba); lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, - "rport devlosstmo:did:x%x type:x%x id:x%x", - ndlp->nlp_DID, ndlp->nlp_type, rport->scsi_target_id); + "rport devlosstmo:did:x%x type:x%x id:x%x", + ndlp->nlp_DID, ndlp->nlp_type, ndlp->nlp_sid); lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, - "3182 dev_loss_tmo_handler x%06x, rport x%px flg x%x\n", - ndlp->nlp_DID, ndlp->rport, ndlp->nlp_flag); - - /* - * lpfc_nlp_remove if reached with dangling rport drops the - * reference. To make sure that does not happen clear rport - * pointer in ndlp before lpfc_nlp_put. - */ - rdata = rport->dd_data; - - /* Don't defer this if we are in the process of deleting the vport - * or unloading the driver. The unload will cleanup the node - * appropriately we just need to cleanup the ndlp rport info here. - */ - if (vport->load_flag & FC_UNLOADING) { - if (ndlp->nlp_sid != NLP_NO_SID) { - /* flush the target */ - lpfc_sli_abort_iocb(vport, - &phba->sli.sli3_ring[LPFC_FCP_RING], - ndlp->nlp_sid, 0, LPFC_CTX_TGT); - } - put_node = rdata->pnode != NULL; - rdata->pnode = NULL; - ndlp->rport = NULL; - if (put_node) - lpfc_nlp_put(ndlp); - - return fcf_inuse; - } + "3182 %s x%06x, nflag x%x xflags x%x\n", + __func__, ndlp->nlp_DID, ndlp->nlp_flag, + ndlp->fc4_xpt_flags); if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, @@ -274,12 +282,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) return fcf_inuse; } - put_node = rdata->pnode != NULL; - rdata->pnode = NULL; - ndlp->rport = NULL; - if (put_node) - lpfc_nlp_put(ndlp); - if (ndlp->nlp_type & NLP_FABRIC) return fcf_inuse; @@ -309,11 +311,12 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ndlp->nlp_state, ndlp->nlp_rpi); } - if (!(ndlp->nlp_flag & NLP_DELAY_TMO) && - !(ndlp->nlp_flag & NLP_NPR_2B_DISC) && - (ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && - (ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE) && - (ndlp->nlp_state != NLP_STE_PRLI_ISSUE)) + /* Should be final reference removal triggering a node free. */ + spin_lock_irqsave(shost->host_lock, iflags); + fc4_xpt_flags = ndlp->fc4_xpt_flags; + spin_unlock_irqrestore(shost->host_lock, iflags); + + if (!(fc4_xpt_flags & (NVME_XPT_REGD | SCSI_XPT_REGD))) lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); return fcf_inuse; @@ -3580,7 +3583,6 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) struct lpfc_vport *vport = pmb->vport; struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf); struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); pmb->ctx_buf = NULL; pmb->ctx_ndlp = NULL; @@ -3603,9 +3605,9 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) * there is another reg login in * process. */ - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); /* * We cannot leave the RPI registered because @@ -4157,6 +4159,7 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) struct lpfc_rport_data *rdata; struct fc_rport_identifiers rport_ids; struct lpfc_hba *phba = vport->phba; + unsigned long flags; if (vport->cfg_enable_fc4_type == LPFC_ENABLE_NVME) return; @@ -4167,33 +4170,23 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) rport_ids.port_id = ndlp->nlp_DID; rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; - /* - * We leave our node pointer in rport->dd_data when we unregister a - * FCP target port. But fc_remote_port_add zeros the space to which - * rport->dd_data points. So, if we're reusing a previously - * registered port, drop the reference that we took the last time we - * registered the port. - */ - rport = ndlp->rport; - if (rport) { - rdata = rport->dd_data; - /* break the link before dropping the ref */ - ndlp->rport = NULL; - if (rdata) { - if (rdata->pnode == ndlp) - lpfc_nlp_put(ndlp); - rdata->pnode = NULL; - } - } lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, - "rport add: did:x%x flg:x%x type x%x", - ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); + "rport add: did:x%x flg:x%x type x%x", + ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); /* Don't add the remote port if unloading. */ if (vport->load_flag & FC_UNLOADING) return; + /* + * Disassociate any older association between this ndlp and rport + */ + if (ndlp->rport) { + rdata = ndlp->rport->dd_data; + rdata->pnode = NULL; + } + ndlp->rport = rport = fc_remote_port_add(shost, 0, &rport_ids); if (!rport) { dev_printk(KERN_WARNING, &phba->pcidev->dev, @@ -4201,7 +4194,7 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) return; } - /* initialize static port data */ + /* Successful port add. Complete initializing node data */ rport->maxframe_size = ndlp->nlp_maxframe; rport->supported_classes = ndlp->nlp_class_sup; rdata = rport->dd_data; @@ -4214,6 +4207,10 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) return; } + spin_lock_irqsave(&ndlp->lock, flags); + ndlp->fc4_xpt_flags |= SCSI_XPT_REGD; + spin_unlock_irqrestore(&ndlp->lock, flags); + if (ndlp->nlp_type & NLP_FCP_TARGET) rport_ids.roles |= FC_PORT_ROLE_FCP_TARGET; if (ndlp->nlp_type & NLP_FCP_INITIATOR) @@ -4229,8 +4226,8 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) fc_remote_port_rolechg(rport, rport_ids.roles); lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, - "3183 rport register x%06x, rport x%px role x%x\n", - ndlp->nlp_DID, rport, rport_ids.roles); + "3183 %s rport x%px DID x%x, role x%x\n", + __func__, rport, rport->port_id, rport->roles); if ((rport->scsi_target_id != -1) && (rport->scsi_target_id < LPFC_MAX_TARGET)) { @@ -4254,12 +4251,12 @@ lpfc_unregister_remote_port(struct lpfc_nodelist *ndlp) ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, - "3184 rport unregister x%06x, rport x%px\n", - ndlp->nlp_DID, rport); + "3184 rport unregister x%06x, rport x%px " + "xptflg x%x\n", + ndlp->nlp_DID, rport, ndlp->fc4_xpt_flags); fc_remote_port_delete(rport); - - return; + lpfc_nlp_put(ndlp); } static void @@ -4305,8 +4302,6 @@ static void lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int old_state, int new_state) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - if (new_state == NLP_STE_UNMAPPED_NODE) { ndlp->nlp_flag &= ~NLP_NODEV_REMOVE; ndlp->nlp_type |= NLP_FC_NODE; @@ -4400,9 +4395,9 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, (!ndlp->rport || ndlp->rport->scsi_target_id == -1 || ndlp->rport->scsi_target_id >= LPFC_MAX_TARGET)) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_TGT_NO_SCSIID; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); } } @@ -4821,11 +4816,9 @@ lpfc_set_unreg_login_mbx_cmpl(struct lpfc_hba *phba, struct lpfc_vport *vport, } else { if (vport->load_flag & FC_UNLOADING) { if (phba->sli_rev == LPFC_SLI_REV4) { - spin_lock_irqsave(&vport->phba->ndlp_lock, - iflags); + spin_lock_irqsave(&ndlp->lock, iflags); ndlp->nlp_flag |= NLP_RELEASE_RPI; - spin_unlock_irqrestore(&vport->phba->ndlp_lock, - iflags); + spin_unlock_irqrestore(&ndlp->lock, iflags); } lpfc_nlp_get(ndlp); } @@ -5053,7 +5046,6 @@ lpfc_unreg_default_rpis(struct lpfc_vport *vport) static int lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; LPFC_MBOXQ_t *mb, *nextmb; struct lpfc_dmabuf *mp; @@ -5112,9 +5104,9 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) lpfc_els_abort(phba, ndlp); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_DELAY_TMO; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); ndlp->nlp_last_elscmd = 0; del_timer_sync(&ndlp->nlp_delayfunc); @@ -5131,88 +5123,15 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) !(ndlp->nlp_rpi == LPFC_RPI_ALLOC_ERROR)) { lpfc_sli4_free_rpi(vport->phba, ndlp->nlp_rpi); - spin_lock_irqsave(&vport->phba->ndlp_lock, - iflags); + spin_lock_irqsave(&ndlp->lock, iflags); ndlp->nlp_flag &= ~NLP_RELEASE_RPI; ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR; - spin_unlock_irqrestore(&vport->phba->ndlp_lock, - iflags); + spin_unlock_irqrestore(&ndlp->lock, iflags); } } return 0; } -/* - * Check to see if we can free the nlp back to the freelist. - * If we are in the middle of using the nlp in the discovery state - * machine, defer the free till we reach the end of the state machine. - */ -static void -lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) -{ - struct lpfc_hba *phba = vport->phba; - struct lpfc_rport_data *rdata; - struct fc_rport *rport; - LPFC_MBOXQ_t *mbox; - int rc; - - lpfc_cancel_retry_delay_tmo(vport, ndlp); - if (!(ndlp->nlp_flag & NLP_REG_LOGIN_SEND) && - !(ndlp->nlp_flag & NLP_RPI_REGISTERED) && - phba->sli_rev != LPFC_SLI_REV4) { - /* For this case we need to cleanup the default rpi - * allocated by the firmware. - */ - lpfc_printf_vlog(vport, KERN_INFO, - LOG_NODE | LOG_DISCOVERY, - "0005 Cleanup Default rpi:x%x DID:x%x flg:x%x " - "ref %d ndlp x%px\n", - ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, - kref_read(&ndlp->kref), - ndlp); - if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) - != NULL) { - rc = lpfc_reg_rpi(phba, vport->vpi, ndlp->nlp_DID, - (uint8_t *) &vport->fc_sparam, mbox, ndlp->nlp_rpi); - if (rc) { - mempool_free(mbox, phba->mbox_mem_pool); - } - else { - mbox->mbox_flag |= LPFC_MBX_IMED_UNREG; - mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi; - mbox->vport = vport; - mbox->ctx_ndlp = ndlp; - rc =lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); - if (rc == MBX_NOT_FINISHED) { - mempool_free(mbox, phba->mbox_mem_pool); - } - } - } - } - lpfc_cleanup_node(vport, ndlp); - - /* - * ndlp->rport must be set to NULL before it reaches here - * i.e. break rport/node link before doing lpfc_nlp_put for - * registered rport and then drop the reference of rport. - */ - if (ndlp->rport) { - /* - * extra lpfc_nlp_put dropped the reference of ndlp - * for registered rport so need to cleanup rport - */ - lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE, - "0940 removed node x%px DID x%x " - "rpi %d rport not null x%px\n", - ndlp, ndlp->nlp_DID, ndlp->nlp_rpi, - ndlp->rport); - rport = ndlp->rport; - rdata = rport->dd_data; - rdata->pnode = NULL; - ndlp->rport = NULL; - } -} - static int lpfc_matchdid(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, uint32_t did) @@ -5348,7 +5267,6 @@ lpfc_findnode_mapped(struct lpfc_vport *vport) struct lpfc_nodelist * lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_nodelist *ndlp; ndlp = lpfc_findnode_did(vport, did); @@ -5369,9 +5287,9 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, vport->fc_flag); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_NPR_2B_DISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); return ndlp; } @@ -5413,9 +5331,9 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) ndlp->nlp_prev_state = ndlp->nlp_state; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_NPR_2B_DISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); } else { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "6456 Skip Setup RSCN Node x%x " @@ -5449,9 +5367,9 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) */ lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_NPR_2B_DISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); } return ndlp; } @@ -6199,6 +6117,8 @@ lpfc_nlp_init(struct lpfc_vport *vport, uint32_t did) memset(ndlp, 0, sizeof (struct lpfc_nodelist)); + spin_lock_init(&ndlp->lock); + lpfc_initialize_node(vport, ndlp, did); INIT_LIST_HEAD(&ndlp->nlp_listp); if (vport->phba->sli_rev == LPFC_SLI_REV4) { @@ -6234,18 +6154,28 @@ lpfc_nlp_release(struct kref *kref) { struct lpfc_nodelist *ndlp = container_of(kref, struct lpfc_nodelist, kref); + struct lpfc_vport *vport = ndlp->vport; lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_NODE, "node release: did:x%x flg:x%x type:x%x", ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_type); - lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, - "0279 %s: ndlp:x%px did %x refcnt:%d rpi:%x\n", - __func__, (void *)ndlp, ndlp->nlp_DID, - kref_read(&ndlp->kref), ndlp->nlp_rpi); + lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, + "0279 %s: ndlp:%p did %x refcnt:%d rpi:%x\n", + __func__, ndlp, ndlp->nlp_DID, + kref_read(&ndlp->kref), ndlp->nlp_rpi); /* remove ndlp from action. */ - lpfc_nlp_remove(ndlp->vport, ndlp); + lpfc_cancel_retry_delay_tmo(vport, ndlp); + lpfc_cleanup_node(vport, ndlp); + + /* Clear Node key fields to give other threads notice + * that this node memory is not valid anymore. + */ + ndlp->vport = NULL; + ndlp->nlp_state = NLP_STE_FREED_NODE; + ndlp->nlp_flag = 0; + ndlp->fc4_xpt_flags = 0; /* free ndlp memory for final ndlp release */ kfree(ndlp->lat_data); @@ -6276,15 +6206,15 @@ lpfc_nlp_get(struct lpfc_nodelist *ndlp) * released. */ phba = ndlp->phba; - spin_lock_irqsave(&phba->ndlp_lock, flags); + spin_lock_irqsave(&ndlp->lock, flags); if (!kref_get_unless_zero(&ndlp->kref)) { - spin_unlock_irqrestore(&phba->ndlp_lock, flags); + spin_unlock_irqrestore(&ndlp->lock, flags); lpfc_printf_vlog(ndlp->vport, KERN_WARNING, LOG_NODE, "0276 %s: ndlp:x%px refcnt:%d\n", __func__, (void *)ndlp, kref_read(&ndlp->kref)); return NULL; } - spin_unlock_irqrestore(&phba->ndlp_lock, flags); + spin_unlock_irqrestore(&ndlp->lock, flags); } else { WARN_ONCE(!ndlp, "**** %s, get ref on NULL ndlp!", __func__); } diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 65b9e4e06b9f..f0cbf98e7caa 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -3497,9 +3497,9 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) continue; } - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_NPR_ADISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); /* * Whenever an SLI4 port goes offline, free the * RPI. Get a new RPI when the adapter port @@ -5828,9 +5828,9 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000)); shost = lpfc_shost_from_vport(vport); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_DELAY_TMO; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); ndlp->nlp_last_elscmd = ELS_CMD_FDISC; vport->port_state = LPFC_FDISC; } else { @@ -6280,9 +6280,6 @@ lpfc_setup_driver_resource_phase1(struct lpfc_hba *phba) atomic_set(&phba->dbg_log_dmping, 0); spin_lock_init(&phba->hbalock); - /* Initialize ndlp management spinlock */ - spin_lock_init(&phba->ndlp_lock); - /* Initialize port_list spinlock */ spin_lock_init(&phba->port_list_lock); INIT_LIST_HEAD(&phba->port_list); diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 5c57aeb1fb0b..1eddb40f009c 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -381,7 +381,6 @@ static int lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, struct lpfc_iocbq *cmdiocb) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; struct lpfc_dmabuf *pcmd; uint64_t nlp_portwwn = 0; @@ -617,9 +616,9 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, * command issued in lpfc_cmpl_els_acc(). */ login_mbox->vport = vport; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI); - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); /* * If there is an outstanding PLOGI issued, abort it before @@ -648,9 +647,9 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, * this ELS request. The only way to do this is * to register, then unregister the RPI. */ - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_RM_DFLT_RPI; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD; stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; rc = lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, @@ -739,7 +738,6 @@ static int lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, struct lpfc_iocbq *cmdiocb) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_iocbq *elsiocb; struct lpfc_dmabuf *pcmd; struct serv_parm *sp; @@ -821,9 +819,9 @@ out: /* 1 sec timeout */ mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000)); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_DELAY_TMO; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; ndlp->nlp_prev_state = ndlp->nlp_state; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); @@ -843,9 +841,9 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* Only call LOGO ACC for first LOGO, this avoids sending unnecessary * PLOGIs during LOGO storms from a device. */ - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_LOGO_ACC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); if (els_cmd == ELS_CMD_PRLO) lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL); else @@ -890,9 +888,9 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, */ mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000)); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_DELAY_TMO; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); ndlp->nlp_last_elscmd = ELS_CMD_FDISC; vport->port_state = LPFC_FDISC; } else { @@ -908,9 +906,9 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* Only try to re-login if this is NOT a Fabric Node */ mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000 * 1)); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_DELAY_TMO; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; } @@ -918,9 +916,9 @@ out: ndlp->nlp_prev_state = ndlp->nlp_state; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_NPR_ADISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); /* The driver has to wait until the ACC completes before it continues * processing the LOGO. The action will resume in * lpfc_cmpl_els_logo_acc routine. Since part of processing includes an @@ -1036,12 +1034,10 @@ lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, static uint32_t lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED)) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_NPR_ADISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); return 0; } @@ -1050,16 +1046,16 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) if (vport->cfg_use_adisc && ((vport->fc_flag & FC_RSCN_MODE) || ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) && (ndlp->nlp_type & NLP_FCP_TARGET)))) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_NPR_ADISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); return 1; } } - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_NPR_ADISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_unreg_rpi(vport, ndlp); return 0; } @@ -1196,12 +1192,11 @@ static uint32_t lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_LOGO_ACC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); return ndlp->nlp_state; @@ -1262,9 +1257,9 @@ lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (lpfc_rcv_plogi(vport, ndlp, cmdiocb) && (ndlp->nlp_flag & NLP_NPR_2B_DISC) && (vport->num_disc_nodes)) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); /* Check if there are more PLOGIs to be sent */ lpfc_more_plogi(vport); if (vport->num_disc_nodes == 0) { @@ -1314,7 +1309,6 @@ static uint32_t lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; @@ -1329,9 +1323,9 @@ lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, /* Put ndlp in npr state set plogi timer for 1 sec */ mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000 * 1)); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_DELAY_TMO; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); @@ -1577,12 +1571,10 @@ static uint32_t lpfc_device_rm_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_NODEV_REMOVE; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); return ndlp->nlp_state; } else { /* software abort outstanding PLOGI */ @@ -1599,7 +1591,6 @@ lpfc_device_recov_plogi_issue(struct lpfc_vport *vport, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; /* Don't do anything that will mess up processing of the @@ -1613,9 +1604,9 @@ lpfc_device_recov_plogi_issue(struct lpfc_vport *vport, ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); return ndlp->nlp_state; } @@ -1624,7 +1615,6 @@ static uint32_t lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *cmdiocb; @@ -1635,9 +1625,9 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) { if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); if (vport->num_disc_nodes) lpfc_more_adisc(vport); } @@ -1708,7 +1698,6 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *cmdiocb, *rspiocb; IOCB_t *irsp; @@ -1726,9 +1715,9 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport, /* 1 sec timeout */ mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000)); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_DELAY_TMO; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; memset(&ndlp->nlp_nodename, 0, sizeof(struct lpfc_name)); @@ -1770,12 +1759,10 @@ static uint32_t lpfc_device_rm_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_NODEV_REMOVE; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); return ndlp->nlp_state; } else { /* software abort outstanding ADISC */ @@ -1792,7 +1779,6 @@ lpfc_device_recov_adisc_issue(struct lpfc_vport *vport, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; /* Don't do anything that will mess up processing of the @@ -1806,9 +1792,9 @@ lpfc_device_recov_adisc_issue(struct lpfc_vport *vport, ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_disc_set_adisc(vport, ndlp); return ndlp->nlp_state; } @@ -1950,7 +1936,6 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg; MAILBOX_t *mb = &pmb->u.mb; @@ -1977,9 +1962,9 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, /* Put ndlp in npr state set plogi timer for 1 sec */ mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000 * 1)); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_DELAY_TMO; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; lpfc_issue_els_logo(vport, ndlp, 0); @@ -2062,12 +2047,10 @@ lpfc_device_rm_reglogin_issue(struct lpfc_vport *vport, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_NODEV_REMOVE; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); return ndlp->nlp_state; } else { lpfc_drop_node(vport, ndlp); @@ -2081,8 +2064,6 @@ lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - /* Don't do anything that will mess up processing of the * previous RSCN. */ @@ -2091,7 +2072,7 @@ lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport, ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); /* If we are a target we won't immediately transition into PRLI, * so if REG_LOGIN already completed we don't need to ignore it. @@ -2101,7 +2082,7 @@ lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport, ndlp->nlp_flag |= NLP_IGNR_REG_CMPL; ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_disc_set_adisc(vport, ndlp); return ndlp->nlp_state; } @@ -2172,7 +2153,6 @@ static uint32_t lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_iocbq *cmdiocb, *rspiocb; struct lpfc_hba *phba = vport->phba; IOCB_t *irsp; @@ -2294,9 +2274,9 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, (vport->port_type == LPFC_NPIV_PORT) && vport->cfg_restrict_login) { out: - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_TARGET_REMOVE; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_issue_els_logo(vport, ndlp, 0); ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; @@ -2348,12 +2328,10 @@ static uint32_t lpfc_device_rm_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_NODEV_REMOVE; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); return ndlp->nlp_state; } else { /* software abort outstanding PLOGI */ @@ -2387,7 +2365,6 @@ lpfc_device_recov_prli_issue(struct lpfc_vport *vport, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_hba *phba = vport->phba; /* Don't do anything that will mess up processing of the @@ -2401,9 +2378,9 @@ lpfc_device_recov_prli_issue(struct lpfc_vport *vport, ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_disc_set_adisc(vport, ndlp); return ndlp->nlp_state; } @@ -2440,12 +2417,11 @@ static uint32_t lpfc_rcv_logo_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_LOGO_ACC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); return ndlp->nlp_state; } @@ -2482,13 +2458,11 @@ static uint32_t lpfc_cmpl_logo_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - ndlp->nlp_prev_state = NLP_STE_LOGO_ISSUE; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_disc_set_adisc(vport, ndlp); return ndlp->nlp_state; } @@ -2582,14 +2556,12 @@ lpfc_device_recov_unmap_node(struct lpfc_vport *vport, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME); - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_disc_set_adisc(vport, ndlp); return ndlp->nlp_state; @@ -2660,14 +2632,12 @@ lpfc_device_recov_mapped_node(struct lpfc_vport *vport, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME); - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_disc_set_adisc(vport, ndlp); return ndlp->nlp_state; } @@ -2676,7 +2646,6 @@ static uint32_t lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; /* Ignore PLOGI if we have an outstanding LOGO */ @@ -2684,9 +2653,9 @@ lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, return ndlp->nlp_state; if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) { lpfc_cancel_retry_delay_tmo(vport, ndlp); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~(NLP_NPR_ADISC | NLP_NPR_2B_DISC); - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); } else if (!(ndlp->nlp_flag & NLP_NPR_2B_DISC)) { /* send PLOGI immediately, move to PLOGI issue state */ if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { @@ -2702,7 +2671,6 @@ static uint32_t lpfc_rcv_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; struct ls_rjt stat; @@ -2713,10 +2681,10 @@ lpfc_rcv_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { if (ndlp->nlp_flag & NLP_NPR_ADISC) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_NPR_ADISC; ndlp->nlp_prev_state = NLP_STE_NPR_NODE; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE); lpfc_issue_els_adisc(vport, ndlp, 0); } else { @@ -2770,27 +2738,26 @@ static uint32_t lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_LOGO_ACC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) { mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000 * 1)); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_DELAY_TMO; ndlp->nlp_flag &= ~NLP_NPR_ADISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); ndlp->nlp_last_elscmd = ELS_CMD_PLOGI; } else { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_NPR_ADISC; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); } return ndlp->nlp_state; } @@ -2893,12 +2860,10 @@ static uint32_t lpfc_device_rm_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_NODEV_REMOVE; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); return ndlp->nlp_state; } lpfc_drop_node(vport, ndlp); @@ -2909,8 +2874,6 @@ static uint32_t lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, void *arg, uint32_t evt) { - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); - /* Don't do anything that will mess up processing of the * previous RSCN. */ @@ -2918,10 +2881,10 @@ lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, return ndlp->nlp_state; lpfc_cancel_retry_delay_tmo(vport, ndlp); - spin_lock_irq(shost->host_lock); + spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME); - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&ndlp->lock); return ndlp->nlp_state; } diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index defdde760dbc..6ad626911cc7 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -381,7 +381,7 @@ lpfc_nvme_remoteport_delete(struct nvme_fc_remote_port *remoteport) lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, "6146 remoteport delete of remoteport %p\n", remoteport); - spin_lock_irq(&vport->phba->hbalock); + spin_lock_irq(&ndlp->lock); /* The register rebind might have occurred before the delete * downcall. Guard against this race. @@ -389,7 +389,7 @@ lpfc_nvme_remoteport_delete(struct nvme_fc_remote_port *remoteport) if (ndlp->fc4_xpt_flags & NLP_WAIT_FOR_UNREG) ndlp->fc4_xpt_flags &= ~(NLP_WAIT_FOR_UNREG | NVME_XPT_REGD); - spin_unlock_irq(&vport->phba->hbalock); + spin_unlock_irq(&ndlp->lock); /* On a devloss timeout event, one more put is executed provided the * NVME and SCSI rport unregister requests are complete. If the vport @@ -2468,13 +2468,13 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) else rpinfo.dev_loss_tmo = vport->cfg_devloss_tmo; - spin_lock_irq(&vport->phba->hbalock); + spin_lock_irq(&ndlp->lock); oldrport = lpfc_ndlp_get_nrport(ndlp); if (oldrport) { prev_ndlp = oldrport->ndlp; - spin_unlock_irq(&vport->phba->hbalock); + spin_unlock_irq(&ndlp->lock); } else { - spin_unlock_irq(&vport->phba->hbalock); + spin_unlock_irq(&ndlp->lock); if (!lpfc_nlp_get(ndlp)) { dev_warn(&vport->phba->pcidev->dev, "Warning - No node ref - exit register\n"); @@ -2491,10 +2491,10 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) /* Guard against an unregister/reregister * race that leaves the WAIT flag set. */ - spin_lock_irq(&vport->phba->hbalock); + spin_lock_irq(&ndlp->lock); ndlp->fc4_xpt_flags &= ~NLP_WAIT_FOR_UNREG; ndlp->fc4_xpt_flags |= NVME_XPT_REGD; - spin_unlock_irq(&vport->phba->hbalock); + spin_unlock_irq(&ndlp->lock); rport = remote_port->private; if (oldrport) { @@ -2502,10 +2502,10 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) * before dropping the ndlp ref from * register. */ - spin_lock_irq(&vport->phba->hbalock); + spin_lock_irq(&ndlp->lock); ndlp->nrport = NULL; ndlp->fc4_xpt_flags &= ~NLP_WAIT_FOR_UNREG; - spin_unlock_irq(&vport->phba->hbalock); + spin_unlock_irq(&ndlp->lock); rport->ndlp = NULL; rport->remoteport = NULL; @@ -2523,9 +2523,9 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) rport->remoteport = remote_port; rport->lport = lport; rport->ndlp = ndlp; - spin_lock_irq(&vport->phba->hbalock); + spin_lock_irq(&ndlp->lock); ndlp->nrport = rport; - spin_unlock_irq(&vport->phba->hbalock); + spin_unlock_irq(&ndlp->lock); lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC | LOG_NODE, "6022 Bind lport x%px to remoteport x%px " @@ -2564,11 +2564,11 @@ lpfc_nvme_rescan_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) struct lpfc_nvme_rport *nrport; struct nvme_fc_remote_port *remoteport = NULL; - spin_lock_irq(&vport->phba->hbalock); + spin_lock_irq(&ndlp->lock); nrport = lpfc_ndlp_get_nrport(ndlp); if (nrport) remoteport = nrport->remoteport; - spin_unlock_irq(&vport->phba->hbalock); + spin_unlock_irq(&ndlp->lock); lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC, "6170 Rescan NPort DID x%06x type x%x " @@ -2631,11 +2631,11 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) if (!lport) goto input_err; - spin_lock_irq(&vport->phba->hbalock); + spin_lock_irq(&ndlp->lock); rport = lpfc_ndlp_get_nrport(ndlp); if (rport) remoteport = rport->remoteport; - spin_unlock_irq(&vport->phba->hbalock); + spin_unlock_irq(&ndlp->lock); if (!remoteport) goto input_err; diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index d22ede4b9d74..e8d6166dd4b9 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -5324,10 +5324,10 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "0722 Target Reset rport failure: rdata x%px\n", rdata); if (pnode) { - spin_lock_irq(shost->host_lock); + spin_lock_irq(&pnode->lock); pnode->nlp_flag &= ~NLP_NPR_ADISC; pnode->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; - spin_unlock_irq(shost->host_lock); + spin_unlock_irq(&pnode->lock); } lpfc_reset_flush_io_context(vport, tgt_id, lun_id, LPFC_CTX_TGT); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 1f020d2abfa0..4f537a07bac6 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2448,10 +2448,10 @@ __lpfc_sli_rpi_release(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) if (ndlp->nlp_flag & NLP_RELEASE_RPI) { lpfc_sli4_free_rpi(vport->phba, ndlp->nlp_rpi); - spin_lock_irqsave(&vport->phba->ndlp_lock, iflags); + spin_lock_irqsave(&ndlp->lock, iflags); ndlp->nlp_flag &= ~NLP_RELEASE_RPI; ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR; - spin_unlock_irqrestore(&vport->phba->ndlp_lock, iflags); + spin_unlock_irqrestore(&ndlp->lock, iflags); } ndlp->nlp_flag &= ~NLP_UNREG_INP; } @@ -19879,7 +19879,6 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) struct lpfc_dmabuf *mp; struct lpfc_nodelist *ndlp; struct lpfc_nodelist *act_mbx_ndlp = NULL; - struct Scsi_Host *shost = lpfc_shost_from_vport(vport); LIST_HEAD(mbox_cmd_list); uint8_t restart_loop; @@ -19933,9 +19932,9 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) mb->mbox_flag |= LPFC_MBX_IMED_UNREG; restart_loop = 1; spin_unlock_irq(&phba->hbalock); - spin_lock(shost->host_lock); + spin_lock(&ndlp->lock); ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL; - spin_unlock(shost->host_lock); + spin_unlock(&ndlp->lock); spin_lock_irq(&phba->hbalock); break; } @@ -19957,9 +19956,9 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) ndlp = (struct lpfc_nodelist *)mb->ctx_ndlp; mb->ctx_ndlp = NULL; if (ndlp) { - spin_lock(shost->host_lock); + spin_lock(&ndlp->lock); ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL; - spin_unlock(shost->host_lock); + spin_unlock(&ndlp->lock); lpfc_nlp_put(ndlp); } } @@ -19968,9 +19967,9 @@ lpfc_cleanup_pending_mbox(struct lpfc_vport *vport) /* Release the ndlp with the cleaned-up active mailbox command */ if (act_mbx_ndlp) { - spin_lock(shost->host_lock); + spin_lock(&act_mbx_ndlp->lock); act_mbx_ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL; - spin_unlock(shost->host_lock); + spin_unlock(&act_mbx_ndlp->lock); lpfc_nlp_put(act_mbx_ndlp); } } -- cgit v1.2.3 From 52edb2caf675684acf2140a125de4774c691fecd Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:35 -0800 Subject: scsi: lpfc: Remove ndlp when a PLOGI/ADISC/PRLI/REG_RPI ultimately fails When a PLOGI/ADISC/PRLI/REG_RPI fails, the node remains in the nodelist in that state. Although the driver now frees a node when the ref count goes to zero, in this case the ref cnt doesn't reach zero because there isn't a mechanism to release the final reference. Discovery just stops. Fix by calling the node discovery state machine DEVICE_RM event whenever one of these commands fail. This will remove the final reference count and trigger node release. Link: https://lore.kernel.org/r/20201115192646.12977-7-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 66 +++++++++++++++++++++++++++++++++++++--- drivers/scsi/lpfc/lpfc_hbadisc.c | 39 +++++++++++++++--------- 2 files changed, 85 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 020300b97bd3..388728fbcc26 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1988,12 +1988,25 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, "2753 PLOGI failure DID:%06X Status:x%x/x%x\n", ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4]); - /* Do not call DSM for lpfc_els_abort'ed ELS cmds. Just execute - * the final node put to free it to the pool. + + /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ + if (lpfc_error_lost_link(irsp)) + goto check_plogi; + else + lpfc_disc_state_machine(vport, ndlp, cmdiocb, + NLP_EVT_CMPL_PLOGI); + + /* As long as this node is not registered with the scsi or nvme + * transport, it is no longer an active node. Otherwise + * devloss handles the final cleanup. */ - if (!lpfc_error_lost_link(irsp)) + if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD))) { + spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; + spin_unlock_irq(&ndlp->lock); lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_DEVICE_RM); + } } else { /* Good status, call state machine */ prsp = list_entry(((struct lpfc_dmabuf *) @@ -2004,6 +2017,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, NLP_EVT_CMPL_PLOGI); } + check_plogi: if (disc && vport->num_disc_nodes) { /* Check to see if there are more PLOGIs to be sent */ lpfc_more_plogi(vport); @@ -2243,6 +2257,20 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, else lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_CMPL_PRLI); + + /* As long as this node is not registered with the SCSI + * or NVMe transport and no other PRLIs are outstanding, + * it is no longer an active node. Otherwise devloss + * handles the final cleanup. + */ + if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD)) && + !ndlp->fc4_prli_sent) { + spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; + spin_unlock_irq(&ndlp->lock); + lpfc_disc_state_machine(vport, ndlp, cmdiocb, + NLP_EVT_DEVICE_RM); + } } else { /* Good status, call state machine. However, if another * PRLI is outstanding, don't call the state machine @@ -2655,14 +2683,29 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4]); /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ - if (!lpfc_error_lost_link(irsp)) + if (lpfc_error_lost_link(irsp)) + goto check_adisc; + else lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_CMPL_ADISC); + + /* As long as this node is not registered with the SCSI or NVMe + * transport, it is no longer an active node. Otherwise + * devloss handles the final cleanup. + */ + if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD))) { + spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; + spin_unlock_irq(&ndlp->lock); + lpfc_disc_state_machine(vport, ndlp, cmdiocb, + NLP_EVT_DEVICE_RM); + } } else /* Good status, call state machine */ lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_CMPL_ADISC); + check_adisc: /* Check to see if there are more ADISCs to be sent */ if (disc && vport->num_disc_nodes) lpfc_more_adisc(vport); @@ -2879,8 +2922,21 @@ out: irsp->un.ulpWord[4], irsp->ulpTimeout, vport->num_disc_nodes); lpfc_disc_start(vport); + return; + } + + /* Cleanup path for failed REG_RPI handling. If REG_RPI fails, the + * driver sends a LOGO to the rport to cleanup. For fabric and + * initiator ports cleanup the node as long as it the node is not + * register with the transport. + */ + if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD))) { + spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; + spin_unlock_irq(&ndlp->lock); + lpfc_disc_state_machine(vport, ndlp, cmdiocb, + NLP_EVT_DEVICE_RM); } - return; } /** diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 8c99e89c7685..c6d7620b49a3 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -204,10 +204,13 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) spin_lock_irqsave(&ndlp->lock, iflags); ndlp->nlp_flag |= NLP_IN_DEV_LOSS; + ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; + /* - * The backend does not expect any more calls assoicated with this - * rport, Remove the association between rport and ndlp + * The backend does not expect any more calls associated with this + * rport. Remove the association between rport and ndlp. */ + ndlp->fc4_xpt_flags &= ~SCSI_XPT_REGD; ((struct lpfc_rport_data *)rport->dd_data)->pnode = NULL; ndlp->rport = NULL; spin_unlock_irqrestore(&ndlp->lock, iflags); @@ -248,7 +251,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) int warn_on = 0; int fcf_inuse = 0; unsigned long iflags; - u32 fc4_xpt_flags; vport = ndlp->vport; shost = lpfc_shost_from_vport(vport); @@ -267,10 +269,11 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ndlp->nlp_DID, ndlp->nlp_type, ndlp->nlp_sid); lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, - "3182 %s x%06x, nflag x%x xflags x%x\n", + "3182 %s x%06x, nflag x%x xflags x%x refcnt %d\n", __func__, ndlp->nlp_DID, ndlp->nlp_flag, - ndlp->fc4_xpt_flags); + ndlp->fc4_xpt_flags, kref_read(&ndlp->kref)); + /* If the driver is recovering the rport, ignore devloss. */ if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) { lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, "0284 Devloss timeout Ignored on " @@ -282,8 +285,11 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) return fcf_inuse; } - if (ndlp->nlp_type & NLP_FABRIC) + /* Fabric nodes are done. */ + if (ndlp->nlp_type & NLP_FABRIC) { + lpfc_nlp_put(ndlp); return fcf_inuse; + } if (ndlp->nlp_sid != NLP_NO_SID) { warn_on = 1; @@ -311,12 +317,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) ndlp->nlp_state, ndlp->nlp_rpi); } - /* Should be final reference removal triggering a node free. */ - spin_lock_irqsave(shost->host_lock, iflags); - fc4_xpt_flags = ndlp->fc4_xpt_flags; - spin_unlock_irqrestore(shost->host_lock, iflags); - - if (!(fc4_xpt_flags & (NVME_XPT_REGD | SCSI_XPT_REGD))) + if (!(ndlp->fc4_xpt_flags & NVME_XPT_REGD)) lpfc_disc_state_machine(vport, ndlp, NULL, NLP_EVT_DEVICE_RM); return fcf_inuse; @@ -3587,7 +3588,7 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) pmb->ctx_buf = NULL; pmb->ctx_ndlp = NULL; - lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, + lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI | LOG_NODE | LOG_DISCOVERY, "0002 rpi:%x DID:%x flg:%x %d x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, kref_read(&ndlp->kref), @@ -4079,8 +4080,16 @@ out: kfree(mp); mempool_free(pmb, phba->mbox_mem_pool); - /* If no other thread is using the ndlp, free it */ - lpfc_nlp_not_used(ndlp); + /* If the node is not registered with the scsi or nvme + * transport, remove the fabric node. The failed reg_login + * is terminal. + */ + if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD))) { + spin_lock_irq(&ndlp->lock); + ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; + spin_unlock_irq(&ndlp->lock); + lpfc_nlp_not_used(ndlp); + } if (phba->fc_topology == LPFC_TOPOLOGY_LOOP) { /* -- cgit v1.2.3 From 9d76d46751594264a91387583fef49af334ccea6 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:36 -0800 Subject: scsi: lpfc: Unsolicited ELS leaves node in incorrect state while dropping it When a target swap happens, under certain conditions the node sends a LOGO. The unsolicited ELS logic responds with a reject. The logic may allocate a new node to handle this. Afterward, the new nodes are dropped incorrectly leaving them in a mis-matched state and refcounting causes a use-after-free situation leading to a crash. It is also possible that the unsolicited els handling finds a node which is in an UNUSED state. The handling moves these nodes to NPR state with a refcount of 1. Although the end of the discovery logic assumes a final put will free such a node, there are codes paths which could increment the reference count, thus the node is in NPR state and not released. Eventually this mismatch in state and refcount leads to premature release of the node causing a crash. Fix by always using the discovery engine DEVICE RM event to decrement and release the nodes (rather than explicit code that tried to do it before). This will take care of moving the node to the UNUSED state and then removes the final ref count. If there is a trigger to reuse this node, the transition from the UNUSED state clearly indicates that the initial reference is then incremented and use can continue. Link: https://lore.kernel.org/r/20201115192646.12977-8-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 388728fbcc26..3bcb02d0bc0f 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -8728,7 +8728,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, lpfc_els_rcv_flogi(vport, elsiocb, ndlp); if (newnode) - lpfc_nlp_put(ndlp); + lpfc_disc_state_machine(vport, ndlp, NULL, + NLP_EVT_DEVICE_RM); break; case ELS_CMD_LOGO: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, @@ -8770,7 +8771,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, phba->fc_stat.elsRcvRSCN++; lpfc_els_rcv_rscn(vport, elsiocb, ndlp); if (newnode) - lpfc_nlp_put(ndlp); + lpfc_disc_state_machine(vport, ndlp, NULL, + NLP_EVT_DEVICE_RM); break; case ELS_CMD_ADISC: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, @@ -8848,7 +8850,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, phba->fc_stat.elsRcvLIRR++; lpfc_els_rcv_lirr(vport, elsiocb, ndlp); if (newnode) - lpfc_nlp_put(ndlp); + lpfc_disc_state_machine(vport, ndlp, NULL, + NLP_EVT_DEVICE_RM); break; case ELS_CMD_RLS: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, @@ -8858,7 +8861,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, phba->fc_stat.elsRcvRLS++; lpfc_els_rcv_rls(vport, elsiocb, ndlp); if (newnode) - lpfc_nlp_put(ndlp); + lpfc_disc_state_machine(vport, ndlp, NULL, + NLP_EVT_DEVICE_RM); break; case ELS_CMD_RPL: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, @@ -8868,7 +8872,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, phba->fc_stat.elsRcvRPL++; lpfc_els_rcv_rpl(vport, elsiocb, ndlp); if (newnode) - lpfc_nlp_put(ndlp); + lpfc_disc_state_machine(vport, ndlp, NULL, + NLP_EVT_DEVICE_RM); break; case ELS_CMD_RNID: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, @@ -8878,7 +8883,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, phba->fc_stat.elsRcvRNID++; lpfc_els_rcv_rnid(vport, elsiocb, ndlp); if (newnode) - lpfc_nlp_put(ndlp); + lpfc_disc_state_machine(vport, ndlp, NULL, + NLP_EVT_DEVICE_RM); break; case ELS_CMD_RTV: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, @@ -8887,7 +8893,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, phba->fc_stat.elsRcvRTV++; lpfc_els_rcv_rtv(vport, elsiocb, ndlp); if (newnode) - lpfc_nlp_put(ndlp); + lpfc_disc_state_machine(vport, ndlp, NULL, + NLP_EVT_DEVICE_RM); break; case ELS_CMD_RRQ: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, @@ -8897,7 +8904,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, phba->fc_stat.elsRcvRRQ++; lpfc_els_rcv_rrq(vport, elsiocb, ndlp); if (newnode) - lpfc_nlp_put(ndlp); + lpfc_disc_state_machine(vport, ndlp, NULL, + NLP_EVT_DEVICE_RM); break; case ELS_CMD_ECHO: lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, @@ -8907,7 +8915,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, phba->fc_stat.elsRcvECHO++; lpfc_els_rcv_echo(vport, elsiocb, ndlp); if (newnode) - lpfc_nlp_put(ndlp); + lpfc_disc_state_machine(vport, ndlp, NULL, + NLP_EVT_DEVICE_RM); break; case ELS_CMD_REC: /* receive this due to exchange closed */ @@ -8938,7 +8947,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, "0115 Unknown ELS command x%x " "received from NPORT x%x\n", cmd, did); if (newnode) - lpfc_nlp_put(ndlp); + lpfc_disc_state_machine(vport, ndlp, NULL, + NLP_EVT_DEVICE_RM); break; } @@ -8952,7 +8962,8 @@ lsrjt: NULL); /* Remove the reference from above for new nodes. */ if (newnode) - lpfc_nlp_put(ndlp); + lpfc_disc_state_machine(vport, ndlp, NULL, + NLP_EVT_DEVICE_RM); } /* Release the reference on this elsiocb, not the ndlp. */ -- cgit v1.2.3 From b3f2e67cc2dd59fffeffd35b1526a081bbec9490 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:37 -0800 Subject: scsi: lpfc: Fix NPIV discovery and Fabric Node detection While testing NPIV and link bounces, the vport would not show a fabric node for the F_Port, would not transition into NPR state during a link fault, or leave the FDMI node untouched during error injection. Cause for this was determined to be an inconsistent manner in which F_Port, Nameserver, and FDMI controller nodes were created and linked. In some cases, the nodes would never be unregistered from the transport, leaving references active. In other cases, the fabric nodes may register with the transport multiple times while still registered. The following changes were made: - Fix the FDISC issue routine, which starts vport (re)creation, to mark the F_Port as a fabric node (NLP_FABRIC) and allow the F_Port node to fully be created and show up in the node list. - When remote ports are cleaned up on vport termination, cleanup the nameserver and FDMI controller nodes on the vport so they unregister from the transport. - On link bounces, don't exclude the NPIV Fabric remote ports from transitioning to the NPR state, allowing them to avoid re-registration if already registered. Link: https://lore.kernel.org/r/20201115192646.12977-9-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 4 ++++ drivers/scsi/lpfc/lpfc_hbadisc.c | 11 +++++------ 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 3bcb02d0bc0f..6520dc4bf6ec 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1508,6 +1508,10 @@ lpfc_initial_fdisc(struct lpfc_vport *vport) ndlp = lpfc_nlp_init(vport, Fabric_DID); if (!ndlp) return 0; + + /* NPIV is only supported in Fabrics. */ + ndlp->nlp_type |= NLP_FABRIC; + /* Put ndlp onto node list */ lpfc_enqueue_node(vport, ndlp); } diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index c6d7620b49a3..cd3df37ee0d3 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -818,12 +818,13 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove) struct lpfc_nodelist *ndlp, *next_ndlp; list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { - if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) continue; + if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) || - ((vport->port_type == LPFC_NPIV_PORT) && - (ndlp->nlp_DID == NameServer_DID))) + ((vport->port_type == LPFC_NPIV_PORT) && + ((ndlp->nlp_DID == NameServer_DID) || + (ndlp->nlp_DID == FDMI_DID)))) lpfc_unreg_rpi(vport, ndlp); /* Leave Fabric nodes alone on link down */ @@ -1037,9 +1038,7 @@ lpfc_linkup_port(struct lpfc_vport *vport) vport->fc_ns_retry = 0; spin_unlock_irq(shost->host_lock); - if (vport->fc_flag & FC_LBIT) - lpfc_linkup_cleanup_nodes(vport); - + lpfc_linkup_cleanup_nodes(vport); } static int -- cgit v1.2.3 From a70e63eee1c14257f73ce9ec6d0c9db28f77f9ad Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:38 -0800 Subject: scsi: lpfc: Fix NPIV Fabric Node reference counting While testing initiator-side cable swaps with NPIV, oops occur. The reference counts for the Fabric nodes on the NPIV vports isn't balanced, resulting in premature node removal. The following fixes were made: - Removed the FC_LBIT check in lpfc_linkup_port. This removed the special case for vports that didn't have them clean up just like the physical port. - Removed the unreg_rpi call in lpfc_cleanup_node. In this section, the node is being removed in the context of a reference count release and a mailbox command can't be issued at this point. - Remove special case handling in the default mailbox completion handler that allowed the skipping of a node reference. Now, reference counting always requires the removal of the reference. - Move the location of the DEVICE_RM event is done during LOGO handling as the driver has additional work to do on the ndlp before puts/releases can be performed. Link: https://lore.kernel.org/r/20201115192646.12977-10-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 47 +++++++++++++++++++++------------------- drivers/scsi/lpfc/lpfc_hbadisc.c | 29 ++++++++++--------------- drivers/scsi/lpfc/lpfc_init.c | 6 ++--- drivers/scsi/lpfc/lpfc_sli.c | 10 ++++++--- 4 files changed, 46 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 6520dc4bf6ec..f5509b1d4c5f 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -2835,8 +2835,9 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* LOGO completes to NPort */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0105 LOGO completes to NPort x%x " - "Data: x%x x%x x%x x%x\n", - ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4], + "refcnt %d nflags x%x Data: x%x x%x x%x x%x\n", + ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp->nlp_flag, + irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout, vport->num_disc_nodes); if (lpfc_els_chk_latt(vport)) { @@ -2844,17 +2845,6 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, goto out; } - /* Check to see if link went down during discovery */ - if (ndlp->nlp_flag & NLP_TARGET_REMOVE) { - /* NLP_EVT_DEVICE_RM should unregister the RPI - * which should abort all outstanding IOs. - */ - lpfc_disc_state_machine(vport, ndlp, cmdiocb, - NLP_EVT_DEVICE_RM); - skip_recovery = 1; - goto out; - } - /* The LOGO will not be retried on failure. A LOGO was * issued to the remote rport and a ACC or RJT or no Answer are * all acceptable. Note the failure and move forward with @@ -2876,6 +2866,19 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* Call state machine. This will unregister the rpi if needed. */ lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO); + /* The driver sets this flag for an NPIV instance that doesn't want to + * log into the remote port. + */ + if (ndlp->nlp_flag & NLP_TARGET_REMOVE) { + lpfc_disc_state_machine(vport, ndlp, cmdiocb, + NLP_EVT_DEVICE_RM); + lpfc_els_free_iocb(phba, cmdiocb); + lpfc_nlp_put(ndlp); + + /* Presume the node was released. */ + return; + } + out: /* Driver is done with the IO. */ lpfc_els_free_iocb(phba, cmdiocb); @@ -4399,10 +4402,10 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, irsp->ulpStatus, irsp->un.ulpWord[4], ndlp->nlp_DID); /* ACC to LOGO completes to NPort */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, - "0109 ACC to LOGO completes to NPort x%x " + "0109 ACC to LOGO completes to NPort x%x refcnt %d" "Data: x%x x%x x%x\n", - ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, - ndlp->nlp_rpi); + ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp->nlp_flag, + ndlp->nlp_state, ndlp->nlp_rpi); if (ndlp->nlp_state == NLP_STE_NPR_NODE) { /* NPort Recovery mode or node is just allocated */ @@ -8650,9 +8653,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, /* ELS command received from NPORT */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0112 ELS command x%x received from NPORT x%x " - "Data: x%x x%x x%x x%x\n", - cmd, did, vport->port_state, vport->fc_flag, - vport->fc_myDID, vport->fc_prevDID); + "refcnt %d Data: x%x x%x x%x x%x\n", + cmd, did, kref_read(&ndlp->kref), vport->port_state, + vport->fc_flag, vport->fc_myDID, vport->fc_prevDID); /* reject till our FLOGI completes or PLOGI assigned DID via PT2PT */ if ((vport->port_state < LPFC_FABRIC_CFG_LINK) && @@ -9144,9 +9147,9 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) spin_lock_irq(shost->host_lock); if (vport->fc_flag & FC_DISC_DELAYED) { spin_unlock_irq(shost->host_lock); - lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, - "3334 Delay fc port discovery for %d seconds\n", - phba->fc_ratov); + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "3334 Delay fc port discovery for %d secs\n", + phba->fc_ratov); mod_timer(&vport->delayed_disc_tmo, jiffies + msecs_to_jiffies(1000 * phba->fc_ratov)); return; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index cd3df37ee0d3..1d554c1dc305 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -4810,8 +4810,14 @@ lpfc_set_unreg_login_mbx_cmpl(struct lpfc_hba *phba, struct lpfc_vport *vport, { unsigned long iflags; + /* Driver always gets a reference on the mailbox job + * in support of async jobs. + */ + mbox->ctx_ndlp = lpfc_nlp_get(ndlp); + if (!mbox->ctx_ndlp) + return; + if (ndlp->nlp_flag & NLP_ISSUE_LOGO) { - mbox->ctx_ndlp = ndlp; mbox->mbox_cmpl = lpfc_nlp_logo_unreg; } else if (phba->sli_rev == LPFC_SLI_REV4 && @@ -4819,7 +4825,6 @@ lpfc_set_unreg_login_mbx_cmpl(struct lpfc_hba *phba, struct lpfc_vport *vport, (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) >= LPFC_SLI_INTF_IF_TYPE_2) && (kref_read(&ndlp->kref) > 0)) { - mbox->ctx_ndlp = lpfc_nlp_get(ndlp); mbox->mbox_cmpl = lpfc_sli4_unreg_rpi_cmpl_clr; } else { if (vport->load_flag & FC_UNLOADING) { @@ -4828,9 +4833,7 @@ lpfc_set_unreg_login_mbx_cmpl(struct lpfc_hba *phba, struct lpfc_vport *vport, ndlp->nlp_flag |= NLP_RELEASE_RPI; spin_unlock_irqrestore(&ndlp->lock, iflags); } - lpfc_nlp_get(ndlp); } - mbox->ctx_ndlp = ndlp; mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; } } @@ -4888,6 +4891,11 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) lpfc_unreg_login(phba, vport->vpi, rpi, mbox); mbox->vport = vport; lpfc_set_unreg_login_mbx_cmpl(phba, vport, ndlp, mbox); + if (!mbox->ctx_ndlp) { + mempool_free(mbox, phba->mbox_mem_pool); + return 1; + } + if (mbox->mbox_cmpl == lpfc_sli4_unreg_rpi_cmpl_clr) /* * accept PLOGIs after unreg_rpi_cmpl @@ -5057,7 +5065,6 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) struct lpfc_hba *phba = vport->phba; LPFC_MBOXQ_t *mb, *nextmb; struct lpfc_dmabuf *mp; - unsigned long iflags; /* Cleanup node for NPort */ lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, @@ -5125,18 +5132,6 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) lpfc_cleanup_vports_rrqs(vport, ndlp); if (phba->sli_rev == LPFC_SLI_REV4) ndlp->nlp_flag |= NLP_RELEASE_RPI; - if (!lpfc_unreg_rpi(vport, ndlp)) { - /* Clean up unregistered and non freed rpis */ - if ((ndlp->nlp_flag & NLP_RELEASE_RPI) && - !(ndlp->nlp_rpi == LPFC_RPI_ALLOC_ERROR)) { - lpfc_sli4_free_rpi(vport->phba, - ndlp->nlp_rpi); - spin_lock_irqsave(&ndlp->lock, iflags); - ndlp->nlp_flag &= ~NLP_RELEASE_RPI; - ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR; - spin_unlock_irqrestore(&ndlp->lock, iflags); - } - } return 0; } diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f0cbf98e7caa..86d9ab4bcebb 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -2851,10 +2851,8 @@ lpfc_cleanup(struct lpfc_vport *vport) continue; } - /* take care of nodes in unused state before the state - * machine taking action. - */ - if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) { + if (ndlp->nlp_DID == Fabric_Cntl_DID && + ndlp->nlp_state == NLP_STE_UNUSED_NODE) { lpfc_nlp_put(ndlp); continue; } diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 4f537a07bac6..116a6822c201 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2541,8 +2541,12 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } else { __lpfc_sli_rpi_release(vport, ndlp); } - if (vport->load_flag & FC_UNLOADING) - lpfc_nlp_put(ndlp); + + /* The unreg_login mailbox is complete and had a + * reference that has to be released. The PLOGI + * got its own ref. + */ + lpfc_nlp_put(ndlp); pmb->ctx_ndlp = NULL; } } @@ -2566,7 +2570,7 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) * * This function is the unreg rpi mailbox completion handler. It * frees the memory resources associated with the completed mailbox - * command. An additional refrenece is put on the ndlp to prevent + * command. An additional reference is put on the ndlp to prevent * lpfc_nlp_release from freeing the rpi bit in the bitmask before * the unreg mailbox command completes, this routine puts the * reference back. -- cgit v1.2.3 From b101eb27fde072866c6f5bdbcc2c28a6bf2c9bf7 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:39 -0800 Subject: scsi: lpfc: Refactor WQE structure definitions for common use In preparation of reworking the driver to use a native SLI-4 WQE interface for the SCSI and NVMe I/O paths, start by commonizing the WQE exchange type and command type attributes. While adjusting these options also noted the variance in the pbde field. Fix this by setting templates to 0 and in NVMe, which explicitly uses this option, setting the value. Link: https://lore.kernel.org/r/20201115192646.12977-11-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hw4.h | 10 +++++++--- drivers/scsi/lpfc/lpfc_nvme.c | 20 +++++++++++--------- drivers/scsi/lpfc/lpfc_nvmet.c | 6 +++--- 3 files changed, 21 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 49f5559f5fed..26a9057fb042 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -4386,9 +4386,11 @@ struct wqe_common { #define wqe_ebde_cnt_SHIFT 0 #define wqe_ebde_cnt_MASK 0x0000000f #define wqe_ebde_cnt_WORD word10 -#define wqe_nvme_SHIFT 4 -#define wqe_nvme_MASK 0x00000001 -#define wqe_nvme_WORD word10 +#define wqe_xchg_SHIFT 4 +#define wqe_xchg_MASK 0x00000001 +#define wqe_xchg_WORD word10 +#define LPFC_SCSI_XCHG 0x0 +#define LPFC_NVME_XCHG 0x1 #define wqe_oas_SHIFT 6 #define wqe_oas_MASK 0x00000001 #define wqe_oas_WORD word10 @@ -4886,6 +4888,8 @@ struct lpfc_grp_hdr { #define NVME_READ_CMD 0x0 #define FCP_COMMAND_DATA_OUT 0x1 #define NVME_WRITE_CMD 0x1 +#define COMMAND_DATA_IN 0x0 +#define COMMAND_DATA_OUT 0x1 #define FCP_COMMAND_TRECEIVE 0x2 #define FCP_COMMAND_TRSP 0x3 #define FCP_COMMAND_TSEND 0x7 diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 6ad626911cc7..1103eb8d929d 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -98,16 +98,16 @@ lpfc_nvme_cmd_template(void) /* Word 10 - dbde, wqes is variable */ bf_set(wqe_qosd, &wqe->fcp_iread.wqe_com, 0); - bf_set(wqe_nvme, &wqe->fcp_iread.wqe_com, 1); + bf_set(wqe_xchg, &wqe->fcp_iread.wqe_com, LPFC_NVME_XCHG); bf_set(wqe_iod, &wqe->fcp_iread.wqe_com, LPFC_WQE_IOD_READ); bf_set(wqe_lenloc, &wqe->fcp_iread.wqe_com, LPFC_WQE_LENLOC_WORD4); bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 0); bf_set(wqe_wqes, &wqe->fcp_iread.wqe_com, 1); /* Word 11 - pbde is variable */ - bf_set(wqe_cmd_type, &wqe->fcp_iread.wqe_com, NVME_READ_CMD); + bf_set(wqe_cmd_type, &wqe->fcp_iread.wqe_com, COMMAND_DATA_IN); bf_set(wqe_cqid, &wqe->fcp_iread.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); - bf_set(wqe_pbde, &wqe->fcp_iread.wqe_com, 1); + bf_set(wqe_pbde, &wqe->fcp_iread.wqe_com, 0); /* Word 12 - is zero */ @@ -139,16 +139,16 @@ lpfc_nvme_cmd_template(void) /* Word 10 - dbde, wqes is variable */ bf_set(wqe_qosd, &wqe->fcp_iwrite.wqe_com, 0); - bf_set(wqe_nvme, &wqe->fcp_iwrite.wqe_com, 1); + bf_set(wqe_xchg, &wqe->fcp_iwrite.wqe_com, LPFC_NVME_XCHG); bf_set(wqe_iod, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_IOD_WRITE); bf_set(wqe_lenloc, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_LENLOC_WORD4); bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 0); bf_set(wqe_wqes, &wqe->fcp_iwrite.wqe_com, 1); /* Word 11 - pbde is variable */ - bf_set(wqe_cmd_type, &wqe->fcp_iwrite.wqe_com, NVME_WRITE_CMD); + bf_set(wqe_cmd_type, &wqe->fcp_iwrite.wqe_com, COMMAND_DATA_OUT); bf_set(wqe_cqid, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); - bf_set(wqe_pbde, &wqe->fcp_iwrite.wqe_com, 1); + bf_set(wqe_pbde, &wqe->fcp_iwrite.wqe_com, 0); /* Word 12 - is zero */ @@ -178,14 +178,14 @@ lpfc_nvme_cmd_template(void) /* Word 10 - dbde, wqes is variable */ bf_set(wqe_qosd, &wqe->fcp_icmd.wqe_com, 1); - bf_set(wqe_nvme, &wqe->fcp_icmd.wqe_com, 1); + bf_set(wqe_xchg, &wqe->fcp_icmd.wqe_com, LPFC_NVME_XCHG); bf_set(wqe_iod, &wqe->fcp_icmd.wqe_com, LPFC_WQE_IOD_NONE); bf_set(wqe_lenloc, &wqe->fcp_icmd.wqe_com, LPFC_WQE_LENLOC_NONE); bf_set(wqe_dbde, &wqe->fcp_icmd.wqe_com, 0); bf_set(wqe_wqes, &wqe->fcp_icmd.wqe_com, 1); /* Word 11 */ - bf_set(wqe_cmd_type, &wqe->fcp_icmd.wqe_com, FCP_COMMAND); + bf_set(wqe_cmd_type, &wqe->fcp_icmd.wqe_com, COMMAND_DATA_IN); bf_set(wqe_cqid, &wqe->fcp_icmd.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); bf_set(wqe_pbde, &wqe->fcp_icmd.wqe_com, 0); @@ -1567,7 +1567,9 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, le32_to_cpu(first_data_sgl->sge_len); bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64; bde->tus.w = cpu_to_le32(bde->tus.w); - /* wqe_pbde is 1 in template */ + + /* Word 11 */ + bf_set(wqe_pbde, &wqe->generic.wqe_com, 1); } else { memset(&wqe->words[13], 0, (sizeof(uint32_t) * 3)); bf_set(wqe_pbde, &wqe->generic.wqe_com, 0); diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 78b934b021aa..99d781e32b8e 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -105,7 +105,7 @@ lpfc_nvmet_cmd_template(void) /* Word 9 - reqtag, rcvoxid is variable */ /* Word 10 - wqes, xc is variable */ - bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1); + bf_set(wqe_xchg, &wqe->fcp_tsend.wqe_com, LPFC_NVME_XCHG); bf_set(wqe_dbde, &wqe->fcp_tsend.wqe_com, 1); bf_set(wqe_wqes, &wqe->fcp_tsend.wqe_com, 0); bf_set(wqe_xc, &wqe->fcp_tsend.wqe_com, 1); @@ -153,7 +153,7 @@ lpfc_nvmet_cmd_template(void) /* Word 10 - xc is variable */ bf_set(wqe_dbde, &wqe->fcp_treceive.wqe_com, 1); bf_set(wqe_wqes, &wqe->fcp_treceive.wqe_com, 0); - bf_set(wqe_nvme, &wqe->fcp_treceive.wqe_com, 1); + bf_set(wqe_xchg, &wqe->fcp_treceive.wqe_com, LPFC_NVME_XCHG); bf_set(wqe_iod, &wqe->fcp_treceive.wqe_com, LPFC_WQE_IOD_READ); bf_set(wqe_lenloc, &wqe->fcp_treceive.wqe_com, LPFC_WQE_LENLOC_WORD12); bf_set(wqe_xc, &wqe->fcp_tsend.wqe_com, 1); @@ -195,7 +195,7 @@ lpfc_nvmet_cmd_template(void) /* Word 10 wqes, xc is variable */ bf_set(wqe_dbde, &wqe->fcp_trsp.wqe_com, 1); - bf_set(wqe_nvme, &wqe->fcp_trsp.wqe_com, 1); + bf_set(wqe_xchg, &wqe->fcp_trsp.wqe_com, LPFC_NVME_XCHG); bf_set(wqe_wqes, &wqe->fcp_trsp.wqe_com, 0); bf_set(wqe_xc, &wqe->fcp_trsp.wqe_com, 0); bf_set(wqe_iod, &wqe->fcp_trsp.wqe_com, LPFC_WQE_IOD_NONE); -- cgit v1.2.3 From 840a470181c72f82f8bc9453b47ac0d2e79f6b4a Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:40 -0800 Subject: scsi: lpfc: Enable common wqe_template support for both SCSI and NVMe The driver is currently using SLI-4 WQE templates only for NVMe. Refactor the template and the placement of the service routine so that it can be used by both SCSI and NVMe. Link: https://lore.kernel.org/r/20201115192646.12977-12-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_crtn.h | 5 +- drivers/scsi/lpfc/lpfc_init.c | 2 +- drivers/scsi/lpfc/lpfc_nvme.c | 133 +----------------------------------------- drivers/scsi/lpfc/lpfc_sli.c | 126 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 132 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 903151aa6f02..03560478f2ce 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -590,7 +590,7 @@ struct lpfc_io_buf *lpfc_get_io_buf(struct lpfc_hba *phba, void lpfc_release_io_buf(struct lpfc_hba *phba, struct lpfc_io_buf *ncmd, struct lpfc_sli4_hdw_queue *qp); void lpfc_io_ktime(struct lpfc_hba *phba, struct lpfc_io_buf *ncmd); -void lpfc_nvme_cmd_template(void); +void lpfc_wqe_cmd_template(void); void lpfc_nvmet_cmd_template(void); void lpfc_nvme_cancel_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn); void lpfc_nvme_prep_abort_wqe(struct lpfc_iocbq *pwqeq, u16 xritag, u8 opt); @@ -598,3 +598,6 @@ extern int lpfc_enable_nvmet_cnt; extern unsigned long long lpfc_enable_nvmet[]; extern int lpfc_no_hba_reset_cnt; extern unsigned long lpfc_no_hba_reset[]; +extern union lpfc_wqe128 lpfc_iread_cmd_template; +extern union lpfc_wqe128 lpfc_iwrite_cmd_template; +extern union lpfc_wqe128 lpfc_icmnd_cmd_template; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 86d9ab4bcebb..f4de75b2f64f 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -14120,7 +14120,7 @@ lpfc_init(void) fc_release_transport(lpfc_transport_template); goto unregister; } - lpfc_nvme_cmd_template(); + lpfc_wqe_cmd_template(); lpfc_nvmet_cmd_template(); /* Initialize in case vector mapping is needed */ diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 1103eb8d929d..2682839108f5 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -62,136 +62,6 @@ lpfc_release_nvme_buf(struct lpfc_hba *, struct lpfc_io_buf *); static struct nvme_fc_port_template lpfc_nvme_template; -static union lpfc_wqe128 lpfc_iread_cmd_template; -static union lpfc_wqe128 lpfc_iwrite_cmd_template; -static union lpfc_wqe128 lpfc_icmnd_cmd_template; - -/* Setup WQE templates for NVME IOs */ -void -lpfc_nvme_cmd_template(void) -{ - union lpfc_wqe128 *wqe; - - /* IREAD template */ - wqe = &lpfc_iread_cmd_template; - memset(wqe, 0, sizeof(union lpfc_wqe128)); - - /* Word 0, 1, 2 - BDE is variable */ - - /* Word 3 - cmd_buff_len, payload_offset_len is zero */ - - /* Word 4 - total_xfer_len is variable */ - - /* Word 5 - is zero */ - - /* Word 6 - ctxt_tag, xri_tag is variable */ - - /* Word 7 */ - bf_set(wqe_cmnd, &wqe->fcp_iread.wqe_com, CMD_FCP_IREAD64_WQE); - bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, PARM_READ_CHECK); - bf_set(wqe_class, &wqe->fcp_iread.wqe_com, CLASS3); - bf_set(wqe_ct, &wqe->fcp_iread.wqe_com, SLI4_CT_RPI); - - /* Word 8 - abort_tag is variable */ - - /* Word 9 - reqtag is variable */ - - /* Word 10 - dbde, wqes is variable */ - bf_set(wqe_qosd, &wqe->fcp_iread.wqe_com, 0); - bf_set(wqe_xchg, &wqe->fcp_iread.wqe_com, LPFC_NVME_XCHG); - bf_set(wqe_iod, &wqe->fcp_iread.wqe_com, LPFC_WQE_IOD_READ); - bf_set(wqe_lenloc, &wqe->fcp_iread.wqe_com, LPFC_WQE_LENLOC_WORD4); - bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 0); - bf_set(wqe_wqes, &wqe->fcp_iread.wqe_com, 1); - - /* Word 11 - pbde is variable */ - bf_set(wqe_cmd_type, &wqe->fcp_iread.wqe_com, COMMAND_DATA_IN); - bf_set(wqe_cqid, &wqe->fcp_iread.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); - bf_set(wqe_pbde, &wqe->fcp_iread.wqe_com, 0); - - /* Word 12 - is zero */ - - /* Word 13, 14, 15 - PBDE is variable */ - - /* IWRITE template */ - wqe = &lpfc_iwrite_cmd_template; - memset(wqe, 0, sizeof(union lpfc_wqe128)); - - /* Word 0, 1, 2 - BDE is variable */ - - /* Word 3 - cmd_buff_len, payload_offset_len is zero */ - - /* Word 4 - total_xfer_len is variable */ - - /* Word 5 - initial_xfer_len is variable */ - - /* Word 6 - ctxt_tag, xri_tag is variable */ - - /* Word 7 */ - bf_set(wqe_cmnd, &wqe->fcp_iwrite.wqe_com, CMD_FCP_IWRITE64_WQE); - bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, PARM_READ_CHECK); - bf_set(wqe_class, &wqe->fcp_iwrite.wqe_com, CLASS3); - bf_set(wqe_ct, &wqe->fcp_iwrite.wqe_com, SLI4_CT_RPI); - - /* Word 8 - abort_tag is variable */ - - /* Word 9 - reqtag is variable */ - - /* Word 10 - dbde, wqes is variable */ - bf_set(wqe_qosd, &wqe->fcp_iwrite.wqe_com, 0); - bf_set(wqe_xchg, &wqe->fcp_iwrite.wqe_com, LPFC_NVME_XCHG); - bf_set(wqe_iod, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_IOD_WRITE); - bf_set(wqe_lenloc, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_LENLOC_WORD4); - bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 0); - bf_set(wqe_wqes, &wqe->fcp_iwrite.wqe_com, 1); - - /* Word 11 - pbde is variable */ - bf_set(wqe_cmd_type, &wqe->fcp_iwrite.wqe_com, COMMAND_DATA_OUT); - bf_set(wqe_cqid, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); - bf_set(wqe_pbde, &wqe->fcp_iwrite.wqe_com, 0); - - /* Word 12 - is zero */ - - /* Word 13, 14, 15 - PBDE is variable */ - - /* ICMND template */ - wqe = &lpfc_icmnd_cmd_template; - memset(wqe, 0, sizeof(union lpfc_wqe128)); - - /* Word 0, 1, 2 - BDE is variable */ - - /* Word 3 - payload_offset_len is variable */ - - /* Word 4, 5 - is zero */ - - /* Word 6 - ctxt_tag, xri_tag is variable */ - - /* Word 7 */ - bf_set(wqe_cmnd, &wqe->fcp_icmd.wqe_com, CMD_FCP_ICMND64_WQE); - bf_set(wqe_pu, &wqe->fcp_icmd.wqe_com, 0); - bf_set(wqe_class, &wqe->fcp_icmd.wqe_com, CLASS3); - bf_set(wqe_ct, &wqe->fcp_icmd.wqe_com, SLI4_CT_RPI); - - /* Word 8 - abort_tag is variable */ - - /* Word 9 - reqtag is variable */ - - /* Word 10 - dbde, wqes is variable */ - bf_set(wqe_qosd, &wqe->fcp_icmd.wqe_com, 1); - bf_set(wqe_xchg, &wqe->fcp_icmd.wqe_com, LPFC_NVME_XCHG); - bf_set(wqe_iod, &wqe->fcp_icmd.wqe_com, LPFC_WQE_IOD_NONE); - bf_set(wqe_lenloc, &wqe->fcp_icmd.wqe_com, LPFC_WQE_LENLOC_NONE); - bf_set(wqe_dbde, &wqe->fcp_icmd.wqe_com, 0); - bf_set(wqe_wqes, &wqe->fcp_icmd.wqe_com, 1); - - /* Word 11 */ - bf_set(wqe_cmd_type, &wqe->fcp_icmd.wqe_com, COMMAND_DATA_IN); - bf_set(wqe_cqid, &wqe->fcp_icmd.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); - bf_set(wqe_pbde, &wqe->fcp_icmd.wqe_com, 0); - - /* Word 12, 13, 14, 15 - is zero */ -} - /** * lpfc_nvme_prep_abort_wqe - set up 'abort' work queue entry. * @pwqeq: Pointer to command iocb. @@ -1400,6 +1270,9 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport, /* Word 9 */ bf_set(wqe_reqtag, &wqe->generic.wqe_com, pwqeq->iotag); + /* Word 10 */ + bf_set(wqe_xchg, &wqe->fcp_iwrite.wqe_com, LPFC_NVME_XCHG); + /* Words 13 14 15 are for PBDE support */ pwqeq->vport = vport; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 116a6822c201..b1d5b4484015 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -90,12 +90,138 @@ static void __lpfc_sli4_consume_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, struct lpfc_cqe *cqe); +union lpfc_wqe128 lpfc_iread_cmd_template; +union lpfc_wqe128 lpfc_iwrite_cmd_template; +union lpfc_wqe128 lpfc_icmnd_cmd_template; + static IOCB_t * lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) { return &iocbq->iocb; } +/* Setup WQE templates for IOs */ +void lpfc_wqe_cmd_template(void) +{ + union lpfc_wqe128 *wqe; + + /* IREAD template */ + wqe = &lpfc_iread_cmd_template; + memset(wqe, 0, sizeof(union lpfc_wqe128)); + + /* Word 0, 1, 2 - BDE is variable */ + + /* Word 3 - cmd_buff_len, payload_offset_len is zero */ + + /* Word 4 - total_xfer_len is variable */ + + /* Word 5 - is zero */ + + /* Word 6 - ctxt_tag, xri_tag is variable */ + + /* Word 7 */ + bf_set(wqe_cmnd, &wqe->fcp_iread.wqe_com, CMD_FCP_IREAD64_WQE); + bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, PARM_READ_CHECK); + bf_set(wqe_class, &wqe->fcp_iread.wqe_com, CLASS3); + bf_set(wqe_ct, &wqe->fcp_iread.wqe_com, SLI4_CT_RPI); + + /* Word 8 - abort_tag is variable */ + + /* Word 9 - reqtag is variable */ + + /* Word 10 - dbde, wqes is variable */ + bf_set(wqe_qosd, &wqe->fcp_iread.wqe_com, 0); + bf_set(wqe_iod, &wqe->fcp_iread.wqe_com, LPFC_WQE_IOD_READ); + bf_set(wqe_lenloc, &wqe->fcp_iread.wqe_com, LPFC_WQE_LENLOC_WORD4); + bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 0); + bf_set(wqe_wqes, &wqe->fcp_iread.wqe_com, 1); + + /* Word 11 - pbde is variable */ + bf_set(wqe_cmd_type, &wqe->fcp_iread.wqe_com, COMMAND_DATA_IN); + bf_set(wqe_cqid, &wqe->fcp_iread.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); + bf_set(wqe_pbde, &wqe->fcp_iread.wqe_com, 0); + + /* Word 12 - is zero */ + + /* Word 13, 14, 15 - PBDE is variable */ + + /* IWRITE template */ + wqe = &lpfc_iwrite_cmd_template; + memset(wqe, 0, sizeof(union lpfc_wqe128)); + + /* Word 0, 1, 2 - BDE is variable */ + + /* Word 3 - cmd_buff_len, payload_offset_len is zero */ + + /* Word 4 - total_xfer_len is variable */ + + /* Word 5 - initial_xfer_len is variable */ + + /* Word 6 - ctxt_tag, xri_tag is variable */ + + /* Word 7 */ + bf_set(wqe_cmnd, &wqe->fcp_iwrite.wqe_com, CMD_FCP_IWRITE64_WQE); + bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, PARM_READ_CHECK); + bf_set(wqe_class, &wqe->fcp_iwrite.wqe_com, CLASS3); + bf_set(wqe_ct, &wqe->fcp_iwrite.wqe_com, SLI4_CT_RPI); + + /* Word 8 - abort_tag is variable */ + + /* Word 9 - reqtag is variable */ + + /* Word 10 - dbde, wqes is variable */ + bf_set(wqe_qosd, &wqe->fcp_iwrite.wqe_com, 0); + bf_set(wqe_iod, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_IOD_WRITE); + bf_set(wqe_lenloc, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_LENLOC_WORD4); + bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 0); + bf_set(wqe_wqes, &wqe->fcp_iwrite.wqe_com, 1); + + /* Word 11 - pbde is variable */ + bf_set(wqe_cmd_type, &wqe->fcp_iwrite.wqe_com, COMMAND_DATA_OUT); + bf_set(wqe_cqid, &wqe->fcp_iwrite.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); + bf_set(wqe_pbde, &wqe->fcp_iwrite.wqe_com, 0); + + /* Word 12 - is zero */ + + /* Word 13, 14, 15 - PBDE is variable */ + + /* ICMND template */ + wqe = &lpfc_icmnd_cmd_template; + memset(wqe, 0, sizeof(union lpfc_wqe128)); + + /* Word 0, 1, 2 - BDE is variable */ + + /* Word 3 - payload_offset_len is variable */ + + /* Word 4, 5 - is zero */ + + /* Word 6 - ctxt_tag, xri_tag is variable */ + + /* Word 7 */ + bf_set(wqe_cmnd, &wqe->fcp_icmd.wqe_com, CMD_FCP_ICMND64_WQE); + bf_set(wqe_pu, &wqe->fcp_icmd.wqe_com, 0); + bf_set(wqe_class, &wqe->fcp_icmd.wqe_com, CLASS3); + bf_set(wqe_ct, &wqe->fcp_icmd.wqe_com, SLI4_CT_RPI); + + /* Word 8 - abort_tag is variable */ + + /* Word 9 - reqtag is variable */ + + /* Word 10 - dbde, wqes is variable */ + bf_set(wqe_qosd, &wqe->fcp_icmd.wqe_com, 1); + bf_set(wqe_iod, &wqe->fcp_icmd.wqe_com, LPFC_WQE_IOD_NONE); + bf_set(wqe_lenloc, &wqe->fcp_icmd.wqe_com, LPFC_WQE_LENLOC_NONE); + bf_set(wqe_dbde, &wqe->fcp_icmd.wqe_com, 0); + bf_set(wqe_wqes, &wqe->fcp_icmd.wqe_com, 1); + + /* Word 11 */ + bf_set(wqe_cmd_type, &wqe->fcp_icmd.wqe_com, COMMAND_DATA_IN); + bf_set(wqe_cqid, &wqe->fcp_icmd.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); + bf_set(wqe_pbde, &wqe->fcp_icmd.wqe_com, 0); + + /* Word 12, 13, 14, 15 - is zero */ +} + #if defined(CONFIG_64BIT) && defined(__LITTLE_ENDIAN) /** * lpfc_sli4_pcimem_bcopy - SLI4 memory copy function -- cgit v1.2.3 From 47ff4c510f029360667eb4a61506ef9bfba5581d Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:41 -0800 Subject: scsi: lpfc: Enable common send_io interface for SCSI and NVMe To set up common use by the SCSI and NVMe I/O paths, create a new routine that issues FCP I/O commands which can be used by either protocol. The new routine addresses SLI-3 vs SLI-4 differences within its implementation. Replace the (SLI-3 centric) iocb routine in the SCSI path with this new WQE-centric common routine. Link: https://lore.kernel.org/r/20201115192646.12977-13-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 3 ++ drivers/scsi/lpfc/lpfc_crtn.h | 2 + drivers/scsi/lpfc/lpfc_scsi.c | 6 ++- drivers/scsi/lpfc/lpfc_sli.c | 87 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 2b92aa7a0762..63a87c103bc5 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -669,6 +669,9 @@ struct lpfc_hba { int (*__lpfc_sli_issue_iocb) (struct lpfc_hba *, uint32_t, struct lpfc_iocbq *, uint32_t); + int (*__lpfc_sli_issue_fcp_io) + (struct lpfc_hba *phba, uint32_t ring_number, + struct lpfc_iocbq *piocb, uint32_t flag); void (*__lpfc_sli_release_iocbq)(struct lpfc_hba *, struct lpfc_iocbq *); int (*lpfc_hba_down_post)(struct lpfc_hba *phba); diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 03560478f2ce..2b1540c0c82e 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -320,6 +320,8 @@ void lpfc_sli_def_mbox_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *, LPFC_MBOXQ_t *); int lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t, struct lpfc_iocbq *, uint32_t); +int lpfc_sli_issue_fcp_io(struct lpfc_hba *phba, uint32_t ring_number, + struct lpfc_iocbq *piocb, uint32_t flag); int lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, struct lpfc_iocbq *pwqe); struct lpfc_sglq *__lpfc_clear_active_sglq(struct lpfc_hba *phba, uint16_t xri); diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index e8d6166dd4b9..790a508921bb 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -4642,8 +4642,10 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO)) this_cpu_inc(phba->sli4_hba.c_stat->xmt_io); #endif - err = lpfc_sli_issue_iocb(phba, LPFC_FCP_RING, - &lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB); + /* Issue I/O to adapter */ + err = lpfc_sli_issue_fcp_io(phba, LPFC_FCP_RING, + &lpfc_cmd->cur_iocbq, + SLI_IOCB_RET_IOCB); #ifdef CONFIG_SCSI_LPFC_DEBUG_FS if (start) { lpfc_cmd->ts_cmd_start = start; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index b1d5b4484015..31c524a3373f 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -276,6 +276,7 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe128 *wqe) /* sanity check on queue memory */ if (unlikely(!q)) return -ENOMEM; + temp_wqe = lpfc_sli4_qe(q, q->host_index); /* If the host has not yet processed the next entry then we are done */ @@ -10228,6 +10229,71 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, return 0; } +/** + * __lpfc_sli_issue_fcp_io_s3 - SLI3 device for sending fcp io iocb + * @phba: Pointer to HBA context object. + * @ring_number: SLI ring number to issue wqe on. + * @piocb: Pointer to command iocb. + * @flag: Flag indicating if this command can be put into txq. + * + * __lpfc_sli_issue_fcp_io_s3 is wrapper function to invoke lockless func to + * send an iocb command to an HBA with SLI-4 interface spec. + * + * This function takes the hbalock before invoking the lockless version. + * The function will return success after it successfully submit the wqe to + * firmware or after adding to the txq. + **/ +static int +__lpfc_sli_issue_fcp_io_s3(struct lpfc_hba *phba, uint32_t ring_number, + struct lpfc_iocbq *piocb, uint32_t flag) +{ + unsigned long iflags; + int rc; + + spin_lock_irqsave(&phba->hbalock, iflags); + rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb, flag); + spin_unlock_irqrestore(&phba->hbalock, iflags); + + return rc; +} + +/** + * __lpfc_sli_issue_fcp_io_s4 - SLI4 device for sending fcp io wqe + * @phba: Pointer to HBA context object. + * @ring_number: SLI ring number to issue wqe on. + * @piocb: Pointer to command iocb. + * @flag: Flag indicating if this command can be put into txq. + * + * __lpfc_sli_issue_fcp_io_s4 is used by other functions in the driver to issue + * an wqe command to an HBA with SLI-4 interface spec. + * + * This function is a lockless version. The function will return success + * after it successfully submit the wqe to firmware or after adding to the + * txq. + **/ +static int +__lpfc_sli_issue_fcp_io_s4(struct lpfc_hba *phba, uint32_t ring_number, + struct lpfc_iocbq *piocb, uint32_t flag) +{ + struct lpfc_sli_ring *pring; + struct lpfc_queue *eq; + unsigned long iflags; + int rc; + + eq = phba->sli4_hba.hdwq[piocb->hba_wqidx].hba_eq; + + pring = lpfc_sli4_calc_ring(phba, piocb); + if (unlikely(pring == NULL)) + return IOCB_ERROR; + + spin_lock_irqsave(&pring->ring_lock, iflags); + rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb, flag); + spin_unlock_irqrestore(&pring->ring_lock, iflags); + + lpfc_sli4_poll_eq(eq, LPFC_POLL_FASTPATH); + return rc; +} + /** * __lpfc_sli_issue_iocb_s4 - SLI4 device lockless ver of lpfc_sli_issue_iocb * @phba: Pointer to HBA context object. @@ -10324,6 +10390,25 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, return 0; } +/** + * lpfc_sli_issue_fcp_io - Wrapper func for issuing fcp i/o + * + * This routine wraps the actual fcp i/o function for issusing WQE for sli-4 + * or IOCB for sli-3 function. + * pointer from the lpfc_hba struct. + * + * Return codes: + * IOCB_ERROR - Error + * IOCB_SUCCESS - Success + * IOCB_BUSY - Busy + **/ +int +lpfc_sli_issue_fcp_io(struct lpfc_hba *phba, uint32_t ring_number, + struct lpfc_iocbq *piocb, uint32_t flag) +{ + return phba->__lpfc_sli_issue_fcp_io(phba, ring_number, piocb, flag); +} + /* * __lpfc_sli_issue_iocb - Wrapper func of lockless version for issuing iocb * @@ -10359,10 +10444,12 @@ lpfc_sli_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) case LPFC_PCI_DEV_LP: phba->__lpfc_sli_issue_iocb = __lpfc_sli_issue_iocb_s3; phba->__lpfc_sli_release_iocbq = __lpfc_sli_release_iocbq_s3; + phba->__lpfc_sli_issue_fcp_io = __lpfc_sli_issue_fcp_io_s3; break; case LPFC_PCI_DEV_OC: phba->__lpfc_sli_issue_iocb = __lpfc_sli_issue_iocb_s4; phba->__lpfc_sli_release_iocbq = __lpfc_sli_release_iocbq_s4; + phba->__lpfc_sli_issue_fcp_io = __lpfc_sli_issue_fcp_io_s4; break; default: lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, -- cgit v1.2.3 From da255e2e7cc889e10820bc89752466322426571f Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:42 -0800 Subject: scsi: lpfc: Convert SCSI path to use common I/O submission path This patch converts the SCSI I/O path from the iocb-centric interfaces to the common I/O submission path which supports native SLI-4 WQEs. A wrapper routine is put in place to distinguish SLI-3 from SLI. If SLI-3, the same iocb-centric paths are used, perhaps with refactored code that is explicitly for SLI-3. For SLI-4, any iocb-related formatting is replaced by wqe-based formatting, although much of that is addressed by the common wqe templates in the SLI-4 path. Link: https://lore.kernel.org/r/20201115192646.12977-14-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc.h | 4 + drivers/scsi/lpfc/lpfc_scsi.c | 455 +++++++++++++++++++++++++++++------------- drivers/scsi/lpfc/lpfc_sli.c | 55 +++-- 3 files changed, 365 insertions(+), 149 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 63a87c103bc5..a54c8da30273 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -664,6 +664,10 @@ struct lpfc_hba { void (*lpfc_scsi_prep_cmnd) (struct lpfc_vport *, struct lpfc_io_buf *, struct lpfc_nodelist *); + int (*lpfc_scsi_prep_cmnd_buf) + (struct lpfc_vport *vport, + struct lpfc_io_buf *lpfc_cmd, + uint8_t tmo); /* IOCB interface function jump table entries */ int (*__lpfc_sli_issue_iocb) diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 790a508921bb..0581b7db2f8d 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -638,7 +638,6 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, struct lpfc_io_buf *lpfc_cmd; struct lpfc_sli4_hdw_queue *qp; struct sli4_sge *sgl; - IOCB_t *iocb; dma_addr_t pdma_phys_fcp_rsp; dma_addr_t pdma_phys_fcp_cmd; uint32_t cpu, idx; @@ -708,24 +707,6 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, sgl->word2 = cpu_to_le32(sgl->word2); sgl->sge_len = cpu_to_le32(sizeof(struct fcp_rsp)); - /* - * Since the IOCB for the FCP I/O is built into this - * lpfc_io_buf, initialize it with all known data now. - */ - iocb = &lpfc_cmd->cur_iocbq.iocb; - iocb->un.fcpi64.bdl.ulpIoTag32 = 0; - iocb->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BDE_64; - /* setting the BLP size to 2 * sizeof BDE may not be correct. - * We are setting the bpl to point to out sgl. An sgl's - * entries are 16 bytes, a bpl entries are 12 bytes. - */ - iocb->un.fcpi64.bdl.bdeSize = sizeof(struct fcp_cmnd); - iocb->un.fcpi64.bdl.addrLow = putPaddrLow(pdma_phys_fcp_cmd); - iocb->un.fcpi64.bdl.addrHigh = putPaddrHigh(pdma_phys_fcp_cmd); - iocb->ulpBdeCount = 1; - iocb->ulpLe = 1; - iocb->ulpClass = CLASS3; - if (lpfc_ndlp_check_qdepth(phba, ndlp)) { atomic_inc(&ndlp->cmd_pending); lpfc_cmd->flags |= LPFC_SBUF_BUMP_QDEPTH; @@ -824,6 +805,25 @@ lpfc_release_scsi_buf(struct lpfc_hba *phba, struct lpfc_io_buf *psb) phba->lpfc_release_scsi_buf(phba, psb); } +/** + * lpfc_fcpcmd_to_iocb - copy the fcp_cmd data into the IOCB + * @data: A pointer to the immediate command data portion of the IOCB. + * @fcp_cmnd: The FCP Command that is provided by the SCSI layer. + * + * The routine copies the entire FCP command from @fcp_cmnd to @data while + * byte swapping the data to big endian format for transmission on the wire. + **/ +static void +lpfc_fcpcmd_to_iocb(u8 *data, struct fcp_cmnd *fcp_cmnd) +{ + int i, j; + + for (i = 0, j = 0; i < sizeof(struct fcp_cmnd); + i += sizeof(uint32_t), j++) { + ((uint32_t *)data)[j] = cpu_to_be32(((uint32_t *)fcp_cmnd)[j]); + } +} + /** * lpfc_scsi_prep_dma_buf_s3 - DMA mapping for scsi buffer to SLI3 IF spec * @phba: The Hba for which this call is being executed. @@ -960,6 +960,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) * we need to set word 4 of IOCB here */ iocb_cmd->un.fcpi.fcpi_parm = scsi_bufflen(scsi_cmnd); + lpfc_fcpcmd_to_iocb(iocb_cmd->unsli3.fcp_ext.icd, fcp_cmnd); return 0; } @@ -3059,7 +3060,9 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd; struct sli4_sge *sgl = (struct sli4_sge *)lpfc_cmd->dma_sgl; struct sli4_sge *first_data_sgl; - IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb; + struct lpfc_iocbq *pwqeq = &lpfc_cmd->cur_iocbq; + struct lpfc_vport *vport = phba->pport; + union lpfc_wqe128 *wqe = &pwqeq->wqe; dma_addr_t physaddr; uint32_t num_bde = 0; uint32_t dma_len; @@ -3200,13 +3203,16 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) if ((phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) || phba->cfg_enable_pbde) { bde = (struct ulp_bde64 *) - &(iocb_cmd->unsli3.sli3Words[5]); + &wqe->words[13]; bde->addrLow = first_data_sgl->addr_lo; bde->addrHigh = first_data_sgl->addr_hi; bde->tus.f.bdeSize = le32_to_cpu(first_data_sgl->sge_len); bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64; bde->tus.w = cpu_to_le32(bde->tus.w); + + } else { + memset(&wqe->words[13], 0, (sizeof(uint32_t) * 3)); } } else { sgl += 1; @@ -3218,11 +3224,15 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) if ((phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) || phba->cfg_enable_pbde) { bde = (struct ulp_bde64 *) - &(iocb_cmd->unsli3.sli3Words[5]); + &wqe->words[13]; memset(bde, 0, (sizeof(uint32_t) * 3)); } } + /* Word 11 */ + if (phba->cfg_enable_pbde) + bf_set(wqe_pbde, &wqe->generic.wqe_com, 1); + /* * Finish initializing those IOCB fields that are dependent on the * scsi_cmnd request_buffer. Note that for SLI-2 the bdeSize is @@ -3230,12 +3240,23 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) * all iocb memory resources are reused. */ fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd)); - - /* - * Due to difference in data length between DIF/non-DIF paths, - * we need to set word 4 of IOCB here - */ - iocb_cmd->un.fcpi.fcpi_parm = scsi_bufflen(scsi_cmnd); + /* Set first-burst provided it was successfully negotiated */ + if (!(phba->hba_flag & HBA_FCOE_MODE) && + vport->cfg_first_burst_size && + scsi_cmnd->sc_data_direction == DMA_TO_DEVICE) { + u32 init_len, total_len; + + total_len = be32_to_cpu(fcp_cmnd->fcpDl); + init_len = min(total_len, vport->cfg_first_burst_size); + + /* Word 4 & 5 */ + wqe->fcp_iwrite.initial_xfer_len = init_len; + wqe->fcp_iwrite.total_xfer_len = total_len; + } else { + /* Word 4 */ + wqe->fcp_iwrite.total_xfer_len = + be32_to_cpu(fcp_cmnd->fcpDl); + } /* * If the OAS driver feature is enabled and the lun is enabled for @@ -3246,6 +3267,17 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) lpfc_cmd->cur_iocbq.iocb_flag |= (LPFC_IO_OAS | LPFC_IO_FOF); lpfc_cmd->cur_iocbq.priority = ((struct lpfc_device_data *) scsi_cmnd->device->hostdata)->priority; + + /* Word 10 */ + bf_set(wqe_oas, &wqe->generic.wqe_com, 1); + bf_set(wqe_ccpe, &wqe->generic.wqe_com, 1); + + if (lpfc_cmd->cur_iocbq.priority) + bf_set(wqe_ccp, &wqe->generic.wqe_com, + (lpfc_cmd->cur_iocbq.priority << 1)); + else + bf_set(wqe_ccp, &wqe->generic.wqe_com, + (phba->cfg_XLanePriority << 1)); } return 0; @@ -3271,7 +3303,8 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd; struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd; struct sli4_sge *sgl = (struct sli4_sge *)(lpfc_cmd->dma_sgl); - IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb; + struct lpfc_iocbq *pwqeq = &lpfc_cmd->cur_iocbq; + union lpfc_wqe128 *wqe = &pwqeq->wqe; uint32_t num_sge = 0; int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction; int prot_group_type = 0; @@ -3403,28 +3436,50 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd); fcp_cmnd->fcpDl = be32_to_cpu(fcpdl); - /* - * Due to difference in data length between DIF/non-DIF paths, - * we need to set word 4 of IOCB here - */ - iocb_cmd->un.fcpi.fcpi_parm = fcpdl; + /* Set first-burst provided it was successfully negotiated */ + if (!(phba->hba_flag & HBA_FCOE_MODE) && + vport->cfg_first_burst_size && + scsi_cmnd->sc_data_direction == DMA_TO_DEVICE) { + u32 init_len, total_len; - /* - * For First burst, we may need to adjust the initial transfer - * length for DIF - */ - if (iocb_cmd->un.fcpi.fcpi_XRdy && - (fcpdl < vport->cfg_first_burst_size)) - iocb_cmd->un.fcpi.fcpi_XRdy = fcpdl; + total_len = be32_to_cpu(fcp_cmnd->fcpDl); + init_len = min(total_len, vport->cfg_first_burst_size); + + /* Word 4 & 5 */ + wqe->fcp_iwrite.initial_xfer_len = init_len; + wqe->fcp_iwrite.total_xfer_len = total_len; + } else { + /* Word 4 */ + wqe->fcp_iwrite.total_xfer_len = + be32_to_cpu(fcp_cmnd->fcpDl); + } /* * If the OAS driver feature is enabled and the lun is enabled for * OAS, set the oas iocb related flags. */ if ((phba->cfg_fof) && ((struct lpfc_device_data *) - scsi_cmnd->device->hostdata)->oas_enabled) + scsi_cmnd->device->hostdata)->oas_enabled) { lpfc_cmd->cur_iocbq.iocb_flag |= (LPFC_IO_OAS | LPFC_IO_FOF); + /* Word 10 */ + bf_set(wqe_oas, &wqe->generic.wqe_com, 1); + bf_set(wqe_ccpe, &wqe->generic.wqe_com, 1); + bf_set(wqe_ccp, &wqe->generic.wqe_com, + (phba->cfg_XLanePriority << 1)); + } + + /* Word 7. DIF Flags */ + if (lpfc_cmd->cur_iocbq.iocb_flag & LPFC_IO_DIF_PASS) + bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_PASSTHRU); + else if (lpfc_cmd->cur_iocbq.iocb_flag & LPFC_IO_DIF_STRIP) + bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_STRIP); + else if (lpfc_cmd->cur_iocbq.iocb_flag & LPFC_IO_DIF_INSERT) + bf_set(wqe_dif, &wqe->generic.wqe_com, LPFC_WQE_DIF_INSERT); + + lpfc_cmd->cur_iocbq.iocb_flag &= ~(LPFC_IO_DIF_PASS | + LPFC_IO_DIF_STRIP | LPFC_IO_DIF_INSERT); + return 0; err: if (lpfc_cmd->seg_cnt) @@ -3483,6 +3538,26 @@ lpfc_bg_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd) return phba->lpfc_bg_scsi_prep_dma_buf(phba, lpfc_cmd); } +/** + * lpfc_scsi_prep_cmnd_buf - Wrapper function for IOCB/WQE mapping of scsi + * buffer + * @phba: The Hba for which this call is being executed. + * @lpfc_cmd: The scsi buffer which is going to be mapped. + * @tmo: Timeout value for IO + * + * This routine initializes IOCB/WQE data structure from scsi command + * + * Return codes: + * 1 - Error + * 0 - Success + **/ +static inline int +lpfc_scsi_prep_cmnd_buf(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, + uint8_t tmo) +{ + return vport->phba->lpfc_scsi_prep_cmnd_buf(vport, lpfc_cmd, tmo); +} + /** * lpfc_send_scsi_error_event - Posts an event when there is SCSI error * @phba: Pointer to hba context object. @@ -4061,72 +4136,30 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, } /** - * lpfc_fcpcmd_to_iocb - copy the fcp_cmd data into the IOCB - * @data: A pointer to the immediate command data portion of the IOCB. - * @fcp_cmnd: The FCP Command that is provided by the SCSI layer. + * lpfc_scsi_prep_cmnd_buf_s3 - SLI-3 IOCB init for the IO + * @phba: Pointer to vport object for which I/O is executed + * @lpfc_cmd: The scsi buffer which is going to be prep'ed. + * @tmo: timeout value for the IO * - * The routine copies the entire FCP command from @fcp_cmnd to @data while - * byte swapping the data to big endian format for transmission on the wire. - **/ -static void -lpfc_fcpcmd_to_iocb(uint8_t *data, struct fcp_cmnd *fcp_cmnd) -{ - int i, j; - for (i = 0, j = 0; i < sizeof(struct fcp_cmnd); - i += sizeof(uint32_t), j++) { - ((uint32_t *)data)[j] = cpu_to_be32(((uint32_t *)fcp_cmnd)[j]); - } -} - -/** - * lpfc_scsi_prep_cmnd - Wrapper func for convert scsi cmnd to FCP info unit - * @vport: The virtual port for which this call is being executed. - * @lpfc_cmd: The scsi command which needs to send. - * @pnode: Pointer to lpfc_nodelist. + * Based on the data-direction of the command, initialize IOCB + * in the I/O buffer. Fill in the IOCB fields which are independent + * of the scsi buffer * - * This routine initializes fcp_cmnd and iocb data structure from scsi command - * to transfer for device with SLI3 interface spec. + * RETURNS 0 - SUCCESS, **/ -static void -lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, - struct lpfc_nodelist *pnode) +static int lpfc_scsi_prep_cmnd_buf_s3(struct lpfc_vport *vport, + struct lpfc_io_buf *lpfc_cmd, + uint8_t tmo) { - struct lpfc_hba *phba = vport->phba; + IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb; + struct lpfc_iocbq *piocbq = &lpfc_cmd->cur_iocbq; struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd; struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd; - IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb; - struct lpfc_iocbq *piocbq = &(lpfc_cmd->cur_iocbq); - struct lpfc_sli4_hdw_queue *hdwq = NULL; + struct lpfc_nodelist *pnode = lpfc_cmd->ndlp; int datadir = scsi_cmnd->sc_data_direction; - int idx; - uint8_t *ptr; - bool sli4; - uint32_t fcpdl; - - if (!pnode) - return; + u32 fcpdl; - lpfc_cmd->fcp_rsp->rspSnsLen = 0; - /* clear task management bits */ - lpfc_cmd->fcp_cmnd->fcpCntl2 = 0; - - int_to_scsilun(lpfc_cmd->pCmd->device->lun, - &lpfc_cmd->fcp_cmnd->fcp_lun); - - ptr = &fcp_cmnd->fcpCdb[0]; - memcpy(ptr, scsi_cmnd->cmnd, scsi_cmnd->cmd_len); - if (scsi_cmnd->cmd_len < LPFC_FCP_CDB_LEN) { - ptr += scsi_cmnd->cmd_len; - memset(ptr, 0, (LPFC_FCP_CDB_LEN - scsi_cmnd->cmd_len)); - } - - fcp_cmnd->fcpCntl1 = SIMPLE_Q; - - sli4 = (phba->sli_rev == LPFC_SLI_REV4); piocbq->iocb.un.fcpi.fcpi_XRdy = 0; - idx = lpfc_cmd->hdwq_no; - if (phba->sli4_hba.hdwq) - hdwq = &phba->sli4_hba.hdwq[idx]; /* * There are three possibilities here - use scatter-gather segment, use @@ -4140,42 +4173,31 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, iocb_cmd->ulpPU = PARM_READ_CHECK; if (vport->cfg_first_burst_size && (pnode->nlp_flag & NLP_FIRSTBURST)) { + u32 xrdy_len; + fcpdl = scsi_bufflen(scsi_cmnd); - if (fcpdl < vport->cfg_first_burst_size) - piocbq->iocb.un.fcpi.fcpi_XRdy = fcpdl; - else - piocbq->iocb.un.fcpi.fcpi_XRdy = - vport->cfg_first_burst_size; + xrdy_len = min(fcpdl, + vport->cfg_first_burst_size); + piocbq->iocb.un.fcpi.fcpi_XRdy = xrdy_len; } fcp_cmnd->fcpCntl3 = WRITE_DATA; - if (hdwq) - hdwq->scsi_cstat.output_requests++; } else { iocb_cmd->ulpCommand = CMD_FCP_IREAD64_CR; iocb_cmd->ulpPU = PARM_READ_CHECK; fcp_cmnd->fcpCntl3 = READ_DATA; - if (hdwq) - hdwq->scsi_cstat.input_requests++; } } else { iocb_cmd->ulpCommand = CMD_FCP_ICMND64_CR; iocb_cmd->un.fcpi.fcpi_parm = 0; iocb_cmd->ulpPU = 0; fcp_cmnd->fcpCntl3 = 0; - if (hdwq) - hdwq->scsi_cstat.control_requests++; } - if (phba->sli_rev == 3 && - !(phba->sli3_options & LPFC_SLI3_BG_ENABLED)) - lpfc_fcpcmd_to_iocb(iocb_cmd->unsli3.fcp_ext.icd, fcp_cmnd); + /* * Finish initializing those IOCB fields that are independent * of the scsi_cmnd request_buffer */ piocbq->iocb.ulpContext = pnode->nlp_rpi; - if (sli4) - piocbq->iocb.ulpContext = - phba->sli4_hba.rpi_ids[pnode->nlp_rpi]; if (pnode->nlp_fcp_info & NLP_FCP_2_DEVICE) piocbq->iocb.ulpFCP2Rcvy = 1; else @@ -4183,9 +4205,160 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, piocbq->iocb.ulpClass = (pnode->nlp_fcp_info & 0x0f); piocbq->context1 = lpfc_cmd; - piocbq->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl; - piocbq->iocb.ulpTimeout = lpfc_cmd->timeout; + if (!piocbq->iocb_cmpl) + piocbq->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl; + piocbq->iocb.ulpTimeout = tmo; piocbq->vport = vport; + return 0; +} + +/** + * lpfc_scsi_prep_cmnd_buf_s4 - SLI-4 WQE init for the IO + * @phba: Pointer to vport object for which I/O is executed + * @lpfc_cmd: The scsi buffer which is going to be prep'ed. + * @tmo: timeout value for the IO + * + * Based on the data-direction of the command copy WQE template + * to I/O buffer WQE. Fill in the WQE fields which are independent + * of the scsi buffer + * + * RETURNS 0 - SUCCESS, + **/ +static int lpfc_scsi_prep_cmnd_buf_s4(struct lpfc_vport *vport, + struct lpfc_io_buf *lpfc_cmd, + uint8_t tmo) +{ + struct lpfc_hba *phba = vport->phba; + struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd; + struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd; + struct lpfc_sli4_hdw_queue *hdwq = NULL; + struct lpfc_iocbq *pwqeq = &lpfc_cmd->cur_iocbq; + struct lpfc_nodelist *pnode = lpfc_cmd->ndlp; + union lpfc_wqe128 *wqe = &pwqeq->wqe; + u16 idx = lpfc_cmd->hdwq_no; + int datadir = scsi_cmnd->sc_data_direction; + + hdwq = &phba->sli4_hba.hdwq[idx]; + + /* Initialize 64 bytes only */ + memset(wqe, 0, sizeof(union lpfc_wqe128)); + + /* + * There are three possibilities here - use scatter-gather segment, use + * the single mapping, or neither. + */ + if (scsi_sg_count(scsi_cmnd)) { + if (datadir == DMA_TO_DEVICE) { + /* From the iwrite template, initialize words 7 - 11 */ + memcpy(&wqe->words[7], + &lpfc_iwrite_cmd_template.words[7], + sizeof(uint32_t) * 5); + + fcp_cmnd->fcpCntl3 = WRITE_DATA; + if (hdwq) + hdwq->scsi_cstat.output_requests++; + } else { + /* From the iread template, initialize words 7 - 11 */ + memcpy(&wqe->words[7], + &lpfc_iread_cmd_template.words[7], + sizeof(uint32_t) * 5); + + /* Word 7 */ + bf_set(wqe_tmo, &wqe->fcp_iread.wqe_com, tmo); + + fcp_cmnd->fcpCntl3 = READ_DATA; + if (hdwq) + hdwq->scsi_cstat.input_requests++; + } + } else { + /* From the icmnd template, initialize words 4 - 11 */ + memcpy(&wqe->words[4], &lpfc_icmnd_cmd_template.words[4], + sizeof(uint32_t) * 8); + + /* Word 7 */ + bf_set(wqe_tmo, &wqe->fcp_icmd.wqe_com, tmo); + + fcp_cmnd->fcpCntl3 = 0; + if (hdwq) + hdwq->scsi_cstat.control_requests++; + } + + /* + * Finish initializing those WQE fields that are independent + * of the request_buffer + */ + + /* Word 3 */ + bf_set(payload_offset_len, &wqe->fcp_icmd, + sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp)); + + /* Word 6 */ + bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com, + phba->sli4_hba.rpi_ids[pnode->nlp_rpi]); + bf_set(wqe_xri_tag, &wqe->generic.wqe_com, pwqeq->sli4_xritag); + + /* Word 7*/ + if (pnode->nlp_fcp_info & NLP_FCP_2_DEVICE) + bf_set(wqe_erp, &wqe->generic.wqe_com, 1); + + bf_set(wqe_class, &wqe->generic.wqe_com, + (pnode->nlp_fcp_info & 0x0f)); + + /* Word 8 */ + wqe->generic.wqe_com.abort_tag = pwqeq->iotag; + + /* Word 9 */ + bf_set(wqe_reqtag, &wqe->generic.wqe_com, pwqeq->iotag); + + pwqeq->vport = vport; + pwqeq->vport = vport; + pwqeq->context1 = lpfc_cmd; + pwqeq->hba_wqidx = lpfc_cmd->hdwq_no; + if (!pwqeq->iocb_cmpl) + pwqeq->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl; + + return 0; +} + +/** + * lpfc_scsi_prep_cmnd - Wrapper func for convert scsi cmnd to FCP info unit + * @vport: The virtual port for which this call is being executed. + * @lpfc_cmd: The scsi command which needs to send. + * @pnode: Pointer to lpfc_nodelist. + * + * This routine initializes fcp_cmnd and iocb data structure from scsi command + * to transfer for device with SLI3 interface spec. + **/ +static int +lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, + struct lpfc_nodelist *pnode) +{ + struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd; + struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd; + u8 *ptr; + + if (!pnode) + return 0; + + lpfc_cmd->fcp_rsp->rspSnsLen = 0; + /* clear task management bits */ + lpfc_cmd->fcp_cmnd->fcpCntl2 = 0; + + int_to_scsilun(lpfc_cmd->pCmd->device->lun, + &lpfc_cmd->fcp_cmnd->fcp_lun); + + ptr = &fcp_cmnd->fcpCdb[0]; + memcpy(ptr, scsi_cmnd->cmnd, scsi_cmnd->cmd_len); + if (scsi_cmnd->cmd_len < LPFC_FCP_CDB_LEN) { + ptr += scsi_cmnd->cmd_len; + memset(ptr, 0, (LPFC_FCP_CDB_LEN - scsi_cmnd->cmd_len)); + } + + fcp_cmnd->fcpCntl1 = SIMPLE_Q; + + lpfc_scsi_prep_cmnd_buf(vport, lpfc_cmd, lpfc_cmd->timeout); + + return 0; } /** @@ -4271,7 +4444,6 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) { phba->lpfc_scsi_unprep_dma_buf = lpfc_scsi_unprep_dma_buf; - phba->lpfc_scsi_prep_cmnd = lpfc_scsi_prep_cmnd; switch (dev_grp) { case LPFC_PCI_DEV_LP: @@ -4279,12 +4451,14 @@ lpfc_scsi_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp) phba->lpfc_bg_scsi_prep_dma_buf = lpfc_bg_scsi_prep_dma_buf_s3; phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s3; phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s3; + phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s3; break; case LPFC_PCI_DEV_OC: phba->lpfc_scsi_prep_dma_buf = lpfc_scsi_prep_dma_buf_s4; phba->lpfc_bg_scsi_prep_dma_buf = lpfc_bg_scsi_prep_dma_buf_s4; phba->lpfc_release_scsi_buf = lpfc_release_scsi_buf_s4; phba->lpfc_get_scsi_buf = lpfc_get_scsi_buf_s4; + phba->lpfc_scsi_prep_cmnd_buf = lpfc_scsi_prep_cmnd_buf_s4; break; default: lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, @@ -4599,8 +4773,13 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) lpfc_cmd->pCmd = cmnd; lpfc_cmd->rdata = rdata; lpfc_cmd->ndlp = ndlp; + lpfc_cmd->cur_iocbq.iocb_cmpl = NULL; cmnd->host_scribble = (unsigned char *)lpfc_cmd; + err = lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp); + if (err) + goto out_host_busy_release_buf; + if (scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) { if (vport->phba->cfg_enable_bg) { lpfc_printf_vlog(vport, @@ -4636,7 +4815,6 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) goto out_host_busy_free_buf; } - lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp); #ifdef CONFIG_SCSI_LPFC_DEBUG_FS if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO)) @@ -4657,24 +4835,30 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) #endif if (err) { lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, - "3376 FCP could not issue IOCB err %x" - "FCP cmd x%x <%d/%llu> " - "sid: x%x did: x%x oxid: x%x " - "Data: x%x x%x x%x x%x\n", - err, cmnd->cmnd[0], - cmnd->device ? cmnd->device->id : 0xffff, - cmnd->device ? cmnd->device->lun : (u64) -1, - vport->fc_myDID, ndlp->nlp_DID, - phba->sli_rev == LPFC_SLI_REV4 ? - lpfc_cmd->cur_iocbq.sli4_xritag : 0xffff, - lpfc_cmd->cur_iocbq.iocb.ulpContext, - lpfc_cmd->cur_iocbq.iocb.ulpIoTag, - lpfc_cmd->cur_iocbq.iocb.ulpTimeout, - (uint32_t) - (cmnd->request->timeout / 1000)); + "3376 FCP could not issue IOCB err %x " + "FCP cmd x%x <%d/%llu> " + "sid: x%x did: x%x oxid: x%x " + "Data: x%x x%x x%x x%x\n", + err, cmnd->cmnd[0], + cmnd->device ? cmnd->device->id : 0xffff, + cmnd->device ? cmnd->device->lun : (u64)-1, + vport->fc_myDID, ndlp->nlp_DID, + phba->sli_rev == LPFC_SLI_REV4 ? + lpfc_cmd->cur_iocbq.sli4_xritag : 0xffff, + phba->sli_rev == LPFC_SLI_REV4 ? + phba->sli4_hba.rpi_ids[ndlp->nlp_rpi] : + lpfc_cmd->cur_iocbq.iocb.ulpContext, + lpfc_cmd->cur_iocbq.iotag, + phba->sli_rev == LPFC_SLI_REV4 ? + bf_get(wqe_tmo, + &lpfc_cmd->cur_iocbq.wqe.generic.wqe_com) : + lpfc_cmd->cur_iocbq.iocb.ulpTimeout, + (uint32_t) + (cmnd->request->timeout / 1000)); goto out_host_busy_free_buf; } + if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) { lpfc_sli_handle_fast_ring_event(phba, &phba->sli.sli3_ring[LPFC_FCP_RING], HA_R0RE_REQ); @@ -4703,6 +4887,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) phba->sli4_hba.hdwq[idx].scsi_cstat.control_requests--; } } + out_host_busy_release_buf: lpfc_release_scsi_buf(phba, lpfc_cmd); out_host_busy: return SCSI_MLQUEUE_HOST_BUSY; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 31c524a3373f..2007835b6a5a 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -10251,7 +10251,7 @@ __lpfc_sli_issue_fcp_io_s3(struct lpfc_hba *phba, uint32_t ring_number, int rc; spin_lock_irqsave(&phba->hbalock, iflags); - rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb, flag); + rc = __lpfc_sli_issue_iocb_s3(phba, ring_number, piocb, flag); spin_unlock_irqrestore(&phba->hbalock, iflags); return rc; @@ -10275,22 +10275,47 @@ static int __lpfc_sli_issue_fcp_io_s4(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, uint32_t flag) { - struct lpfc_sli_ring *pring; - struct lpfc_queue *eq; - unsigned long iflags; int rc; + struct lpfc_io_buf *lpfc_cmd = + (struct lpfc_io_buf *)piocb->context1; + union lpfc_wqe128 *wqe = &piocb->wqe; + struct sli4_sge *sgl; - eq = phba->sli4_hba.hdwq[piocb->hba_wqidx].hba_eq; + /* 128 byte wqe support here */ + sgl = (struct sli4_sge *)lpfc_cmd->dma_sgl; - pring = lpfc_sli4_calc_ring(phba, piocb); - if (unlikely(pring == NULL)) - return IOCB_ERROR; + if (phba->fcp_embed_io) { + struct fcp_cmnd *fcp_cmnd; + u32 *ptr; - spin_lock_irqsave(&pring->ring_lock, iflags); - rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb, flag); - spin_unlock_irqrestore(&pring->ring_lock, iflags); + fcp_cmnd = lpfc_cmd->fcp_cmnd; + + /* Word 0-2 - FCP_CMND */ + wqe->generic.bde.tus.f.bdeFlags = + BUFF_TYPE_BDE_IMMED; + wqe->generic.bde.tus.f.bdeSize = sgl->sge_len; + wqe->generic.bde.addrHigh = 0; + wqe->generic.bde.addrLow = 88; /* Word 22 */ - lpfc_sli4_poll_eq(eq, LPFC_POLL_FASTPATH); + bf_set(wqe_wqes, &wqe->fcp_iwrite.wqe_com, 1); + bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 0); + + /* Word 22-29 FCP CMND Payload */ + ptr = &wqe->words[22]; + memcpy(ptr, fcp_cmnd, sizeof(struct fcp_cmnd)); + } else { + /* Word 0-2 - Inline BDE */ + wqe->generic.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64; + wqe->generic.bde.tus.f.bdeSize = sizeof(struct fcp_cmnd); + wqe->generic.bde.addrHigh = sgl->addr_hi; + wqe->generic.bde.addrLow = sgl->addr_lo; + + /* Word 10 */ + bf_set(wqe_dbde, &wqe->generic.wqe_com, 1); + bf_set(wqe_wqes, &wqe->generic.wqe_com, 0); + } + + rc = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, piocb); return rc; } @@ -10360,9 +10385,10 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, } } } - } else if (piocb->iocb_flag & LPFC_IO_FCP) + } else if (piocb->iocb_flag & LPFC_IO_FCP) { /* These IO's already have an XRI and a mapped sgl. */ sglq = NULL; + } else { /* * This is a continuation of a commandi,(CX) so this @@ -20468,7 +20494,8 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, } /* NVME_FCREQ and NVME_ABTS requests */ - if (pwqe->iocb_flag & LPFC_IO_NVME) { + if (pwqe->iocb_flag & LPFC_IO_NVME || + pwqe->iocb_flag & LPFC_IO_FCP) { /* Get the IO distribution (hba_wqidx) for WQ assignment. */ wq = qp->io_wq; pring = wq->pring; -- cgit v1.2.3 From 96e209be6ecb7b96dfb56f2737401adce33aef8e Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:43 -0800 Subject: scsi: lpfc: Convert SCSI I/O completions to SLI-3 and SLI-4 handlers The current driver implementation uses SLI-4 WQE to iocb conversion before calling the cmpl callback function. Rework the FCP I/O completion path to utilize the SLI-4 WQE. This patch converts the SCSI I/O completion paths from the iocb-centric interfaces to the routines are native for whether I/Os are iocb-based (SLI-3) or WQE-based (SLI-4). Most existing routines were iocb-based, so this creates a lot of SLI-4 specific routines to provide the functionality. Link: https://lore.kernel.org/r/20201115192646.12977-15-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_scsi.c | 490 ++++++++++++++++++++++++++++++++++++++++-- drivers/scsi/lpfc/lpfc_sli.c | 5 +- 2 files changed, 481 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 0581b7db2f8d..63c1ea3fd359 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -2891,6 +2891,150 @@ out: } } +/* + * This function checks for BlockGuard errors detected by + * the HBA. In case of errors, the ASC/ASCQ fields in the + * sense buffer will be set accordingly, paired with + * ILLEGAL_REQUEST to signal to the kernel that the HBA + * detected corruption. + * + * Returns: + * 0 - No error found + * 1 - BlockGuard error found + * -1 - Internal error (bad profile, ...etc) + */ +static int +lpfc_sli4_parse_bg_err(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd, + struct lpfc_wcqe_complete *wcqe) +{ + struct scsi_cmnd *cmd = lpfc_cmd->pCmd; + int ret = 0; + u32 status = bf_get(lpfc_wcqe_c_status, wcqe); + u32 bghm = 0; + u32 bgstat = 0; + u64 failing_sector = 0; + + if (status == CQE_STATUS_DI_ERROR) { + if (bf_get(lpfc_wcqe_c_bg_ge, wcqe)) /* Guard Check failed */ + bgstat |= BGS_GUARD_ERR_MASK; + if (bf_get(lpfc_wcqe_c_bg_ae, wcqe)) /* AppTag Check failed */ + bgstat |= BGS_APPTAG_ERR_MASK; + if (bf_get(lpfc_wcqe_c_bg_re, wcqe)) /* RefTag Check failed */ + bgstat |= BGS_REFTAG_ERR_MASK; + + /* Check to see if there was any good data before the error */ + if (bf_get(lpfc_wcqe_c_bg_tdpv, wcqe)) { + bgstat |= BGS_HI_WATER_MARK_PRESENT_MASK; + bghm = wcqe->total_data_placed; + } + + /* + * Set ALL the error bits to indicate we don't know what + * type of error it is. + */ + if (!bgstat) + bgstat |= (BGS_REFTAG_ERR_MASK | BGS_APPTAG_ERR_MASK | + BGS_GUARD_ERR_MASK); + } + + if (lpfc_bgs_get_guard_err(bgstat)) { + ret = 1; + + scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, + 0x10, 0x1); + cmd->result = DRIVER_SENSE << 24 | DID_ABORT << 16 | + SAM_STAT_CHECK_CONDITION; + phba->bg_guard_err_cnt++; + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, + "9059 BLKGRD: Guard Tag error in cmd" + " 0x%x lba 0x%llx blk cnt 0x%x " + "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], + (unsigned long long)scsi_get_lba(cmd), + blk_rq_sectors(cmd->request), bgstat, bghm); + } + + if (lpfc_bgs_get_reftag_err(bgstat)) { + ret = 1; + + scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, + 0x10, 0x3); + cmd->result = DRIVER_SENSE << 24 | DID_ABORT << 16 | + SAM_STAT_CHECK_CONDITION; + + phba->bg_reftag_err_cnt++; + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, + "9060 BLKGRD: Ref Tag error in cmd" + " 0x%x lba 0x%llx blk cnt 0x%x " + "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], + (unsigned long long)scsi_get_lba(cmd), + blk_rq_sectors(cmd->request), bgstat, bghm); + } + + if (lpfc_bgs_get_apptag_err(bgstat)) { + ret = 1; + + scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, + 0x10, 0x2); + cmd->result = DRIVER_SENSE << 24 | DID_ABORT << 16 | + SAM_STAT_CHECK_CONDITION; + + phba->bg_apptag_err_cnt++; + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, + "9062 BLKGRD: App Tag error in cmd" + " 0x%x lba 0x%llx blk cnt 0x%x " + "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], + (unsigned long long)scsi_get_lba(cmd), + blk_rq_sectors(cmd->request), bgstat, bghm); + } + + if (lpfc_bgs_get_hi_water_mark_present(bgstat)) { + /* + * setup sense data descriptor 0 per SPC-4 as an information + * field, and put the failing LBA in it. + * This code assumes there was also a guard/app/ref tag error + * indication. + */ + cmd->sense_buffer[7] = 0xc; /* Additional sense length */ + cmd->sense_buffer[8] = 0; /* Information descriptor type */ + cmd->sense_buffer[9] = 0xa; /* Additional descriptor length */ + cmd->sense_buffer[10] = 0x80; /* Validity bit */ + + /* bghm is a "on the wire" FC frame based count */ + switch (scsi_get_prot_op(cmd)) { + case SCSI_PROT_READ_INSERT: + case SCSI_PROT_WRITE_STRIP: + bghm /= cmd->device->sector_size; + break; + case SCSI_PROT_READ_STRIP: + case SCSI_PROT_WRITE_INSERT: + case SCSI_PROT_READ_PASS: + case SCSI_PROT_WRITE_PASS: + bghm /= (cmd->device->sector_size + + sizeof(struct scsi_dif_tuple)); + break; + } + + failing_sector = scsi_get_lba(cmd); + failing_sector += bghm; + + /* Descriptor Information */ + put_unaligned_be64(failing_sector, &cmd->sense_buffer[12]); + } + + if (!ret) { + /* No error was reported - problem in FW? */ + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, + "9068 BLKGRD: Unknown error in cmd" + " 0x%x lba 0x%llx blk cnt 0x%x " + "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], + (unsigned long long)scsi_get_lba(cmd), + blk_rq_sectors(cmd->request), bgstat, bghm); + + /* Calcuate what type of error it was */ + lpfc_calc_bg_err(phba, lpfc_cmd); + } + return ret; +} /* * This function checks for BlockGuard errors detected by @@ -3570,12 +3714,11 @@ lpfc_scsi_prep_cmnd_buf(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, **/ static void lpfc_send_scsi_error_event(struct lpfc_hba *phba, struct lpfc_vport *vport, - struct lpfc_io_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb) { + struct lpfc_io_buf *lpfc_cmd, uint32_t fcpi_parm) { struct scsi_cmnd *cmnd = lpfc_cmd->pCmd; struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp; uint32_t resp_info = fcprsp->rspStatus2; uint32_t scsi_status = fcprsp->rspStatus3; - uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm; struct lpfc_fast_path_event *fast_path_evt = NULL; struct lpfc_nodelist *pnode = lpfc_cmd->rdata->pnode; unsigned long flags; @@ -3690,13 +3833,11 @@ lpfc_scsi_unprep_dma_buf(struct lpfc_hba *phba, struct lpfc_io_buf *psb) **/ static void lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, - struct lpfc_iocbq *rsp_iocb) + uint32_t fcpi_parm) { - struct lpfc_hba *phba = vport->phba; struct scsi_cmnd *cmnd = lpfc_cmd->pCmd; struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd; struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp; - uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm; uint32_t resp_info = fcprsp->rspStatus2; uint32_t scsi_status = fcprsp->rspStatus3; uint32_t *lp; @@ -3831,13 +3972,10 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, */ } else if (fcpi_parm) { lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR, - "9029 FCP %s Check Error xri x%x Data: " + "9029 FCP %s Check Error Data: " "x%x x%x x%x x%x x%x\n", ((cmnd->sc_data_direction == DMA_FROM_DEVICE) ? "Read" : "Write"), - ((phba->sli_rev == LPFC_SLI_REV4) ? - lpfc_cmd->cur_iocbq.sli4_xritag : - rsp_iocb->iocb.ulpContext), fcpDl, be32_to_cpu(fcprsp->rspResId), fcpi_parm, cmnd->cmnd[0], scsi_status); @@ -3864,7 +4002,333 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd, out: cmnd->result = host_status << 16 | scsi_status; - lpfc_send_scsi_error_event(vport->phba, vport, lpfc_cmd, rsp_iocb); + lpfc_send_scsi_error_event(vport->phba, vport, lpfc_cmd, fcpi_parm); +} + +/** + * lpfc_fcp_io_cmd_wqe_cmpl - Complete a FCP IO + * @phba: The hba for which this call is being executed. + * @pwqeIn: The command WQE for the scsi cmnd. + * @pwqeOut: The response WQE for the scsi cmnd. + * + * This routine assigns scsi command result by looking into response WQE + * status field appropriately. This routine handles QUEUE FULL condition as + * well by ramping down device queue depth. + **/ +static void +lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, + struct lpfc_wcqe_complete *wcqe) +{ + struct lpfc_io_buf *lpfc_cmd = + (struct lpfc_io_buf *)pwqeIn->context1; + struct lpfc_vport *vport = pwqeIn->vport; + struct lpfc_rport_data *rdata = lpfc_cmd->rdata; + struct lpfc_nodelist *ndlp = rdata->pnode; + struct scsi_cmnd *cmd; + unsigned long flags; + struct lpfc_fast_path_event *fast_path_evt; + struct Scsi_Host *shost; + u32 logit = LOG_FCP; + u32 status, idx; + unsigned long iflags = 0; + + /* Sanity check on return of outstanding command */ + if (!lpfc_cmd) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "9032 Null lpfc_cmd pointer. No " + "release, skip completion\n"); + return; + } + + if (bf_get(lpfc_wcqe_c_xb, wcqe)) { + /* TOREMOVE - currently this flag is checked during + * the release of lpfc_iocbq. Remove once we move + * to lpfc_wqe_job construct. + * + * This needs to be done outside buf_lock + */ + spin_lock_irqsave(&phba->hbalock, iflags); + lpfc_cmd->cur_iocbq.iocb_flag |= LPFC_EXCHANGE_BUSY; + spin_unlock_irqrestore(&phba->hbalock, iflags); + } + + /* Guard against abort handler being called at same time */ + spin_lock(&lpfc_cmd->buf_lock); + + /* Sanity check on return of outstanding command */ + cmd = lpfc_cmd->pCmd; + if (!cmd || !phba) { + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, + "9042 I/O completion: Not an active IO\n"); + spin_unlock(&lpfc_cmd->buf_lock); + lpfc_release_scsi_buf(phba, lpfc_cmd); + return; + } + idx = lpfc_cmd->cur_iocbq.hba_wqidx; + if (phba->sli4_hba.hdwq) + phba->sli4_hba.hdwq[idx].scsi_cstat.io_cmpls++; + +#ifdef CONFIG_SCSI_LPFC_DEBUG_FS + if (unlikely(phba->hdwqstat_on & LPFC_CHECK_SCSI_IO)) + this_cpu_inc(phba->sli4_hba.c_stat->cmpl_io); +#endif + shost = cmd->device->host; + + status = bf_get(lpfc_wcqe_c_status, wcqe); + lpfc_cmd->status = (status & LPFC_IOCB_STATUS_MASK); + lpfc_cmd->result = (wcqe->parameter & IOERR_PARAM_MASK); + + lpfc_cmd->flags &= ~LPFC_SBUF_XBUSY; + if (bf_get(lpfc_wcqe_c_xb, wcqe)) + lpfc_cmd->flags |= LPFC_SBUF_XBUSY; + +#ifdef CONFIG_SCSI_LPFC_DEBUG_FS + if (lpfc_cmd->prot_data_type) { + struct scsi_dif_tuple *src = NULL; + + src = (struct scsi_dif_tuple *)lpfc_cmd->prot_data_segment; + /* + * Used to restore any changes to protection + * data for error injection. + */ + switch (lpfc_cmd->prot_data_type) { + case LPFC_INJERR_REFTAG: + src->ref_tag = + lpfc_cmd->prot_data; + break; + case LPFC_INJERR_APPTAG: + src->app_tag = + (uint16_t)lpfc_cmd->prot_data; + break; + case LPFC_INJERR_GUARD: + src->guard_tag = + (uint16_t)lpfc_cmd->prot_data; + break; + default: + break; + } + + lpfc_cmd->prot_data = 0; + lpfc_cmd->prot_data_type = 0; + lpfc_cmd->prot_data_segment = NULL; + } +#endif + if (unlikely(lpfc_cmd->status)) { + if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT && + (lpfc_cmd->result & IOERR_DRVR_MASK)) + lpfc_cmd->status = IOSTAT_DRIVER_REJECT; + else if (lpfc_cmd->status >= IOSTAT_CNT) + lpfc_cmd->status = IOSTAT_DEFAULT; + if (lpfc_cmd->status == IOSTAT_FCP_RSP_ERROR && + !lpfc_cmd->fcp_rsp->rspStatus3 && + (lpfc_cmd->fcp_rsp->rspStatus2 & RESID_UNDER) && + !(vport->cfg_log_verbose & LOG_FCP_UNDER)) + logit = 0; + else + logit = LOG_FCP | LOG_FCP_UNDER; + lpfc_printf_vlog(vport, KERN_WARNING, logit, + "9034 FCP cmd x%x failed <%d/%lld> " + "status: x%x result: x%x " + "sid: x%x did: x%x oxid: x%x " + "Data: x%x x%x x%x\n", + cmd->cmnd[0], + cmd->device ? cmd->device->id : 0xffff, + cmd->device ? cmd->device->lun : 0xffff, + lpfc_cmd->status, lpfc_cmd->result, + vport->fc_myDID, + (ndlp) ? ndlp->nlp_DID : 0, + lpfc_cmd->cur_iocbq.sli4_xritag, + wcqe->parameter, wcqe->total_data_placed, + lpfc_cmd->cur_iocbq.iotag); + } + + switch (lpfc_cmd->status) { + case IOSTAT_SUCCESS: + cmd->result = DID_OK << 16; + break; + case IOSTAT_FCP_RSP_ERROR: + lpfc_handle_fcp_err(vport, lpfc_cmd, + pwqeIn->wqe.fcp_iread.total_xfer_len - + wcqe->total_data_placed); + break; + case IOSTAT_NPORT_BSY: + case IOSTAT_FABRIC_BSY: + cmd->result = DID_TRANSPORT_DISRUPTED << 16; + fast_path_evt = lpfc_alloc_fast_evt(phba); + if (!fast_path_evt) + break; + fast_path_evt->un.fabric_evt.event_type = + FC_REG_FABRIC_EVENT; + fast_path_evt->un.fabric_evt.subcategory = + (lpfc_cmd->status == IOSTAT_NPORT_BSY) ? + LPFC_EVENT_PORT_BUSY : LPFC_EVENT_FABRIC_BUSY; + if (ndlp) { + memcpy(&fast_path_evt->un.fabric_evt.wwpn, + &ndlp->nlp_portname, + sizeof(struct lpfc_name)); + memcpy(&fast_path_evt->un.fabric_evt.wwnn, + &ndlp->nlp_nodename, + sizeof(struct lpfc_name)); + } + fast_path_evt->vport = vport; + fast_path_evt->work_evt.evt = + LPFC_EVT_FASTPATH_MGMT_EVT; + spin_lock_irqsave(&phba->hbalock, flags); + list_add_tail(&fast_path_evt->work_evt.evt_listp, + &phba->work_list); + spin_unlock_irqrestore(&phba->hbalock, flags); + lpfc_worker_wake_up(phba); + lpfc_printf_vlog(vport, KERN_WARNING, logit, + "9035 Fabric/Node busy FCP cmd x%x failed" + " <%d/%lld> " + "status: x%x result: x%x " + "sid: x%x did: x%x oxid: x%x " + "Data: x%x x%x x%x\n", + cmd->cmnd[0], + cmd->device ? cmd->device->id : 0xffff, + cmd->device ? cmd->device->lun : 0xffff, + lpfc_cmd->status, lpfc_cmd->result, + vport->fc_myDID, + (ndlp) ? ndlp->nlp_DID : 0, + lpfc_cmd->cur_iocbq.sli4_xritag, + wcqe->parameter, + wcqe->total_data_placed, + lpfc_cmd->cur_iocbq.iocb.ulpIoTag); + break; + case IOSTAT_REMOTE_STOP: + if (ndlp) { + /* This I/O was aborted by the target, we don't + * know the rxid and because we did not send the + * ABTS we cannot generate and RRQ. + */ + lpfc_set_rrq_active(phba, ndlp, + lpfc_cmd->cur_iocbq.sli4_lxritag, + 0, 0); + } + fallthrough; + case IOSTAT_LOCAL_REJECT: + if (lpfc_cmd->result & IOERR_DRVR_MASK) + lpfc_cmd->status = IOSTAT_DRIVER_REJECT; + if (lpfc_cmd->result == IOERR_ELXSEC_KEY_UNWRAP_ERROR || + lpfc_cmd->result == + IOERR_ELXSEC_KEY_UNWRAP_COMPARE_ERROR || + lpfc_cmd->result == IOERR_ELXSEC_CRYPTO_ERROR || + lpfc_cmd->result == + IOERR_ELXSEC_CRYPTO_COMPARE_ERROR) { + cmd->result = DID_NO_CONNECT << 16; + break; + } + if (lpfc_cmd->result == IOERR_INVALID_RPI || + lpfc_cmd->result == IOERR_NO_RESOURCES || + lpfc_cmd->result == IOERR_ABORT_REQUESTED || + lpfc_cmd->result == IOERR_SLER_CMD_RCV_FAILURE) { + cmd->result = DID_REQUEUE << 16; + break; + } + if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED || + lpfc_cmd->result == IOERR_TX_DMA_FAILED) && + status == CQE_STATUS_DI_ERROR) { + if (scsi_get_prot_op(cmd) != + SCSI_PROT_NORMAL) { + /* + * This is a response for a BG enabled + * cmd. Parse BG error + */ + lpfc_sli4_parse_bg_err(phba, lpfc_cmd, + wcqe); + break; + } + lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, + "9040 non-zero BGSTAT on unprotected cmd\n"); + } + lpfc_printf_vlog(vport, KERN_WARNING, logit, + "9036 Local Reject FCP cmd x%x failed" + " <%d/%lld> " + "status: x%x result: x%x " + "sid: x%x did: x%x oxid: x%x " + "Data: x%x x%x x%x\n", + cmd->cmnd[0], + cmd->device ? cmd->device->id : 0xffff, + cmd->device ? cmd->device->lun : 0xffff, + lpfc_cmd->status, lpfc_cmd->result, + vport->fc_myDID, + (ndlp) ? ndlp->nlp_DID : 0, + lpfc_cmd->cur_iocbq.sli4_xritag, + wcqe->parameter, + wcqe->total_data_placed, + lpfc_cmd->cur_iocbq.iocb.ulpIoTag); + fallthrough; + default: + if (lpfc_cmd->status >= IOSTAT_CNT) + lpfc_cmd->status = IOSTAT_DEFAULT; + cmd->result = DID_ERROR << 16; + lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR, + "9037 FCP Completion Error: xri %x " + "status x%x result x%x [x%x] " + "placed x%x\n", + lpfc_cmd->cur_iocbq.sli4_xritag, + lpfc_cmd->status, lpfc_cmd->result, + wcqe->parameter, + wcqe->total_data_placed); + } + if (cmd->result || lpfc_cmd->fcp_rsp->rspSnsLen) { + u32 *lp = (u32 *)cmd->sense_buffer; + + lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, + "9039 Iodone <%d/%llu> cmd x%p, error " + "x%x SNS x%x x%x Data: x%x x%x\n", + cmd->device->id, cmd->device->lun, cmd, + cmd->result, *lp, *(lp + 3), cmd->retries, + scsi_get_resid(cmd)); + } + + lpfc_update_stats(vport, lpfc_cmd); + + if (vport->cfg_max_scsicmpl_time && + time_after(jiffies, lpfc_cmd->start_time + + msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) { + spin_lock_irqsave(shost->host_lock, flags); + if (ndlp) { + if (ndlp->cmd_qdepth > + atomic_read(&ndlp->cmd_pending) && + (atomic_read(&ndlp->cmd_pending) > + LPFC_MIN_TGT_QDEPTH) && + (cmd->cmnd[0] == READ_10 || + cmd->cmnd[0] == WRITE_10)) + ndlp->cmd_qdepth = + atomic_read(&ndlp->cmd_pending); + + ndlp->last_change_time = jiffies; + } + spin_unlock_irqrestore(shost->host_lock, flags); + } + lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd); + +#ifdef CONFIG_SCSI_LPFC_DEBUG_FS + if (lpfc_cmd->ts_cmd_start) { + lpfc_cmd->ts_isr_cmpl = lpfc_cmd->cur_iocbq.isr_timestamp; + lpfc_cmd->ts_data_io = ktime_get_ns(); + phba->ktime_last_cmd = lpfc_cmd->ts_data_io; + lpfc_io_ktime(phba, lpfc_cmd); + } +#endif + lpfc_cmd->pCmd = NULL; + spin_unlock(&lpfc_cmd->buf_lock); + + /* The sdev is not guaranteed to be valid post scsi_done upcall. */ + cmd->scsi_done(cmd); + + /* + * If there is an abort thread waiting for command completion + * wake up the thread. + */ + spin_lock(&lpfc_cmd->buf_lock); + lpfc_cmd->cur_iocbq.iocb_flag &= ~LPFC_DRIVER_ABORTED; + if (lpfc_cmd->waitq) + wake_up(lpfc_cmd->waitq); + spin_unlock(&lpfc_cmd->buf_lock); + + lpfc_release_scsi_buf(phba, lpfc_cmd); } /** @@ -3987,7 +4451,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, switch (lpfc_cmd->status) { case IOSTAT_FCP_RSP_ERROR: /* Call FCP RSP handler to determine result */ - lpfc_handle_fcp_err(vport, lpfc_cmd, pIocbOut); + lpfc_handle_fcp_err(vport, lpfc_cmd, + pIocbOut->iocb.un.fcpi.fcpi_parm); break; case IOSTAT_NPORT_BSY: case IOSTAT_FABRIC_BSY: @@ -4314,8 +4779,7 @@ static int lpfc_scsi_prep_cmnd_buf_s4(struct lpfc_vport *vport, pwqeq->vport = vport; pwqeq->context1 = lpfc_cmd; pwqeq->hba_wqidx = lpfc_cmd->hdwq_no; - if (!pwqeq->iocb_cmpl) - pwqeq->iocb_cmpl = lpfc_scsi_cmd_iocb_cmpl; + pwqeq->wqe_cmpl = lpfc_fcp_io_cmd_wqe_cmpl; return 0; } diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 2007835b6a5a..e58ad2ea11be 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -14339,7 +14339,9 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, #endif if (cmdiocbq->iocb_cmpl == NULL) { if (cmdiocbq->wqe_cmpl) { - if (cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) { + /* For FCP the flag is cleared in wqe_cmpl */ + if (!(cmdiocbq->iocb_flag & LPFC_IO_FCP) && + cmdiocbq->iocb_flag & LPFC_DRIVER_ABORTED) { spin_lock_irqsave(&phba->hbalock, iflags); cmdiocbq->iocb_flag &= ~LPFC_DRIVER_ABORTED; spin_unlock_irqrestore(&phba->hbalock, iflags); @@ -14356,6 +14358,7 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, return; } + /* Only SLI4 non-IO commands stil use IOCB */ /* Fake the irspiocb and copy necessary response information */ lpfc_sli4_iocb_param_transfer(phba, &irspiocbq, cmdiocbq, wcqe); -- cgit v1.2.3 From db7531d2b3775c662466e4eeda774986472c6d18 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:44 -0800 Subject: scsi: lpfc: Convert abort handling to SLI-3 and SLI-4 handlers This patch reworks the abort interfaces such that SLI-3 retains the iocb-based formatting and completions and SLI-4 now uses native WQEs and completion routines. The following changes are made: - The code is refactored from a confusing 2 routine sequence of xx_abort_iotag_issue(), which creates/formats and abort cmd, and xx_issue_abort_tag(), which then issues and handles the completion of the abort cmd - into a single interface of xx_issue_abort_iotag(). The new interface will determine whether SLI-3 or SLI-4 and then call the appropriate handler. A completion handler can now be specified to address the differences in completion handling. Note: original code is all iocb based, with SLI-4 converting to SLI-3 for the SCSI/ELS path, and NVMe natively using wqes. - The SLI-3 side is refactored: The older iocb-base lpfc_sli_issue_abort_iotag() routine is combined with the logic of lpfc_sli_abort_iotag_issue() as well as the iocb-specific code in lpfc_abort_handler() and lpfc_sli_abort_iocb() to create the new single SLI-3 abort routine that formats and issues the iocb. - The SLI-4 side is refactored and added to: The native WQE abort code in NVMe is moved to the new SLI-4 issue_abort_iotag() routine. Items in SCSI that set fields not set by NVMe is migrated into the new routine. Thus the routine supports NVMe and SCSI initiators. The nvmet block (target) formats the abort slightly different (like the old NVMe initiator) thus it has its own prep routine stolen from NVMe initiator and it retains the current code it has for issuing the WQE (does not use the commonized routine the initiators do). SLI-4 completion handlers were also added. - lpfc_abort_handler now becomes a wrapper that determines whether SLI-3 or SLI-4 and calls the proper abort handler. Link: https://lore.kernel.org/r/20201115192646.12977-16-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_bsg.c | 4 +- drivers/scsi/lpfc/lpfc_crtn.h | 7 +- drivers/scsi/lpfc/lpfc_els.c | 7 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 2 +- drivers/scsi/lpfc/lpfc_nvme.c | 72 +------- drivers/scsi/lpfc/lpfc_nvmet.c | 42 ++++- drivers/scsi/lpfc/lpfc_scsi.c | 62 ++----- drivers/scsi/lpfc/lpfc_sli.c | 329 ++++++++++++++++++++----------------- drivers/scsi/lpfc/lpfc_sli.h | 5 + 10 files changed, 253 insertions(+), 279 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 6bbdfaf6ddfe..d4955119380d 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -5927,7 +5927,7 @@ lpfc_bsg_timeout(struct bsg_job *job) } } if (list_empty(&completions)) - lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb); + lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb, NULL); spin_unlock_irqrestore(&phba->hbalock, flags); if (!list_empty(&completions)) { lpfc_sli_cancel_iocbs(phba, &completions, @@ -5964,7 +5964,7 @@ lpfc_bsg_timeout(struct bsg_job *job) } } if (list_empty(&completions)) - lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb); + lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb, NULL); spin_unlock_irqrestore(&phba->hbalock, flags); if (!list_empty(&completions)) { lpfc_sli_cancel_iocbs(phba, &completions, diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 2b1540c0c82e..69b1a357007b 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -324,6 +324,8 @@ int lpfc_sli_issue_fcp_io(struct lpfc_hba *phba, uint32_t ring_number, struct lpfc_iocbq *piocb, uint32_t flag); int lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, struct lpfc_iocbq *pwqe); +int lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba, + struct lpfc_iocbq *cmdiocb, void *cmpl); struct lpfc_sglq *__lpfc_clear_active_sglq(struct lpfc_hba *phba, uint16_t xri); struct lpfc_sglq *__lpfc_sli_get_nvmet_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq); @@ -348,7 +350,7 @@ int lpfc_sli_hbqbuf_add_hbqs(struct lpfc_hba *, uint32_t); void lpfc_sli_hbqbuf_free_all(struct lpfc_hba *); int lpfc_sli_hbq_size(void); int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *, - struct lpfc_iocbq *); + struct lpfc_iocbq *, void *); int lpfc_sli_sum_iocb(struct lpfc_vport *, uint16_t, uint64_t, lpfc_ctx_cmd); int lpfc_sli_abort_iocb(struct lpfc_vport *, struct lpfc_sli_ring *, uint16_t, uint64_t, lpfc_ctx_cmd); @@ -371,6 +373,8 @@ int lpfc_sli_issue_iocb_wait(struct lpfc_hba *, uint32_t, uint32_t); void lpfc_sli_abort_fcp_cmpl(struct lpfc_hba *, struct lpfc_iocbq *, struct lpfc_iocbq *); +void lpfc_sli4_abort_fcp_cmpl(struct lpfc_hba *h, struct lpfc_iocbq *i, + struct lpfc_wcqe_complete *w); void lpfc_sli_free_hbq(struct lpfc_hba *, struct hbq_dmabuf *); @@ -595,7 +599,6 @@ void lpfc_io_ktime(struct lpfc_hba *phba, struct lpfc_io_buf *ncmd); void lpfc_wqe_cmd_template(void); void lpfc_nvmet_cmd_template(void); void lpfc_nvme_cancel_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn); -void lpfc_nvme_prep_abort_wqe(struct lpfc_iocbq *pwqeq, u16 xritag, u8 opt); extern int lpfc_enable_nvmet_cnt; extern unsigned long long lpfc_enable_nvmet[]; extern int lpfc_no_hba_reset_cnt; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index f5509b1d4c5f..03f47d1b21fe 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1424,7 +1424,8 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba) if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) { ndlp = (struct lpfc_nodelist *)(iocb->context1); if (ndlp && (ndlp->nlp_DID == Fabric_DID)) - lpfc_sli_issue_abort_iotag(phba, pring, iocb); + lpfc_sli_issue_abort_iotag(phba, pring, iocb, + NULL); } } spin_unlock_irq(&phba->hbalock); @@ -8135,7 +8136,7 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) remote_ID, cmd->ulpCommand, cmd->ulpIoTag); spin_lock_irq(&phba->hbalock); list_del_init(&piocb->dlist); - lpfc_sli_issue_abort_iotag(phba, pring, piocb); + lpfc_sli_issue_abort_iotag(phba, pring, piocb, NULL); spin_unlock_irq(&phba->hbalock); } @@ -8235,7 +8236,7 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) { spin_lock_irqsave(&phba->hbalock, iflags); list_del_init(&piocb->dlist); - lpfc_sli_issue_abort_iotag(phba, pring, piocb); + lpfc_sli_issue_abort_iotag(phba, pring, piocb, NULL); spin_unlock_irqrestore(&phba->hbalock, iflags); } if (!list_empty(&abort_list)) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 1d554c1dc305..c8911a3d00ee 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -5610,7 +5610,7 @@ lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) icmd = &iocb->iocb; if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR || icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX) { - lpfc_sli_issue_abort_iotag(phba, pring, iocb); + lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL); } } spin_unlock_irq(&phba->hbalock); diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 1eddb40f009c..297fc92d01ce 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -247,7 +247,7 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) list_for_each_entry_safe(iocb, next_iocb, &abort_list, dlist) { spin_lock_irq(&phba->hbalock); list_del_init(&iocb->dlist); - lpfc_sli_issue_abort_iotag(phba, pring, iocb); + lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL); spin_unlock_irq(&phba->hbalock); } diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 2682839108f5..f9f4926b682f 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -62,46 +62,6 @@ lpfc_release_nvme_buf(struct lpfc_hba *, struct lpfc_io_buf *); static struct nvme_fc_port_template lpfc_nvme_template; -/** - * lpfc_nvme_prep_abort_wqe - set up 'abort' work queue entry. - * @pwqeq: Pointer to command iocb. - * @xritag: Tag that uniqely identifies the local exchange resource. - * @opt: Option bits - - * bit 0 = inhibit sending abts on the link - * - * This function is called with hbalock held. - **/ -void -lpfc_nvme_prep_abort_wqe(struct lpfc_iocbq *pwqeq, u16 xritag, u8 opt) -{ - union lpfc_wqe128 *wqe = &pwqeq->wqe; - - /* WQEs are reused. Clear stale data and set key fields to - * zero like ia, iaab, iaar, xri_tag, and ctxt_tag. - */ - memset(wqe, 0, sizeof(*wqe)); - - if (opt & INHIBIT_ABORT) - bf_set(abort_cmd_ia, &wqe->abort_cmd, 1); - /* Abort specified xri tag, with the mask deliberately zeroed */ - bf_set(abort_cmd_criteria, &wqe->abort_cmd, T_XRI_TAG); - - bf_set(wqe_cmnd, &wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX); - - /* Abort the IO associated with this outstanding exchange ID. */ - wqe->abort_cmd.wqe_com.abort_tag = xritag; - - /* iotag for the wqe completion. */ - bf_set(wqe_reqtag, &wqe->abort_cmd.wqe_com, pwqeq->iotag); - - bf_set(wqe_qosd, &wqe->abort_cmd.wqe_com, 1); - bf_set(wqe_lenloc, &wqe->abort_cmd.wqe_com, LPFC_WQE_LENLOC_NONE); - - bf_set(wqe_cmd_type, &wqe->abort_cmd.wqe_com, OTHER_COMMAND); - bf_set(wqe_wqec, &wqe->abort_cmd.wqe_com, 1); - bf_set(wqe_cqid, &wqe->abort_cmd.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); -} - /** * lpfc_nvme_create_queue - * @pnvme_lport: Transport localport that LS is to be issued from @@ -766,7 +726,7 @@ __lpfc_nvme_ls_abort(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, spin_unlock(&pring->ring_lock); if (foundit) - lpfc_sli_issue_abort_iotag(phba, pring, wqe); + lpfc_sli_issue_abort_iotag(phba, pring, wqe, NULL); spin_unlock_irq(&phba->hbalock); if (foundit) @@ -1772,7 +1732,6 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, struct lpfc_vport *vport; struct lpfc_hba *phba; struct lpfc_io_buf *lpfc_nbuf; - struct lpfc_iocbq *abts_buf; struct lpfc_iocbq *nvmereq_wqe; struct lpfc_nvme_fcpreq_priv *freqpriv; unsigned long flags; @@ -1883,42 +1842,23 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, goto out_unlock; } - abts_buf = __lpfc_sli_get_iocbq(phba); - if (!abts_buf) { - lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, - "6136 No available abort wqes. Skipping " - "Abts req for nvme_fcreq x%px xri x%x\n", - pnvme_fcreq, nvmereq_wqe->sli4_xritag); - goto out_unlock; - } - - /* Ready - mark outstanding as aborted by driver. */ - nvmereq_wqe->iocb_flag |= LPFC_DRIVER_ABORTED; + ret_val = lpfc_sli4_issue_abort_iotag(phba, nvmereq_wqe, + lpfc_nvme_abort_fcreq_cmpl); - lpfc_nvme_prep_abort_wqe(abts_buf, nvmereq_wqe->sli4_xritag, 0); - - /* ABTS WQE must go to the same WQ as the WQE to be aborted */ - abts_buf->iocb_flag |= LPFC_IO_NVME; - abts_buf->hba_wqidx = nvmereq_wqe->hba_wqidx; - abts_buf->vport = vport; - abts_buf->wqe_cmpl = lpfc_nvme_abort_fcreq_cmpl; - ret_val = lpfc_sli4_issue_wqe(phba, lpfc_nbuf->hdwq, abts_buf); spin_unlock(&lpfc_nbuf->buf_lock); spin_unlock_irqrestore(&phba->hbalock, flags); - if (ret_val) { + if (ret_val != WQE_SUCCESS) { lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, "6137 Failed abts issue_wqe with status x%x " "for nvme_fcreq x%px.\n", ret_val, pnvme_fcreq); - lpfc_sli_release_iocbq(phba, abts_buf); return; } lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_ABTS, "6138 Transport Abort NVME Request Issued for " - "ox_id x%x on reqtag x%x\n", - nvmereq_wqe->sli4_xritag, - abts_buf->iotag); + "ox_id x%x\n", + nvmereq_wqe->sli4_xritag); return; out_unlock: diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 99d781e32b8e..88192137bcdd 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -3327,6 +3327,46 @@ lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba, return 1; } +/** + * lpfc_nvmet_prep_abort_wqe - set up 'abort' work queue entry. + * @pwqeq: Pointer to command iocb. + * @xritag: Tag that uniqely identifies the local exchange resource. + * @opt: Option bits - + * bit 0 = inhibit sending abts on the link + * + * This function is called with hbalock held. + **/ +void +lpfc_nvmet_prep_abort_wqe(struct lpfc_iocbq *pwqeq, u16 xritag, u8 opt) +{ + union lpfc_wqe128 *wqe = &pwqeq->wqe; + + /* WQEs are reused. Clear stale data and set key fields to + * zero like ia, iaab, iaar, xri_tag, and ctxt_tag. + */ + memset(wqe, 0, sizeof(*wqe)); + + if (opt & INHIBIT_ABORT) + bf_set(abort_cmd_ia, &wqe->abort_cmd, 1); + /* Abort specified xri tag, with the mask deliberately zeroed */ + bf_set(abort_cmd_criteria, &wqe->abort_cmd, T_XRI_TAG); + + bf_set(wqe_cmnd, &wqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX); + + /* Abort the I/O associated with this outstanding exchange ID. */ + wqe->abort_cmd.wqe_com.abort_tag = xritag; + + /* iotag for the wqe completion. */ + bf_set(wqe_reqtag, &wqe->abort_cmd.wqe_com, pwqeq->iotag); + + bf_set(wqe_qosd, &wqe->abort_cmd.wqe_com, 1); + bf_set(wqe_lenloc, &wqe->abort_cmd.wqe_com, LPFC_WQE_LENLOC_NONE); + + bf_set(wqe_cmd_type, &wqe->abort_cmd.wqe_com, OTHER_COMMAND); + bf_set(wqe_wqec, &wqe->abort_cmd.wqe_com, 1); + bf_set(wqe_cqid, &wqe->abort_cmd.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); +} + static int lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba, struct lpfc_async_xchg_ctx *ctxp, @@ -3422,7 +3462,7 @@ lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba, /* Ready - mark outstanding as aborted by driver. */ abts_wqeq->iocb_flag |= LPFC_DRIVER_ABORTED; - lpfc_nvme_prep_abort_wqe(abts_wqeq, ctxp->wqeq->sli4_xritag, opt); + lpfc_nvmet_prep_abort_wqe(abts_wqeq, ctxp->wqeq->sli4_xritag, opt); /* ABTS WQE must go to the same WQ as the WQE to be aborted */ abts_wqeq->hba_wqidx = ctxp->wqeq->hba_wqidx; diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 63c1ea3fd359..f989490359a5 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -5385,11 +5385,10 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *iocb; - struct lpfc_iocbq *abtsiocb; struct lpfc_io_buf *lpfc_cmd; - IOCB_t *cmd, *icmd; int ret = SUCCESS, status = 0; struct lpfc_sli_ring *pring_s4 = NULL; + struct lpfc_sli_ring *pring = NULL; int ret_val; unsigned long flags; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq); @@ -5466,64 +5465,22 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) goto wait_for_cmpl; } - abtsiocb = __lpfc_sli_get_iocbq(phba); - if (abtsiocb == NULL) { - ret = FAILED; - goto out_unlock_ring; - } - - /* Indicate the IO is being aborted by the driver. */ - iocb->iocb_flag |= LPFC_DRIVER_ABORTED; - - /* - * The scsi command can not be in txq and it is in flight because the - * pCmd is still pointig at the SCSI command we have to abort. There - * is no need to search the txcmplq. Just send an abort to the FW. - */ - - cmd = &iocb->iocb; - icmd = &abtsiocb->iocb; - icmd->un.acxri.abortType = ABORT_TYPE_ABTS; - icmd->un.acxri.abortContextTag = cmd->ulpContext; - if (phba->sli_rev == LPFC_SLI_REV4) - icmd->un.acxri.abortIoTag = iocb->sli4_xritag; - else - icmd->un.acxri.abortIoTag = cmd->ulpIoTag; - - icmd->ulpLe = 1; - icmd->ulpClass = cmd->ulpClass; - - /* ABTS WQE must go to the same WQ as the WQE to be aborted */ - abtsiocb->hba_wqidx = iocb->hba_wqidx; - abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX; - if (iocb->iocb_flag & LPFC_IO_FOF) - abtsiocb->iocb_flag |= LPFC_IO_FOF; - - if (lpfc_is_link_up(phba)) - icmd->ulpCommand = CMD_ABORT_XRI_CN; - else - icmd->ulpCommand = CMD_CLOSE_XRI_CN; - - abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; - abtsiocb->vport = vport; lpfc_cmd->waitq = &waitq; if (phba->sli_rev == LPFC_SLI_REV4) { - /* Note: both hbalock and ring_lock must be set here */ - ret_val = __lpfc_sli_issue_iocb(phba, pring_s4->ringno, - abtsiocb, 0); spin_unlock(&pring_s4->ring_lock); + ret_val = lpfc_sli4_issue_abort_iotag(phba, iocb, + lpfc_sli4_abort_fcp_cmpl); } else { - ret_val = __lpfc_sli_issue_iocb(phba, LPFC_FCP_RING, - abtsiocb, 0); + pring = &phba->sli.sli3_ring[LPFC_FCP_RING]; + ret_val = lpfc_sli_issue_abort_iotag(phba, pring, iocb, + lpfc_sli_abort_fcp_cmpl); } - if (ret_val == IOCB_ERROR) { + if (ret_val != IOCB_SUCCESS) { /* Indicate the IO is not being aborted by the driver. */ - iocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; lpfc_cmd->waitq = NULL; spin_unlock(&lpfc_cmd->buf_lock); spin_unlock_irqrestore(&phba->hbalock, flags); - lpfc_sli_release_iocbq(phba, abtsiocb); ret = FAILED; goto out; } @@ -5537,7 +5494,10 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) &phba->sli.sli3_ring[LPFC_FCP_RING], HA_R0RE_REQ); wait_for_cmpl: - /* Wait for abort to complete */ + /* + * iocb_flag is set to LPFC_DRIVER_ABORTED before we wait + * for abort to complete. + */ wait_event_timeout(waitq, (lpfc_cmd->pCmd != cmnd), msecs_to_jiffies(2*vport->cfg_devloss_tmo*1000)); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index e58ad2ea11be..62218e41933e 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -4209,7 +4209,7 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) spin_lock_irq(&phba->hbalock); /* Next issue ABTS for everything on the txcmplq */ list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) - lpfc_sli_issue_abort_iotag(phba, pring, iocb); + lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL); spin_unlock_irq(&phba->hbalock); } else { spin_lock_irq(&phba->hbalock); @@ -4218,7 +4218,7 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) /* Next issue ABTS for everything on the txcmplq */ list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) - lpfc_sli_issue_abort_iotag(phba, pring, iocb); + lpfc_sli_issue_abort_iotag(phba, pring, iocb, NULL); spin_unlock_irq(&phba->hbalock); } @@ -11181,7 +11181,8 @@ lpfc_sli_host_down(struct lpfc_vport *vport) &pring->txcmplq, list) { if (iocb->vport != vport) continue; - lpfc_sli_issue_abort_iotag(phba, pring, iocb); + lpfc_sli_issue_abort_iotag(phba, pring, iocb, + NULL); } pring->flag = prev_pring_flag; } @@ -11208,7 +11209,8 @@ lpfc_sli_host_down(struct lpfc_vport *vport) &pring->txcmplq, list) { if (iocb->vport != vport) continue; - lpfc_sli_issue_abort_iotag(phba, pring, iocb); + lpfc_sli_issue_abort_iotag(phba, pring, iocb, + NULL); } pring->flag = prev_pring_flag; } @@ -11605,27 +11607,29 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } /** - * lpfc_sli_abort_iotag_issue - Issue abort for a command iocb + * lpfc_sli_issue_abort_iotag - Abort function for a command iocb * @phba: Pointer to HBA context object. * @pring: Pointer to driver SLI ring object. * @cmdiocb: Pointer to driver command iocb object. + * @cmpl: completion function. + * + * This function issues an abort iocb for the provided command iocb. In case + * of unloading, the abort iocb will not be issued to commands on the ELS + * ring. Instead, the callback function shall be changed to those commands + * so that nothing happens when them finishes. This function is called with + * hbalock held andno ring_lock held (SLI4). The function returns IOCB_SUCCESS + * when the command iocb is an abort request. * - * This function issues an abort iocb for the provided command iocb down to - * the port. Other than the case the outstanding command iocb is an abort - * request, this function issues abort out unconditionally. This function is - * called with hbalock held. The function returns 0 when it fails due to - * memory allocation failure or when the command iocb is an abort request. - * The hbalock is asserted held in the code path calling this routine. **/ -static int -lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, - struct lpfc_iocbq *cmdiocb) +int +lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, + struct lpfc_iocbq *cmdiocb, void *cmpl) { struct lpfc_vport *vport = cmdiocb->vport; struct lpfc_iocbq *abtsiocbp; IOCB_t *icmd = NULL; IOCB_t *iabt = NULL; - int retval; + int retval = IOCB_ERROR; unsigned long iflags; struct lpfc_nodelist *ndlp; @@ -11638,12 +11642,33 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, if (icmd->ulpCommand == CMD_ABORT_XRI_CN || icmd->ulpCommand == CMD_CLOSE_XRI_CN || (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0) - return 0; + return IOCB_ABORTING; + + if (!pring) { + if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) + cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; + else + cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; + return retval; + } + + /* + * If we're unloading, don't abort iocb on the ELS ring, but change + * the callback so that nothing happens when it finishes. + */ + if ((vport->load_flag & FC_UNLOADING) && + pring->ringno == LPFC_ELS_RING) { + if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) + cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; + else + cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; + return retval; + } /* issue ABTS for this IOCB based on iotag */ abtsiocbp = __lpfc_sli_get_iocbq(phba); if (abtsiocbp == NULL) - return 0; + return IOCB_NORESOURCE; /* This signals the response to set the correct status * before calling the completion handler @@ -11655,7 +11680,8 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, iabt->un.acxri.abortContextTag = icmd->ulpContext; if (phba->sli_rev == LPFC_SLI_REV4) { iabt->un.acxri.abortIoTag = cmdiocb->sli4_xritag; - iabt->un.acxri.abortContextTag = cmdiocb->iotag; + if (pring->ringno == LPFC_ELS_RING) + iabt->un.acxri.abortContextTag = cmdiocb->iotag; } else { iabt->un.acxri.abortIoTag = icmd->ulpIoTag; if (pring->ringno == LPFC_ELS_RING) { @@ -11668,8 +11694,10 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, /* ABTS WQE must go to the same WQ as the WQE to be aborted */ abtsiocbp->hba_wqidx = cmdiocb->hba_wqidx; - if (cmdiocb->iocb_flag & LPFC_IO_FCP) + if (cmdiocb->iocb_flag & LPFC_IO_FCP) { + abtsiocbp->iocb_flag |= LPFC_IO_FCP; abtsiocbp->iocb_flag |= LPFC_USE_FCPWQIDX; + } if (cmdiocb->iocb_flag & LPFC_IO_FOF) abtsiocbp->iocb_flag |= LPFC_IO_FOF; @@ -11678,20 +11706,16 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, else iabt->ulpCommand = CMD_CLOSE_XRI_CN; - abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl; + if (cmpl) + abtsiocbp->iocb_cmpl = cmpl; + else + abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl; abtsiocbp->vport = vport; - lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, - "0339 Abort xri x%x, original iotag x%x, " - "abort cmd iotag x%x\n", - iabt->un.acxri.abortIoTag, - iabt->un.acxri.abortContextTag, - abtsiocbp->iotag); - if (phba->sli_rev == LPFC_SLI_REV4) { pring = lpfc_sli4_calc_ring(phba, abtsiocbp); if (unlikely(pring == NULL)) - return 0; + goto abort_iotag_exit; /* Note: both hbalock and ring_lock need to be set here */ spin_lock_irqsave(&pring->ring_lock, iflags); retval = __lpfc_sli_issue_iocb(phba, pring->ringno, @@ -11702,76 +11726,20 @@ lpfc_sli_abort_iotag_issue(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, abtsiocbp, 0); } - if (retval) - __lpfc_sli_release_iocbq(phba, abtsiocbp); - - /* - * Caller to this routine should check for IOCB_ERROR - * and handle it properly. This routine no longer removes - * iocb off txcmplq and call compl in case of IOCB_ERROR. - */ - return retval; -} - -/** - * lpfc_sli_issue_abort_iotag - Abort function for a command iocb - * @phba: Pointer to HBA context object. - * @pring: Pointer to driver SLI ring object. - * @cmdiocb: Pointer to driver command iocb object. - * - * This function issues an abort iocb for the provided command iocb. In case - * of unloading, the abort iocb will not be issued to commands on the ELS - * ring. Instead, the callback function shall be changed to those commands - * so that nothing happens when them finishes. This function is called with - * hbalock held. The function returns 0 when the command iocb is an abort - * request. - **/ -int -lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, - struct lpfc_iocbq *cmdiocb) -{ - struct lpfc_vport *vport = cmdiocb->vport; - int retval = IOCB_ERROR; - IOCB_t *icmd = NULL; - - lockdep_assert_held(&phba->hbalock); - - /* - * There are certain command types we don't want to abort. And we - * don't want to abort commands that are already in the process of - * being aborted. - */ - icmd = &cmdiocb->iocb; - if (icmd->ulpCommand == CMD_ABORT_XRI_CN || - icmd->ulpCommand == CMD_CLOSE_XRI_CN || - (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0) - return 0; +abort_iotag_exit: - if (!pring) { - if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) - cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; - else - cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; - goto abort_iotag_exit; - } + lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, + "0339 Abort xri x%x, original iotag x%x, " + "abort cmd iotag x%x retval x%x\n", + iabt->un.acxri.abortIoTag, + iabt->un.acxri.abortContextTag, + abtsiocbp->iotag, retval); - /* - * If we're unloading, don't abort iocb on the ELS ring, but change - * the callback so that nothing happens when it finishes. - */ - if ((vport->load_flag & FC_UNLOADING) && - (pring->ringno == LPFC_ELS_RING)) { - if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) - cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; - else - cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl; - goto abort_iotag_exit; + if (retval) { + cmdiocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; + __lpfc_sli_release_iocbq(phba, abtsiocbp); } - /* Now, we try to issue the abort to the cmdiocb out */ - retval = lpfc_sli_abort_iotag_issue(phba, pring, cmdiocb); - -abort_iotag_exit: /* * Caller to this routine should check for IOCB_ERROR * and handle it properly. This routine no longer removes @@ -11915,6 +11883,33 @@ lpfc_sli_sum_iocb(struct lpfc_vport *vport, uint16_t tgt_id, uint64_t lun_id, return sum; } +/** + * lpfc_sli4_abort_fcp_cmpl - Completion handler function for aborted FCP IOCBs + * @phba: Pointer to HBA context object + * @cmdiocb: Pointer to command iocb object. + * @wcqe: pointer to the complete wcqe + * + * This function is called when an aborted FCP iocb completes. This + * function is called by the ring event handler with no lock held. + * This function frees the iocb. It is called for sli-4 adapters. + **/ +void +lpfc_sli4_abort_fcp_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + struct lpfc_wcqe_complete *wcqe) +{ + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "3017 ABORT_XRI_CN completing on rpi x%x " + "original iotag x%x, abort cmd iotag x%x " + "status 0x%x, reason 0x%x\n", + cmdiocb->iocb.un.acxri.abortContextTag, + cmdiocb->iocb.un.acxri.abortIoTag, + cmdiocb->iotag, + (bf_get(lpfc_wcqe_c_status, wcqe) + & LPFC_IOCB_STATUS_MASK), + wcqe->parameter); + lpfc_sli_release_iocbq(phba, cmdiocb); +} + /** * lpfc_sli_abort_fcp_cmpl - Completion handler function for aborted FCP IOCBs * @phba: Pointer to HBA context object @@ -11968,10 +11963,8 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, { struct lpfc_hba *phba = vport->phba; struct lpfc_iocbq *iocbq; - struct lpfc_iocbq *abtsiocb; - struct lpfc_sli_ring *pring_s4; - IOCB_t *cmd = NULL; int errcnt = 0, ret_val = 0; + unsigned long iflags; int i; /* all I/Os are in process of being flushed */ @@ -11985,62 +11978,12 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct lpfc_sli_ring *pring, abort_cmd) != 0) continue; - /* - * If the iocbq is already being aborted, don't take a second - * action, but do count it. - */ - if (iocbq->iocb_flag & LPFC_DRIVER_ABORTED) - continue; - - /* issue ABTS for this IOCB based on iotag */ - abtsiocb = lpfc_sli_get_iocbq(phba); - if (abtsiocb == NULL) { - errcnt++; - continue; - } - - /* indicate the IO is being aborted by the driver. */ - iocbq->iocb_flag |= LPFC_DRIVER_ABORTED; - - cmd = &iocbq->iocb; - abtsiocb->iocb.un.acxri.abortType = ABORT_TYPE_ABTS; - abtsiocb->iocb.un.acxri.abortContextTag = cmd->ulpContext; - if (phba->sli_rev == LPFC_SLI_REV4) - abtsiocb->iocb.un.acxri.abortIoTag = iocbq->sli4_xritag; - else - abtsiocb->iocb.un.acxri.abortIoTag = cmd->ulpIoTag; - abtsiocb->iocb.ulpLe = 1; - abtsiocb->iocb.ulpClass = cmd->ulpClass; - abtsiocb->vport = vport; - - /* ABTS WQE must go to the same WQ as the WQE to be aborted */ - abtsiocb->hba_wqidx = iocbq->hba_wqidx; - if (iocbq->iocb_flag & LPFC_IO_FCP) - abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX; - if (iocbq->iocb_flag & LPFC_IO_FOF) - abtsiocb->iocb_flag |= LPFC_IO_FOF; - - if (lpfc_is_link_up(phba)) - abtsiocb->iocb.ulpCommand = CMD_ABORT_XRI_CN; - else - abtsiocb->iocb.ulpCommand = CMD_CLOSE_XRI_CN; - - /* Setup callback routine and issue the command. */ - abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl; - if (phba->sli_rev == LPFC_SLI_REV4) { - pring_s4 = lpfc_sli4_calc_ring(phba, iocbq); - if (!pring_s4) - continue; - ret_val = lpfc_sli_issue_iocb(phba, pring_s4->ringno, - abtsiocb, 0); - } else - ret_val = lpfc_sli_issue_iocb(phba, pring->ringno, - abtsiocb, 0); - if (ret_val == IOCB_ERROR) { - lpfc_sli_release_iocbq(phba, abtsiocb); + spin_lock_irqsave(&phba->hbalock, iflags); + ret_val = lpfc_sli_issue_abort_iotag(phba, pring, iocbq, + lpfc_sli_abort_fcp_cmpl); + spin_unlock_irqrestore(&phba->hbalock, iflags); + if (ret_val != IOCB_SUCCESS) errcnt++; - continue; - } } return errcnt; @@ -20551,6 +20494,88 @@ lpfc_sli4_issue_wqe(struct lpfc_hba *phba, struct lpfc_sli4_hdw_queue *qp, return WQE_ERROR; } +/** + * lpfc_sli4_issue_abort_iotag - SLI-4 WQE init & issue for the Abort + * @phba: Pointer to HBA context object. + * @cmdiocb: Pointer to driver command iocb object. + * @cmpl: completion function. + * + * Fill the appropriate fields for the abort WQE and call + * internal routine lpfc_sli4_issue_wqe to send the WQE + * This function is called with hbalock held and no ring_lock held. + * + * RETURNS 0 - SUCCESS + **/ + +int +lpfc_sli4_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + void *cmpl) +{ + struct lpfc_vport *vport = cmdiocb->vport; + struct lpfc_iocbq *abtsiocb = NULL; + union lpfc_wqe128 *abtswqe; + struct lpfc_io_buf *lpfc_cmd; + int retval = IOCB_ERROR; + u16 xritag = cmdiocb->sli4_xritag; + + /* + * The scsi command can not be in txq and it is in flight because the + * pCmd is still pointing at the SCSI command we have to abort. There + * is no need to search the txcmplq. Just send an abort to the FW. + */ + + abtsiocb = __lpfc_sli_get_iocbq(phba); + if (!abtsiocb) + return WQE_NORESOURCE; + + /* Indicate the IO is being aborted by the driver. */ + cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED; + + abtswqe = &abtsiocb->wqe; + memset(abtswqe, 0, sizeof(*abtswqe)); + + if (lpfc_is_link_up(phba)) + bf_set(abort_cmd_ia, &abtswqe->abort_cmd, 1); + else + bf_set(abort_cmd_ia, &abtswqe->abort_cmd, 0); + bf_set(abort_cmd_criteria, &abtswqe->abort_cmd, T_XRI_TAG); + abtswqe->abort_cmd.rsrvd5 = 0; + abtswqe->abort_cmd.wqe_com.abort_tag = xritag; + bf_set(wqe_reqtag, &abtswqe->abort_cmd.wqe_com, abtsiocb->iotag); + bf_set(wqe_cmnd, &abtswqe->abort_cmd.wqe_com, CMD_ABORT_XRI_CX); + bf_set(wqe_xri_tag, &abtswqe->generic.wqe_com, 0); + bf_set(wqe_qosd, &abtswqe->abort_cmd.wqe_com, 1); + bf_set(wqe_lenloc, &abtswqe->abort_cmd.wqe_com, LPFC_WQE_LENLOC_NONE); + bf_set(wqe_cmd_type, &abtswqe->abort_cmd.wqe_com, OTHER_COMMAND); + + /* ABTS WQE must go to the same WQ as the WQE to be aborted */ + abtsiocb->hba_wqidx = cmdiocb->hba_wqidx; + abtsiocb->iocb_flag |= LPFC_USE_FCPWQIDX; + if (cmdiocb->iocb_flag & LPFC_IO_FCP) + abtsiocb->iocb_flag |= LPFC_IO_FCP; + if (cmdiocb->iocb_flag & LPFC_IO_NVME) + abtsiocb->iocb_flag |= LPFC_IO_NVME; + if (cmdiocb->iocb_flag & LPFC_IO_FOF) + abtsiocb->iocb_flag |= LPFC_IO_FOF; + abtsiocb->vport = vport; + abtsiocb->wqe_cmpl = cmpl; + + lpfc_cmd = container_of(cmdiocb, struct lpfc_io_buf, cur_iocbq); + retval = lpfc_sli4_issue_wqe(phba, lpfc_cmd->hdwq, abtsiocb); + + lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI | LOG_NVME_ABTS | LOG_FCP, + "0359 Abort xri x%x, original iotag x%x, " + "abort cmd iotag x%x retval x%x\n", + xritag, cmdiocb->iotag, abtsiocb->iotag, retval); + + if (retval) { + cmdiocb->iocb_flag &= ~LPFC_DRIVER_ABORTED; + __lpfc_sli_release_iocbq(phba, abtsiocb); + } + + return retval; +} + #ifdef LPFC_MXP_STAT /** * lpfc_snapshot_mxp - Snapshot pbl, pvt and busy count diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 93d976ea8c5d..3ddaac57f99e 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -130,6 +130,9 @@ struct lpfc_iocbq { #define IOCB_BUSY 1 #define IOCB_ERROR 2 #define IOCB_TIMEDOUT 3 +#define IOCB_ABORTED 4 +#define IOCB_ABORTING 5 +#define IOCB_NORESOURCE 6 #define SLI_WQE_RET_WQE 1 /* Return WQE if cmd ring full */ @@ -138,6 +141,8 @@ struct lpfc_iocbq { #define WQE_ERROR 2 #define WQE_TIMEDOUT 3 #define WQE_ABORTED 4 +#define WQE_ABORTING 5 +#define WQE_NORESOURCE 6 #define LPFC_MBX_WAKE 1 #define LPFC_MBX_IMED_UNREG 2 -- cgit v1.2.3 From ab4dfa4dd5a121681e06b791f9a5dc81afa5e192 Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:45 -0800 Subject: scsi: lpfc: Update lpfc version to 12.8.0.6 Update lpfc version to 12.8.0.6 Link: https://lore.kernel.org/r/20201115192646.12977-17-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index d91ee125abd0..234dca60995b 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -20,7 +20,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "12.8.0.5" +#define LPFC_DRIVER_VERSION "12.8.0.6" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ @@ -32,6 +32,6 @@ #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \ LPFC_DRIVER_VERSION -#define LPFC_COPYRIGHT "Copyright (C) 2017-2019 Broadcom. All Rights " \ +#define LPFC_COPYRIGHT "Copyright (C) 2017-2020 Broadcom. All Rights " \ "Reserved. The term \"Broadcom\" refers to Broadcom Inc. " \ "and/or its subsidiaries." -- cgit v1.2.3 From 983f761cd5c5741f228c7b5dc437678899e3a64c Mon Sep 17 00:00:00 2001 From: James Smart Date: Sun, 15 Nov 2020 11:26:46 -0800 Subject: scsi: lpfc: Update changed file copyrights for 2020 Update Copyright in files changed by the 12.8.0.6 patch set to 2020 Link: https://lore.kernel.org/r/20201115192646.12977-18-james.smart@broadcom.com Co-developed-by: Dick Kennedy Signed-off-by: Dick Kennedy Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_bsg.c | 2 +- drivers/scsi/lpfc/lpfc_crtn.h | 2 +- drivers/scsi/lpfc/lpfc_debugfs.c | 2 +- drivers/scsi/lpfc/lpfc_disc.h | 2 +- drivers/scsi/lpfc/lpfc_hw4.h | 2 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 2 +- drivers/scsi/lpfc/lpfc_nvme.c | 2 +- drivers/scsi/lpfc/lpfc_nvme.h | 2 +- drivers/scsi/lpfc/lpfc_nvmet.c | 2 +- drivers/scsi/lpfc/lpfc_sli.h | 2 +- drivers/scsi/lpfc/lpfc_vport.c | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index d4955119380d..35f4998504c1 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2009-2015 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 69b1a357007b..f78e52a18b0b 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 9ecf8962b2a0..bc79a017e1a2 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2007-2015 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 7757175a5c37..ea07afcb750a 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2013 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 26a9057fb042..541b9aef6bfe 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2009-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 297fc92d01ce..1ac855640fc5 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index f9f4926b682f..1cb82fa6a60e 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h index 4e11ce8d5e31..69a5a844c69c 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.h +++ b/drivers/scsi/lpfc/lpfc_nvme.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index 88192137bcdd..c8b9434ae5cf 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channsel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 3ddaac57f99e..4f6936014ff5 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index f590d18b3f06..a99fdfba7d27 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * -- cgit v1.2.3 From 54770cbebe2caa89423a13ff32fa0d497c392214 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Mon, 16 Nov 2020 14:50:46 +0800 Subject: scsi: ufs: ufs-mediatek: Refactor performance scaling functions Refactor performance scaling related functions in MediaTek UFS driver. Link: https://lore.kernel.org/r/20201116065054.7658-2-stanley.chu@mediatek.com Reviewed-by: Bean Huo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 7fed7630d36c..b9b423752ee1 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -514,6 +514,19 @@ static void ufs_mtk_init_host_caps(struct ufs_hba *hba) dev_info(hba->dev, "caps: 0x%x", host->caps); } +static void ufs_mtk_scale_perf(struct ufs_hba *hba, bool up) +{ + struct ufs_mtk_host *host = ufshcd_get_variant(hba); + + ufs_mtk_boost_crypt(hba, up); + ufs_mtk_setup_ref_clk(hba, up); + + if (up) + phy_power_on(host->mphy); + else + phy_power_off(host->mphy); +} + /** * ufs_mtk_setup_clocks - enables/disable clocks * @hba: host controller instance @@ -555,15 +568,10 @@ static int ufs_mtk_setup_clocks(struct ufs_hba *hba, bool on, clk_pwr_off = true; } - if (clk_pwr_off) { - ufs_mtk_boost_crypt(hba, on); - ufs_mtk_setup_ref_clk(hba, on); - phy_power_off(host->mphy); - } + if (clk_pwr_off) + ufs_mtk_scale_perf(hba, false); } else if (on && status == POST_CHANGE) { - phy_power_on(host->mphy); - ufs_mtk_setup_ref_clk(hba, on); - ufs_mtk_boost_crypt(hba, on); + ufs_mtk_scale_perf(hba, true); } return ret; -- cgit v1.2.3 From 65858014ee20c842eaff65514e75d2c640c70007 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Mon, 16 Nov 2020 14:50:47 +0800 Subject: scsi: ufs: Introduce device parameter initialization function Nowadays many vendors initialize their device parameters in their own vendor drivers. The initialization code is almost the same as well as the pre-defined definitions. Introduce a common device parameter initialization function which assign the most common initial values. With this function, we could remove those duplicated codes in vendor drivers. Link: https://lore.kernel.org/r/20201116065054.7658-3-stanley.chu@mediatek.com Reviewed-by: Bean Huo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd-pltfrm.c | 17 +++++++++++++++++ drivers/scsi/ufs/ufshcd-pltfrm.h | 1 + 2 files changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index 3db0af66c71c..a6f76399b3ae 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -354,6 +354,23 @@ int ufshcd_get_pwr_dev_param(struct ufs_dev_params *pltfrm_param, } EXPORT_SYMBOL_GPL(ufshcd_get_pwr_dev_param); +void ufshcd_init_pwr_dev_param(struct ufs_dev_params *dev_param) +{ + dev_param->tx_lanes = 2; + dev_param->rx_lanes = 2; + dev_param->hs_rx_gear = UFS_HS_G3; + dev_param->hs_tx_gear = UFS_HS_G3; + dev_param->pwm_rx_gear = UFS_PWM_G4; + dev_param->pwm_tx_gear = UFS_PWM_G4; + dev_param->rx_pwr_pwm = SLOW_MODE; + dev_param->tx_pwr_pwm = SLOW_MODE; + dev_param->rx_pwr_hs = FAST_MODE; + dev_param->tx_pwr_hs = FAST_MODE; + dev_param->hs_rate = PA_HS_MODE_B; + dev_param->desired_working_mode = UFS_HS_MODE; +} +EXPORT_SYMBOL_GPL(ufshcd_init_pwr_dev_param); + /** * ufshcd_pltfrm_init - probe routine of the driver * @pdev: pointer to Platform device handle diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.h b/drivers/scsi/ufs/ufshcd-pltfrm.h index b79cdf9129a0..772a8e848098 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.h +++ b/drivers/scsi/ufs/ufshcd-pltfrm.h @@ -28,6 +28,7 @@ struct ufs_dev_params { int ufshcd_get_pwr_dev_param(struct ufs_dev_params *dev_param, struct ufs_pa_layer_attr *dev_max, struct ufs_pa_layer_attr *agreed_pwr); +void ufshcd_init_pwr_dev_param(struct ufs_dev_params *dev_param); int ufshcd_pltfrm_init(struct platform_device *pdev, const struct ufs_hba_variant_ops *vops); void ufshcd_pltfrm_shutdown(struct platform_device *pdev); -- cgit v1.2.3 From a4b537ea656e9f48b2cbcd7b8883f21b3fc5cef9 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Mon, 16 Nov 2020 14:50:48 +0800 Subject: scsi: ufs: ufs-mediatek: Use device parameter initialization function Use common device parameter initialization function instead of initializing those parameters by vendor driver itself. Link: https://lore.kernel.org/r/20201116065054.7658-4-stanley.chu@mediatek.com Reviewed-by: Bean Huo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek.c | 16 +++------------- drivers/scsi/ufs/ufs-mediatek.h | 16 ---------------- 2 files changed, 3 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index b9b423752ee1..87b4bf125e23 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -680,19 +680,9 @@ static int ufs_mtk_pre_pwr_change(struct ufs_hba *hba, u32 adapt_val; int ret; - host_cap.tx_lanes = UFS_MTK_LIMIT_NUM_LANES_TX; - host_cap.rx_lanes = UFS_MTK_LIMIT_NUM_LANES_RX; - host_cap.hs_rx_gear = UFS_MTK_LIMIT_HSGEAR_RX; - host_cap.hs_tx_gear = UFS_MTK_LIMIT_HSGEAR_TX; - host_cap.pwm_rx_gear = UFS_MTK_LIMIT_PWMGEAR_RX; - host_cap.pwm_tx_gear = UFS_MTK_LIMIT_PWMGEAR_TX; - host_cap.rx_pwr_pwm = UFS_MTK_LIMIT_RX_PWR_PWM; - host_cap.tx_pwr_pwm = UFS_MTK_LIMIT_TX_PWR_PWM; - host_cap.rx_pwr_hs = UFS_MTK_LIMIT_RX_PWR_HS; - host_cap.tx_pwr_hs = UFS_MTK_LIMIT_TX_PWR_HS; - host_cap.hs_rate = UFS_MTK_LIMIT_HS_RATE; - host_cap.desired_working_mode = - UFS_MTK_LIMIT_DESIRED_MODE; + ufshcd_init_pwr_dev_param(&host_cap); + host_cap.hs_rx_gear = UFS_HS_G4; + host_cap.hs_tx_gear = UFS_HS_G4; ret = ufshcd_get_pwr_dev_param(&host_cap, dev_max_params, diff --git a/drivers/scsi/ufs/ufs-mediatek.h b/drivers/scsi/ufs/ufs-mediatek.h index ac37b11803fb..93d35097dfb0 100644 --- a/drivers/scsi/ufs/ufs-mediatek.h +++ b/drivers/scsi/ufs/ufs-mediatek.h @@ -30,22 +30,6 @@ #define REFCLK_REQ_TIMEOUT_US 3000 -/* - * Vendor specific pre-defined parameters - */ -#define UFS_MTK_LIMIT_NUM_LANES_RX 2 -#define UFS_MTK_LIMIT_NUM_LANES_TX 2 -#define UFS_MTK_LIMIT_HSGEAR_RX UFS_HS_G4 -#define UFS_MTK_LIMIT_HSGEAR_TX UFS_HS_G4 -#define UFS_MTK_LIMIT_PWMGEAR_RX UFS_PWM_G4 -#define UFS_MTK_LIMIT_PWMGEAR_TX UFS_PWM_G4 -#define UFS_MTK_LIMIT_RX_PWR_PWM SLOW_MODE -#define UFS_MTK_LIMIT_TX_PWR_PWM SLOW_MODE -#define UFS_MTK_LIMIT_RX_PWR_HS FAST_MODE -#define UFS_MTK_LIMIT_TX_PWR_HS FAST_MODE -#define UFS_MTK_LIMIT_HS_RATE PA_HS_MODE_B -#define UFS_MTK_LIMIT_DESIRED_MODE UFS_HS_MODE - /* * Other attributes */ -- cgit v1.2.3 From 8beef54716e652fb08ac6ab45c2ce239ec3f5856 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Mon, 16 Nov 2020 14:50:49 +0800 Subject: scsi: ufs: ufs-qcom: Use device parameter initialization function Use common device parameter initialization function instead of initializing those parameters by vendor driver itself. Link: https://lore.kernel.org/r/20201116065054.7658-5-stanley.chu@mediatek.com Reviewed-by: Bean Huo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-qcom.c | 13 +------------ drivers/scsi/ufs/ufs-qcom.h | 11 ----------- 2 files changed, 1 insertion(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 357c3b49321d..04adfbd10753 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -691,19 +691,8 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba, switch (status) { case PRE_CHANGE: - ufs_qcom_cap.tx_lanes = UFS_QCOM_LIMIT_NUM_LANES_TX; - ufs_qcom_cap.rx_lanes = UFS_QCOM_LIMIT_NUM_LANES_RX; - ufs_qcom_cap.hs_rx_gear = UFS_QCOM_LIMIT_HSGEAR_RX; - ufs_qcom_cap.hs_tx_gear = UFS_QCOM_LIMIT_HSGEAR_TX; - ufs_qcom_cap.pwm_rx_gear = UFS_QCOM_LIMIT_PWMGEAR_RX; - ufs_qcom_cap.pwm_tx_gear = UFS_QCOM_LIMIT_PWMGEAR_TX; - ufs_qcom_cap.rx_pwr_pwm = UFS_QCOM_LIMIT_RX_PWR_PWM; - ufs_qcom_cap.tx_pwr_pwm = UFS_QCOM_LIMIT_TX_PWR_PWM; - ufs_qcom_cap.rx_pwr_hs = UFS_QCOM_LIMIT_RX_PWR_HS; - ufs_qcom_cap.tx_pwr_hs = UFS_QCOM_LIMIT_TX_PWR_HS; + ufshcd_init_pwr_dev_param(&ufs_qcom_cap); ufs_qcom_cap.hs_rate = UFS_QCOM_LIMIT_HS_RATE; - ufs_qcom_cap.desired_working_mode = - UFS_QCOM_LIMIT_DESIRED_MODE; if (host->hw_ver.major == 0x1) { /* diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h index 3f4922743b3e..8208e3a3ef59 100644 --- a/drivers/scsi/ufs/ufs-qcom.h +++ b/drivers/scsi/ufs/ufs-qcom.h @@ -27,18 +27,7 @@ #define SLOW 1 #define FAST 2 -#define UFS_QCOM_LIMIT_NUM_LANES_RX 2 -#define UFS_QCOM_LIMIT_NUM_LANES_TX 2 -#define UFS_QCOM_LIMIT_HSGEAR_RX UFS_HS_G3 -#define UFS_QCOM_LIMIT_HSGEAR_TX UFS_HS_G3 -#define UFS_QCOM_LIMIT_PWMGEAR_RX UFS_PWM_G4 -#define UFS_QCOM_LIMIT_PWMGEAR_TX UFS_PWM_G4 -#define UFS_QCOM_LIMIT_RX_PWR_PWM SLOW_MODE -#define UFS_QCOM_LIMIT_TX_PWR_PWM SLOW_MODE -#define UFS_QCOM_LIMIT_RX_PWR_HS FAST_MODE -#define UFS_QCOM_LIMIT_TX_PWR_HS FAST_MODE #define UFS_QCOM_LIMIT_HS_RATE PA_HS_MODE_B -#define UFS_QCOM_LIMIT_DESIRED_MODE FAST /* QCOM UFS host controller vendor specific registers */ enum { -- cgit v1.2.3 From 5b3573d68d9ac45c904af6d6e9bc415af45ccc41 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Mon, 16 Nov 2020 14:50:50 +0800 Subject: scsi: ufs: ufs-exynos: Use device parameter initialization function Use common device parameter initialization function instead of initializing those parameters by vendor driver itself. Link: https://lore.kernel.org/r/20201116065054.7658-6-stanley.chu@mediatek.com Reviewed-by: Bean Huo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-exynos.c | 15 +-------------- drivers/scsi/ufs/ufs-exynos.h | 13 ------------- 2 files changed, 1 insertion(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-exynos.c b/drivers/scsi/ufs/ufs-exynos.c index 5e6b95dbb578..a8770ff14588 100644 --- a/drivers/scsi/ufs/ufs-exynos.c +++ b/drivers/scsi/ufs/ufs-exynos.c @@ -617,20 +617,7 @@ static int exynos_ufs_pre_pwr_mode(struct ufs_hba *hba, goto out; } - - ufs_exynos_cap.tx_lanes = UFS_EXYNOS_LIMIT_NUM_LANES_TX; - ufs_exynos_cap.rx_lanes = UFS_EXYNOS_LIMIT_NUM_LANES_RX; - ufs_exynos_cap.hs_rx_gear = UFS_EXYNOS_LIMIT_HSGEAR_RX; - ufs_exynos_cap.hs_tx_gear = UFS_EXYNOS_LIMIT_HSGEAR_TX; - ufs_exynos_cap.pwm_rx_gear = UFS_EXYNOS_LIMIT_PWMGEAR_RX; - ufs_exynos_cap.pwm_tx_gear = UFS_EXYNOS_LIMIT_PWMGEAR_TX; - ufs_exynos_cap.rx_pwr_pwm = UFS_EXYNOS_LIMIT_RX_PWR_PWM; - ufs_exynos_cap.tx_pwr_pwm = UFS_EXYNOS_LIMIT_TX_PWR_PWM; - ufs_exynos_cap.rx_pwr_hs = UFS_EXYNOS_LIMIT_RX_PWR_HS; - ufs_exynos_cap.tx_pwr_hs = UFS_EXYNOS_LIMIT_TX_PWR_HS; - ufs_exynos_cap.hs_rate = UFS_EXYNOS_LIMIT_HS_RATE; - ufs_exynos_cap.desired_working_mode = - UFS_EXYNOS_LIMIT_DESIRED_MODE; + ufshcd_init_pwr_dev_param(&ufs_exynos_cap); ret = ufshcd_get_pwr_dev_param(&ufs_exynos_cap, dev_max_params, dev_req_params); diff --git a/drivers/scsi/ufs/ufs-exynos.h b/drivers/scsi/ufs/ufs-exynos.h index 76d6e39efb2f..06ee565f7eb0 100644 --- a/drivers/scsi/ufs/ufs-exynos.h +++ b/drivers/scsi/ufs/ufs-exynos.h @@ -90,19 +90,6 @@ struct exynos_ufs; #define SLOW 1 #define FAST 2 -#define UFS_EXYNOS_LIMIT_NUM_LANES_RX 2 -#define UFS_EXYNOS_LIMIT_NUM_LANES_TX 2 -#define UFS_EXYNOS_LIMIT_HSGEAR_RX UFS_HS_G3 -#define UFS_EXYNOS_LIMIT_HSGEAR_TX UFS_HS_G3 -#define UFS_EXYNOS_LIMIT_PWMGEAR_RX UFS_PWM_G4 -#define UFS_EXYNOS_LIMIT_PWMGEAR_TX UFS_PWM_G4 -#define UFS_EXYNOS_LIMIT_RX_PWR_PWM SLOW_MODE -#define UFS_EXYNOS_LIMIT_TX_PWR_PWM SLOW_MODE -#define UFS_EXYNOS_LIMIT_RX_PWR_HS FAST_MODE -#define UFS_EXYNOS_LIMIT_TX_PWR_HS FAST_MODE -#define UFS_EXYNOS_LIMIT_HS_RATE PA_HS_MODE_B -#define UFS_EXYNOS_LIMIT_DESIRED_MODE FAST - #define RX_ADV_FINE_GRAN_SUP_EN 0x1 #define RX_ADV_FINE_GRAN_STEP_VAL 0x3 #define RX_ADV_MIN_ACTV_TIME_CAP 0x9 -- cgit v1.2.3 From 85d6d3c18953b9653d0934c087fe73ff02e43c79 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Mon, 16 Nov 2020 14:50:51 +0800 Subject: scsi: ufs: ufs-hisi: Use device parameter initialization function Use common device parameter initialization function instead of initializing those parameters by vendor driver itself. Link: https://lore.kernel.org/r/20201116065054.7658-7-stanley.chu@mediatek.com Reviewed-by: Bean Huo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-hisi.c | 13 +------------ drivers/scsi/ufs/ufs-hisi.h | 13 ------------- 2 files changed, 1 insertion(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c index 074a6a055a4c..0aa58131e791 100644 --- a/drivers/scsi/ufs/ufs-hisi.c +++ b/drivers/scsi/ufs/ufs-hisi.c @@ -293,18 +293,7 @@ static int ufs_hisi_link_startup_notify(struct ufs_hba *hba, static void ufs_hisi_set_dev_cap(struct ufs_dev_params *hisi_param) { - hisi_param->rx_lanes = UFS_HISI_LIMIT_NUM_LANES_RX; - hisi_param->tx_lanes = UFS_HISI_LIMIT_NUM_LANES_TX; - hisi_param->hs_rx_gear = UFS_HISI_LIMIT_HSGEAR_RX; - hisi_param->hs_tx_gear = UFS_HISI_LIMIT_HSGEAR_TX; - hisi_param->pwm_rx_gear = UFS_HISI_LIMIT_PWMGEAR_RX; - hisi_param->pwm_tx_gear = UFS_HISI_LIMIT_PWMGEAR_TX; - hisi_param->rx_pwr_pwm = UFS_HISI_LIMIT_RX_PWR_PWM; - hisi_param->tx_pwr_pwm = UFS_HISI_LIMIT_TX_PWR_PWM; - hisi_param->rx_pwr_hs = UFS_HISI_LIMIT_RX_PWR_HS; - hisi_param->tx_pwr_hs = UFS_HISI_LIMIT_TX_PWR_HS; - hisi_param->hs_rate = UFS_HISI_LIMIT_HS_RATE; - hisi_param->desired_working_mode = UFS_HISI_LIMIT_DESIRED_MODE; + ufshcd_init_pwr_dev_param(hisi_param); } static void ufs_hisi_pwr_change_pre_change(struct ufs_hba *hba) diff --git a/drivers/scsi/ufs/ufs-hisi.h b/drivers/scsi/ufs/ufs-hisi.h index 3231d3d81c98..5a90c0f4e90c 100644 --- a/drivers/scsi/ufs/ufs-hisi.h +++ b/drivers/scsi/ufs/ufs-hisi.h @@ -76,19 +76,6 @@ enum { #define SLOW 1 #define FAST 2 -#define UFS_HISI_LIMIT_NUM_LANES_RX 2 -#define UFS_HISI_LIMIT_NUM_LANES_TX 2 -#define UFS_HISI_LIMIT_HSGEAR_RX UFS_HS_G3 -#define UFS_HISI_LIMIT_HSGEAR_TX UFS_HS_G3 -#define UFS_HISI_LIMIT_PWMGEAR_RX UFS_PWM_G4 -#define UFS_HISI_LIMIT_PWMGEAR_TX UFS_PWM_G4 -#define UFS_HISI_LIMIT_RX_PWR_PWM SLOW_MODE -#define UFS_HISI_LIMIT_TX_PWR_PWM SLOW_MODE -#define UFS_HISI_LIMIT_RX_PWR_HS FAST_MODE -#define UFS_HISI_LIMIT_TX_PWR_HS FAST_MODE -#define UFS_HISI_LIMIT_HS_RATE PA_HS_MODE_B -#define UFS_HISI_LIMIT_DESIRED_MODE FAST - #define UFS_HISI_CAP_RESERVED BIT(0) #define UFS_HISI_CAP_PHY10nm BIT(1) -- cgit v1.2.3 From fc85a74e28fe087dceb80eb69f37307ec97b6b47 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Mon, 16 Nov 2020 14:50:52 +0800 Subject: scsi: ufs: Refactor ADAPT configuration function Several vendors are using same code to configure ADAPT settings for HS-G4. Simply refactor it as common function. Link: https://lore.kernel.org/r/20201116065054.7658-8-stanley.chu@mediatek.com Reviewed-by: Bean Huo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 16 ++++++++++++++++ drivers/scsi/ufs/ufshcd.h | 3 +++ 2 files changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 9186ee01379a..80cbce414678 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -3587,6 +3587,22 @@ static int ufshcd_dme_reset(struct ufs_hba *hba) return ret; } +int ufshcd_dme_configure_adapt(struct ufs_hba *hba, + int agreed_gear, + int adapt_val) +{ + int ret; + + if (agreed_gear != UFS_HS_G4) + adapt_val = PA_INITIAL_ADAPT; + + ret = ufshcd_dme_set(hba, + UIC_ARG_MIB(PA_TXHSADAPTTYPE), + adapt_val); + return ret; +} +EXPORT_SYMBOL_GPL(ufshcd_dme_configure_adapt); + /** * ufshcd_dme_enable - UIC command for DME_ENABLE * @hba: per adapter instance diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 5191d87f6263..d0b68df07eef 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -956,6 +956,9 @@ extern int ufshcd_runtime_idle(struct ufs_hba *hba); extern int ufshcd_system_suspend(struct ufs_hba *hba); extern int ufshcd_system_resume(struct ufs_hba *hba); extern int ufshcd_shutdown(struct ufs_hba *hba); +extern int ufshcd_dme_configure_adapt(struct ufs_hba *hba, + int agreed_gear, + int adapt_val); extern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel, u8 attr_set, u32 mib_val, u8 peer); extern int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel, -- cgit v1.2.3 From e1e25d1b89967035059cf8e098270cc3300b5bd9 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Mon, 16 Nov 2020 14:50:53 +0800 Subject: scsi: ufs: ufs-mediatek: Use common ADAPT configuration function Use common ADAPT configuration function to reduce duplicated code in UFS drivers. Link: https://lore.kernel.org/r/20201116065054.7658-9-stanley.chu@mediatek.com Reviewed-by: Bean Huo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 87b4bf125e23..1d3c5cd4592e 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -677,7 +677,6 @@ static int ufs_mtk_pre_pwr_change(struct ufs_hba *hba, { struct ufs_mtk_host *host = ufshcd_get_variant(hba); struct ufs_dev_params host_cap; - u32 adapt_val; int ret; ufshcd_init_pwr_dev_param(&host_cap); @@ -693,13 +692,9 @@ static int ufs_mtk_pre_pwr_change(struct ufs_hba *hba, } if (host->hw_ver.major >= 3) { - if (dev_req_params->gear_tx == UFS_HS_G4) - adapt_val = PA_INITIAL_ADAPT; - else - adapt_val = PA_NO_ADAPT; - ufshcd_dme_set(hba, - UIC_ARG_MIB(PA_TXHSADAPTTYPE), - adapt_val); + ret = ufshcd_dme_configure_adapt(hba, + dev_req_params->gear_tx, + PA_INITIAL_ADAPT); } return ret; -- cgit v1.2.3 From d9fa1e731e243525861517ba256b179072070c1d Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Mon, 16 Nov 2020 14:50:54 +0800 Subject: scsi: ufs: ufs-qcom: Use common ADAPT configuration function Use common ADAPT configuration function to reduce duplicated code in UFS drivers. Link: https://lore.kernel.org/r/20201116065054.7658-10-stanley.chu@mediatek.com Reviewed-by: Bean Huo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-qcom.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 04adfbd10753..1e434cce0f79 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -723,17 +723,9 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba, ufs_qcom_dev_ref_clk_ctrl(host, true); if (host->hw_ver.major >= 0x4) { - if (dev_req_params->gear_tx == UFS_HS_G4) { - /* INITIAL ADAPT */ - ufshcd_dme_set(hba, - UIC_ARG_MIB(PA_TXHSADAPTTYPE), - PA_INITIAL_ADAPT); - } else { - /* NO ADAPT */ - ufshcd_dme_set(hba, - UIC_ARG_MIB(PA_TXHSADAPTTYPE), - PA_NO_ADAPT); - } + ufshcd_dme_configure_adapt(hba, + dev_req_params->gear_tx, + PA_INITIAL_ADAPT); } break; case POST_CHANGE: -- cgit v1.2.3 From cf4d4d8ebdb838ee996e09e3ee18deb9a7737dea Mon Sep 17 00:00:00 2001 From: Jing Xiangfeng Date: Tue, 3 Nov 2020 20:01:37 +0800 Subject: scsi: qla4xxx: Remove redundant assignment to variable rval The variable rval has been initialized with 'QLA_ERROR'. The assignment is redundant in an error path. Remove it. Link: https://lore.kernel.org/r/20201103120137.109717-1-jingxiangfeng@huawei.com Signed-off-by: Jing Xiangfeng Signed-off-by: Martin K. Petersen --- drivers/scsi/qla4xxx/ql4_os.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 2c23b692e318..a4b014e1cd8c 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -685,7 +685,6 @@ static int qla4xxx_get_chap_by_index(struct scsi_qla_host *ha, if (!ha->chap_list) { ql4_printk(KERN_ERR, ha, "CHAP table cache is empty!\n"); - rval = QLA_ERROR; goto exit_get_chap; } @@ -697,14 +696,12 @@ static int qla4xxx_get_chap_by_index(struct scsi_qla_host *ha, if (chap_index > max_chap_entries) { ql4_printk(KERN_ERR, ha, "Invalid Chap index\n"); - rval = QLA_ERROR; goto exit_get_chap; } *chap_entry = (struct ql4_chap_table *)ha->chap_list + chap_index; if ((*chap_entry)->cookie != __constant_cpu_to_le16(CHAP_VALID_COOKIE)) { - rval = QLA_ERROR; *chap_entry = NULL; } else { rval = QLA_SUCCESS; -- cgit v1.2.3 From fd62de114f8c9df098dcd43b5d83c5714176dd12 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 17 Nov 2020 08:58:33 -0800 Subject: scsi: ufs: Avoid to call REQ_CLKS_OFF to CLKS_OFF Once UFS is gated with CLKS_OFF, it should not call REQ_CLKS_OFF again. This can lead to hibern8_enter failure. Link: https://lore.kernel.org/r/20201117165839.1643377-2-jaegeuk@kernel.org Reviewed-by: Can Guo Signed-off-by: Jaegeuk Kim Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 80cbce414678..9f53f6391342 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1755,7 +1755,8 @@ static void __ufshcd_release(struct ufs_hba *hba) if (hba->clk_gating.active_reqs || hba->clk_gating.is_suspended || hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL || ufshcd_any_tag_in_use(hba) || hba->outstanding_tasks || - hba->active_uic_cmd || hba->uic_async_done) + hba->active_uic_cmd || hba->uic_async_done || + hba->clk_gating.state == CLKS_OFF) return; hba->clk_gating.state = REQ_CLKS_OFF; -- cgit v1.2.3 From b664511297644eac34038df877b3ad7bcaa81913 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 17 Nov 2020 08:58:34 -0800 Subject: scsi: ufs: Atomic update for clkgating_enable While running a stress test which enables/disables clkgating, we occasionally hit device timeout. This patch avoids a subtle race condition to address it. Link: https://lore.kernel.org/r/20201117165839.1643377-3-jaegeuk@kernel.org Reviewed-by: Can Guo Signed-off-by: Jaegeuk Kim Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 9f53f6391342..32874029b9b4 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1818,19 +1818,19 @@ static ssize_t ufshcd_clkgate_enable_store(struct device *dev, return -EINVAL; value = !!value; + + spin_lock_irqsave(hba->host->host_lock, flags); if (value == hba->clk_gating.is_enabled) goto out; - if (value) { - ufshcd_release(hba); - } else { - spin_lock_irqsave(hba->host->host_lock, flags); + if (value) + __ufshcd_release(hba); + else hba->clk_gating.active_reqs++; - spin_unlock_irqrestore(hba->host->host_lock, flags); - } hba->clk_gating.is_enabled = value; out: + spin_unlock_irqrestore(hba->host->host_lock, flags); return count; } -- cgit v1.2.3 From 4f3e900b628226011a5f71c19e53b175c014eb58 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 17 Nov 2020 08:58:35 -0800 Subject: scsi: ufs: Clear UAC for FFU and RPMB LUNs In order to conduct FFU or RPMB operations, UFS needs to clear UNIT ATTENTION condition. Clear it explicitly so that we get no failures during initialization. Link: https://lore.kernel.org/r/20201117165839.1643377-4-jaegeuk@kernel.org Signed-off-by: Jaegeuk Kim Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 70 +++++++++++++++++++++++++++++++++++++++++++---- drivers/scsi/ufs/ufshcd.h | 1 + 2 files changed, 65 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 32874029b9b4..439eef559dc5 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -7091,7 +7091,6 @@ static inline void ufshcd_blk_pm_runtime_init(struct scsi_device *sdev) static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) { int ret = 0; - struct scsi_device *sdev_rpmb; struct scsi_device *sdev_boot; hba->sdev_ufs_device = __scsi_add_device(hba->host, 0, 0, @@ -7104,14 +7103,14 @@ static int ufshcd_scsi_add_wlus(struct ufs_hba *hba) ufshcd_blk_pm_runtime_init(hba->sdev_ufs_device); scsi_device_put(hba->sdev_ufs_device); - sdev_rpmb = __scsi_add_device(hba->host, 0, 0, + hba->sdev_rpmb = __scsi_add_device(hba->host, 0, 0, ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_RPMB_WLUN), NULL); - if (IS_ERR(sdev_rpmb)) { - ret = PTR_ERR(sdev_rpmb); + if (IS_ERR(hba->sdev_rpmb)) { + ret = PTR_ERR(hba->sdev_rpmb); goto remove_sdev_ufs_device; } - ufshcd_blk_pm_runtime_init(sdev_rpmb); - scsi_device_put(sdev_rpmb); + ufshcd_blk_pm_runtime_init(hba->sdev_rpmb); + scsi_device_put(hba->sdev_rpmb); sdev_boot = __scsi_add_device(hba->host, 0, 0, ufshcd_upiu_wlun_to_scsi_wlun(UFS_UPIU_BOOT_WLUN), NULL); @@ -7635,6 +7634,63 @@ out: return ret; } +static int +ufshcd_send_request_sense(struct ufs_hba *hba, struct scsi_device *sdp); + +static int ufshcd_clear_ua_wlun(struct ufs_hba *hba, u8 wlun) +{ + struct scsi_device *sdp; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(hba->host->host_lock, flags); + if (wlun == UFS_UPIU_UFS_DEVICE_WLUN) + sdp = hba->sdev_ufs_device; + else if (wlun == UFS_UPIU_RPMB_WLUN) + sdp = hba->sdev_rpmb; + else + BUG_ON(1); + if (sdp) { + ret = scsi_device_get(sdp); + if (!ret && !scsi_device_online(sdp)) { + ret = -ENODEV; + scsi_device_put(sdp); + } + } else { + ret = -ENODEV; + } + spin_unlock_irqrestore(hba->host->host_lock, flags); + if (ret) + goto out_err; + + ret = ufshcd_send_request_sense(hba, sdp); + scsi_device_put(sdp); +out_err: + if (ret) + dev_err(hba->dev, "%s: UAC clear LU=%x ret = %d\n", + __func__, wlun, ret); + return ret; +} + +static int ufshcd_clear_ua_wluns(struct ufs_hba *hba) +{ + int ret = 0; + + if (!hba->wlun_dev_clr_ua) + goto out; + + ret = ufshcd_clear_ua_wlun(hba, UFS_UPIU_UFS_DEVICE_WLUN); + if (!ret) + ret = ufshcd_clear_ua_wlun(hba, UFS_UPIU_RPMB_WLUN); + if (!ret) + hba->wlun_dev_clr_ua = false; +out: + if (ret) + dev_err(hba->dev, "%s: Failed to clear UAC WLUNS ret = %d\n", + __func__, ret); + return ret; +} + /** * ufshcd_probe_hba - probe hba to detect device and initialize * @hba: per-adapter instance @@ -7754,6 +7810,8 @@ out: pm_runtime_put_sync(hba->dev); ufshcd_exit_clk_scaling(hba); ufshcd_hba_exit(hba); + } else { + ufshcd_clear_ua_wluns(hba); } } diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index d0b68df07eef..61344c49c2cc 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -703,6 +703,7 @@ struct ufs_hba { * "UFS device" W-LU. */ struct scsi_device *sdev_ufs_device; + struct scsi_device *sdev_rpmb; enum ufs_dev_pwr_mode curr_dev_pwr_mode; enum uic_link_state uic_link_state; -- cgit v1.2.3 From e93e6e49fa31989b149c48526d4098b278205c8a Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 17 Nov 2020 08:58:36 -0800 Subject: scsi: ufs: Use WQ_HIGHPRI for gating work Must have WQ_MEM_RECLAIM ``WQ_MEM_RECLAIM`` All workqueues which might be used in the memory reclaim paths **MUST** have this flag set. The wq is guaranteed to have at least one execution context regardless of memory pressure. Link: https://lore.kernel.org/r/20201117165839.1643377-5-jaegeuk@kernel.org Reviewed-by: Asutosh Das Signed-off-by: Jaegeuk Kim Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 439eef559dc5..c4400014d13d 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1878,7 +1878,7 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba) snprintf(wq_name, ARRAY_SIZE(wq_name), "ufs_clk_gating_%d", hba->host->host_no); hba->clk_gating.clk_gating_workq = alloc_ordered_workqueue(wq_name, - WQ_MEM_RECLAIM); + WQ_MEM_RECLAIM | WQ_HIGHPRI); hba->clk_gating.is_enabled = true; -- cgit v1.2.3 From 69a314d6a155c5bfa9720b25d6456656f0b38bd1 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 17 Nov 2020 08:58:37 -0800 Subject: scsi: ufs: Add more contexts in the ufs tracepoints This adds user-friendly tracepoints with group id. Link: https://lore.kernel.org/r/20201117165839.1643377-6-jaegeuk@kernel.org Reviewed-by: Can Guo Signed-off-by: Jaegeuk Kim Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 6 ++++-- include/trace/events/ufs.h | 21 +++++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index c4400014d13d..55d795fdaab3 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -355,7 +355,7 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, unsigned int tag, const char *str) { sector_t lba = -1; - u8 opcode = 0; + u8 opcode = 0, group_id = 0; u32 intr, doorbell; struct ufshcd_lrb *lrbp = &hba->lrb[tag]; struct scsi_cmnd *cmd = lrbp->cmd; @@ -381,13 +381,15 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, lba = cmd->request->bio->bi_iter.bi_sector; transfer_len = be32_to_cpu( lrbp->ucd_req_ptr->sc.exp_data_transfer_len); + if (opcode == WRITE_10) + group_id = lrbp->cmd->cmnd[6]; } } intr = ufshcd_readl(hba, REG_INTERRUPT_STATUS); doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); trace_ufshcd_command(dev_name(hba->dev), str, tag, - doorbell, transfer_len, intr, lba, opcode); + doorbell, transfer_len, intr, lba, opcode, group_id); } static void ufshcd_print_clk_freqs(struct ufs_hba *hba) diff --git a/include/trace/events/ufs.h b/include/trace/events/ufs.h index 2362244c2a9e..0bd54a184391 100644 --- a/include/trace/events/ufs.h +++ b/include/trace/events/ufs.h @@ -11,6 +11,15 @@ #include +#define str_opcode(opcode) \ + __print_symbolic(opcode, \ + { WRITE_16, "WRITE_16" }, \ + { WRITE_10, "WRITE_10" }, \ + { READ_16, "READ_16" }, \ + { READ_10, "READ_10" }, \ + { SYNCHRONIZE_CACHE, "SYNC" }, \ + { UNMAP, "UNMAP" }) + #define UFS_LINK_STATES \ EM(UIC_LINK_OFF_STATE) \ EM(UIC_LINK_ACTIVE_STATE) \ @@ -216,9 +225,10 @@ DEFINE_EVENT(ufshcd_template, ufshcd_init, TRACE_EVENT(ufshcd_command, TP_PROTO(const char *dev_name, const char *str, unsigned int tag, u32 doorbell, int transfer_len, u32 intr, u64 lba, - u8 opcode), + u8 opcode, u8 group_id), - TP_ARGS(dev_name, str, tag, doorbell, transfer_len, intr, lba, opcode), + TP_ARGS(dev_name, str, tag, doorbell, transfer_len, + intr, lba, opcode, group_id), TP_STRUCT__entry( __string(dev_name, dev_name) @@ -229,6 +239,7 @@ TRACE_EVENT(ufshcd_command, __field(u32, intr) __field(u64, lba) __field(u8, opcode) + __field(u8, group_id) ), TP_fast_assign( @@ -240,13 +251,15 @@ TRACE_EVENT(ufshcd_command, __entry->intr = intr; __entry->lba = lba; __entry->opcode = opcode; + __entry->group_id = group_id; ), TP_printk( - "%s: %s: tag: %u, DB: 0x%x, size: %d, IS: %u, LBA: %llu, opcode: 0x%x", + "%s: %s: tag: %u, DB: 0x%x, size: %d, IS: %u, LBA: %llu, opcode: 0x%x (%s), group_id: 0x%x", __get_str(str), __get_str(dev_name), __entry->tag, __entry->doorbell, __entry->transfer_len, - __entry->intr, __entry->lba, (u32)__entry->opcode + __entry->intr, __entry->lba, (u32)__entry->opcode, + str_opcode(__entry->opcode), (u32)__entry->group_id ) ); -- cgit v1.2.3 From 8eb456be75af7e5a7ac0cd223eaa198cf7ee2ac1 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 17 Nov 2020 08:58:38 -0800 Subject: scsi: ufs: Fix clkgating on/off The following call stack prevents clk_gating at every I/O completion. We can remove the condition, ufshcd_any_tag_in_use(), since clkgating_work will check it again. ufshcd_complete_requests(struct ufs_hba *hba) ufshcd_transfer_req_compl() __ufshcd_transfer_req_compl() __ufshcd_release(hba) if (ufshcd_any_tag_in_use() == 1) return; ufshcd_tmc_handler(hba); blk_mq_tagset_busy_iter(); Note that this still requires work to deal with a potential race condition when user sets clkgating.delay_ms to very small value. That can cause preventing clkgating by the check of ufshcd_any_tag_in_use() in gate_work. Link: https://lore.kernel.org/r/20201117165839.1643377-7-jaegeuk@kernel.org Fixes: 7252a3603015 ("scsi: ufs: Avoid busy-waiting by eliminating tag conflicts") Reviewed-by: Asutosh Das Reviewed-by: Can Guo Signed-off-by: Jaegeuk Kim Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 55d795fdaab3..deaaac67e055 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1756,7 +1756,7 @@ static void __ufshcd_release(struct ufs_hba *hba) if (hba->clk_gating.active_reqs || hba->clk_gating.is_suspended || hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL || - ufshcd_any_tag_in_use(hba) || hba->outstanding_tasks || + hba->outstanding_tasks || hba->active_uic_cmd || hba->uic_async_done || hba->clk_gating.state == CLKS_OFF) return; -- cgit v1.2.3 From 3754cde8df9106bda396b2956ea6f9758e26b25e Mon Sep 17 00:00:00 2001 From: Leo Liou Date: Tue, 17 Nov 2020 08:58:39 -0800 Subject: scsi: ufs: Show LBA and length for UNMAP commands We have LBA and length for unmap commands. Link: https://lore.kernel.org/r/20201117165839.1643377-8-jaegeuk@kernel.org Reviewed-by: Stanley Chu Reviewed-by: Can Guo Signed-off-by: Leo Liou Signed-off-by: Jaegeuk Kim Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index deaaac67e055..0e5473d4699b 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -383,6 +383,11 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba, lrbp->ucd_req_ptr->sc.exp_data_transfer_len); if (opcode == WRITE_10) group_id = lrbp->cmd->cmnd[6]; + } else if (opcode == UNMAP) { + if (cmd->request) { + lba = scsi_get_lba(cmd); + transfer_len = blk_rq_bytes(cmd->request); + } } } -- cgit v1.2.3 From 61bdb4eec8d1efc0dc3259d8392e43e20a01deae Mon Sep 17 00:00:00 2001 From: Tyrel Datwyler Date: Tue, 17 Nov 2020 12:50:29 -0600 Subject: scsi: ibmvfc: Byte swap login_buf.resp values in attribute show functions Both ibmvfc_show_host_(capabilities|npiv_version) functions retrieve values from vhost->login_buf.resp buffer. This is the MAD response buffer from the VIOS and as such any multi-byte non-string values are in big endian format. Byte swap these values to host CPU endian format for better human readability. Link: https://lore.kernel.org/r/20201117185031.129939-1-tyreld@linux.ibm.com Signed-off-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi/ibmvfc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 070cf516b98f..01fe65de9086 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -3025,7 +3025,7 @@ static ssize_t ibmvfc_show_host_npiv_version(struct device *dev, { struct Scsi_Host *shost = class_to_shost(dev); struct ibmvfc_host *vhost = shost_priv(shost); - return snprintf(buf, PAGE_SIZE, "%d\n", vhost->login_buf->resp.version); + return snprintf(buf, PAGE_SIZE, "%d\n", be32_to_cpu(vhost->login_buf->resp.version)); } static ssize_t ibmvfc_show_host_capabilities(struct device *dev, @@ -3033,7 +3033,7 @@ static ssize_t ibmvfc_show_host_capabilities(struct device *dev, { struct Scsi_Host *shost = class_to_shost(dev); struct ibmvfc_host *vhost = shost_priv(shost); - return snprintf(buf, PAGE_SIZE, "%llx\n", vhost->login_buf->resp.capabilities); + return snprintf(buf, PAGE_SIZE, "%llx\n", be64_to_cpu(vhost->login_buf->resp.capabilities)); } /** -- cgit v1.2.3 From 4e0716199ab656815c14de41740b658bb918e85e Mon Sep 17 00:00:00 2001 From: Tyrel Datwyler Date: Tue, 17 Nov 2020 12:50:30 -0600 Subject: scsi: ibmvfc: Remove trailing semicolon Remove a superfluous semicolon following a closing function block bracket. Link: https://lore.kernel.org/r/20201117185031.129939-2-tyreld@linux.ibm.com Signed-off-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi/ibmvfc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 01fe65de9086..0cab4b852b48 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -4391,7 +4391,7 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *vhost) ibmvfc_dbg(vhost, "Sent NPIV login\n"); else ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); -}; +} /** * ibmvfc_npiv_logout_done - Completion handler for NPIV Logout -- cgit v1.2.3 From 2aa0102c6688306548d81a958a6293936904ca75 Mon Sep 17 00:00:00 2001 From: Tyrel Datwyler Date: Tue, 17 Nov 2020 12:50:31 -0600 Subject: scsi: ibmvfc: Use correlation token to tag commands The vfcFrame correlation field is a 64bit handle that is intended to trace I/O operations through both the client stack and VIOS stack when the underlying physical FC adapter supports tagging. Tag vfcFrames with the associated ibmvfc_event pointer handle. Link: https://lore.kernel.org/r/20201117185031.129939-3-tyreld@linux.ibm.com Signed-off-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi/ibmvfc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 0cab4b852b48..3922441a117d 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -1693,6 +1693,8 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd, vfc_cmd->iu.pri_task_attr = IBMVFC_SIMPLE_TASK; } + vfc_cmd->correlation = cpu_to_be64(evt); + if (likely(!(rc = ibmvfc_map_sg_data(cmnd, evt, vfc_cmd, vhost->dev)))) return ibmvfc_send_event(evt, vhost, 0); @@ -2370,6 +2372,8 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; evt->sync_iu = &rsp_iu; + tmf->correlation = cpu_to_be64(evt); + init_completion(&evt->comp); rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); } -- cgit v1.2.3 From fad74a1be2dbeae02d71e072418eeb307ce46103 Mon Sep 17 00:00:00 2001 From: Tyrel Datwyler Date: Tue, 17 Nov 2020 19:10:59 -0600 Subject: scsi: ibmvfc: Deduplicate common ibmvfc_cmd init code The virtual FC frame command exchanged with the VIOS is used for device reset and command abort TMF as well as normally queued commands. When initializing the ibmvfc_cmd there are several elements of the command that are set the same way regardless of the command type. Deduplicate code by moving these commonally set fields into a initialization helper routine, namely ibmvfc_init_vfc_cmd(). Link: https://lore.kernel.org/r/20201118011104.296999-2-tyreld@linux.ibm.com Acked-by: Brian King Signed-off-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi/ibmvfc.c | 56 ++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 3922441a117d..316902074abe 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -1646,6 +1646,25 @@ static inline int ibmvfc_host_chkready(struct ibmvfc_host *vhost) return result; } +static struct ibmvfc_cmd *ibmvfc_init_vfc_cmd(struct ibmvfc_event *evt, struct scsi_device *sdev) +{ + struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); + struct ibmvfc_cmd *vfc_cmd = &evt->iu.cmd; + size_t offset = offsetof(struct ibmvfc_cmd, rsp); + + memset(vfc_cmd, 0, sizeof(*vfc_cmd)); + vfc_cmd->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offset); + vfc_cmd->resp.len = cpu_to_be32(sizeof(vfc_cmd->rsp)); + vfc_cmd->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); + vfc_cmd->payload_len = cpu_to_be32(sizeof(vfc_cmd->iu)); + vfc_cmd->resp_len = cpu_to_be32(sizeof(vfc_cmd->rsp)); + vfc_cmd->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); + vfc_cmd->tgt_scsi_id = cpu_to_be64(rport->port_id); + int_to_scsilun(sdev->lun, &vfc_cmd->iu.lun); + + return vfc_cmd; +} + /** * ibmvfc_queuecommand - The queuecommand function of the scsi template * @cmnd: struct scsi_cmnd to be executed @@ -1675,17 +1694,10 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd, ibmvfc_init_event(evt, ibmvfc_scsi_done, IBMVFC_CMD_FORMAT); evt->cmnd = cmnd; cmnd->scsi_done = done; - vfc_cmd = &evt->iu.cmd; - memset(vfc_cmd, 0, sizeof(*vfc_cmd)); - vfc_cmd->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp)); - vfc_cmd->resp.len = cpu_to_be32(sizeof(vfc_cmd->rsp)); - vfc_cmd->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); - vfc_cmd->payload_len = cpu_to_be32(sizeof(vfc_cmd->iu)); - vfc_cmd->resp_len = cpu_to_be32(sizeof(vfc_cmd->rsp)); - vfc_cmd->cancel_key = cpu_to_be32((unsigned long)cmnd->device->hostdata); - vfc_cmd->tgt_scsi_id = cpu_to_be64(rport->port_id); + + vfc_cmd = ibmvfc_init_vfc_cmd(evt, cmnd->device); + vfc_cmd->iu.xfer_len = cpu_to_be32(scsi_bufflen(cmnd)); - int_to_scsilun(cmnd->device->lun, &vfc_cmd->iu.lun); memcpy(vfc_cmd->iu.cdb, cmnd->cmnd, cmnd->cmd_len); if (cmnd->flags & SCMD_TAGGED) { @@ -2014,7 +2026,6 @@ out: static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) { struct ibmvfc_host *vhost = shost_priv(sdev->host); - struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); struct ibmvfc_cmd *tmf; struct ibmvfc_event *evt = NULL; union ibmvfc_iu rsp_iu; @@ -2027,17 +2038,8 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) if (vhost->state == IBMVFC_ACTIVE) { evt = ibmvfc_get_event(vhost); ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); + tmf = ibmvfc_init_vfc_cmd(evt, sdev); - tmf = &evt->iu.cmd; - memset(tmf, 0, sizeof(*tmf)); - tmf->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp)); - tmf->resp.len = cpu_to_be32(sizeof(tmf->rsp)); - tmf->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); - tmf->payload_len = cpu_to_be32(sizeof(tmf->iu)); - tmf->resp_len = cpu_to_be32(sizeof(tmf->rsp)); - tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); - tmf->tgt_scsi_id = cpu_to_be64(rport->port_id); - int_to_scsilun(sdev->lun, &tmf->iu.lun); tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); tmf->iu.tmf_flags = type; evt->sync_iu = &rsp_iu; @@ -2329,7 +2331,6 @@ static int ibmvfc_match_evt(struct ibmvfc_event *evt, void *match) static int ibmvfc_abort_task_set(struct scsi_device *sdev) { struct ibmvfc_host *vhost = shost_priv(sdev->host); - struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); struct ibmvfc_cmd *tmf; struct ibmvfc_event *evt, *found_evt; union ibmvfc_iu rsp_iu; @@ -2357,17 +2358,8 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) if (vhost->state == IBMVFC_ACTIVE) { evt = ibmvfc_get_event(vhost); ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); + tmf = ibmvfc_init_vfc_cmd(evt, sdev); - tmf = &evt->iu.cmd; - memset(tmf, 0, sizeof(*tmf)); - tmf->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp)); - tmf->resp.len = cpu_to_be32(sizeof(tmf->rsp)); - tmf->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); - tmf->payload_len = cpu_to_be32(sizeof(tmf->iu)); - tmf->resp_len = cpu_to_be32(sizeof(tmf->rsp)); - tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); - tmf->tgt_scsi_id = cpu_to_be64(rport->port_id); - int_to_scsilun(sdev->lun, &tmf->iu.lun); tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; evt->sync_iu = &rsp_iu; -- cgit v1.2.3 From c16b8a6d8af15364e562ed4d61b05fb826151712 Mon Sep 17 00:00:00 2001 From: Tyrel Datwyler Date: Tue, 17 Nov 2020 19:11:00 -0600 Subject: scsi: ibmvfc: Add new fields for version 2 of several MADs Introduce a target_wwpn field to several MADs. Its possible that a SCSI ID of a target can change due to some fabric changes. The WWPN of the SCSI target provides a better way to identify the target. Also, add flags for receiving MAD versioning information and advertising client support for targetWWPN with the VIOS. This latter capability flag will be required for future clients capable of requesting multiple hardware queues from the host adapter. Link: https://lore.kernel.org/r/20201118011104.296999-3-tyreld@linux.ibm.com Acked-by: Brian King Signed-off-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi/ibmvfc.c | 58 ++++++++++++++++++++++-------------------- drivers/scsi/ibmvscsi/ibmvfc.h | 28 +++++++++++++++++--- 2 files changed, 55 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 316902074abe..d33b24668367 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -149,6 +149,7 @@ static void ibmvfc_trc_start(struct ibmvfc_event *evt) struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_cmd *vfc_cmd = &evt->iu.cmd; struct ibmvfc_mad_common *mad = &evt->iu.mad_common; + struct ibmvfc_fcp_cmd_iu *iu = &vfc_cmd->v1.iu; struct ibmvfc_trace_entry *entry; entry = &vhost->trace[vhost->trace_index++]; @@ -159,11 +160,11 @@ static void ibmvfc_trc_start(struct ibmvfc_event *evt) switch (entry->fmt) { case IBMVFC_CMD_FORMAT: - entry->op_code = vfc_cmd->iu.cdb[0]; + entry->op_code = iu->cdb[0]; entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id); - entry->lun = scsilun_to_int(&vfc_cmd->iu.lun); - entry->tmf_flags = vfc_cmd->iu.tmf_flags; - entry->u.start.xfer_len = be32_to_cpu(vfc_cmd->iu.xfer_len); + entry->lun = scsilun_to_int(&iu->lun); + entry->tmf_flags = iu->tmf_flags; + entry->u.start.xfer_len = be32_to_cpu(iu->xfer_len); break; case IBMVFC_MAD_FORMAT: entry->op_code = be32_to_cpu(mad->opcode); @@ -183,6 +184,8 @@ static void ibmvfc_trc_end(struct ibmvfc_event *evt) struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd; struct ibmvfc_mad_common *mad = &evt->xfer_iu->mad_common; + struct ibmvfc_fcp_cmd_iu *iu = &vfc_cmd->v1.iu; + struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->v1.rsp; struct ibmvfc_trace_entry *entry = &vhost->trace[vhost->trace_index++]; entry->evt = evt; @@ -192,15 +195,15 @@ static void ibmvfc_trc_end(struct ibmvfc_event *evt) switch (entry->fmt) { case IBMVFC_CMD_FORMAT: - entry->op_code = vfc_cmd->iu.cdb[0]; + entry->op_code = iu->cdb[0]; entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id); - entry->lun = scsilun_to_int(&vfc_cmd->iu.lun); - entry->tmf_flags = vfc_cmd->iu.tmf_flags; + entry->lun = scsilun_to_int(&iu->lun); + entry->tmf_flags = iu->tmf_flags; entry->u.end.status = be16_to_cpu(vfc_cmd->status); entry->u.end.error = be16_to_cpu(vfc_cmd->error); - entry->u.end.fcp_rsp_flags = vfc_cmd->rsp.flags; - entry->u.end.rsp_code = vfc_cmd->rsp.data.info.rsp_code; - entry->u.end.scsi_status = vfc_cmd->rsp.scsi_status; + entry->u.end.fcp_rsp_flags = rsp->flags; + entry->u.end.rsp_code = rsp->data.info.rsp_code; + entry->u.end.scsi_status = rsp->scsi_status; break; case IBMVFC_MAD_FORMAT: entry->op_code = be32_to_cpu(mad->opcode); @@ -263,7 +266,7 @@ static const char *ibmvfc_get_cmd_error(u16 status, u16 error) static int ibmvfc_get_err_result(struct ibmvfc_cmd *vfc_cmd) { int err; - struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp; + struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->v1.rsp; int fc_rsp_len = be32_to_cpu(rsp->fcp_rsp_len); if ((rsp->flags & FCP_RSP_LEN_VALID) && @@ -1378,6 +1381,7 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd, int sg_mapped; struct srp_direct_buf *data = &vfc_cmd->ioba; struct ibmvfc_host *vhost = dev_get_drvdata(dev); + struct ibmvfc_fcp_cmd_iu *iu = &vfc_cmd->v1.iu; if (cls3_error) vfc_cmd->flags |= cpu_to_be16(IBMVFC_CLASS_3_ERR); @@ -1394,10 +1398,10 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd, if (scmd->sc_data_direction == DMA_TO_DEVICE) { vfc_cmd->flags |= cpu_to_be16(IBMVFC_WRITE); - vfc_cmd->iu.add_cdb_len |= IBMVFC_WRDATA; + iu->add_cdb_len |= IBMVFC_WRDATA; } else { vfc_cmd->flags |= cpu_to_be16(IBMVFC_READ); - vfc_cmd->iu.add_cdb_len |= IBMVFC_RDDATA; + iu->add_cdb_len |= IBMVFC_RDDATA; } if (sg_mapped == 1) { @@ -1516,7 +1520,7 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt) { struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd; struct ibmvfc_host *vhost = evt->vhost; - struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp; + struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->v1.rsp; struct scsi_cmnd *cmnd = evt->cmnd; const char *err = unknown_error; int index = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error)); @@ -1570,7 +1574,7 @@ static void ibmvfc_relogin(struct scsi_device *sdev) static void ibmvfc_scsi_done(struct ibmvfc_event *evt) { struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd; - struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp; + struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->v1.rsp; struct scsi_cmnd *cmnd = evt->cmnd; u32 rsp_len = 0; u32 sense_len = be32_to_cpu(rsp->fcp_sense_len); @@ -1650,17 +1654,17 @@ static struct ibmvfc_cmd *ibmvfc_init_vfc_cmd(struct ibmvfc_event *evt, struct s { struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); struct ibmvfc_cmd *vfc_cmd = &evt->iu.cmd; - size_t offset = offsetof(struct ibmvfc_cmd, rsp); + size_t offset = offsetof(struct ibmvfc_cmd, v1.rsp); memset(vfc_cmd, 0, sizeof(*vfc_cmd)); vfc_cmd->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offset); - vfc_cmd->resp.len = cpu_to_be32(sizeof(vfc_cmd->rsp)); + vfc_cmd->resp.len = cpu_to_be32(sizeof(vfc_cmd->v1.rsp)); vfc_cmd->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); - vfc_cmd->payload_len = cpu_to_be32(sizeof(vfc_cmd->iu)); - vfc_cmd->resp_len = cpu_to_be32(sizeof(vfc_cmd->rsp)); + vfc_cmd->payload_len = cpu_to_be32(sizeof(vfc_cmd->v1.iu)); + vfc_cmd->resp_len = cpu_to_be32(sizeof(vfc_cmd->v1.rsp)); vfc_cmd->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); vfc_cmd->tgt_scsi_id = cpu_to_be64(rport->port_id); - int_to_scsilun(sdev->lun, &vfc_cmd->iu.lun); + int_to_scsilun(sdev->lun, &vfc_cmd->v1.iu.lun); return vfc_cmd; } @@ -1697,12 +1701,12 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd, vfc_cmd = ibmvfc_init_vfc_cmd(evt, cmnd->device); - vfc_cmd->iu.xfer_len = cpu_to_be32(scsi_bufflen(cmnd)); - memcpy(vfc_cmd->iu.cdb, cmnd->cmnd, cmnd->cmd_len); + vfc_cmd->v1.iu.xfer_len = cpu_to_be32(scsi_bufflen(cmnd)); + memcpy(vfc_cmd->v1.iu.cdb, cmnd->cmnd, cmnd->cmd_len); if (cmnd->flags & SCMD_TAGGED) { vfc_cmd->task_tag = cpu_to_be64(cmnd->tag); - vfc_cmd->iu.pri_task_attr = IBMVFC_SIMPLE_TASK; + vfc_cmd->v1.iu.pri_task_attr = IBMVFC_SIMPLE_TASK; } vfc_cmd->correlation = cpu_to_be64(evt); @@ -2029,7 +2033,7 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) struct ibmvfc_cmd *tmf; struct ibmvfc_event *evt = NULL; union ibmvfc_iu rsp_iu; - struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.rsp; + struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.v1.rsp; int rsp_rc = -EBUSY; unsigned long flags; int rsp_code = 0; @@ -2041,7 +2045,7 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) tmf = ibmvfc_init_vfc_cmd(evt, sdev); tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); - tmf->iu.tmf_flags = type; + tmf->v1.iu.tmf_flags = type; evt->sync_iu = &rsp_iu; init_completion(&evt->comp); @@ -2334,7 +2338,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) struct ibmvfc_cmd *tmf; struct ibmvfc_event *evt, *found_evt; union ibmvfc_iu rsp_iu; - struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.rsp; + struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.v1.rsp; int rc, rsp_rc = -EBUSY; unsigned long flags, timeout = IBMVFC_ABORT_TIMEOUT; int rsp_code = 0; @@ -2361,7 +2365,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) tmf = ibmvfc_init_vfc_cmd(evt, sdev); tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); - tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; + tmf->v1.iu.tmf_flags = IBMVFC_ABORT_TASK_SET; evt->sync_iu = &rsp_iu; tmf->correlation = cpu_to_be64(evt); diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index 34debccfb142..9d58cfd774d3 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -54,6 +54,7 @@ #define IBMVFC_MAD_SUCCESS 0x00 #define IBMVFC_MAD_NOT_SUPPORTED 0xF1 +#define IBMVFC_MAD_VERSION_NOT_SUPP 0xF2 #define IBMVFC_MAD_FAILED 0xF7 #define IBMVFC_MAD_DRIVER_FAILED 0xEE #define IBMVFC_MAD_CRQ_ERROR 0xEF @@ -168,6 +169,8 @@ struct ibmvfc_npiv_login { #define IBMVFC_CAN_MIGRATE 0x01 #define IBMVFC_CAN_USE_CHANNELS 0x02 #define IBMVFC_CAN_HANDLE_FPIN 0x04 +#define IBMVFC_CAN_USE_MAD_VERSION 0x08 +#define IBMVFC_CAN_SEND_VF_WWPN 0x10 __be64 node_name; struct srp_direct_buf async; u8 partition_name[IBMVFC_MAX_NAME]; @@ -211,7 +214,9 @@ 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 +#define IBMVFC_MAD_VERSION_CAP 0x20 +#define IBMVFC_HANDLE_VF_WWPN 0x40 +#define IBMVFC_CAN_SUPPORT_CHANNELS 0x80 __be32 max_cmds; __be32 scsi_id_sz; __be64 max_dma_len; @@ -293,6 +298,7 @@ struct ibmvfc_port_login { __be32 reserved2; struct ibmvfc_service_parms service_parms; struct ibmvfc_service_parms service_parms_change; + __be64 target_wwpn; __be64 reserved3[2]; } __packed __aligned(8); @@ -344,6 +350,7 @@ struct ibmvfc_process_login { __be16 status; __be16 error; /* also fc_reason */ __be32 reserved2; + __be64 target_wwpn; __be64 reserved3[2]; } __packed __aligned(8); @@ -378,6 +385,8 @@ struct ibmvfc_tmf { __be32 cancel_key; __be32 my_cancel_key; __be32 pad; + __be64 target_wwpn; + __be64 task_tag; __be64 reserved[2]; } __packed __aligned(8); @@ -474,9 +483,19 @@ struct ibmvfc_cmd { __be64 correlation; __be64 tgt_scsi_id; __be64 tag; - __be64 reserved3[2]; - struct ibmvfc_fcp_cmd_iu iu; - struct ibmvfc_fcp_rsp rsp; + __be64 target_wwpn; + __be64 reserved3; + union { + struct { + struct ibmvfc_fcp_cmd_iu iu; + struct ibmvfc_fcp_rsp rsp; + } v1; + struct { + __be64 reserved4; + struct ibmvfc_fcp_cmd_iu iu; + struct ibmvfc_fcp_rsp rsp; + } v2; + }; } __packed __aligned(8); struct ibmvfc_passthru_fc_iu { @@ -503,6 +522,7 @@ struct ibmvfc_passthru_iu { __be64 correlation; __be64 scsi_id; __be64 tag; + __be64 target_wwpn; __be64 reserved2[2]; } __packed __aligned(8); -- cgit v1.2.3 From a318c2b71ccee720134e9a43b9b1afbea50f0578 Mon Sep 17 00:00:00 2001 From: Tyrel Datwyler Date: Tue, 17 Nov 2020 19:11:01 -0600 Subject: scsi: ibmvfc: Add helper for testing capability flags Testing the NPIV Login response capabilities is a long winded process of dereferencing the vhost->login_buf->resp.capabilities field, then byte swapping that value to host endian, and performing the bitwise test. Currently we only ever check this in ibmvfc_cancel_all(), but follow-up patches will need to regularly check for targetWWPN and channelization support. Add a helper to simplify checking various VIOS capabilities, namely ibmvfc_check_caps(). Link: https://lore.kernel.org/r/20201118011104.296999-4-tyreld@linux.ibm.com Acked-by: Brian King Signed-off-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi/ibmvfc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index d33b24668367..a68602cd1255 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -138,6 +138,13 @@ static void ibmvfc_tgt_move_login(struct ibmvfc_target *); static const char *unknown_error = "unknown error"; +static int ibmvfc_check_caps(struct ibmvfc_host *vhost, unsigned long cap_flags) +{ + u64 host_caps = be64_to_cpu(vhost->login_buf->resp.capabilities); + + return (host_caps & cap_flags) ? 1 : 0; +} + #ifdef CONFIG_SCSI_IBMVFC_TRACE /** * ibmvfc_trc_start - Log a start trace entry @@ -2240,7 +2247,7 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) tmf->common.length = cpu_to_be16(sizeof(*tmf)); tmf->scsi_id = cpu_to_be64(rport->port_id); int_to_scsilun(sdev->lun, &tmf->lun); - if (!(be64_to_cpu(vhost->login_buf->resp.capabilities) & IBMVFC_CAN_SUPPRESS_ABTS)) + if (!ibmvfc_check_caps(vhost, IBMVFC_CAN_SUPPRESS_ABTS)) type &= ~IBMVFC_TMF_SUPPRESS_ABTS; if (vhost->state == IBMVFC_ACTIVE) tmf->flags = cpu_to_be32((type | IBMVFC_TMF_LUA_VALID)); -- cgit v1.2.3 From 5a9d16f71c264addd7ed6fffd8f27839b0ad8433 Mon Sep 17 00:00:00 2001 From: Tyrel Datwyler Date: Tue, 17 Nov 2020 19:11:02 -0600 Subject: scsi: ibmvfc: Add FC payload retrieval routines for versioned vfcFrames The FC iu and response payloads are located at different offsets depending on the ibmvfc_cmd version. This is a result of the version 2 vfcFrame definition adding an extra 64bytes of reserved space to the structure prior to the payloads. Add helper routines to determine the current vfcFrame version and return a pointer to the proper iu or response structure within that ibmvfc_cmd. Link: https://lore.kernel.org/r/20201118011104.296999-5-tyreld@linux.ibm.com Acked-by: Brian King Signed-off-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi/ibmvfc.c | 77 +++++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index a68602cd1255..3427c686fb10 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -145,6 +145,24 @@ static int ibmvfc_check_caps(struct ibmvfc_host *vhost, unsigned long cap_flags) return (host_caps & cap_flags) ? 1 : 0; } +static struct ibmvfc_fcp_cmd_iu *ibmvfc_get_fcp_iu(struct ibmvfc_host *vhost, + struct ibmvfc_cmd *vfc_cmd) +{ + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) + return &vfc_cmd->v2.iu; + else + return &vfc_cmd->v1.iu; +} + +static struct ibmvfc_fcp_rsp *ibmvfc_get_fcp_rsp(struct ibmvfc_host *vhost, + struct ibmvfc_cmd *vfc_cmd) +{ + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) + return &vfc_cmd->v2.rsp; + else + return &vfc_cmd->v1.rsp; +} + #ifdef CONFIG_SCSI_IBMVFC_TRACE /** * ibmvfc_trc_start - Log a start trace entry @@ -156,7 +174,7 @@ static void ibmvfc_trc_start(struct ibmvfc_event *evt) struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_cmd *vfc_cmd = &evt->iu.cmd; struct ibmvfc_mad_common *mad = &evt->iu.mad_common; - struct ibmvfc_fcp_cmd_iu *iu = &vfc_cmd->v1.iu; + struct ibmvfc_fcp_cmd_iu *iu = ibmvfc_get_fcp_iu(vhost, vfc_cmd); struct ibmvfc_trace_entry *entry; entry = &vhost->trace[vhost->trace_index++]; @@ -191,8 +209,8 @@ static void ibmvfc_trc_end(struct ibmvfc_event *evt) struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd; struct ibmvfc_mad_common *mad = &evt->xfer_iu->mad_common; - struct ibmvfc_fcp_cmd_iu *iu = &vfc_cmd->v1.iu; - struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->v1.rsp; + struct ibmvfc_fcp_cmd_iu *iu = ibmvfc_get_fcp_iu(vhost, vfc_cmd); + struct ibmvfc_fcp_rsp *rsp = ibmvfc_get_fcp_rsp(vhost, vfc_cmd); struct ibmvfc_trace_entry *entry = &vhost->trace[vhost->trace_index++]; entry->evt = evt; @@ -270,10 +288,10 @@ static const char *ibmvfc_get_cmd_error(u16 status, u16 error) * Return value: * SCSI result value to return for completed command **/ -static int ibmvfc_get_err_result(struct ibmvfc_cmd *vfc_cmd) +static int ibmvfc_get_err_result(struct ibmvfc_host *vhost, struct ibmvfc_cmd *vfc_cmd) { int err; - struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->v1.rsp; + struct ibmvfc_fcp_rsp *rsp = ibmvfc_get_fcp_rsp(vhost, vfc_cmd); int fc_rsp_len = be32_to_cpu(rsp->fcp_rsp_len); if ((rsp->flags & FCP_RSP_LEN_VALID) && @@ -1388,7 +1406,7 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd, int sg_mapped; struct srp_direct_buf *data = &vfc_cmd->ioba; struct ibmvfc_host *vhost = dev_get_drvdata(dev); - struct ibmvfc_fcp_cmd_iu *iu = &vfc_cmd->v1.iu; + struct ibmvfc_fcp_cmd_iu *iu = ibmvfc_get_fcp_iu(evt->vhost, vfc_cmd); if (cls3_error) vfc_cmd->flags |= cpu_to_be16(IBMVFC_CLASS_3_ERR); @@ -1527,7 +1545,7 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt) { struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd; struct ibmvfc_host *vhost = evt->vhost; - struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->v1.rsp; + struct ibmvfc_fcp_rsp *rsp = ibmvfc_get_fcp_rsp(vhost, vfc_cmd); struct scsi_cmnd *cmnd = evt->cmnd; const char *err = unknown_error; int index = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error)); @@ -1581,7 +1599,7 @@ static void ibmvfc_relogin(struct scsi_device *sdev) static void ibmvfc_scsi_done(struct ibmvfc_event *evt) { struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd; - struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->v1.rsp; + struct ibmvfc_fcp_rsp *rsp = ibmvfc_get_fcp_rsp(evt->vhost, vfc_cmd); struct scsi_cmnd *cmnd = evt->cmnd; u32 rsp_len = 0; u32 sense_len = be32_to_cpu(rsp->fcp_sense_len); @@ -1595,7 +1613,7 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt) scsi_set_resid(cmnd, 0); if (vfc_cmd->status) { - cmnd->result = ibmvfc_get_err_result(vfc_cmd); + cmnd->result = ibmvfc_get_err_result(evt->vhost, vfc_cmd); if (rsp->flags & FCP_RSP_LEN_VALID) rsp_len = be32_to_cpu(rsp->fcp_rsp_len); @@ -1660,18 +1678,25 @@ static inline int ibmvfc_host_chkready(struct ibmvfc_host *vhost) static struct ibmvfc_cmd *ibmvfc_init_vfc_cmd(struct ibmvfc_event *evt, struct scsi_device *sdev) { struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); + struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_cmd *vfc_cmd = &evt->iu.cmd; - size_t offset = offsetof(struct ibmvfc_cmd, v1.rsp); + struct ibmvfc_fcp_cmd_iu *iu = ibmvfc_get_fcp_iu(vhost, vfc_cmd); + struct ibmvfc_fcp_rsp *rsp = ibmvfc_get_fcp_rsp(vhost, vfc_cmd); + size_t offset; memset(vfc_cmd, 0, sizeof(*vfc_cmd)); + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) + offset = offsetof(struct ibmvfc_cmd, v2.rsp); + else + offset = offsetof(struct ibmvfc_cmd, v1.rsp); vfc_cmd->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offset); - vfc_cmd->resp.len = cpu_to_be32(sizeof(vfc_cmd->v1.rsp)); + vfc_cmd->resp.len = cpu_to_be32(sizeof(*rsp)); vfc_cmd->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); - vfc_cmd->payload_len = cpu_to_be32(sizeof(vfc_cmd->v1.iu)); - vfc_cmd->resp_len = cpu_to_be32(sizeof(vfc_cmd->v1.rsp)); + vfc_cmd->payload_len = cpu_to_be32(sizeof(*iu)); + vfc_cmd->resp_len = cpu_to_be32(sizeof(*rsp)); vfc_cmd->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); vfc_cmd->tgt_scsi_id = cpu_to_be64(rport->port_id); - int_to_scsilun(sdev->lun, &vfc_cmd->v1.iu.lun); + int_to_scsilun(sdev->lun, &iu->lun); return vfc_cmd; } @@ -1690,6 +1715,7 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd, struct ibmvfc_host *vhost = shost_priv(cmnd->device->host); struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); struct ibmvfc_cmd *vfc_cmd; + struct ibmvfc_fcp_cmd_iu *iu; struct ibmvfc_event *evt; int rc; @@ -1707,13 +1733,14 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd, cmnd->scsi_done = done; vfc_cmd = ibmvfc_init_vfc_cmd(evt, cmnd->device); + iu = ibmvfc_get_fcp_iu(vhost, vfc_cmd); - vfc_cmd->v1.iu.xfer_len = cpu_to_be32(scsi_bufflen(cmnd)); - memcpy(vfc_cmd->v1.iu.cdb, cmnd->cmnd, cmnd->cmd_len); + iu->xfer_len = cpu_to_be32(scsi_bufflen(cmnd)); + memcpy(iu->cdb, cmnd->cmnd, cmnd->cmd_len); if (cmnd->flags & SCMD_TAGGED) { vfc_cmd->task_tag = cpu_to_be64(cmnd->tag); - vfc_cmd->v1.iu.pri_task_attr = IBMVFC_SIMPLE_TASK; + iu->pri_task_attr = IBMVFC_SIMPLE_TASK; } vfc_cmd->correlation = cpu_to_be64(evt); @@ -2040,7 +2067,8 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) struct ibmvfc_cmd *tmf; struct ibmvfc_event *evt = NULL; union ibmvfc_iu rsp_iu; - struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.v1.rsp; + struct ibmvfc_fcp_cmd_iu *iu; + struct ibmvfc_fcp_rsp *fc_rsp = ibmvfc_get_fcp_rsp(vhost, &rsp_iu.cmd); int rsp_rc = -EBUSY; unsigned long flags; int rsp_code = 0; @@ -2050,9 +2078,10 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) evt = ibmvfc_get_event(vhost); ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); tmf = ibmvfc_init_vfc_cmd(evt, sdev); + iu = ibmvfc_get_fcp_iu(vhost, tmf); tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); - tmf->v1.iu.tmf_flags = type; + iu->tmf_flags = type; evt->sync_iu = &rsp_iu; init_completion(&evt->comp); @@ -2070,7 +2099,7 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) wait_for_completion(&evt->comp); if (rsp_iu.cmd.status) - rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd); + rsp_code = ibmvfc_get_err_result(vhost, &rsp_iu.cmd); if (rsp_code) { if (fc_rsp->flags & FCP_RSP_LEN_VALID) @@ -2345,7 +2374,8 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) struct ibmvfc_cmd *tmf; struct ibmvfc_event *evt, *found_evt; union ibmvfc_iu rsp_iu; - struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.v1.rsp; + struct ibmvfc_fcp_cmd_iu *iu; + struct ibmvfc_fcp_rsp *fc_rsp = ibmvfc_get_fcp_rsp(vhost, &rsp_iu.cmd); int rc, rsp_rc = -EBUSY; unsigned long flags, timeout = IBMVFC_ABORT_TIMEOUT; int rsp_code = 0; @@ -2370,9 +2400,10 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) evt = ibmvfc_get_event(vhost); ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); tmf = ibmvfc_init_vfc_cmd(evt, sdev); + iu = ibmvfc_get_fcp_iu(vhost, tmf); + iu->tmf_flags = IBMVFC_ABORT_TASK_SET; tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); - tmf->v1.iu.tmf_flags = IBMVFC_ABORT_TASK_SET; evt->sync_iu = &rsp_iu; tmf->correlation = cpu_to_be64(evt); @@ -2421,7 +2452,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) } if (rsp_iu.cmd.status) - rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd); + rsp_code = ibmvfc_get_err_result(vhost, &rsp_iu.cmd); if (rsp_code) { if (fc_rsp->flags & FCP_RSP_LEN_VALID) -- cgit v1.2.3 From ebc7c74bd2dcdb5b9b1aa54036a0f4e9c90ce0d4 Mon Sep 17 00:00:00 2001 From: Tyrel Datwyler Date: Tue, 17 Nov 2020 19:11:03 -0600 Subject: scsi: ibmvfc: Add support for target_wwpn field in v2 MADs and vfcFrame Several version 2 MADs and the version 2 vfcFrame structures introduced a new targetWWPN field for better identification of a target over the scsi_id. Set this field and MAD versioning fields when the VIOS advertises the IBMVFC_HANDLE_VF_WWPN capability. Link: https://lore.kernel.org/r/20201118011104.296999-6-tyreld@linux.ibm.com Acked-by: Brian King Signed-off-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi/ibmvfc.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 3427c686fb10..83627e11e85e 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -1685,9 +1685,10 @@ static struct ibmvfc_cmd *ibmvfc_init_vfc_cmd(struct ibmvfc_event *evt, struct s size_t offset; memset(vfc_cmd, 0, sizeof(*vfc_cmd)); - if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) { offset = offsetof(struct ibmvfc_cmd, v2.rsp); - else + vfc_cmd->target_wwpn = cpu_to_be64(rport->port_name); + } else offset = offsetof(struct ibmvfc_cmd, v1.rsp); vfc_cmd->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offset); vfc_cmd->resp.len = cpu_to_be32(sizeof(*rsp)); @@ -2064,6 +2065,7 @@ out: static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) { struct ibmvfc_host *vhost = shost_priv(sdev->host); + struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); struct ibmvfc_cmd *tmf; struct ibmvfc_event *evt = NULL; union ibmvfc_iu rsp_iu; @@ -2081,6 +2083,8 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) iu = ibmvfc_get_fcp_iu(vhost, tmf); tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) + tmf->target_wwpn = cpu_to_be64(rport->port_name); iu->tmf_flags = type; evt->sync_iu = &rsp_iu; @@ -2271,7 +2275,12 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) tmf = &evt->iu.tmf; memset(tmf, 0, sizeof(*tmf)); - tmf->common.version = cpu_to_be32(1); + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) { + tmf->common.version = cpu_to_be32(2); + tmf->target_wwpn = cpu_to_be64(rport->port_name); + } else { + tmf->common.version = cpu_to_be32(1); + } tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD); tmf->common.length = cpu_to_be16(sizeof(*tmf)); tmf->scsi_id = cpu_to_be64(rport->port_id); @@ -2371,6 +2380,7 @@ static int ibmvfc_match_evt(struct ibmvfc_event *evt, void *match) static int ibmvfc_abort_task_set(struct scsi_device *sdev) { struct ibmvfc_host *vhost = shost_priv(sdev->host); + struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); struct ibmvfc_cmd *tmf; struct ibmvfc_event *evt, *found_evt; union ibmvfc_iu rsp_iu; @@ -2402,6 +2412,8 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) tmf = ibmvfc_init_vfc_cmd(evt, sdev); iu = ibmvfc_get_fcp_iu(vhost, tmf); + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) + tmf->target_wwpn = cpu_to_be64(rport->port_name); iu->tmf_flags = IBMVFC_ABORT_TASK_SET; tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); evt->sync_iu = &rsp_iu; @@ -3483,7 +3495,12 @@ static void ibmvfc_tgt_send_prli(struct ibmvfc_target *tgt) evt->tgt = tgt; prli = &evt->iu.prli; memset(prli, 0, sizeof(*prli)); - prli->common.version = cpu_to_be32(1); + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) { + prli->common.version = cpu_to_be32(2); + prli->target_wwpn = cpu_to_be64(tgt->wwpn); + } else { + prli->common.version = cpu_to_be32(1); + } prli->common.opcode = cpu_to_be32(IBMVFC_PROCESS_LOGIN); prli->common.length = cpu_to_be16(sizeof(*prli)); prli->scsi_id = cpu_to_be64(tgt->scsi_id); @@ -3586,7 +3603,12 @@ static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *tgt) evt->tgt = tgt; plogi = &evt->iu.plogi; memset(plogi, 0, sizeof(*plogi)); - plogi->common.version = cpu_to_be32(1); + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) { + plogi->common.version = cpu_to_be32(2); + plogi->target_wwpn = cpu_to_be64(tgt->wwpn); + } else { + plogi->common.version = cpu_to_be32(1); + } plogi->common.opcode = cpu_to_be32(IBMVFC_PORT_LOGIN); plogi->common.length = cpu_to_be16(sizeof(*plogi)); plogi->scsi_id = cpu_to_be64(tgt->scsi_id); @@ -3986,7 +4008,12 @@ static void ibmvfc_adisc_timeout(struct timer_list *t) evt->tgt = tgt; tmf = &evt->iu.tmf; memset(tmf, 0, sizeof(*tmf)); - tmf->common.version = cpu_to_be32(1); + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) { + tmf->common.version = cpu_to_be32(2); + tmf->target_wwpn = cpu_to_be64(tgt->wwpn); + } else { + tmf->common.version = cpu_to_be32(1); + } tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD); tmf->common.length = cpu_to_be16(sizeof(*tmf)); tmf->scsi_id = cpu_to_be64(tgt->scsi_id); -- cgit v1.2.3 From e4af87b7079ebf1bba86c7011ef5d5df45af8f56 Mon Sep 17 00:00:00 2001 From: Tyrel Datwyler Date: Tue, 17 Nov 2020 19:11:04 -0600 Subject: scsi: ibmvfc: Advertise client support for targetWWPN using v2 commands The previous patch added support for the targetWWPN field in version 2 MADs and vfcFrame structures. Set the IBMVFC_CAN_SEND_VF_WWPN bit in our capabailites flag during NPIV Login to inform the VIOS that this client supports the feature. Link: https://lore.kernel.org/r/20201118011104.296999-7-tyreld@linux.ibm.com Acked-by: Brian King Signed-off-by: Tyrel Datwyler Signed-off-by: Martin K. Petersen --- drivers/scsi/ibmvscsi/ibmvfc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 83627e11e85e..42e4d35e0d35 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -1255,7 +1255,7 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost) login_info->flags |= cpu_to_be16(IBMVFC_CLIENT_MIGRATED); login_info->max_cmds = cpu_to_be32(max_requests + IBMVFC_NUM_INTERNAL_REQ); - login_info->capabilities = cpu_to_be64(IBMVFC_CAN_MIGRATE); + login_info->capabilities = cpu_to_be64(IBMVFC_CAN_MIGRATE | IBMVFC_CAN_SEND_VF_WWPN); login_info->async.va = cpu_to_be64(vhost->async_crq.msg_token); login_info->async.len = cpu_to_be32(vhost->async_crq.size * sizeof(*vhost->async_crq.msgs)); strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME); -- cgit v1.2.3 From 1e7dddb2e76a593627643c42f9bf57e5c0078f06 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 18 Nov 2020 13:13:45 +0000 Subject: scsi: lpfc: Fix pointer defereference before it is null checked issue There is a null check on pointer lpfc_cmd after the pointer has been dereferenced when pointers rdata and ndlp are initialized at the start of the function. Fix this by only assigning rdata and ndlp after the pointer lpfc_cmd has been null checked. Link: https://lore.kernel.org/r/20201118131345.460631-1-colin.king@canonical.com Fixes: 96e209be6ecb ("scsi: lpfc: Convert SCSI I/O completions to SLI-3 and SLI-4 handlers") Reviewed-by: James Smart Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen Addresses-Coverity: ("Dereference before null check") --- drivers/scsi/lpfc/lpfc_scsi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index f989490359a5..3b989f720937 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -4022,8 +4022,8 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, struct lpfc_io_buf *lpfc_cmd = (struct lpfc_io_buf *)pwqeIn->context1; struct lpfc_vport *vport = pwqeIn->vport; - struct lpfc_rport_data *rdata = lpfc_cmd->rdata; - struct lpfc_nodelist *ndlp = rdata->pnode; + struct lpfc_rport_data *rdata; + struct lpfc_nodelist *ndlp; struct scsi_cmnd *cmd; unsigned long flags; struct lpfc_fast_path_event *fast_path_evt; @@ -4040,6 +4040,9 @@ lpfc_fcp_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, return; } + rdata = lpfc_cmd->rdata; + ndlp = rdata->pnode; + if (bf_get(lpfc_wcqe_c_xb, wcqe)) { /* TOREMOVE - currently this flag is checked during * the release of lpfc_iocbq. Remove once we move -- cgit v1.2.3 From 61795a5316ad8786fb4bb896198733188a60eab8 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 18 Nov 2020 13:37:44 +0000 Subject: scsi: lpfc: Remove dead code on second !ndlp check Currently there is a null check on the pointer ndlp that exits via error path issue_ct_rsp_exit followed by another null check on the same pointer that is almost identical to the previous null check stanza and yet can never can be reached because the previous check exited via issue_ct_rsp_exit. This is deadcode and can be removed. Link: https://lore.kernel.org/r/20201118133744.461385-1-colin.king@canonical.com Reviewed-by: James Smart Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen Addresses-Coverity: ("Logically dead code") --- drivers/scsi/lpfc/lpfc_bsg.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 35f4998504c1..41e3657c2d8d 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -1526,12 +1526,6 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct bsg_job *job, uint32_t tag, goto issue_ct_rsp_exit; } - /* Check if the ndlp is active */ - if (!ndlp) { - rc = IOCB_ERROR; - goto issue_ct_rsp_exit; - } - /* get a refernece count so the ndlp doesn't go away while * we respond */ -- cgit v1.2.3 From 14c1dd9504112ffe86688ff0cd64149e16d36772 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 18 Nov 2020 14:13:14 +0000 Subject: scsi: lpfc: Fix memory leak on lcb_context Currently there is an error return path that neglects to free the allocation for lcb_context. Fix this by adding a new error free exit path that kfree's lcb_context before returning. Use this new kfree exit path in another exit error path that also kfree's the same object, allowing a line of code to be removed. Link: https://lore.kernel.org/r/20201118141314.462471-1-colin.king@canonical.com Fixes: 4430f7fd09ec ("scsi: lpfc: Rework locations of ndlp reference taking") Reviewed-by: James Smart Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen Addresses-Coverity: ("Resource leak") --- drivers/scsi/lpfc/lpfc_els.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 03f47d1b21fe..cfd95ca69888 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -6515,18 +6515,20 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, lcb_context->ndlp = lpfc_nlp_get(ndlp); if (!lcb_context->ndlp) { rjt_err = LSRJT_UNABLE_TPC; - goto rjt; + goto rjt_free; } if (lpfc_sli4_set_beacon(vport, lcb_context, state)) { lpfc_printf_vlog(ndlp->vport, KERN_ERR, LOG_TRACE_EVENT, "0193 failed to send mail box"); - kfree(lcb_context); lpfc_nlp_put(ndlp); rjt_err = LSRJT_UNABLE_TPC; - goto rjt; + goto rjt_free; } return 0; + +rjt_free: + kfree(lcb_context); rjt: memset(&stat, 0, sizeof(stat)); stat.un.b.lsRjtRsnCode = rjt_err; -- cgit v1.2.3 From 809032ddf9c6c779a9eb0f0c55c21a1e8913557f Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 19 Nov 2020 12:33:28 -0800 Subject: scsi: lpfc: Fix missing prototype warning for lpfc_fdmi_vendor_attr_mi() Function needs to be declared as static. Link: https://lore.kernel.org/r/20201119203328.121772-1-james.smart@broadcom.com Fixes: 8aaa7bcf07a2 ("scsi: lpfc: Add FDMI Vendor MIB support") Reported-by: kernel test robot Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_ct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index ef4b8620c0e8..dd0b432f7ac5 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -3295,7 +3295,7 @@ lpfc_fdmi_smart_attr_security(struct lpfc_vport *vport, return size; } -int +static int lpfc_fdmi_vendor_attr_mi(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) { -- cgit v1.2.3 From 4a119d8a4c6058d445db89c22db87ef8316c4286 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 19 Nov 2020 12:33:40 -0800 Subject: scsi: lpfc: Fix set but not used warnings from Rework remote port lock handling Remove local variables that are set but not used. Link: https://lore.kernel.org/r/20201119203340.121819-1-james.smart@broadcom.com Fixes: c6adba150191 ("scsi: lpfc: Rework remote port lock handling") Reported-by: kernel test robot Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 6 ------ drivers/scsi/lpfc/lpfc_hbadisc.c | 4 ---- drivers/scsi/lpfc/lpfc_init.c | 2 -- 3 files changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index cfd95ca69888..fd5c581cd67a 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -2075,7 +2075,6 @@ int lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) { struct lpfc_hba *phba = vport->phba; - struct Scsi_Host *shost; struct serv_parm *sp; struct lpfc_nodelist *ndlp; struct lpfc_iocbq *elsiocb; @@ -2113,7 +2112,6 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry) if (!elsiocb) return 1; - shost = lpfc_shost_from_vport(vport); spin_lock_irq(&ndlp->lock); ndlp->nlp_flag &= ~NLP_FCP_PRLI_RJT; spin_unlock_irq(&ndlp->lock); @@ -8574,7 +8572,6 @@ static void lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb) { - struct Scsi_Host *shost; struct lpfc_nodelist *ndlp; struct ls_rjt stat; uint32_t *payload, payload_len; @@ -8635,7 +8632,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, * Do not process any unsolicited ELS commands * if the ndlp is in DEV_LOSS */ - shost = lpfc_shost_from_vport(vport); spin_lock_irq(&ndlp->lock); if (ndlp->nlp_flag & NLP_IN_DEV_LOSS) { spin_unlock_irq(&ndlp->lock); @@ -9405,7 +9401,6 @@ void lpfc_retry_pport_discovery(struct lpfc_hba *phba) { struct lpfc_nodelist *ndlp; - struct Scsi_Host *shost; /* Cancel the all vports retry delay retry timers */ lpfc_cancel_all_vport_retry_delay_timer(phba); @@ -9415,7 +9410,6 @@ lpfc_retry_pport_discovery(struct lpfc_hba *phba) if (!ndlp) return; - shost = lpfc_shost_from_vport(phba->pport); mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000)); spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_DELAY_TMO; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index c8911a3d00ee..44eddddff0dc 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -84,7 +84,6 @@ lpfc_rport_invalid(struct fc_rport *rport) { struct lpfc_rport_data *rdata; struct lpfc_nodelist *ndlp; - struct lpfc_vport *vport; if (!rport) { pr_err("**** %s: NULL rport, exit.\n", __func__); @@ -105,7 +104,6 @@ lpfc_rport_invalid(struct fc_rport *rport) return -EINVAL; } - vport = ndlp->vport; if (!ndlp->vport) { pr_err("**** %s: Null vport on ndlp %p, DID x%x rport %p " "SID x%x\n", __func__, ndlp, ndlp->nlp_DID, rport, @@ -6195,7 +6193,6 @@ lpfc_nlp_release(struct kref *kref) struct lpfc_nodelist * lpfc_nlp_get(struct lpfc_nodelist *ndlp) { - struct lpfc_hba *phba; unsigned long flags; if (ndlp) { @@ -6208,7 +6205,6 @@ lpfc_nlp_get(struct lpfc_nodelist *ndlp) * ndlp reference count that is in the process of being * released. */ - phba = ndlp->phba; spin_lock_irqsave(&ndlp->lock, flags); if (!kref_get_unless_zero(&ndlp->kref)) { spin_unlock_irqrestore(&ndlp->lock, flags); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f4de75b2f64f..f4cf60f125f5 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -5644,7 +5644,6 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, int rc; struct lpfc_vport *vport; struct lpfc_nodelist *ndlp; - struct Scsi_Host *shost; int active_vlink_present; struct lpfc_vport **vports; int i; @@ -5825,7 +5824,6 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, */ mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000)); - shost = lpfc_shost_from_vport(vport); spin_lock_irq(&ndlp->lock); ndlp->nlp_flag |= NLP_DELAY_TMO; spin_unlock_irq(&ndlp->lock); -- cgit v1.2.3 From 09b15e35071d35947b6e6da5b1a1d0cab73c12a6 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 19 Nov 2020 12:33:53 -0800 Subject: scsi: lpfc: Fix set but unused variables in lpfc_dev_loss_tmo_handler() Remove set but not used variable shost in lpfc_dev_loss_tmo_handler(). Link: https://lore.kernel.org/r/20201119203353.121866-1-james.smart@broadcom.com Fixes: 52edb2caf675 ("scsi: lpfc: Remove ndlp when a PLOGI/ADISC/PRLI/REG_RPI ultimately fails") Reported-by: kernel test robot Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 44eddddff0dc..2b6b5fc671fe 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -244,14 +244,12 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) { struct lpfc_vport *vport; struct lpfc_hba *phba; - struct Scsi_Host *shost; uint8_t *name; int warn_on = 0; int fcf_inuse = 0; unsigned long iflags; vport = ndlp->vport; - shost = lpfc_shost_from_vport(vport); name = (uint8_t *)&ndlp->nlp_portname; phba = vport->phba; -- cgit v1.2.3 From 185d17e11e7f98e0d1f499d702d9792a4ed5ae47 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 19 Nov 2020 12:33:16 -0800 Subject: scsi: lpfc: Fix missing prototype for lpfc_nvmet_prep_abort_wqe() lpfc_nvmet_prep_abort_wqe() needs to be declared static. Link: https://lore.kernel.org/r/20201119203316.121725-1-james.smart@broadcom.com Fixes: db7531d2b377 ("scsi: lpfc: Convert abort handling to SLI-3 and SLI-4 handlers") Reported-by: kernel test robot Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_nvmet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index c8b9434ae5cf..a71df8788fff 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -3336,7 +3336,7 @@ lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba, * * This function is called with hbalock held. **/ -void +static void lpfc_nvmet_prep_abort_wqe(struct lpfc_iocbq *pwqeq, u16 xritag, u8 opt) { union lpfc_wqe128 *wqe = &pwqeq->wqe; -- cgit v1.2.3 From 6998ff4e21619d47ebf4f5eb4cafa65c65856221 Mon Sep 17 00:00:00 2001 From: James Smart Date: Thu, 19 Nov 2020 12:34:07 -0800 Subject: scsi: lpfc: Fix variable 'vport' set but not used in lpfc_sli4_abts_err_handler() Remove vport variable that is assigned but not used in lpfc_sli4_abts_err_handler(). Link: https://lore.kernel.org/r/20201119203407.121913-1-james.smart@broadcom.com Fixes: e7dab164a9aa ("scsi: lpfc: Fix scheduling call while in softirq context in lpfc_unreg_rpi") Reported-by: kernel test robot Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_sli.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 62218e41933e..95caad764fb7 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -10700,7 +10700,6 @@ lpfc_sli4_abts_err_handler(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, struct sli4_wcqe_xri_aborted *axri) { - struct lpfc_vport *vport; uint32_t ext_status = 0; if (!ndlp) { @@ -10710,7 +10709,6 @@ lpfc_sli4_abts_err_handler(struct lpfc_hba *phba, return; } - vport = ndlp->vport; lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, "3116 Port generated FCP XRI ABORT event on " "vpi %d rpi %d xri x%x status 0x%x parameter x%x\n", -- cgit v1.2.3 From 66df79ccbc2f617a2bbaa7108a2b50a6869de5d4 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 20 Nov 2020 20:48:10 -0800 Subject: scsi: ufs: Adjust logic in common ADAPT helper The introduction of ufshcd_dme_configure_adapt() refactored out duplication from the Mediatek and Qualcomm drivers. Both these implementations had the logic of: gear_tx == UFS_HS_G4 => PA_INITIAL_ADAPT gear_tx != UFS_HS_G4 => PA_NO_ADAPT but now both implementations pass PA_INITIAL_ADAPT as "adapt_val" and if gear_tx is not UFS_HS_G4 that is replaced with PA_INITIAL_ADAPT. In other words, it's PA_INITIAL_ADAPT in both above cases. The result is that e.g. Qualcomm SM8150 has no longer functional UFS, so adjust the logic to match the previous implementation. Link: https://lore.kernel.org/r/20201121044810.507288-1-bjorn.andersson@linaro.org Fixes: fc85a74e28fe ("scsi: ufs: Refactor ADAPT configuration function") Reviewed-by: Can Guo Reviewed-by: Stanley Chu Signed-off-by: Bjorn Andersson Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 0e5473d4699b..92d433d5f3ca 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -3602,7 +3602,7 @@ int ufshcd_dme_configure_adapt(struct ufs_hba *hba, int ret; if (agreed_gear != UFS_HS_G4) - adapt_val = PA_INITIAL_ADAPT; + adapt_val = PA_NO_ADAPT; ret = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_TXHSADAPTTYPE), -- cgit v1.2.3 From 03fe6a640a05c5dc04b6bcdddfb981d015e84ed4 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Fri, 20 Nov 2020 15:39:56 +1100 Subject: scsi: atari_scsi: Fix race condition between .queuecommand and EH It is possible that bus_reset_cleanup() or .eh_abort_handler could be invoked during NCR5380_queuecommand(). If that takes place before the new command is enqueued and after the ST-DMA "lock" has been acquired, the ST-DMA "lock" will be released again. This will result in a lost DMA interrupt and a command timeout. Fix this by excluding EH and interrupt handlers while the new command is enqueued. Link: https://lore.kernel.org/r/af25163257796b50bb99d4ede4025cea55787b8f.1605847196.git.fthain@telegraphics.com.au Tested-by: Michael Schmitz Reviewed-by: Michael Schmitz Signed-off-by: Finn Thain Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 9 ++++++--- drivers/scsi/atari_scsi.c | 10 +++------- 2 files changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index d654a6cc4162..ea4b5749e7da 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -580,11 +580,14 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, cmd->result = 0; - if (!NCR5380_acquire_dma_irq(instance)) - return SCSI_MLQUEUE_HOST_BUSY; - spin_lock_irqsave(&hostdata->lock, flags); + if (!NCR5380_acquire_dma_irq(instance)) { + spin_unlock_irqrestore(&hostdata->lock, flags); + + return SCSI_MLQUEUE_HOST_BUSY; + } + /* * Insert the cmd into the issue queue. Note that REQUEST SENSE * commands are added to the head of the queue since any command will diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index a82b63a66635..95d7a3586083 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -376,15 +376,11 @@ static int falcon_get_lock(struct Scsi_Host *instance) if (IS_A_TT()) return 1; - if (stdma_is_locked_by(scsi_falcon_intr) && - instance->hostt->can_queue > 1) + if (stdma_is_locked_by(scsi_falcon_intr)) return 1; - if (in_interrupt()) - return stdma_try_lock(scsi_falcon_intr, instance); - - stdma_lock(scsi_falcon_intr, instance); - return 1; + /* stdma_lock() may sleep which means it can't be used here */ + return stdma_try_lock(scsi_falcon_intr, instance); } #ifndef MODULE -- cgit v1.2.3 From bdd1cc0377d3ce96683d178f30714da478f6a955 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Fri, 20 Nov 2020 15:39:56 +1100 Subject: scsi: NCR5380: Reduce NCR5380_maybe_release_dma_irq() call sites Refactor to avoid needless calls to NCR5380_maybe_release_dma_irq(). This makes the machine code smaller and the source more readable. Link: https://lore.kernel.org/r/c1317ae8fdcb498460de5d7ea0bd62a42f5eeca8.1605847196.git.fthain@telegraphics.com.au Tested-by: Michael Schmitz Reviewed-by: Michael Schmitz Signed-off-by: Finn Thain Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index ea4b5749e7da..d597d7493a62 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -725,7 +725,6 @@ static void NCR5380_main(struct work_struct *work) if (!NCR5380_select(instance, cmd)) { dsprintk(NDEBUG_MAIN, instance, "main: select complete\n"); - maybe_release_dma_irq(instance); } else { dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, instance, "main: select failed, returning %p to queue\n", cmd); @@ -737,8 +736,10 @@ static void NCR5380_main(struct work_struct *work) NCR5380_information_transfer(instance); done = 0; } - if (!hostdata->connected) + if (!hostdata->connected) { NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); + maybe_release_dma_irq(instance); + } spin_unlock_irq(&hostdata->lock); if (!done) cond_resched(); @@ -1844,7 +1845,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) */ NCR5380_write(TARGET_COMMAND_REG, 0); - maybe_release_dma_irq(instance); return; case MESSAGE_REJECT: /* Accept message by clearing ACK */ @@ -1976,7 +1976,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun); cmd->result = DID_ERROR << 16; complete_cmd(instance, cmd); - maybe_release_dma_irq(instance); return; } msgout = NOP; @@ -2312,7 +2311,6 @@ out: } queue_work(hostdata->work_q, &hostdata->main_task); - maybe_release_dma_irq(instance); spin_unlock_irqrestore(&hostdata->lock, flags); return result; @@ -2368,7 +2366,6 @@ static void bus_reset_cleanup(struct Scsi_Host *instance) hostdata->dma_len = 0; queue_work(hostdata->work_q, &hostdata->main_task); - maybe_release_dma_irq(instance); } /** -- cgit v1.2.3 From 27a34943bd89c101d3fb4a895d51d41a3c35ccab Mon Sep 17 00:00:00 2001 From: Xu Wang Date: Fri, 20 Nov 2020 08:36:48 +0000 Subject: scsi: pm8001: Remove typecast for pointer returned by kcalloc() Stop typecasting the value returned by kcalloc(). Link: https://lore.kernel.org/r/20201120083648.9319-1-vulab@iscas.ac.cn Acked-by: Jack Wang Signed-off-by: Xu Wang Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index fb471ad3720a..fefa82378986 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -1187,7 +1187,7 @@ pm8001_init_ccb_tag(struct pm8001_hba_info *pm8001_ha, struct Scsi_Host *shost, goto err_out; /* Memory region for ccb_info*/ - pm8001_ha->ccb_info = (struct pm8001_ccb_info *) + pm8001_ha->ccb_info = kcalloc(ccb_count, sizeof(struct pm8001_ccb_info), GFP_KERNEL); if (!pm8001_ha->ccb_info) { PM8001_FAIL_DBG(pm8001_ha, pm8001_printk -- cgit v1.2.3 From 1b5d2793283dcb97b401b3b2c02b8a94eee29af1 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 20 Nov 2020 15:16:09 -0800 Subject: scsi: pm8001: Neaten debug logging macros and uses Every PM8001__DBG macro uses an internal call to pm8001_printk. Convert all uses of: PM8001__DBG(hba, pm8001_printk(fmt, ...)) to pm8001_dbg(hba, , fmt, ...) so the visual complexity of each macro is reduced. The repetitive macro definitions are converted to a single pm8001_dbg and the level is concatenated using PM8001_##level##_LOGGING for the specific level test. Done with coccinelle, checkpatch and a little typing of the new macro definition. Miscellanea: - Coalesce formats - Realign arguments - Add missing terminating newlines to formats - Remove trailing spaces from formats - Change defective loop with printk(KERN_INFO... to emit a 16 byte hex block to %p16h Link: https://lore.kernel.org/r/49f36a93af7752b613d03c89a87078243567fd9a.1605914030.git.joe@perches.com Reported-by: kernel test robot Acked-by: Jack Wang Signed-off-by: Joe Perches Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_ctl.c | 7 +- drivers/scsi/pm8001/pm8001_hwi.c | 1370 +++++++++++++------------------ drivers/scsi/pm8001/pm8001_init.c | 91 +-- drivers/scsi/pm8001/pm8001_sas.c | 132 ++- drivers/scsi/pm8001/pm8001_sas.h | 45 +- drivers/scsi/pm8001/pm80xx_hwi.c | 1596 ++++++++++++++++--------------------- 6 files changed, 1354 insertions(+), 1887 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index 3587f7c8a428..12035baf0997 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c @@ -841,10 +841,9 @@ static ssize_t pm8001_store_update_fw(struct device *cdev, pm8001_ha->dev); if (ret) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk( - "Failed to load firmware image file %s, error %d\n", - filename_ptr, ret)); + pm8001_dbg(pm8001_ha, FAIL, + "Failed to load firmware image file %s, error %d\n", + filename_ptr, ret); pm8001_ha->fw_status = FAIL_OPEN_BIOS_FILE; goto out; } diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 0a1e09b1cd58..08d6cc9b50db 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -400,9 +400,9 @@ int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue) } while ((regVal != shiftValue) && time_before(jiffies, start)); if (regVal != shiftValue) { - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("TIMEOUT:SPC_IBW_AXI_TRANSLATION_LOW" - " = 0x%x\n", regVal)); + pm8001_dbg(pm8001_ha, INIT, + "TIMEOUT:SPC_IBW_AXI_TRANSLATION_LOW = 0x%x\n", + regVal); return -1; } return 0; @@ -623,12 +623,10 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha) value = pm8001_cr32(pm8001_ha, 0, 0x44); offset = value & 0x03FFFFFF; - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("Scratchpad 0 Offset: %x\n", offset)); + pm8001_dbg(pm8001_ha, INIT, "Scratchpad 0 Offset: %x\n", offset); pcilogic = (value & 0xFC000000) >> 26; pcibar = get_pci_bar_index(pcilogic); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("Scratchpad 0 PCI BAR: %d\n", pcibar)); + pm8001_dbg(pm8001_ha, INIT, "Scratchpad 0 PCI BAR: %d\n", pcibar); pm8001_ha->main_cfg_tbl_addr = base_addr = pm8001_ha->io_mem[pcibar].memvirtaddr + offset; pm8001_ha->general_stat_tbl_addr = @@ -652,16 +650,15 @@ static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha) * as this is shared with BIOS data */ if (deviceid == 0x8081 || deviceid == 0x0042) { if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_SM_BASE)) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Shift Bar4 to 0x%x failed\n", - GSM_SM_BASE)); + pm8001_dbg(pm8001_ha, FAIL, + "Shift Bar4 to 0x%x failed\n", + GSM_SM_BASE); return -1; } } /* check the firmware status */ if (-1 == check_fw_ready(pm8001_ha)) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Firmware is not ready!\n")); + pm8001_dbg(pm8001_ha, FAIL, "Firmware is not ready!\n"); return -EBUSY; } @@ -686,8 +683,7 @@ static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha) } /* notify firmware update finished and check initialization status */ if (0 == mpi_init_check(pm8001_ha)) { - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("MPI initialize successful!\n")); + pm8001_dbg(pm8001_ha, INIT, "MPI initialize successful!\n"); } else return -EBUSY; /*This register is a 16-bit timer with a resolution of 1us. This is the @@ -709,9 +705,9 @@ static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha) pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid); if (deviceid == 0x8081 || deviceid == 0x0042) { if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_SM_BASE)) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Shift Bar4 to 0x%x failed\n", - GSM_SM_BASE)); + pm8001_dbg(pm8001_ha, FAIL, + "Shift Bar4 to 0x%x failed\n", + GSM_SM_BASE); return -1; } } @@ -729,8 +725,8 @@ static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha) } while ((value != 0) && (--max_wait_count)); if (!max_wait_count) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("TIMEOUT:IBDB value/=0x%x\n", value)); + pm8001_dbg(pm8001_ha, FAIL, "TIMEOUT:IBDB value/=0x%x\n", + value); return -1; } @@ -747,9 +743,8 @@ static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha) break; } while (--max_wait_count); if (!max_wait_count) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk(" TIME OUT MPI State = 0x%x\n", - gst_len_mpistate & GST_MPI_STATE_MASK)); + pm8001_dbg(pm8001_ha, FAIL, " TIME OUT MPI State = 0x%x\n", + gst_len_mpistate & GST_MPI_STATE_MASK); return -1; } return 0; @@ -763,25 +758,23 @@ static u32 soft_reset_ready_check(struct pm8001_hba_info *pm8001_ha) { u32 regVal, regVal1, regVal2; if (mpi_uninit_check(pm8001_ha) != 0) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("MPI state is not ready\n")); + pm8001_dbg(pm8001_ha, FAIL, "MPI state is not ready\n"); return -1; } /* read the scratch pad 2 register bit 2 */ regVal = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2) & SCRATCH_PAD2_FWRDY_RST; if (regVal == SCRATCH_PAD2_FWRDY_RST) { - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("Firmware is ready for reset .\n")); + pm8001_dbg(pm8001_ha, INIT, "Firmware is ready for reset.\n"); } else { unsigned long flags; /* Trigger NMI twice via RB6 */ spin_lock_irqsave(&pm8001_ha->lock, flags); if (-1 == pm8001_bar4_shift(pm8001_ha, RB6_ACCESS_REG)) { spin_unlock_irqrestore(&pm8001_ha->lock, flags); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Shift Bar4 to 0x%x failed\n", - RB6_ACCESS_REG)); + pm8001_dbg(pm8001_ha, FAIL, + "Shift Bar4 to 0x%x failed\n", + RB6_ACCESS_REG); return -1; } pm8001_cw32(pm8001_ha, 2, SPC_RB6_OFFSET, @@ -794,16 +787,14 @@ static u32 soft_reset_ready_check(struct pm8001_hba_info *pm8001_ha) if (regVal != SCRATCH_PAD2_FWRDY_RST) { regVal1 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); regVal2 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("TIMEOUT:MSGU_SCRATCH_PAD1" - "=0x%x, MSGU_SCRATCH_PAD2=0x%x\n", - regVal1, regVal2)); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("SCRATCH_PAD0 value = 0x%x\n", - pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0))); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("SCRATCH_PAD3 value = 0x%x\n", - pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3))); + pm8001_dbg(pm8001_ha, FAIL, "TIMEOUT:MSGU_SCRATCH_PAD1=0x%x, MSGU_SCRATCH_PAD2=0x%x\n", + regVal1, regVal2); + pm8001_dbg(pm8001_ha, FAIL, + "SCRATCH_PAD0 value = 0x%x\n", + pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0)); + pm8001_dbg(pm8001_ha, FAIL, + "SCRATCH_PAD3 value = 0x%x\n", + pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3)); spin_unlock_irqrestore(&pm8001_ha->lock, flags); return -1; } @@ -828,7 +819,7 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) /* step1: Check FW is ready for soft reset */ if (soft_reset_ready_check(pm8001_ha) != 0) { - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("FW is not ready\n")); + pm8001_dbg(pm8001_ha, FAIL, "FW is not ready\n"); return -1; } @@ -838,46 +829,43 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) spin_lock_irqsave(&pm8001_ha->lock, flags); if (-1 == pm8001_bar4_shift(pm8001_ha, MBIC_AAP1_ADDR_BASE)) { spin_unlock_irqrestore(&pm8001_ha->lock, flags); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Shift Bar4 to 0x%x failed\n", - MBIC_AAP1_ADDR_BASE)); + pm8001_dbg(pm8001_ha, FAIL, "Shift Bar4 to 0x%x failed\n", + MBIC_AAP1_ADDR_BASE); return -1; } regVal = pm8001_cr32(pm8001_ha, 2, MBIC_NMI_ENABLE_VPE0_IOP); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("MBIC - NMI Enable VPE0 (IOP)= 0x%x\n", regVal)); + pm8001_dbg(pm8001_ha, INIT, "MBIC - NMI Enable VPE0 (IOP)= 0x%x\n", + regVal); pm8001_cw32(pm8001_ha, 2, MBIC_NMI_ENABLE_VPE0_IOP, 0x0); /* map 0x70000 to BAR4(0x20), BAR2(win) */ if (-1 == pm8001_bar4_shift(pm8001_ha, MBIC_IOP_ADDR_BASE)) { spin_unlock_irqrestore(&pm8001_ha->lock, flags); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Shift Bar4 to 0x%x failed\n", - MBIC_IOP_ADDR_BASE)); + pm8001_dbg(pm8001_ha, FAIL, "Shift Bar4 to 0x%x failed\n", + MBIC_IOP_ADDR_BASE); return -1; } regVal = pm8001_cr32(pm8001_ha, 2, MBIC_NMI_ENABLE_VPE0_AAP1); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("MBIC - NMI Enable VPE0 (AAP1)= 0x%x\n", regVal)); + pm8001_dbg(pm8001_ha, INIT, "MBIC - NMI Enable VPE0 (AAP1)= 0x%x\n", + regVal); pm8001_cw32(pm8001_ha, 2, MBIC_NMI_ENABLE_VPE0_AAP1, 0x0); regVal = pm8001_cr32(pm8001_ha, 1, PCIE_EVENT_INTERRUPT_ENABLE); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("PCIE -Event Interrupt Enable = 0x%x\n", regVal)); + pm8001_dbg(pm8001_ha, INIT, "PCIE -Event Interrupt Enable = 0x%x\n", + regVal); pm8001_cw32(pm8001_ha, 1, PCIE_EVENT_INTERRUPT_ENABLE, 0x0); regVal = pm8001_cr32(pm8001_ha, 1, PCIE_EVENT_INTERRUPT); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("PCIE - Event Interrupt = 0x%x\n", regVal)); + pm8001_dbg(pm8001_ha, INIT, "PCIE - Event Interrupt = 0x%x\n", + regVal); pm8001_cw32(pm8001_ha, 1, PCIE_EVENT_INTERRUPT, regVal); regVal = pm8001_cr32(pm8001_ha, 1, PCIE_ERROR_INTERRUPT_ENABLE); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("PCIE -Error Interrupt Enable = 0x%x\n", regVal)); + pm8001_dbg(pm8001_ha, INIT, "PCIE -Error Interrupt Enable = 0x%x\n", + regVal); pm8001_cw32(pm8001_ha, 1, PCIE_ERROR_INTERRUPT_ENABLE, 0x0); regVal = pm8001_cr32(pm8001_ha, 1, PCIE_ERROR_INTERRUPT); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("PCIE - Error Interrupt = 0x%x\n", regVal)); + pm8001_dbg(pm8001_ha, INIT, "PCIE - Error Interrupt = 0x%x\n", regVal); pm8001_cw32(pm8001_ha, 1, PCIE_ERROR_INTERRUPT, regVal); /* read the scratch pad 1 register bit 2 */ @@ -893,15 +881,13 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) /* map 0x0700000 to BAR4(0x20), BAR2(win) */ if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_ADDR_BASE)) { spin_unlock_irqrestore(&pm8001_ha->lock, flags); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Shift Bar4 to 0x%x failed\n", - GSM_ADDR_BASE)); + pm8001_dbg(pm8001_ha, FAIL, "Shift Bar4 to 0x%x failed\n", + GSM_ADDR_BASE); return -1; } - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GSM 0x0(0x00007b88)-GSM Configuration and" - " Reset = 0x%x\n", - pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET))); + pm8001_dbg(pm8001_ha, INIT, + "GSM 0x0(0x00007b88)-GSM Configuration and Reset = 0x%x\n", + pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET)); /* step 3: host read GSM Configuration and Reset register */ regVal = pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET); @@ -916,59 +902,52 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) regVal &= ~(0x00003b00); /* host write GSM Configuration and Reset register */ pm8001_cw32(pm8001_ha, 2, GSM_CONFIG_RESET, regVal); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GSM 0x0 (0x00007b88 ==> 0x00004088) - GSM " - "Configuration and Reset is set to = 0x%x\n", - pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET))); + pm8001_dbg(pm8001_ha, INIT, + "GSM 0x0 (0x00007b88 ==> 0x00004088) - GSM Configuration and Reset is set to = 0x%x\n", + pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET)); /* step 4: */ /* disable GSM - Read Address Parity Check */ regVal1 = pm8001_cr32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GSM 0x700038 - Read Address Parity Check " - "Enable = 0x%x\n", regVal1)); + pm8001_dbg(pm8001_ha, INIT, + "GSM 0x700038 - Read Address Parity Check Enable = 0x%x\n", + regVal1); pm8001_cw32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK, 0x0); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GSM 0x700038 - Read Address Parity Check Enable" - "is set to = 0x%x\n", - pm8001_cr32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK))); + pm8001_dbg(pm8001_ha, INIT, + "GSM 0x700038 - Read Address Parity Check Enable is set to = 0x%x\n", + pm8001_cr32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK)); /* disable GSM - Write Address Parity Check */ regVal2 = pm8001_cr32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GSM 0x700040 - Write Address Parity Check" - " Enable = 0x%x\n", regVal2)); + pm8001_dbg(pm8001_ha, INIT, + "GSM 0x700040 - Write Address Parity Check Enable = 0x%x\n", + regVal2); pm8001_cw32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK, 0x0); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GSM 0x700040 - Write Address Parity Check " - "Enable is set to = 0x%x\n", - pm8001_cr32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK))); + pm8001_dbg(pm8001_ha, INIT, + "GSM 0x700040 - Write Address Parity Check Enable is set to = 0x%x\n", + pm8001_cr32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK)); /* disable GSM - Write Data Parity Check */ regVal3 = pm8001_cr32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GSM 0x300048 - Write Data Parity Check" - " Enable = 0x%x\n", regVal3)); + pm8001_dbg(pm8001_ha, INIT, "GSM 0x300048 - Write Data Parity Check Enable = 0x%x\n", + regVal3); pm8001_cw32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK, 0x0); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GSM 0x300048 - Write Data Parity Check Enable" - "is set to = 0x%x\n", - pm8001_cr32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK))); + pm8001_dbg(pm8001_ha, INIT, + "GSM 0x300048 - Write Data Parity Check Enable is set to = 0x%x\n", + pm8001_cr32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK)); /* step 5: delay 10 usec */ udelay(10); /* step 5-b: set GPIO-0 output control to tristate anyway */ if (-1 == pm8001_bar4_shift(pm8001_ha, GPIO_ADDR_BASE)) { spin_unlock_irqrestore(&pm8001_ha->lock, flags); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("Shift Bar4 to 0x%x failed\n", - GPIO_ADDR_BASE)); + pm8001_dbg(pm8001_ha, INIT, "Shift Bar4 to 0x%x failed\n", + GPIO_ADDR_BASE); return -1; } regVal = pm8001_cr32(pm8001_ha, 2, GPIO_GPIO_0_0UTPUT_CTL_OFFSET); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GPIO Output Control Register:" - " = 0x%x\n", regVal)); + pm8001_dbg(pm8001_ha, INIT, "GPIO Output Control Register: = 0x%x\n", + regVal); /* set GPIO-0 output control to tri-state */ regVal &= 0xFFFFFFFC; pm8001_cw32(pm8001_ha, 2, GPIO_GPIO_0_0UTPUT_CTL_OFFSET, regVal); @@ -977,23 +956,20 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) /* map 0x00000 to BAR4(0x20), BAR2(win) */ if (-1 == pm8001_bar4_shift(pm8001_ha, SPC_TOP_LEVEL_ADDR_BASE)) { spin_unlock_irqrestore(&pm8001_ha->lock, flags); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("SPC Shift Bar4 to 0x%x failed\n", - SPC_TOP_LEVEL_ADDR_BASE)); + pm8001_dbg(pm8001_ha, FAIL, "SPC Shift Bar4 to 0x%x failed\n", + SPC_TOP_LEVEL_ADDR_BASE); return -1; } regVal = pm8001_cr32(pm8001_ha, 2, SPC_REG_RESET); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("Top Register before resetting IOP/AAP1" - ":= 0x%x\n", regVal)); + pm8001_dbg(pm8001_ha, INIT, "Top Register before resetting IOP/AAP1:= 0x%x\n", + regVal); regVal &= ~(SPC_REG_RESET_PCS_IOP_SS | SPC_REG_RESET_PCS_AAP1_SS); pm8001_cw32(pm8001_ha, 2, SPC_REG_RESET, regVal); /* step 7: Reset the BDMA/OSSP */ regVal = pm8001_cr32(pm8001_ha, 2, SPC_REG_RESET); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("Top Register before resetting BDMA/OSSP" - ": = 0x%x\n", regVal)); + pm8001_dbg(pm8001_ha, INIT, "Top Register before resetting BDMA/OSSP: = 0x%x\n", + regVal); regVal &= ~(SPC_REG_RESET_BDMA_CORE | SPC_REG_RESET_OSSP); pm8001_cw32(pm8001_ha, 2, SPC_REG_RESET, regVal); @@ -1002,9 +978,9 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) /* step 9: bring the BDMA and OSSP out of reset */ regVal = pm8001_cr32(pm8001_ha, 2, SPC_REG_RESET); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("Top Register before bringing up BDMA/OSSP" - ":= 0x%x\n", regVal)); + pm8001_dbg(pm8001_ha, INIT, + "Top Register before bringing up BDMA/OSSP:= 0x%x\n", + regVal); regVal |= (SPC_REG_RESET_BDMA_CORE | SPC_REG_RESET_OSSP); pm8001_cw32(pm8001_ha, 2, SPC_REG_RESET, regVal); @@ -1015,14 +991,13 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) /* map 0x0700000 to BAR4(0x20), BAR2(win) */ if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_ADDR_BASE)) { spin_unlock_irqrestore(&pm8001_ha->lock, flags); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("SPC Shift Bar4 to 0x%x failed\n", - GSM_ADDR_BASE)); + pm8001_dbg(pm8001_ha, FAIL, "SPC Shift Bar4 to 0x%x failed\n", + GSM_ADDR_BASE); return -1; } - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GSM 0x0 (0x00007b88)-GSM Configuration and " - "Reset = 0x%x\n", pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET))); + pm8001_dbg(pm8001_ha, INIT, + "GSM 0x0 (0x00007b88)-GSM Configuration and Reset = 0x%x\n", + pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET)); regVal = pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET); /* Put those bits to high */ /* GSM XCBI offset = 0x70 0000 @@ -1034,44 +1009,37 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) */ regVal |= (GSM_CONFIG_RESET_VALUE); pm8001_cw32(pm8001_ha, 2, GSM_CONFIG_RESET, regVal); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GSM (0x00004088 ==> 0x00007b88) - GSM" - " Configuration and Reset is set to = 0x%x\n", - pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET))); + pm8001_dbg(pm8001_ha, INIT, "GSM (0x00004088 ==> 0x00007b88) - GSM Configuration and Reset is set to = 0x%x\n", + pm8001_cr32(pm8001_ha, 2, GSM_CONFIG_RESET)); /* step 12: Restore GSM - Read Address Parity Check */ regVal = pm8001_cr32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK); /* just for debugging */ - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GSM 0x700038 - Read Address Parity Check Enable" - " = 0x%x\n", regVal)); + pm8001_dbg(pm8001_ha, INIT, + "GSM 0x700038 - Read Address Parity Check Enable = 0x%x\n", + regVal); pm8001_cw32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK, regVal1); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GSM 0x700038 - Read Address Parity" - " Check Enable is set to = 0x%x\n", - pm8001_cr32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK))); + pm8001_dbg(pm8001_ha, INIT, "GSM 0x700038 - Read Address Parity Check Enable is set to = 0x%x\n", + pm8001_cr32(pm8001_ha, 2, GSM_READ_ADDR_PARITY_CHECK)); /* Restore GSM - Write Address Parity Check */ regVal = pm8001_cr32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK); pm8001_cw32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK, regVal2); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GSM 0x700040 - Write Address Parity Check" - " Enable is set to = 0x%x\n", - pm8001_cr32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK))); + pm8001_dbg(pm8001_ha, INIT, + "GSM 0x700040 - Write Address Parity Check Enable is set to = 0x%x\n", + pm8001_cr32(pm8001_ha, 2, GSM_WRITE_ADDR_PARITY_CHECK)); /* Restore GSM - Write Data Parity Check */ regVal = pm8001_cr32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK); pm8001_cw32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK, regVal3); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GSM 0x700048 - Write Data Parity Check Enable" - "is set to = 0x%x\n", - pm8001_cr32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK))); + pm8001_dbg(pm8001_ha, INIT, + "GSM 0x700048 - Write Data Parity Check Enableis set to = 0x%x\n", + pm8001_cr32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK)); /* step 13: bring the IOP and AAP1 out of reset */ /* map 0x00000 to BAR4(0x20), BAR2(win) */ if (-1 == pm8001_bar4_shift(pm8001_ha, SPC_TOP_LEVEL_ADDR_BASE)) { spin_unlock_irqrestore(&pm8001_ha->lock, flags); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Shift Bar4 to 0x%x failed\n", - SPC_TOP_LEVEL_ADDR_BASE)); + pm8001_dbg(pm8001_ha, FAIL, "Shift Bar4 to 0x%x failed\n", + SPC_TOP_LEVEL_ADDR_BASE); return -1; } regVal = pm8001_cr32(pm8001_ha, 2, SPC_REG_RESET); @@ -1094,22 +1062,20 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) if (!max_wait_count) { regVal = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("TIMEOUT : ToggleVal 0x%x," - "MSGU_SCRATCH_PAD1 = 0x%x\n", - toggleVal, regVal)); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("SCRATCH_PAD0 value = 0x%x\n", - pm8001_cr32(pm8001_ha, 0, - MSGU_SCRATCH_PAD_0))); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("SCRATCH_PAD2 value = 0x%x\n", - pm8001_cr32(pm8001_ha, 0, - MSGU_SCRATCH_PAD_2))); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("SCRATCH_PAD3 value = 0x%x\n", - pm8001_cr32(pm8001_ha, 0, - MSGU_SCRATCH_PAD_3))); + pm8001_dbg(pm8001_ha, FAIL, "TIMEOUT : ToggleVal 0x%x,MSGU_SCRATCH_PAD1 = 0x%x\n", + toggleVal, regVal); + pm8001_dbg(pm8001_ha, FAIL, + "SCRATCH_PAD0 value = 0x%x\n", + pm8001_cr32(pm8001_ha, 0, + MSGU_SCRATCH_PAD_0)); + pm8001_dbg(pm8001_ha, FAIL, + "SCRATCH_PAD2 value = 0x%x\n", + pm8001_cr32(pm8001_ha, 0, + MSGU_SCRATCH_PAD_2)); + pm8001_dbg(pm8001_ha, FAIL, + "SCRATCH_PAD3 value = 0x%x\n", + pm8001_cr32(pm8001_ha, 0, + MSGU_SCRATCH_PAD_3)); spin_unlock_irqrestore(&pm8001_ha->lock, flags); return -1; } @@ -1124,22 +1090,22 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) if (check_fw_ready(pm8001_ha) == -1) { regVal = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); /* return error if MPI Configuration Table not ready */ - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("FW not ready SCRATCH_PAD1" - " = 0x%x\n", regVal)); + pm8001_dbg(pm8001_ha, INIT, + "FW not ready SCRATCH_PAD1 = 0x%x\n", + regVal); regVal = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2); /* return error if MPI Configuration Table not ready */ - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("FW not ready SCRATCH_PAD2" - " = 0x%x\n", regVal)); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("SCRATCH_PAD0 value = 0x%x\n", - pm8001_cr32(pm8001_ha, 0, - MSGU_SCRATCH_PAD_0))); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("SCRATCH_PAD3 value = 0x%x\n", - pm8001_cr32(pm8001_ha, 0, - MSGU_SCRATCH_PAD_3))); + pm8001_dbg(pm8001_ha, INIT, + "FW not ready SCRATCH_PAD2 = 0x%x\n", + regVal); + pm8001_dbg(pm8001_ha, INIT, + "SCRATCH_PAD0 value = 0x%x\n", + pm8001_cr32(pm8001_ha, 0, + MSGU_SCRATCH_PAD_0)); + pm8001_dbg(pm8001_ha, INIT, + "SCRATCH_PAD3 value = 0x%x\n", + pm8001_cr32(pm8001_ha, 0, + MSGU_SCRATCH_PAD_3)); spin_unlock_irqrestore(&pm8001_ha->lock, flags); return -1; } @@ -1147,8 +1113,7 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) pm8001_bar4_shift(pm8001_ha, 0); spin_unlock_irqrestore(&pm8001_ha->lock, flags); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("SPC soft reset Complete\n")); + pm8001_dbg(pm8001_ha, INIT, "SPC soft reset Complete\n"); return 0; } @@ -1156,8 +1121,7 @@ static void pm8001_hw_chip_rst(struct pm8001_hba_info *pm8001_ha) { u32 i; u32 regVal; - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("chip reset start\n")); + pm8001_dbg(pm8001_ha, INIT, "chip reset start\n"); /* do SPC chip reset. */ regVal = pm8001_cr32(pm8001_ha, 1, SPC_REG_RESET); @@ -1181,8 +1145,7 @@ static void pm8001_hw_chip_rst(struct pm8001_hba_info *pm8001_ha) mdelay(1); } while ((--i) != 0); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("chip reset finished\n")); + pm8001_dbg(pm8001_ha, INIT, "chip reset finished\n"); } /** @@ -1365,8 +1328,7 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, rv = pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size, &pMessage); if (rv < 0) { - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("No free mpi buffer\n")); + pm8001_dbg(pm8001_ha, IO, "No free mpi buffer\n"); rv = -ENOMEM; goto done; } @@ -1387,10 +1349,10 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, /*Update the PI to the firmware*/ pm8001_cw32(pm8001_ha, circularQ->pi_pci_bar, circularQ->pi_offset, circularQ->producer_idx); - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n", - responseQueue, opCode, circularQ->producer_idx, - circularQ->consumer_index)); + pm8001_dbg(pm8001_ha, DEVIO, + "INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n", + responseQueue, opCode, circularQ->producer_idx, + circularQ->consumer_index); done: spin_unlock_irqrestore(&circularQ->iq_lock, flags); return rv; @@ -1407,17 +1369,17 @@ u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg, pOutBoundMsgHeader = (struct mpi_msg_hdr *)(circularQ->base_virt + circularQ->consumer_idx * pm8001_ha->iomb_size); if (pOutBoundMsgHeader != msgHeader) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("consumer_idx = %d msgHeader = %p\n", - circularQ->consumer_idx, msgHeader)); + pm8001_dbg(pm8001_ha, FAIL, + "consumer_idx = %d msgHeader = %p\n", + circularQ->consumer_idx, msgHeader); /* Update the producer index from SPC */ producer_index = pm8001_read_32(circularQ->pi_virt); circularQ->producer_index = cpu_to_le32(producer_index); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("consumer_idx = %d producer_index = %d" - "msgHeader = %p\n", circularQ->consumer_idx, - circularQ->producer_index, msgHeader)); + pm8001_dbg(pm8001_ha, FAIL, + "consumer_idx = %d producer_index = %dmsgHeader = %p\n", + circularQ->consumer_idx, + circularQ->producer_index, msgHeader); return 0; } /* free the circular queue buffer elements associated with the message*/ @@ -1429,9 +1391,8 @@ u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg, /* Update the producer index from SPC*/ producer_index = pm8001_read_32(circularQ->pi_virt); circularQ->producer_index = cpu_to_le32(producer_index); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk(" CI=%d PI=%d\n", circularQ->consumer_idx, - circularQ->producer_index)); + pm8001_dbg(pm8001_ha, IO, " CI=%d PI=%d\n", + circularQ->consumer_idx, circularQ->producer_index); return 0; } @@ -1461,10 +1422,10 @@ u32 pm8001_mpi_msg_consume(struct pm8001_hba_info *pm8001_ha, /* read header */ header_tmp = pm8001_read_32(msgHeader); msgHeader_tmp = cpu_to_le32(header_tmp); - PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( - "outbound opcode msgheader:%x ci=%d pi=%d\n", - msgHeader_tmp, circularQ->consumer_idx, - circularQ->producer_index)); + pm8001_dbg(pm8001_ha, DEVIO, + "outbound opcode msgheader:%x ci=%d pi=%d\n", + msgHeader_tmp, circularQ->consumer_idx, + circularQ->producer_index); if (0 != (le32_to_cpu(msgHeader_tmp) & 0x80000000)) { if (OPC_OUB_SKIP_ENTRY != (le32_to_cpu(msgHeader_tmp) & 0xfff)) { @@ -1473,12 +1434,11 @@ u32 pm8001_mpi_msg_consume(struct pm8001_hba_info *pm8001_ha, sizeof(struct mpi_msg_hdr); *pBC = (u8)((le32_to_cpu(msgHeader_tmp) >> 24) & 0x1f); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk(": CI=%d PI=%d " - "msgHeader=%x\n", - circularQ->consumer_idx, - circularQ->producer_index, - msgHeader_tmp)); + pm8001_dbg(pm8001_ha, IO, + ": CI=%d PI=%d msgHeader=%x\n", + circularQ->consumer_idx, + circularQ->producer_index, + msgHeader_tmp); return MPI_IO_STATUS_SUCCESS; } else { circularQ->consumer_idx = @@ -1594,10 +1554,8 @@ void pm8001_work_fn(struct work_struct *work) t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags1); - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("task 0x%p" - " done with event 0x%x resp 0x%x stat 0x%x but" - " aborted by upper layer!\n", - t, pw->handler, ts->resp, ts->stat)); + pm8001_dbg(pm8001_ha, FAIL, "task 0x%p done with event 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", + t, pw->handler, ts->resp, ts->stat); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); spin_unlock_irqrestore(&pm8001_ha->lock, flags); } else { @@ -1617,26 +1575,16 @@ void pm8001_work_fn(struct work_struct *work) unsigned long flags, flags1; int i, ret = 0; - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n"); ret = pm8001_query_task(t); - PM8001_IO_DBG(pm8001_ha, - switch (ret) { - case TMF_RESP_FUNC_SUCC: - pm8001_printk("...Task on lu\n"); - break; - - case TMF_RESP_FUNC_COMPLETE: - pm8001_printk("...Task NOT on lu\n"); - break; - - default: - PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( - "...query task failed!!!\n")); - break; - }); + if (ret == TMF_RESP_FUNC_SUCC) + pm8001_dbg(pm8001_ha, IO, "...Task on lu\n"); + else if (ret == TMF_RESP_FUNC_COMPLETE) + pm8001_dbg(pm8001_ha, IO, "...Task NOT on lu\n"); + else + pm8001_dbg(pm8001_ha, DEVIO, "...query task failed!!!\n"); spin_lock_irqsave(&pm8001_ha->lock, flags); @@ -1681,8 +1629,7 @@ void pm8001_work_fn(struct work_struct *work) break; default: /* device misbehavior */ ret = TMF_RESP_FUNC_FAILED; - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("...Reset phy\n")); + pm8001_dbg(pm8001_ha, IO, "...Reset phy\n"); pm8001_I_T_nexus_reset(dev); break; } @@ -1696,15 +1643,14 @@ void pm8001_work_fn(struct work_struct *work) default: /* device misbehavior */ spin_unlock_irqrestore(&pm8001_ha->lock, flags); ret = TMF_RESP_FUNC_FAILED; - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("...Reset phy\n")); + pm8001_dbg(pm8001_ha, IO, "...Reset phy\n"); pm8001_I_T_nexus_reset(dev); } if (ret == TMF_RESP_FUNC_FAILED) t = NULL; pm8001_open_reject_retry(pm8001_ha, t, pm8001_dev); - PM8001_IO_DBG(pm8001_ha, pm8001_printk("...Complete\n")); + pm8001_dbg(pm8001_ha, IO, "...Complete\n"); } break; case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: dev = pm8001_dev->sas_device; @@ -1758,15 +1704,14 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha, int ret; if (!pm8001_ha_dev) { - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("dev is null\n")); + pm8001_dbg(pm8001_ha, FAIL, "dev is null\n"); return; } task = sas_alloc_slow_task(GFP_ATOMIC); if (!task) { - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot " - "allocate task\n")); + pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task\n"); return; } @@ -1811,8 +1756,7 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha, task = sas_alloc_slow_task(GFP_ATOMIC); if (!task) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("cannot allocate task !!!\n")); + pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task !!!\n"); return; } task->task_done = pm8001_task_done; @@ -1820,8 +1764,7 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha, res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); if (res) { sas_free_task(task); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("cannot allocate tag !!!\n")); + pm8001_dbg(pm8001_ha, FAIL, "cannot allocate tag !!!\n"); return; } @@ -1832,8 +1775,8 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha, if (!dev) { sas_free_task(task); pm8001_tag_free(pm8001_ha, ccb_tag); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Domain device cannot be allocated\n")); + pm8001_dbg(pm8001_ha, FAIL, + "Domain device cannot be allocated\n"); return; } task->dev = dev; @@ -1910,27 +1853,25 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) t = ccb->task; if (status && status != IO_UNDERFLOW) - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("sas IO status 0x%x\n", status)); + pm8001_dbg(pm8001_ha, FAIL, "sas IO status 0x%x\n", status); if (unlikely(!t || !t->lldd_task || !t->dev)) return; ts = &t->task_status; /* Print sas address of IO failed device */ if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && (status != IO_UNDERFLOW)) - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("SAS Address of IO Failure Drive:" - "%016llx", SAS_ADDR(t->dev->sas_addr))); + pm8001_dbg(pm8001_ha, FAIL, "SAS Address of IO Failure Drive:%016llx\n", + SAS_ADDR(t->dev->sas_addr)); if (status) - PM8001_IOERR_DBG(pm8001_ha, pm8001_printk( - "status:0x%x, tag:0x%x, task:0x%p\n", - status, tag, t)); + pm8001_dbg(pm8001_ha, IOERR, + "status:0x%x, tag:0x%x, task:0x%p\n", + status, tag, t); switch (status) { case IO_SUCCESS: - PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS" - ",param = %d\n", param)); + pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS,param = %d\n", + param); if (param == 0) { ts->resp = SAS_TASK_COMPLETE; ts->stat = SAM_STAT_GOOD; @@ -1945,15 +1886,14 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_ABORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_ABORTED IOMB Tag\n")); + pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB Tag\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; break; case IO_UNDERFLOW: /* SSP Completion with error */ - PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW" - ",param = %d\n", param)); + pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW,param = %d\n", + param); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_UNDERRUN; ts->residual = param; @@ -1961,50 +1901,45 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_NO_DEVICE: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_NO_DEVICE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n"); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_PHY_DOWN; break; case IO_XFER_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; /* Force the midlayer to retry */ ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_XFER_ERROR_PHY_NOT_READY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_EPROTO; break; case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; break; case IO_OPEN_CNX_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; @@ -2014,68 +1949,59 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); break; case IO_OPEN_CNX_ERROR_BAD_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_BAD_DEST; break; case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_CONNECTION_RATE_" - "NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_CONN_RATE; break; case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_WRONG_DEST; break; case IO_XFER_ERROR_NAK_RECEIVED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_XFER_ERROR_ACK_NAK_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; break; case IO_XFER_ERROR_DMA: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_DMA\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_DMA\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; break; case IO_XFER_OPEN_RETRY_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_XFER_ERROR_OFFSET_MISMATCH: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; break; case IO_PORT_IN_RESET: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_PORT_IN_RESET\n")); + pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; break; case IO_DS_NON_OPERATIONAL: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_DS_NON_OPERATIONAL\n")); + pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; if (!t->uldd_task) @@ -2084,51 +2010,44 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) IO_DS_NON_OPERATIONAL); break; case IO_DS_IN_RECOVERY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_DS_IN_RECOVERY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; break; case IO_TM_TAG_NOT_FOUND: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_TM_TAG_NOT_FOUND\n")); + pm8001_dbg(pm8001_ha, IO, "IO_TM_TAG_NOT_FOUND\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; break; case IO_SSP_EXT_IU_ZERO_LEN_ERROR: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_SSP_EXT_IU_ZERO_LEN_ERROR\n")); + pm8001_dbg(pm8001_ha, IO, "IO_SSP_EXT_IU_ZERO_LEN_ERROR\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; break; case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("Unknown status 0x%x\n", status)); + pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status); /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; break; } - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("scsi_status = %x\n ", - psspPayload->ssp_resp_iu.status)); + pm8001_dbg(pm8001_ha, IO, "scsi_status = %x\n", + psspPayload->ssp_resp_iu.status); spin_lock_irqsave(&t->task_state_lock, flags); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("task 0x%p done with" - " io_status 0x%x resp 0x%x " - "stat 0x%x but aborted by upper layer!\n", - t, status, ts->resp, ts->stat)); + pm8001_dbg(pm8001_ha, FAIL, "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", + t, status, ts->resp, ts->stat); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); } else { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -2157,17 +2076,15 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) t = ccb->task; pm8001_dev = ccb->device; if (event) - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("sas IO status 0x%x\n", event)); + pm8001_dbg(pm8001_ha, FAIL, "sas IO status 0x%x\n", event); if (unlikely(!t || !t->lldd_task || !t->dev)) return; ts = &t->task_status; - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("port_id = %x,device_id = %x\n", - port_id, dev_id)); + pm8001_dbg(pm8001_ha, DEVIO, "port_id = %x,device_id = %x\n", + port_id, dev_id); switch (event) { case IO_OVERFLOW: - PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n");) + pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; ts->residual = 0; @@ -2175,42 +2092,36 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); pm8001_handle_event(pm8001_ha, t, IO_XFER_ERROR_BREAK); return; case IO_XFER_ERROR_PHY_NOT_READY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT" - "_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_EPROTO; break; case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; break; case IO_OPEN_CNX_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; @@ -2220,88 +2131,78 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); break; case IO_OPEN_CNX_ERROR_BAD_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_BAD_DEST; break; case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_CONNECTION_RATE_" - "NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_CONN_RATE; break; case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_WRONG_DEST; break; case IO_XFER_ERROR_NAK_RECEIVED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_XFER_ERROR_ACK_NAK_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; break; case IO_XFER_OPEN_RETRY_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n"); pm8001_handle_event(pm8001_ha, t, IO_XFER_OPEN_RETRY_TIMEOUT); return; case IO_XFER_ERROR_UNEXPECTED_PHASE: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_UNEXPECTED_PHASE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_UNEXPECTED_PHASE\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; break; case IO_XFER_ERROR_XFER_RDY_OVERRUN: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_XFER_RDY_OVERRUN\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_XFER_RDY_OVERRUN\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; break; case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; break; case IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; break; case IO_XFER_ERROR_OFFSET_MISMATCH: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; break; case IO_XFER_ERROR_XFER_ZERO_DATA_LEN: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; break; case IO_XFER_CMD_FRAME_ISSUED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk(" IO_XFER_CMD_FRAME_ISSUED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_CMD_FRAME_ISSUED\n"); return; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("Unknown status 0x%x\n", event)); + pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", event); /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; @@ -2313,10 +2214,8 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("task 0x%p done with" - " event 0x%x resp 0x%x " - "stat 0x%x but aborted by upper layer!\n", - t, event, ts->resp, ts->stat)); + pm8001_dbg(pm8001_ha, FAIL, "task 0x%p done with event 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", + t, event, ts->resp, ts->stat); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); } else { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -2352,8 +2251,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) tag = le32_to_cpu(psataPayload->tag); if (!tag) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("tag null\n")); + pm8001_dbg(pm8001_ha, FAIL, "tag null\n"); return; } ccb = &pm8001_ha->ccb_info[tag]; @@ -2362,8 +2260,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) t = ccb->task; pm8001_dev = ccb->device; } else { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("ccb null\n")); + pm8001_dbg(pm8001_ha, FAIL, "ccb null\n"); return; } @@ -2371,29 +2268,26 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) if (t->dev && (t->dev->lldd_dev)) pm8001_dev = t->dev->lldd_dev; } else { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("task null\n")); + pm8001_dbg(pm8001_ha, FAIL, "task null\n"); return; } if ((pm8001_dev && !(pm8001_dev->id & NCQ_READ_LOG_FLAG)) && unlikely(!t || !t->lldd_task || !t->dev)) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("task or dev null\n")); + pm8001_dbg(pm8001_ha, FAIL, "task or dev null\n"); return; } ts = &t->task_status; if (!ts) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("ts null\n")); + pm8001_dbg(pm8001_ha, FAIL, "ts null\n"); return; } if (status) - PM8001_IOERR_DBG(pm8001_ha, pm8001_printk( - "status:0x%x, tag:0x%x, task::0x%p\n", - status, tag, t)); + pm8001_dbg(pm8001_ha, IOERR, + "status:0x%x, tag:0x%x, task::0x%p\n", + status, tag, t); /* Print sas address of IO failed device */ if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && @@ -2425,19 +2319,19 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) & 0xff000000)) + pm8001_dev->attached_phy + 0x10); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("SAS Address of IO Failure Drive:" - "%08x%08x", temp_sata_addr_hi, - temp_sata_addr_low)); + pm8001_dbg(pm8001_ha, FAIL, + "SAS Address of IO Failure Drive:%08x%08x\n", + temp_sata_addr_hi, + temp_sata_addr_low); } else { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("SAS Address of IO Failure Drive:" - "%016llx", SAS_ADDR(t->dev->sas_addr))); + pm8001_dbg(pm8001_ha, FAIL, + "SAS Address of IO Failure Drive:%016llx\n", + SAS_ADDR(t->dev->sas_addr)); } } switch (status) { case IO_SUCCESS: - PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); + pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS\n"); if (param == 0) { ts->resp = SAS_TASK_COMPLETE; ts->stat = SAM_STAT_GOOD; @@ -2459,39 +2353,38 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_PROTO_RESPONSE; ts->residual = param; - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("SAS_PROTO_RESPONSE len = %d\n", - param)); + pm8001_dbg(pm8001_ha, IO, + "SAS_PROTO_RESPONSE len = %d\n", + param); sata_resp = &psataPayload->sata_resp[0]; resp = (struct ata_task_resp *)ts->buf; if (t->ata_task.dma_xfer == 0 && t->data_dir == DMA_FROM_DEVICE) { len = sizeof(struct pio_setup_fis); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("PIO read len = %d\n", len)); + pm8001_dbg(pm8001_ha, IO, + "PIO read len = %d\n", len); } else if (t->ata_task.use_ncq) { len = sizeof(struct set_dev_bits_fis); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("FPDMA len = %d\n", len)); + pm8001_dbg(pm8001_ha, IO, "FPDMA len = %d\n", + len); } else { len = sizeof(struct dev_to_host_fis); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("other len = %d\n", len)); + pm8001_dbg(pm8001_ha, IO, "other len = %d\n", + len); } if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) { resp->frame_len = len; memcpy(&resp->ending_fis[0], sata_resp, len); ts->buf_valid_size = sizeof(*resp); } else - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("response to large\n")); + pm8001_dbg(pm8001_ha, IO, + "response too large\n"); } if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_ABORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_ABORTED IOMB Tag\n")); + pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB Tag\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; if (pm8001_dev) @@ -2500,8 +2393,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) /* following cases are to do cases */ case IO_UNDERFLOW: /* SATA Completion with error */ - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_UNDERFLOW param = %d\n", param)); + pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW param = %d\n", param); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_UNDERRUN; ts->residual = param; @@ -2509,24 +2401,21 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_NO_DEVICE: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_NO_DEVICE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n"); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_PHY_DOWN; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_INTERRUPTED; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_PHY_NOT_READY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; @@ -2534,9 +2423,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT" - "_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_EPROTO; @@ -2544,8 +2431,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; @@ -2553,8 +2440,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; @@ -2562,8 +2448,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; if (!t->uldd_task) { @@ -2577,8 +2462,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case IO_OPEN_CNX_ERROR_BAD_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_BAD_DEST; @@ -2593,9 +2478,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_CONNECTION_RATE_" - "NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_CONN_RATE; @@ -2603,9 +2486,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_STP_RESOURCES" - "_BUSY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; if (!t->uldd_task) { @@ -2619,8 +2500,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_WRONG_DEST; @@ -2628,64 +2509,56 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_NAK_RECEIVED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_ACK_NAK_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_DMA: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_DMA\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_DMA\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_SATA_LINK_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_SATA_LINK_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_SATA_LINK_TIMEOUT\n"); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_DEV_NO_RESPONSE; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_REJECTED_NCQ_MODE: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_REJECTED_NCQ_MODE\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_UNDERRUN; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_OPEN_RETRY_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_PORT_IN_RESET: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_PORT_IN_RESET\n")); + pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_DS_NON_OPERATIONAL: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_DS_NON_OPERATIONAL\n")); + pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; if (!t->uldd_task) { @@ -2698,16 +2571,14 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case IO_DS_IN_RECOVERY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk(" IO_DS_IN_RECOVERY\n")); + pm8001_dbg(pm8001_ha, IO, " IO_DS_IN_RECOVERY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_DS_IN_ERROR: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_DS_IN_ERROR\n")); + pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_ERROR\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; if (!t->uldd_task) { @@ -2720,8 +2591,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; @@ -2729,8 +2600,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("Unknown status 0x%x\n", status)); + pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status); /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; @@ -2744,10 +2614,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("task 0x%p done with io_status 0x%x" - " resp 0x%x stat 0x%x but aborted by upper layer!\n", - t, status, ts->resp, ts->stat)); + pm8001_dbg(pm8001_ha, FAIL, + "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", + t, status, ts->resp, ts->stat); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); } else { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -2776,12 +2645,10 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) t = ccb->task; pm8001_dev = ccb->device; } else { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("No CCB !!!. returning\n")); + pm8001_dbg(pm8001_ha, FAIL, "No CCB !!!. returning\n"); } if (event) - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("SATA EVENT 0x%x\n", event)); + pm8001_dbg(pm8001_ha, FAIL, "SATA EVENT 0x%x\n", event); /* Check if this is NCQ error */ if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) { @@ -2797,17 +2664,16 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) t = ccb->task; pm8001_dev = ccb->device; if (event) - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("sata IO status 0x%x\n", event)); + pm8001_dbg(pm8001_ha, FAIL, "sata IO status 0x%x\n", event); if (unlikely(!t || !t->lldd_task || !t->dev)) return; ts = &t->task_status; - PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( - "port_id:0x%x, device_id:0x%x, tag:0x%x, event:0x%x\n", - port_id, dev_id, tag, event)); + pm8001_dbg(pm8001_ha, DEVIO, + "port_id:0x%x, device_id:0x%x, tag:0x%x, event:0x%x\n", + port_id, dev_id, tag, event); switch (event) { case IO_OVERFLOW: - PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n")); + pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; ts->residual = 0; @@ -2815,43 +2681,37 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_INTERRUPTED; break; case IO_XFER_ERROR_PHY_NOT_READY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT" - "_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_EPROTO; break; case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; break; case IO_OPEN_CNX_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; break; case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_DEV_NO_RESPONSE; if (!t->uldd_task) { @@ -2865,94 +2725,82 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) } break; case IO_OPEN_CNX_ERROR_BAD_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_BAD_DEST; break; case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_CONNECTION_RATE_" - "NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_CONN_RATE; break; case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_WRONG_DEST; break; case IO_XFER_ERROR_NAK_RECEIVED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; break; case IO_XFER_ERROR_PEER_ABORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_PEER_ABORTED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PEER_ABORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; break; case IO_XFER_ERROR_REJECTED_NCQ_MODE: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_REJECTED_NCQ_MODE\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_UNDERRUN; break; case IO_XFER_OPEN_RETRY_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; case IO_XFER_ERROR_UNEXPECTED_PHASE: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_UNEXPECTED_PHASE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_UNEXPECTED_PHASE\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; case IO_XFER_ERROR_XFER_RDY_OVERRUN: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_XFER_RDY_OVERRUN\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_XFER_RDY_OVERRUN\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; case IO_XFER_ERROR_OFFSET_MISMATCH: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; case IO_XFER_ERROR_XFER_ZERO_DATA_LEN: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; case IO_XFER_CMD_FRAME_ISSUED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_CMD_FRAME_ISSUED\n"); break; case IO_XFER_PIO_SETUP_ERROR: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_PIO_SETUP_ERROR\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_PIO_SETUP_ERROR\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("Unknown status 0x%x\n", event)); + pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", event); /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; @@ -2964,10 +2812,9 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("task 0x%p done with io_status 0x%x" - " resp 0x%x stat 0x%x but aborted by upper layer!\n", - t, event, ts->resp, ts->stat)); + pm8001_dbg(pm8001_ha, FAIL, + "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", + t, event, ts->resp, ts->stat); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); } else { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -2997,33 +2844,31 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts = &t->task_status; pm8001_dev = ccb->device; if (status) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("smp IO status 0x%x\n", status)); - PM8001_IOERR_DBG(pm8001_ha, - pm8001_printk("status:0x%x, tag:0x%x, task:0x%p\n", - status, tag, t)); + pm8001_dbg(pm8001_ha, FAIL, "smp IO status 0x%x\n", status); + pm8001_dbg(pm8001_ha, IOERR, + "status:0x%x, tag:0x%x, task:0x%p\n", + status, tag, t); } if (unlikely(!t || !t->lldd_task || !t->dev)) return; switch (status) { case IO_SUCCESS: - PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); + pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAM_STAT_GOOD; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_ABORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_ABORTED IOMB\n")); + pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_OVERFLOW: - PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n")); + pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; ts->residual = 0; @@ -3031,52 +2876,47 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_NO_DEVICE: - PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_PHY_DOWN; break; case IO_ERROR_HW_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_ERROR_HW_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_ERROR_HW_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAM_STAT_BUSY; break; case IO_XFER_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAM_STAT_BUSY; break; case IO_XFER_ERROR_PHY_NOT_READY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAM_STAT_BUSY; break; case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; break; case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; break; case IO_OPEN_CNX_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; break; case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; @@ -3085,76 +2925,67 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); break; case IO_OPEN_CNX_ERROR_BAD_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_BAD_DEST; break; case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_CONNECTION_RATE_" - "NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_CONN_RATE; break; case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_WRONG_DEST; break; case IO_XFER_ERROR_RX_FRAME: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_RX_FRAME\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_RX_FRAME\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; break; case IO_XFER_OPEN_RETRY_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_ERROR_INTERNAL_SMP_RESOURCE: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_ERROR_INTERNAL_SMP_RESOURCE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_ERROR_INTERNAL_SMP_RESOURCE\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_QUEUE_FULL; break; case IO_PORT_IN_RESET: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_PORT_IN_RESET\n")); + pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_DS_NON_OPERATIONAL: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_DS_NON_OPERATIONAL\n")); + pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; break; case IO_DS_IN_RECOVERY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_DS_IN_RECOVERY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("Unknown status 0x%x\n", status)); + pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; /* not allowed case. Therefore, return failed status */ @@ -3166,10 +2997,8 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("task 0x%p done with" - " io_status 0x%x resp 0x%x " - "stat 0x%x but aborted by upper layer!\n", - t, status, ts->resp, ts->stat)); + pm8001_dbg(pm8001_ha, FAIL, "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", + t, status, ts->resp, ts->stat); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); } else { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -3191,9 +3020,8 @@ void pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha, u32 device_id = le32_to_cpu(pPayload->device_id); u8 pds = le32_to_cpu(pPayload->pds_nds) & PDS_BITS; u8 nds = le32_to_cpu(pPayload->pds_nds) & NDS_BITS; - PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Set device id = 0x%x state " - "from 0x%x to 0x%x status = 0x%x!\n", - device_id, pds, nds, status)); + pm8001_dbg(pm8001_ha, MSG, "Set device id = 0x%x state from 0x%x to 0x%x status = 0x%x!\n", + device_id, pds, nds, status); complete(pm8001_dev->setds_completion); ccb->task = NULL; ccb->ccb_tag = 0xFFFFFFFF; @@ -3208,10 +3036,9 @@ void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[tag]; u32 dlen_status = le32_to_cpu(pPayload->dlen_status); complete(pm8001_ha->nvmd_completion); - PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Set nvm data complete!\n")); + pm8001_dbg(pm8001_ha, MSG, "Set nvm data complete!\n"); if ((dlen_status & NVMD_STAT) != 0) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Set nvm data error!\n")); + pm8001_dbg(pm8001_ha, FAIL, "Set nvm data error!\n"); return; } ccb->task = NULL; @@ -3233,26 +3060,22 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) void *virt_addr = pm8001_ha->memoryMap.region[NVMD].virt_ptr; fw_control_context = ccb->fw_control_context; - PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Get nvm data complete!\n")); + pm8001_dbg(pm8001_ha, MSG, "Get nvm data complete!\n"); if ((dlen_status & NVMD_STAT) != 0) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Get nvm data error!\n")); + pm8001_dbg(pm8001_ha, FAIL, "Get nvm data error!\n"); complete(pm8001_ha->nvmd_completion); return; } if (ir_tds_bn_dps_das_nvm & IPMode) { /* indirect mode - IR bit set */ - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("Get NVMD success, IR=1\n")); + pm8001_dbg(pm8001_ha, MSG, "Get NVMD success, IR=1\n"); if ((ir_tds_bn_dps_das_nvm & NVMD_TYPE) == TWI_DEVICE) { if (ir_tds_bn_dps_das_nvm == 0x80a80200) { memcpy(pm8001_ha->sas_addr, ((u8 *)virt_addr + 4), SAS_ADDR_SIZE); - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("Get SAS address" - " from VPD successfully!\n")); + pm8001_dbg(pm8001_ha, MSG, "Get SAS address from VPD successfully!\n"); } } else if (((ir_tds_bn_dps_das_nvm & NVMD_TYPE) == C_SEEPROM) || ((ir_tds_bn_dps_das_nvm & NVMD_TYPE) == VPD_FLASH) || @@ -3263,14 +3086,14 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) ; } else { /* Should not be happened*/ - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("(IR=1)Wrong Device type 0x%x\n", - ir_tds_bn_dps_das_nvm)); + pm8001_dbg(pm8001_ha, MSG, + "(IR=1)Wrong Device type 0x%x\n", + ir_tds_bn_dps_das_nvm); } } else /* direct mode */{ - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("Get NVMD success, IR=0, dataLen=%d\n", - (dlen_status & NVMD_LEN) >> 24)); + pm8001_dbg(pm8001_ha, MSG, + "Get NVMD success, IR=0, dataLen=%d\n", + (dlen_status & NVMD_LEN) >> 24); } /* Though fw_control_context is freed below, usrAddr still needs * to be updated as this holds the response to the request function @@ -3284,7 +3107,7 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) * fw_control_context->usrAddr */ complete(pm8001_ha->nvmd_completion); - PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Set nvm data complete!\n")); + pm8001_dbg(pm8001_ha, MSG, "Set nvm data complete!\n"); ccb->task = NULL; ccb->ccb_tag = 0xFFFFFFFF; pm8001_tag_free(pm8001_ha, tag); @@ -3300,13 +3123,13 @@ int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb) u32 phy_op = le32_to_cpu(pPayload->phyop_phyid) & OP_BITS; tag = le32_to_cpu(pPayload->tag); if (status != 0) { - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("%x phy execute %x phy op failed!\n", - phy_id, phy_op)); + pm8001_dbg(pm8001_ha, MSG, + "%x phy execute %x phy op failed!\n", + phy_id, phy_op); } else { - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("%x phy execute %x phy op success!\n", - phy_id, phy_op)); + pm8001_dbg(pm8001_ha, MSG, + "%x phy execute %x phy op success!\n", + phy_id, phy_op); pm8001_ha->phy[phy_id].reset_success = true; } if (pm8001_ha->phy[phy_id].enable_completion) { @@ -3353,7 +3176,7 @@ void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i) } else if (phy->phy_type & PORT_TYPE_SATA) { /*Nothing*/ } - PM8001_MSG_DBG(pm8001_ha, pm8001_printk("phy %d byte dmaded.\n", i)); + pm8001_dbg(pm8001_ha, MSG, "phy %d byte dmaded.\n", i); sas_phy->frame_rcvd_size = phy->frame_rcvd_size; pm8001_ha->sas->notify_port_event(sas_phy, PORTE_BYTES_DMAED); @@ -3476,37 +3299,34 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) u8 deviceType = pPayload->sas_identify.dev_type; port->port_state = portstate; phy->phy_state = PHY_STATE_LINK_UP_SPC; - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_SAS_PHY_UP port id = %d, phy id = %d\n", - port_id, phy_id)); + pm8001_dbg(pm8001_ha, MSG, + "HW_EVENT_SAS_PHY_UP port id = %d, phy id = %d\n", + port_id, phy_id); switch (deviceType) { case SAS_PHY_UNUSED: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("device type no device.\n")); + pm8001_dbg(pm8001_ha, MSG, "device type no device.\n"); break; case SAS_END_DEVICE: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk("end device.\n")); + pm8001_dbg(pm8001_ha, MSG, "end device.\n"); pm8001_chip_phy_ctl_req(pm8001_ha, phy_id, PHY_NOTIFY_ENABLE_SPINUP); port->port_attached = 1; pm8001_get_lrate_mode(phy, link_rate); break; case SAS_EDGE_EXPANDER_DEVICE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("expander device.\n")); + pm8001_dbg(pm8001_ha, MSG, "expander device.\n"); port->port_attached = 1; pm8001_get_lrate_mode(phy, link_rate); break; case SAS_FANOUT_EXPANDER_DEVICE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("fanout expander device.\n")); + pm8001_dbg(pm8001_ha, MSG, "fanout expander device.\n"); port->port_attached = 1; pm8001_get_lrate_mode(phy, link_rate); break; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("unknown device type(%x)\n", deviceType)); + pm8001_dbg(pm8001_ha, DEVIO, "unknown device type(%x)\n", + deviceType); break; } phy->phy_type |= PORT_TYPE_SAS; @@ -3552,9 +3372,8 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) struct sas_ha_struct *sas_ha = pm8001_ha->sas; struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; unsigned long flags; - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_SATA_PHY_UP port id = %d," - " phy id = %d\n", port_id, phy_id)); + pm8001_dbg(pm8001_ha, DEVIO, "HW_EVENT_SATA_PHY_UP port id = %d, phy id = %d\n", + port_id, phy_id); port->port_state = portstate; phy->phy_state = PHY_STATE_LINK_UP_SPC; port->port_attached = 1; @@ -3602,37 +3421,35 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) case PORT_VALID: break; case PORT_INVALID: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" PortInvalid portID %d\n", port_id)); - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" Last phy Down and port invalid\n")); + pm8001_dbg(pm8001_ha, MSG, " PortInvalid portID %d\n", + port_id); + pm8001_dbg(pm8001_ha, MSG, + " Last phy Down and port invalid\n"); port->port_attached = 0; pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN, port_id, phy_id, 0, 0); break; case PORT_IN_RESET: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" Port In Reset portID %d\n", port_id)); + pm8001_dbg(pm8001_ha, MSG, " Port In Reset portID %d\n", + port_id); break; case PORT_NOT_ESTABLISHED: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" phy Down and PORT_NOT_ESTABLISHED\n")); + pm8001_dbg(pm8001_ha, MSG, + " phy Down and PORT_NOT_ESTABLISHED\n"); port->port_attached = 0; break; case PORT_LOSTCOMM: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" phy Down and PORT_LOSTCOMM\n")); - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" Last phy Down and port invalid\n")); + pm8001_dbg(pm8001_ha, MSG, " phy Down and PORT_LOSTCOMM\n"); + pm8001_dbg(pm8001_ha, MSG, + " Last phy Down and port invalid\n"); port->port_attached = 0; pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN, port_id, phy_id, 0, 0); break; default: port->port_attached = 0; - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk(" phy Down and(default) = %x\n", - portstate)); + pm8001_dbg(pm8001_ha, DEVIO, " phy Down and(default) = %x\n", + portstate); break; } @@ -3663,44 +3480,42 @@ int pm8001_mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_dev = ccb->device; status = le32_to_cpu(registerRespPayload->status); device_id = le32_to_cpu(registerRespPayload->device_id); - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" register device is status = %d\n", status)); + pm8001_dbg(pm8001_ha, MSG, " register device is status = %d\n", + status); switch (status) { case DEVREG_SUCCESS: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk("DEVREG_SUCCESS\n")); + pm8001_dbg(pm8001_ha, MSG, "DEVREG_SUCCESS\n"); pm8001_dev->device_id = device_id; break; case DEVREG_FAILURE_OUT_OF_RESOURCE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("DEVREG_FAILURE_OUT_OF_RESOURCE\n")); + pm8001_dbg(pm8001_ha, MSG, "DEVREG_FAILURE_OUT_OF_RESOURCE\n"); break; case DEVREG_FAILURE_DEVICE_ALREADY_REGISTERED: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("DEVREG_FAILURE_DEVICE_ALREADY_REGISTERED\n")); + pm8001_dbg(pm8001_ha, MSG, + "DEVREG_FAILURE_DEVICE_ALREADY_REGISTERED\n"); break; case DEVREG_FAILURE_INVALID_PHY_ID: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("DEVREG_FAILURE_INVALID_PHY_ID\n")); + pm8001_dbg(pm8001_ha, MSG, "DEVREG_FAILURE_INVALID_PHY_ID\n"); break; case DEVREG_FAILURE_PHY_ID_ALREADY_REGISTERED: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("DEVREG_FAILURE_PHY_ID_ALREADY_REGISTERED\n")); + pm8001_dbg(pm8001_ha, MSG, + "DEVREG_FAILURE_PHY_ID_ALREADY_REGISTERED\n"); break; case DEVREG_FAILURE_PORT_ID_OUT_OF_RANGE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("DEVREG_FAILURE_PORT_ID_OUT_OF_RANGE\n")); + pm8001_dbg(pm8001_ha, MSG, + "DEVREG_FAILURE_PORT_ID_OUT_OF_RANGE\n"); break; case DEVREG_FAILURE_PORT_NOT_VALID_STATE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("DEVREG_FAILURE_PORT_NOT_VALID_STATE\n")); + pm8001_dbg(pm8001_ha, MSG, + "DEVREG_FAILURE_PORT_NOT_VALID_STATE\n"); break; case DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID\n")); + pm8001_dbg(pm8001_ha, MSG, + "DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID\n"); break; default: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("DEVREG_FAILURE_DEVICE_TYPE_NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, MSG, + "DEVREG_FAILURE_DEVICE_TYPE_NOT_SUPPORTED\n"); break; } complete(pm8001_dev->dcompletion); @@ -3720,9 +3535,9 @@ int pm8001_mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) status = le32_to_cpu(registerRespPayload->status); device_id = le32_to_cpu(registerRespPayload->device_id); if (status != 0) - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" deregister device failed ,status = %x" - ", device_id = %x\n", status, device_id)); + pm8001_dbg(pm8001_ha, MSG, + " deregister device failed ,status = %x, device_id = %x\n", + status, device_id); return 0; } @@ -3742,44 +3557,37 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, status = le32_to_cpu(ppayload->status); switch (status) { case FLASH_UPDATE_COMPLETE_PENDING_REBOOT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(": FLASH_UPDATE_COMPLETE_PENDING_REBOOT\n")); + pm8001_dbg(pm8001_ha, MSG, + ": FLASH_UPDATE_COMPLETE_PENDING_REBOOT\n"); break; case FLASH_UPDATE_IN_PROGRESS: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(": FLASH_UPDATE_IN_PROGRESS\n")); + pm8001_dbg(pm8001_ha, MSG, ": FLASH_UPDATE_IN_PROGRESS\n"); break; case FLASH_UPDATE_HDR_ERR: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(": FLASH_UPDATE_HDR_ERR\n")); + pm8001_dbg(pm8001_ha, MSG, ": FLASH_UPDATE_HDR_ERR\n"); break; case FLASH_UPDATE_OFFSET_ERR: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(": FLASH_UPDATE_OFFSET_ERR\n")); + pm8001_dbg(pm8001_ha, MSG, ": FLASH_UPDATE_OFFSET_ERR\n"); break; case FLASH_UPDATE_CRC_ERR: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(": FLASH_UPDATE_CRC_ERR\n")); + pm8001_dbg(pm8001_ha, MSG, ": FLASH_UPDATE_CRC_ERR\n"); break; case FLASH_UPDATE_LENGTH_ERR: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(": FLASH_UPDATE_LENGTH_ERR\n")); + pm8001_dbg(pm8001_ha, MSG, ": FLASH_UPDATE_LENGTH_ERR\n"); break; case FLASH_UPDATE_HW_ERR: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(": FLASH_UPDATE_HW_ERR\n")); + pm8001_dbg(pm8001_ha, MSG, ": FLASH_UPDATE_HW_ERR\n"); break; case FLASH_UPDATE_DNLD_NOT_SUPPORTED: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(": FLASH_UPDATE_DNLD_NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, MSG, + ": FLASH_UPDATE_DNLD_NOT_SUPPORTED\n"); break; case FLASH_UPDATE_DISABLED: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(": FLASH_UPDATE_DISABLED\n")); + pm8001_dbg(pm8001_ha, MSG, ": FLASH_UPDATE_DISABLED\n"); break; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("No matched status = %d\n", status)); + pm8001_dbg(pm8001_ha, DEVIO, "No matched status = %d\n", + status); break; } kfree(ccb->fw_control_context); @@ -3797,12 +3605,11 @@ int pm8001_mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb) struct general_event_resp *pPayload = (struct general_event_resp *)(piomb + 4); status = le32_to_cpu(pPayload->status); - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" status = 0x%x\n", status)); + pm8001_dbg(pm8001_ha, MSG, " status = 0x%x\n", status); for (i = 0; i < GENERAL_EVENT_PAYLOAD; i++) - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("inb_IOMB_payload[0x%x] 0x%x,\n", i, - pPayload->inb_IOMB_payload[i])); + pm8001_dbg(pm8001_ha, MSG, "inb_IOMB_payload[0x%x] 0x%x,\n", + i, + pPayload->inb_IOMB_payload[i]); return 0; } @@ -3822,8 +3629,7 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) status = le32_to_cpu(pPayload->status); tag = le32_to_cpu(pPayload->tag); if (!tag) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk(" TAG NULL. RETURNING !!!")); + pm8001_dbg(pm8001_ha, FAIL, " TAG NULL. RETURNING !!!\n"); return -1; } @@ -3833,23 +3639,21 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_dev = ccb->device; /* retrieve device */ if (!t) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk(" TASK NULL. RETURNING !!!")); + pm8001_dbg(pm8001_ha, FAIL, " TASK NULL. RETURNING !!!\n"); return -1; } ts = &t->task_status; if (status != 0) - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("task abort failed status 0x%x ," - "tag = 0x%x, scp= 0x%x\n", status, tag, scp)); + pm8001_dbg(pm8001_ha, FAIL, "task abort failed status 0x%x ,tag = 0x%x, scp= 0x%x\n", + status, tag, scp); switch (status) { case IO_SUCCESS: - PM8001_EH_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); + pm8001_dbg(pm8001_ha, EH, "IO_SUCCESS\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAM_STAT_GOOD; break; case IO_NOT_VALID: - PM8001_EH_DBG(pm8001_ha, pm8001_printk("IO_NOT_VALID\n")); + pm8001_dbg(pm8001_ha, EH, "IO_NOT_VALID\n"); ts->resp = TMF_RESP_FUNC_FAILED; break; } @@ -3894,14 +3698,13 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) struct sas_ha_struct *sas_ha = pm8001_ha->sas; struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; - PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( - "SPC HW event for portid:%d, phyid:%d, event:%x, status:%x\n", - port_id, phy_id, eventType, status)); + pm8001_dbg(pm8001_ha, DEVIO, + "SPC HW event for portid:%d, phyid:%d, event:%x, status:%x\n", + port_id, phy_id, eventType, status); switch (eventType) { case HW_EVENT_PHY_START_STATUS: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PHY_START_STATUS" - " status = %x\n", status)); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_START_STATUS status = %x\n", + status); if (status == 0) { phy->phy_state = 1; if (pm8001_ha->flags == PM8001F_RUN_TIME && @@ -3910,38 +3713,32 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) } break; case HW_EVENT_SAS_PHY_UP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PHY_START_STATUS\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_START_STATUS\n"); hw_event_sas_phy_up(pm8001_ha, piomb); break; case HW_EVENT_SATA_PHY_UP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_SATA_PHY_UP\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_PHY_UP\n"); hw_event_sata_phy_up(pm8001_ha, piomb); break; case HW_EVENT_PHY_STOP_STATUS: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PHY_STOP_STATUS " - "status = %x\n", status)); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_STOP_STATUS status = %x\n", + status); if (status == 0) phy->phy_state = 0; break; case HW_EVENT_SATA_SPINUP_HOLD: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_SPINUP_HOLD\n"); sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD); break; case HW_EVENT_PHY_DOWN: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PHY_DOWN\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_DOWN\n"); sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL); phy->phy_attached = 0; phy->phy_state = 0; hw_event_phy_down(pm8001_ha, piomb); break; case HW_EVENT_PORT_INVALID: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PORT_INVALID\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_INVALID\n"); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); @@ -3949,8 +3746,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) /* the broadcast change primitive received, tell the LIBSAS this event to revalidate the sas domain*/ case HW_EVENT_BROADCAST_CHANGE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_BROADCAST_CHANGE\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_CHANGE\n"); pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_BROADCAST_CHANGE, port_id, phy_id, 1, 0); spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); @@ -3959,23 +3755,21 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); break; case HW_EVENT_PHY_ERROR: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PHY_ERROR\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_ERROR\n"); sas_phy_disconnected(&phy->sas_phy); phy->phy_attached = 0; sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR); break; case HW_EVENT_BROADCAST_EXP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_BROADCAST_EXP\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_EXP\n"); spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); sas_phy->sas_prim = HW_EVENT_BROADCAST_EXP; spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); break; case HW_EVENT_LINK_ERR_INVALID_DWORD: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_LINK_ERR_INVALID_DWORD\n")); + pm8001_dbg(pm8001_ha, MSG, + "HW_EVENT_LINK_ERR_INVALID_DWORD\n"); pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0); sas_phy_disconnected(sas_phy); @@ -3983,8 +3777,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_LINK_ERR_DISPARITY_ERROR: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_LINK_ERR_DISPARITY_ERROR\n")); + pm8001_dbg(pm8001_ha, MSG, + "HW_EVENT_LINK_ERR_DISPARITY_ERROR\n"); pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_DISPARITY_ERROR, port_id, phy_id, 0, 0); @@ -3993,8 +3787,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_LINK_ERR_CODE_VIOLATION: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_LINK_ERR_CODE_VIOLATION\n")); + pm8001_dbg(pm8001_ha, MSG, + "HW_EVENT_LINK_ERR_CODE_VIOLATION\n"); pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_CODE_VIOLATION, port_id, phy_id, 0, 0); @@ -4003,8 +3797,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH\n")); + pm8001_dbg(pm8001_ha, MSG, + "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH\n"); pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH, port_id, phy_id, 0, 0); @@ -4013,39 +3807,34 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_MALFUNCTION: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_MALFUNCTION\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_MALFUNCTION\n"); break; case HW_EVENT_BROADCAST_SES: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_BROADCAST_SES\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_SES\n"); spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); sas_phy->sas_prim = HW_EVENT_BROADCAST_SES; spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); break; case HW_EVENT_INBOUND_CRC_ERROR: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_INBOUND_CRC_ERROR\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_INBOUND_CRC_ERROR\n"); pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_INBOUND_CRC_ERROR, port_id, phy_id, 0, 0); break; case HW_EVENT_HARD_RESET_RECEIVED: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_HARD_RESET_RECEIVED\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_HARD_RESET_RECEIVED\n"); sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET); break; case HW_EVENT_ID_FRAME_TIMEOUT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_ID_FRAME_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_ID_FRAME_TIMEOUT\n"); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_LINK_ERR_PHY_RESET_FAILED: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n")); + pm8001_dbg(pm8001_ha, MSG, + "HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n"); pm8001_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_PHY_RESET_FAILED, port_id, phy_id, 0, 0); @@ -4054,34 +3843,30 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void* piomb) sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_PORT_RESET_TIMER_TMO: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PORT_RESET_TIMER_TMO\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_TIMER_TMO\n"); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_PORT_RECOVERY_TIMER_TMO: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PORT_RECOVERY_TIMER_TMO\n")); + pm8001_dbg(pm8001_ha, MSG, + "HW_EVENT_PORT_RECOVERY_TIMER_TMO\n"); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_PORT_RECOVER: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PORT_RECOVER\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RECOVER\n"); break; case HW_EVENT_PORT_RESET_COMPLETE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PORT_RESET_COMPLETE\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_COMPLETE\n"); break; case EVENT_BROADCAST_ASYNCH_EVENT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("EVENT_BROADCAST_ASYNCH_EVENT\n")); + pm8001_dbg(pm8001_ha, MSG, "EVENT_BROADCAST_ASYNCH_EVENT\n"); break; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("Unknown event type = %x\n", eventType)); + pm8001_dbg(pm8001_ha, DEVIO, "Unknown event type = %x\n", + eventType); break; } return 0; @@ -4097,163 +3882,132 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) __le32 pHeader = *(__le32 *)piomb; u8 opc = (u8)((le32_to_cpu(pHeader)) & 0xFFF); - PM8001_MSG_DBG(pm8001_ha, pm8001_printk("process_one_iomb:")); + pm8001_dbg(pm8001_ha, MSG, "process_one_iomb:\n"); switch (opc) { case OPC_OUB_ECHO: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk("OPC_OUB_ECHO\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_ECHO\n"); break; case OPC_OUB_HW_EVENT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_HW_EVENT\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_HW_EVENT\n"); mpi_hw_event(pm8001_ha, piomb); break; case OPC_OUB_SSP_COMP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SSP_COMP\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_COMP\n"); mpi_ssp_completion(pm8001_ha, piomb); break; case OPC_OUB_SMP_COMP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SMP_COMP\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SMP_COMP\n"); mpi_smp_completion(pm8001_ha, piomb); break; case OPC_OUB_LOCAL_PHY_CNTRL: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_LOCAL_PHY_CNTRL\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_LOCAL_PHY_CNTRL\n"); pm8001_mpi_local_phy_ctl(pm8001_ha, piomb); break; case OPC_OUB_DEV_REGIST: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_DEV_REGIST\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEV_REGIST\n"); pm8001_mpi_reg_resp(pm8001_ha, piomb); break; case OPC_OUB_DEREG_DEV: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("unregister the device\n")); + pm8001_dbg(pm8001_ha, MSG, "unregister the device\n"); pm8001_mpi_dereg_resp(pm8001_ha, piomb); break; case OPC_OUB_GET_DEV_HANDLE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_GET_DEV_HANDLE\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_DEV_HANDLE\n"); break; case OPC_OUB_SATA_COMP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SATA_COMP\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_COMP\n"); mpi_sata_completion(pm8001_ha, piomb); break; case OPC_OUB_SATA_EVENT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SATA_EVENT\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_EVENT\n"); mpi_sata_event(pm8001_ha, piomb); break; case OPC_OUB_SSP_EVENT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SSP_EVENT\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_EVENT\n"); mpi_ssp_event(pm8001_ha, piomb); break; case OPC_OUB_DEV_HANDLE_ARRIV: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_DEV_HANDLE_ARRIV\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEV_HANDLE_ARRIV\n"); /*This is for target*/ break; case OPC_OUB_SSP_RECV_EVENT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SSP_RECV_EVENT\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_RECV_EVENT\n"); /*This is for target*/ break; case OPC_OUB_DEV_INFO: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_DEV_INFO\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEV_INFO\n"); break; case OPC_OUB_FW_FLASH_UPDATE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_FW_FLASH_UPDATE\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_FW_FLASH_UPDATE\n"); pm8001_mpi_fw_flash_update_resp(pm8001_ha, piomb); break; case OPC_OUB_GPIO_RESPONSE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_GPIO_RESPONSE\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GPIO_RESPONSE\n"); break; case OPC_OUB_GPIO_EVENT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_GPIO_EVENT\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GPIO_EVENT\n"); break; case OPC_OUB_GENERAL_EVENT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_GENERAL_EVENT\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GENERAL_EVENT\n"); pm8001_mpi_general_event(pm8001_ha, piomb); break; case OPC_OUB_SSP_ABORT_RSP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SSP_ABORT_RSP\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_ABORT_RSP\n"); pm8001_mpi_task_abort_resp(pm8001_ha, piomb); break; case OPC_OUB_SATA_ABORT_RSP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SATA_ABORT_RSP\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_ABORT_RSP\n"); pm8001_mpi_task_abort_resp(pm8001_ha, piomb); break; case OPC_OUB_SAS_DIAG_MODE_START_END: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SAS_DIAG_MODE_START_END\n")); + pm8001_dbg(pm8001_ha, MSG, + "OPC_OUB_SAS_DIAG_MODE_START_END\n"); break; case OPC_OUB_SAS_DIAG_EXECUTE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SAS_DIAG_EXECUTE\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SAS_DIAG_EXECUTE\n"); break; case OPC_OUB_GET_TIME_STAMP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_GET_TIME_STAMP\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_TIME_STAMP\n"); break; case OPC_OUB_SAS_HW_EVENT_ACK: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SAS_HW_EVENT_ACK\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SAS_HW_EVENT_ACK\n"); break; case OPC_OUB_PORT_CONTROL: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_PORT_CONTROL\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_PORT_CONTROL\n"); break; case OPC_OUB_SMP_ABORT_RSP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SMP_ABORT_RSP\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SMP_ABORT_RSP\n"); pm8001_mpi_task_abort_resp(pm8001_ha, piomb); break; case OPC_OUB_GET_NVMD_DATA: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_GET_NVMD_DATA\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_NVMD_DATA\n"); pm8001_mpi_get_nvmd_resp(pm8001_ha, piomb); break; case OPC_OUB_SET_NVMD_DATA: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SET_NVMD_DATA\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_NVMD_DATA\n"); pm8001_mpi_set_nvmd_resp(pm8001_ha, piomb); break; case OPC_OUB_DEVICE_HANDLE_REMOVAL: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_DEVICE_HANDLE_REMOVAL\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEVICE_HANDLE_REMOVAL\n"); break; case OPC_OUB_SET_DEVICE_STATE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SET_DEVICE_STATE\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_DEVICE_STATE\n"); pm8001_mpi_set_dev_state_resp(pm8001_ha, piomb); break; case OPC_OUB_GET_DEVICE_STATE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_GET_DEVICE_STATE\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_DEVICE_STATE\n"); break; case OPC_OUB_SET_DEV_INFO: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SET_DEV_INFO\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_DEV_INFO\n"); break; case OPC_OUB_SAS_RE_INITIALIZE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SAS_RE_INITIALIZE\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SAS_RE_INITIALIZE\n"); break; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("Unknown outbound Queue IOMB OPC = %x\n", - opc)); + pm8001_dbg(pm8001_ha, DEVIO, + "Unknown outbound Queue IOMB OPC = %x\n", + opc); break; } } @@ -4466,19 +4220,19 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha, circularQ = &pm8001_ha->inbnd_q_tbl[0]; if (task->data_dir == DMA_NONE) { ATAP = 0x04; /* no data*/ - PM8001_IO_DBG(pm8001_ha, pm8001_printk("no data\n")); + pm8001_dbg(pm8001_ha, IO, "no data\n"); } else if (likely(!task->ata_task.device_control_reg_update)) { if (task->ata_task.dma_xfer) { ATAP = 0x06; /* DMA */ - PM8001_IO_DBG(pm8001_ha, pm8001_printk("DMA\n")); + pm8001_dbg(pm8001_ha, IO, "DMA\n"); } else { ATAP = 0x05; /* PIO*/ - PM8001_IO_DBG(pm8001_ha, pm8001_printk("PIO\n")); + pm8001_dbg(pm8001_ha, IO, "PIO\n"); } if (task->ata_task.use_ncq && dev->sata_dev.class != ATA_DEV_ATAPI) { ATAP = 0x07; /* FPDMA */ - PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n")); + pm8001_dbg(pm8001_ha, IO, "FPDMA\n"); } } if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) { @@ -4535,10 +4289,10 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha, SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&task->task_state_lock, flags); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("task 0x%p resp 0x%x " - " stat 0x%x but aborted by upper layer " - "\n", task, ts->resp, ts->stat)); + pm8001_dbg(pm8001_ha, FAIL, + "task 0x%p resp 0x%x stat 0x%x but aborted by upper layer\n", + task, ts->resp, + ts->stat); pm8001_ccb_task_free(pm8001_ha, task, ccb, tag); } else { spin_unlock_irqrestore(&task->task_state_lock, @@ -4687,8 +4441,8 @@ int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha, memset(&payload, 0, sizeof(payload)); payload.tag = cpu_to_le32(1); payload.device_id = cpu_to_le32(device_id); - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("unregister device device_id = %d\n", device_id)); + pm8001_dbg(pm8001_ha, MSG, "unregister device device_id = %d\n", + device_id); ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, sizeof(payload), 0); return ret; @@ -4740,9 +4494,9 @@ static irqreturn_t pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec) { pm8001_chip_interrupt_disable(pm8001_ha, vec); - PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( - "irq vec %d, ODMR:0x%x\n", - vec, pm8001_cr32(pm8001_ha, 0, 0x30))); + pm8001_dbg(pm8001_ha, DEVIO, + "irq vec %d, ODMR:0x%x\n", + vec, pm8001_cr32(pm8001_ha, 0, 0x30)); process_oq(pm8001_ha, vec); pm8001_chip_interrupt_enable(pm8001_ha, vec); return IRQ_HANDLED; @@ -4779,9 +4533,8 @@ int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha, { u32 opc, device_id; int rc = TMF_RESP_FUNC_FAILED; - PM8001_EH_DBG(pm8001_ha, - pm8001_printk("cmd_tag = %x, abort task tag = 0x%x", - cmd_tag, task_tag)); + pm8001_dbg(pm8001_ha, EH, "cmd_tag = %x, abort task tag = 0x%x\n", + cmd_tag, task_tag); if (pm8001_dev->dev_type == SAS_END_DEVICE) opc = OPC_INB_SSP_ABORT; else if (pm8001_dev->dev_type == SAS_SATA_DEV) @@ -4792,7 +4545,7 @@ int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha, rc = send_task_abort(pm8001_ha, opc, device_id, flag, task_tag, cmd_tag); if (rc != TMF_RESP_FUNC_COMPLETE) - PM8001_EH_DBG(pm8001_ha, pm8001_printk("rc= %d\n", rc)); + pm8001_dbg(pm8001_ha, EH, "rc= %d\n", rc); return rc; } @@ -5058,8 +4811,9 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, if (!fw_control_context) return -ENOMEM; fw_control = (struct fw_control_info *)&ioctl_payload->func_specific; - PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( - "dma fw_control context input length :%x\n", fw_control->len)); + pm8001_dbg(pm8001_ha, DEVIO, + "dma fw_control context input length :%x\n", + fw_control->len); memcpy(buffer, fw_control->buffer, fw_control->len); flash_update_info.sgl.addr = cpu_to_le64(phys_addr); flash_update_info.sgl.im_len.len = cpu_to_le32(fw_control->len); diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index fefa82378986..43ba55842602 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -271,15 +271,14 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, spin_lock_init(&pm8001_ha->lock); spin_lock_init(&pm8001_ha->bitmap_lock); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("pm8001_alloc: PHY:%x\n", - pm8001_ha->chip->n_phy)); + pm8001_dbg(pm8001_ha, INIT, "pm8001_alloc: PHY:%x\n", + pm8001_ha->chip->n_phy); /* Setup Interrupt */ rc = pm8001_setup_irq(pm8001_ha); if (rc) { - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( - "pm8001_setup_irq failed [ret: %d]\n", rc)); + pm8001_dbg(pm8001_ha, FAIL, + "pm8001_setup_irq failed [ret: %d]\n", rc); goto err_out_shost; } /* Request Interrupt */ @@ -394,9 +393,9 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, &pm8001_ha->memoryMap.region[i].phys_addr_lo, pm8001_ha->memoryMap.region[i].total_len, pm8001_ha->memoryMap.region[i].alignment) != 0) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Mem%d alloc failed\n", - i)); + pm8001_dbg(pm8001_ha, FAIL, + "Mem%d alloc failed\n", + i); goto err_out; } } @@ -467,15 +466,15 @@ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha) pm8001_ha->io_mem[logicalBar].memvirtaddr = ioremap(pm8001_ha->io_mem[logicalBar].membase, pm8001_ha->io_mem[logicalBar].memsize); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("PCI: bar %d, logicalBar %d ", - bar, logicalBar)); - PM8001_INIT_DBG(pm8001_ha, pm8001_printk( - "base addr %llx virt_addr=%llx len=%d\n", - (u64)pm8001_ha->io_mem[logicalBar].membase, - (u64)(unsigned long) - pm8001_ha->io_mem[logicalBar].memvirtaddr, - pm8001_ha->io_mem[logicalBar].memsize)); + pm8001_dbg(pm8001_ha, INIT, + "PCI: bar %d, logicalBar %d\n", + bar, logicalBar); + pm8001_dbg(pm8001_ha, INIT, + "base addr %llx virt_addr=%llx len=%d\n", + (u64)pm8001_ha->io_mem[logicalBar].membase, + (u64)(unsigned long) + pm8001_ha->io_mem[logicalBar].memvirtaddr, + pm8001_ha->io_mem[logicalBar].memsize); } else { pm8001_ha->io_mem[logicalBar].membase = 0; pm8001_ha->io_mem[logicalBar].memsize = 0; @@ -520,8 +519,8 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev, else { pm8001_ha->link_rate = LINKRATE_15 | LINKRATE_30 | LINKRATE_60 | LINKRATE_120; - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( - "Setting link rate to default value\n")); + pm8001_dbg(pm8001_ha, FAIL, + "Setting link rate to default value\n"); } sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id); /* IOMB size is 128 for 8088/89 controllers */ @@ -684,13 +683,13 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) payload.offset = 0; payload.func_specific = kzalloc(payload.rd_length, GFP_KERNEL); if (!payload.func_specific) { - PM8001_INIT_DBG(pm8001_ha, pm8001_printk("mem alloc fail\n")); + pm8001_dbg(pm8001_ha, INIT, "mem alloc fail\n"); return; } rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); if (rc) { kfree(payload.func_specific); - PM8001_INIT_DBG(pm8001_ha, pm8001_printk("nvmd failed\n")); + pm8001_dbg(pm8001_ha, INIT, "nvmd failed\n"); return; } wait_for_completion(&completion); @@ -718,9 +717,8 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) sas_add[7] = sas_add[7] + 4; memcpy(&pm8001_ha->phy[i].dev_sas_addr, sas_add, SAS_ADDR_SIZE); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("phy %d sas_addr = %016llx\n", i, - pm8001_ha->phy[i].dev_sas_addr)); + pm8001_dbg(pm8001_ha, INIT, "phy %d sas_addr = %016llx\n", i, + pm8001_ha->phy[i].dev_sas_addr); } kfree(payload.func_specific); #else @@ -760,7 +758,7 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha) rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); if (rc) { kfree(payload.func_specific); - PM8001_INIT_DBG(pm8001_ha, pm8001_printk("nvmd failed\n")); + pm8001_dbg(pm8001_ha, INIT, "nvmd failed\n"); return -ENOMEM; } wait_for_completion(&completion); @@ -854,9 +852,9 @@ void pm8001_get_phy_mask(struct pm8001_hba_info *pm8001_ha, int *phymask) break; default: - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("Unknown subsystem device=0x%.04x", - pm8001_ha->pdev->subsystem_device)); + pm8001_dbg(pm8001_ha, INIT, + "Unknown subsystem device=0x%.04x\n", + pm8001_ha->pdev->subsystem_device); } } @@ -950,9 +948,9 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) /* Maximum queue number updating in HBA structure */ pm8001_ha->max_q_num = number_of_intr; - PM8001_INIT_DBG(pm8001_ha, pm8001_printk( - "pci_alloc_irq_vectors request ret:%d no of intr %d\n", - rc, pm8001_ha->number_of_intr)); + pm8001_dbg(pm8001_ha, INIT, + "pci_alloc_irq_vectors request ret:%d no of intr %d\n", + rc, pm8001_ha->number_of_intr); return 0; } @@ -964,9 +962,9 @@ static u32 pm8001_request_msix(struct pm8001_hba_info *pm8001_ha) if (pm8001_ha->chip_id != chip_8001) flag &= ~IRQF_SHARED; - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("pci_enable_msix request number of intr %d\n", - pm8001_ha->number_of_intr)); + pm8001_dbg(pm8001_ha, INIT, + "pci_enable_msix request number of intr %d\n", + pm8001_ha->number_of_intr); for (i = 0; i < pm8001_ha->number_of_intr; i++) { snprintf(pm8001_ha->intr_drvname[i], @@ -1002,8 +1000,7 @@ static u32 pm8001_setup_irq(struct pm8001_hba_info *pm8001_ha) #ifdef PM8001_USE_MSIX if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) return pm8001_setup_msix(pm8001_ha); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("MSIX not supported!!!\n")); + pm8001_dbg(pm8001_ha, INIT, "MSIX not supported!!!\n"); #endif return 0; } @@ -1023,8 +1020,7 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha) if (pdev->msix_cap && pci_msi_enabled()) return pm8001_request_msix(pm8001_ha); else { - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("MSIX not supported!!!\n")); + pm8001_dbg(pm8001_ha, INIT, "MSIX not supported!!!\n"); goto intx; } #endif @@ -1108,8 +1104,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev, PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); rc = PM8001_CHIP_DISP->chip_init(pm8001_ha); if (rc) { - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( - "chip_init failed [ret: %d]\n", rc)); + pm8001_dbg(pm8001_ha, FAIL, + "chip_init failed [ret: %d]\n", rc); goto err_out_ha_free; } @@ -1137,8 +1133,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev, pm8001_post_sas_ha_init(shost, chip); rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); if (rc) { - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( - "sas_register_ha failed [ret: %d]\n", rc)); + pm8001_dbg(pm8001_ha, FAIL, + "sas_register_ha failed [ret: %d]\n", rc); goto err_out_shost; } list_add_tail(&pm8001_ha->list, &hba_list); @@ -1190,8 +1186,8 @@ pm8001_init_ccb_tag(struct pm8001_hba_info *pm8001_ha, struct Scsi_Host *shost, pm8001_ha->ccb_info = kcalloc(ccb_count, sizeof(struct pm8001_ccb_info), GFP_KERNEL); if (!pm8001_ha->ccb_info) { - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk - ("Unable to allocate memory for ccb\n")); + pm8001_dbg(pm8001_ha, FAIL, + "Unable to allocate memory for ccb\n"); goto err_out_noccb; } for (i = 0; i < ccb_count; i++) { @@ -1199,8 +1195,8 @@ pm8001_init_ccb_tag(struct pm8001_hba_info *pm8001_ha, struct Scsi_Host *shost, sizeof(struct pm8001_prd) * PM8001_MAX_DMA_SG, &pm8001_ha->ccb_info[i].ccb_dma_handle); if (!pm8001_ha->ccb_info[i].buf_prd) { - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk - ("pm80xx: ccb prd memory allocation error\n")); + pm8001_dbg(pm8001_ha, FAIL, + "pm80xx: ccb prd memory allocation error\n"); goto err_out; } pm8001_ha->ccb_info[i].task = NULL; @@ -1344,8 +1340,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev) /* chip soft rst only for spc */ if (pm8001_ha->chip_id == chip_8001) { PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("chip soft reset successful\n")); + pm8001_dbg(pm8001_ha, INIT, "chip soft reset successful\n"); } rc = PM8001_CHIP_DISP->chip_init(pm8001_ha); if (rc) diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index e91497847620..505a885b4c77 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -250,8 +250,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, spin_unlock_irqrestore(&pm8001_ha->lock, flags); return 0; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("func 0x%x\n", func)); + pm8001_dbg(pm8001_ha, DEVIO, "func 0x%x\n", func); rc = -EOPNOTSUPP; } msleep(300); @@ -405,7 +404,7 @@ static int pm8001_task_exec(struct sas_task *task, t->task_done(t); return 0; } - PM8001_IO_DBG(pm8001_ha, pm8001_printk("pm8001_task_exec device \n ")); + pm8001_dbg(pm8001_ha, IO, "pm8001_task_exec device\n"); spin_lock_irqsave(&pm8001_ha->lock, flags); do { dev = t->dev; @@ -480,8 +479,7 @@ static int pm8001_task_exec(struct sas_task *task, } if (rc) { - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("rc is %x\n", rc)); + pm8001_dbg(pm8001_ha, IO, "rc is %x\n", rc); atomic_dec(&pm8001_dev->running_req); goto err_out_tag; } @@ -570,9 +568,9 @@ static struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha) } } if (dev == PM8001_MAX_DEVICES) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("max support %d devices, ignore ..\n", - PM8001_MAX_DEVICES)); + pm8001_dbg(pm8001_ha, FAIL, + "max support %d devices, ignore ..\n", + PM8001_MAX_DEVICES); } return NULL; } @@ -590,8 +588,7 @@ struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha, return &pm8001_ha->devices[dev]; } if (dev == PM8001_MAX_DEVICES) { - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("NO MATCHING " - "DEVICE FOUND !!!\n")); + pm8001_dbg(pm8001_ha, FAIL, "NO MATCHING DEVICE FOUND !!!\n"); } return NULL; } @@ -652,10 +649,10 @@ static int pm8001_dev_found_notify(struct domain_device *dev) } } if (phy_id == parent_dev->ex_dev.num_phys) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Error: no attached dev:%016llx" - " at ex:%016llx.\n", SAS_ADDR(dev->sas_addr), - SAS_ADDR(parent_dev->sas_addr))); + pm8001_dbg(pm8001_ha, FAIL, + "Error: no attached dev:%016llx at ex:%016llx.\n", + SAS_ADDR(dev->sas_addr), + SAS_ADDR(parent_dev->sas_addr)); res = -1; } } else { @@ -665,7 +662,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev) flag = 1; /* directly sata */ } } /*register this device to HBA*/ - PM8001_DISC_DBG(pm8001_ha, pm8001_printk("Found device\n")); + pm8001_dbg(pm8001_ha, DISC, "Found device\n"); PM8001_CHIP_DISP->reg_dev_req(pm8001_ha, pm8001_device, flag); spin_unlock_irqrestore(&pm8001_ha->lock, flags); wait_for_completion(&completion); @@ -737,9 +734,7 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev, if (res) { del_timer(&task->slow_task->timer); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Executing internal task " - "failed\n")); + pm8001_dbg(pm8001_ha, FAIL, "Executing internal task failed\n"); goto ex_err; } wait_for_completion(&task->slow_task->completion); @@ -753,9 +748,9 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev, /* Even TMF timed out, return direct. */ if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("TMF task[%x]timeout.\n", - tmf->tmf)); + pm8001_dbg(pm8001_ha, FAIL, + "TMF task[%x]timeout.\n", + tmf->tmf); goto ex_err; } } @@ -776,17 +771,15 @@ static int pm8001_exec_internal_tmf_task(struct domain_device *dev, if (task->task_status.resp == SAS_TASK_COMPLETE && task->task_status.stat == SAS_DATA_OVERRUN) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Blocked task error.\n")); + pm8001_dbg(pm8001_ha, FAIL, "Blocked task error.\n"); res = -EMSGSIZE; break; } else { - PM8001_EH_DBG(pm8001_ha, - pm8001_printk(" Task to dev %016llx response:" - "0x%x status 0x%x\n", - SAS_ADDR(dev->sas_addr), - task->task_status.resp, - task->task_status.stat)); + pm8001_dbg(pm8001_ha, EH, + " Task to dev %016llx response:0x%x status 0x%x\n", + SAS_ADDR(dev->sas_addr), + task->task_status.resp, + task->task_status.stat); sas_free_task(task); task = NULL; } @@ -833,9 +826,7 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha, if (res) { del_timer(&task->slow_task->timer); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Executing internal task " - "failed\n")); + pm8001_dbg(pm8001_ha, FAIL, "Executing internal task failed\n"); goto ex_err; } wait_for_completion(&task->slow_task->completion); @@ -843,8 +834,8 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha, /* Even TMF timed out, return direct. */ if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("TMF task timeout.\n")); + pm8001_dbg(pm8001_ha, FAIL, + "TMF task timeout.\n"); goto ex_err; } } @@ -855,12 +846,11 @@ pm8001_exec_internal_task_abort(struct pm8001_hba_info *pm8001_ha, break; } else { - PM8001_EH_DBG(pm8001_ha, - pm8001_printk(" Task to dev %016llx response: " - "0x%x status 0x%x\n", - SAS_ADDR(dev->sas_addr), - task->task_status.resp, - task->task_status.stat)); + pm8001_dbg(pm8001_ha, EH, + " Task to dev %016llx response: 0x%x status 0x%x\n", + SAS_ADDR(dev->sas_addr), + task->task_status.resp, + task->task_status.stat); sas_free_task(task); task = NULL; } @@ -886,9 +876,8 @@ static void pm8001_dev_gone_notify(struct domain_device *dev) if (pm8001_dev) { u32 device_id = pm8001_dev->device_id; - PM8001_DISC_DBG(pm8001_ha, - pm8001_printk("found dev[%d:%x] is gone.\n", - pm8001_dev->device_id, pm8001_dev->dev_type)); + pm8001_dbg(pm8001_ha, DISC, "found dev[%d:%x] is gone.\n", + pm8001_dev->device_id, pm8001_dev->dev_type); if (atomic_read(&pm8001_dev->running_req)) { spin_unlock_irqrestore(&pm8001_ha->lock, flags); pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , @@ -900,8 +889,7 @@ static void pm8001_dev_gone_notify(struct domain_device *dev) PM8001_CHIP_DISP->dereg_dev_req(pm8001_ha, device_id); pm8001_free_dev(pm8001_dev); } else { - PM8001_DISC_DBG(pm8001_ha, - pm8001_printk("Found dev has gone.\n")); + pm8001_dbg(pm8001_ha, DISC, "Found dev has gone.\n"); } dev->lldd_dev = NULL; spin_unlock_irqrestore(&pm8001_ha->lock, flags); @@ -1021,9 +1009,9 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev) } rc = sas_phy_reset(phy, 1); if (rc) { - PM8001_EH_DBG(pm8001_ha, - pm8001_printk("phy reset failed for device %x\n" - "with rc %d\n", pm8001_dev->device_id, rc)); + pm8001_dbg(pm8001_ha, EH, + "phy reset failed for device %x\n" + "with rc %d\n", pm8001_dev->device_id, rc); rc = TMF_RESP_FUNC_FAILED; goto out; } @@ -1031,17 +1019,16 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev) rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , dev, 1, 0); if (rc) { - PM8001_EH_DBG(pm8001_ha, - pm8001_printk("task abort failed %x\n" - "with rc %d\n", pm8001_dev->device_id, rc)); + pm8001_dbg(pm8001_ha, EH, "task abort failed %x\n" + "with rc %d\n", pm8001_dev->device_id, rc); rc = TMF_RESP_FUNC_FAILED; } } else { rc = sas_phy_reset(phy, 1); msleep(2000); } - PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n", - pm8001_dev->device_id, rc)); + pm8001_dbg(pm8001_ha, EH, " for device[%x]:rc=%d\n", + pm8001_dev->device_id, rc); out: sas_put_local_phy(phy); return rc; @@ -1064,8 +1051,7 @@ int pm8001_I_T_nexus_event_handler(struct domain_device *dev) pm8001_dev = dev->lldd_dev; pm8001_ha = pm8001_find_ha_by_dev(dev); - PM8001_EH_DBG(pm8001_ha, - pm8001_printk("I_T_Nexus handler invoked !!")); + pm8001_dbg(pm8001_ha, EH, "I_T_Nexus handler invoked !!\n"); phy = sas_get_local_phy(dev); @@ -1104,8 +1090,8 @@ int pm8001_I_T_nexus_event_handler(struct domain_device *dev) rc = sas_phy_reset(phy, 1); msleep(2000); } - PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n", - pm8001_dev->device_id, rc)); + pm8001_dbg(pm8001_ha, EH, " for device[%x]:rc=%d\n", + pm8001_dev->device_id, rc); out: sas_put_local_phy(phy); @@ -1134,8 +1120,8 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun) rc = pm8001_issue_ssp_tmf(dev, lun, &tmf_task); } /* If failed, fall-through I_T_Nexus reset */ - PM8001_EH_DBG(pm8001_ha, pm8001_printk("for device[%x]:rc=%d\n", - pm8001_dev->device_id, rc)); + pm8001_dbg(pm8001_ha, EH, "for device[%x]:rc=%d\n", + pm8001_dev->device_id, rc); return rc; } @@ -1143,7 +1129,6 @@ int pm8001_lu_reset(struct domain_device *dev, u8 *lun) int pm8001_query_task(struct sas_task *task) { u32 tag = 0xdeadbeef; - int i = 0; struct scsi_lun lun; struct pm8001_tmf_task tmf_task; int rc = TMF_RESP_FUNC_FAILED; @@ -1162,10 +1147,7 @@ int pm8001_query_task(struct sas_task *task) rc = TMF_RESP_FUNC_FAILED; return rc; } - PM8001_EH_DBG(pm8001_ha, pm8001_printk("Query:[")); - for (i = 0; i < 16; i++) - printk(KERN_INFO "%02x ", cmnd->cmnd[i]); - printk(KERN_INFO "]\n"); + pm8001_dbg(pm8001_ha, EH, "Query:[%16ph]\n", cmnd->cmnd); tmf_task.tmf = TMF_QUERY_TASK; tmf_task.tag_of_task_to_be_managed = tag; @@ -1173,15 +1155,14 @@ int pm8001_query_task(struct sas_task *task) switch (rc) { /* The task is still in Lun, release it then */ case TMF_RESP_FUNC_SUCC: - PM8001_EH_DBG(pm8001_ha, - pm8001_printk("The task is still in Lun\n")); + pm8001_dbg(pm8001_ha, EH, + "The task is still in Lun\n"); break; /* The task is not in Lun or failed, reset the phy */ case TMF_RESP_FUNC_FAILED: case TMF_RESP_FUNC_COMPLETE: - PM8001_EH_DBG(pm8001_ha, - pm8001_printk("The task is not in Lun or failed," - " reset the phy\n")); + pm8001_dbg(pm8001_ha, EH, + "The task is not in Lun or failed, reset the phy\n"); break; } } @@ -1267,8 +1248,8 @@ int pm8001_abort_task(struct sas_task *task) * leaking the task in libsas or losing the race and * getting a double free. */ - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("Waiting for local phy ctl\n")); + pm8001_dbg(pm8001_ha, MSG, + "Waiting for local phy ctl\n"); ret = wait_for_completion_timeout(&completion, PM8001_TASK_TIMEOUT * HZ); if (!ret || !phy->reset_success) { @@ -1278,8 +1259,8 @@ int pm8001_abort_task(struct sas_task *task) /* 3. Wait for Port Reset complete or * Port reset TMO */ - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("Waiting for Port reset\n")); + pm8001_dbg(pm8001_ha, MSG, + "Waiting for Port reset\n"); ret = wait_for_completion_timeout( &completion_reset, PM8001_TASK_TIMEOUT * HZ); @@ -1358,9 +1339,8 @@ int pm8001_clear_task_set(struct domain_device *dev, u8 *lun) struct pm8001_device *pm8001_dev = dev->lldd_dev; struct pm8001_hba_info *pm8001_ha = pm8001_find_ha_by_dev(dev); - PM8001_EH_DBG(pm8001_ha, - pm8001_printk("I_T_L_Q clear task set[%x]\n", - pm8001_dev->device_id)); + pm8001_dbg(pm8001_ha, EH, "I_T_L_Q clear task set[%x]\n", + pm8001_dev->device_id); tmf_task.tmf = TMF_CLEAR_TASK_SET; return pm8001_issue_ssp_tmf(dev, lun, &tmf_task); } diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 091574721ea1..5cd6fe6a7d2d 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -69,45 +69,16 @@ #define PM8001_DEV_LOGGING 0x80 /* development message logging */ #define PM8001_DEVIO_LOGGING 0x100 /* development io message logging */ #define PM8001_IOERR_LOGGING 0x200 /* development io err message logging */ -#define pm8001_printk(format, arg...) pr_info("%s:: %s %d:" \ - format, pm8001_ha->name, __func__, __LINE__, ## arg) -#define PM8001_CHECK_LOGGING(HBA, LEVEL, CMD) \ -do { \ - if (unlikely(HBA->logging_level & LEVEL)) \ - do { \ - CMD; \ - } while (0); \ -} while (0); -#define PM8001_EH_DBG(HBA, CMD) \ - PM8001_CHECK_LOGGING(HBA, PM8001_EH_LOGGING, CMD) +#define pm8001_printk(fmt, ...) \ + pr_info("%s:: %s %d:" fmt, \ + pm8001_ha->name, __func__, __LINE__, ##__VA_ARGS__) -#define PM8001_INIT_DBG(HBA, CMD) \ - PM8001_CHECK_LOGGING(HBA, PM8001_INIT_LOGGING, CMD) - -#define PM8001_DISC_DBG(HBA, CMD) \ - PM8001_CHECK_LOGGING(HBA, PM8001_DISC_LOGGING, CMD) - -#define PM8001_IO_DBG(HBA, CMD) \ - PM8001_CHECK_LOGGING(HBA, PM8001_IO_LOGGING, CMD) - -#define PM8001_FAIL_DBG(HBA, CMD) \ - PM8001_CHECK_LOGGING(HBA, PM8001_FAIL_LOGGING, CMD) - -#define PM8001_IOCTL_DBG(HBA, CMD) \ - PM8001_CHECK_LOGGING(HBA, PM8001_IOCTL_LOGGING, CMD) - -#define PM8001_MSG_DBG(HBA, CMD) \ - PM8001_CHECK_LOGGING(HBA, PM8001_MSG_LOGGING, CMD) - -#define PM8001_DEV_DBG(HBA, CMD) \ - PM8001_CHECK_LOGGING(HBA, PM8001_DEV_LOGGING, CMD) - -#define PM8001_DEVIO_DBG(HBA, CMD) \ - PM8001_CHECK_LOGGING(HBA, PM8001_DEVIO_LOGGING, CMD) - -#define PM8001_IOERR_DBG(HBA, CMD) \ - PM8001_CHECK_LOGGING(HBA, PM8001_IOERR_LOGGING, CMD) +#define pm8001_dbg(HBA, level, fmt, ...) \ +do { \ + if (unlikely((HBA)->logging_level & PM8001_##level##_LOGGING)) \ + pm8001_printk(fmt, ##__VA_ARGS__); \ +} while (0) #define PM8001_USE_TASKLET #define PM8001_USE_MSIX diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 24a4f6b9e79d..69f8244539e0 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -58,9 +58,8 @@ int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shift_value) reg_val = pm8001_cr32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER); } while ((reg_val != shift_value) && time_before(jiffies, start)); if (reg_val != shift_value) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("TIMEOUT:MEMBASE_II_SHIFT_REGISTER" - " = 0x%x\n", reg_val)); + pm8001_dbg(pm8001_ha, FAIL, "TIMEOUT:MEMBASE_II_SHIFT_REGISTER = 0x%x\n", + reg_val); return -1; } return 0; @@ -109,8 +108,8 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev, } /* initialize variables for very first call from host application */ if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) { - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("forensic_info TYPE_NON_FATAL..............\n")); + pm8001_dbg(pm8001_ha, IO, + "forensic_info TYPE_NON_FATAL..............\n"); direct_data = (u8 *)fatal_error_data; pm8001_ha->forensic_info.data_type = TYPE_NON_FATAL; pm8001_ha->forensic_info.data_buf.direct_len = SYSFS_OFFSET; @@ -123,17 +122,13 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev, MPI_FATAL_EDUMP_TABLE_SIGNATURE, 0x1234abcd); pm8001_ha->forensic_info.data_buf.direct_data = direct_data; - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("ossaHwCB: status1 %d\n", status)); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("ossaHwCB: read_len 0x%x\n", - pm8001_ha->forensic_info.data_buf.read_len)); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("ossaHwCB: direct_len 0x%x\n", - pm8001_ha->forensic_info.data_buf.direct_len)); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("ossaHwCB: direct_offset 0x%x\n", - pm8001_ha->forensic_info.data_buf.direct_offset)); + pm8001_dbg(pm8001_ha, IO, "ossaHwCB: status1 %d\n", status); + pm8001_dbg(pm8001_ha, IO, "ossaHwCB: read_len 0x%x\n", + pm8001_ha->forensic_info.data_buf.read_len); + pm8001_dbg(pm8001_ha, IO, "ossaHwCB: direct_len 0x%x\n", + pm8001_ha->forensic_info.data_buf.direct_len); + pm8001_dbg(pm8001_ha, IO, "ossaHwCB: direct_offset 0x%x\n", + pm8001_ha->forensic_info.data_buf.direct_offset); } if (pm8001_ha->forensic_info.data_buf.direct_offset == 0) { /* start to get data */ @@ -153,29 +148,24 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev, */ length_to_read = accum_len - pm8001_ha->forensic_preserved_accumulated_transfer; - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("get_fatal_spcv: accum_len 0x%x\n", accum_len)); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("get_fatal_spcv: length_to_read 0x%x\n", - length_to_read)); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("get_fatal_spcv: last_offset 0x%x\n", - pm8001_ha->forensic_last_offset)); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("get_fatal_spcv: read_len 0x%x\n", - pm8001_ha->forensic_info.data_buf.read_len)); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("get_fatal_spcv:: direct_len 0x%x\n", - pm8001_ha->forensic_info.data_buf.direct_len)); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("get_fatal_spcv:: direct_offset 0x%x\n", - pm8001_ha->forensic_info.data_buf.direct_offset)); + pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: accum_len 0x%x\n", + accum_len); + pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: length_to_read 0x%x\n", + length_to_read); + pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: last_offset 0x%x\n", + pm8001_ha->forensic_last_offset); + pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: read_len 0x%x\n", + pm8001_ha->forensic_info.data_buf.read_len); + pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv:: direct_len 0x%x\n", + pm8001_ha->forensic_info.data_buf.direct_len); + pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv:: direct_offset 0x%x\n", + pm8001_ha->forensic_info.data_buf.direct_offset); /* If accumulated length failed to read correctly fail the attempt.*/ if (accum_len == 0xFFFFFFFF) { - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("Possible PCI issue 0x%x not expected\n", - accum_len)); + pm8001_dbg(pm8001_ha, IO, + "Possible PCI issue 0x%x not expected\n", + accum_len); return status; } /* If accumulated length is zero fail the attempt */ @@ -239,8 +229,8 @@ moreData: offset = (int) ((char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("get_fatal_spcv:return1 0x%x\n", offset)); + pm8001_dbg(pm8001_ha, IO, + "get_fatal_spcv:return1 0x%x\n", offset); return (char *)pm8001_ha-> forensic_info.data_buf.direct_data - (char *)buf; @@ -262,8 +252,8 @@ moreData: offset = (int) ((char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("get_fatal_spcv:return2 0x%x\n", offset)); + pm8001_dbg(pm8001_ha, IO, + "get_fatal_spcv:return2 0x%x\n", offset); return (char *)pm8001_ha-> forensic_info.data_buf.direct_data - (char *)buf; @@ -289,8 +279,8 @@ moreData: offset = (int) ((char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("get_fatal_spcv: return3 0x%x\n", offset)); + pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: return3 0x%x\n", + offset); return (char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf; } @@ -327,9 +317,9 @@ moreData: } while ((reg_val) && time_before(jiffies, start)); if (reg_val != 0) { - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( - "TIMEOUT:MPI_FATAL_EDUMP_TABLE_HDSHAKE 0x%x\n", - reg_val)); + pm8001_dbg(pm8001_ha, FAIL, + "TIMEOUT:MPI_FATAL_EDUMP_TABLE_HDSHAKE 0x%x\n", + reg_val); /* Fail the dump if a timeout occurs */ pm8001_ha->forensic_info.data_buf.direct_data += sprintf( @@ -351,9 +341,9 @@ moreData: time_before(jiffies, start)); if (reg_val < 2) { - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( - "TIMEOUT:MPI_FATAL_EDUMP_TABLE_STATUS = 0x%x\n", - reg_val)); + pm8001_dbg(pm8001_ha, FAIL, + "TIMEOUT:MPI_FATAL_EDUMP_TABLE_STATUS = 0x%x\n", + reg_val); /* Fail the dump if a timeout occurs */ pm8001_ha->forensic_info.data_buf.direct_data += sprintf( @@ -387,8 +377,7 @@ moreData: } offset = (int)((char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("get_fatal_spcv: return4 0x%x\n", offset)); + pm8001_dbg(pm8001_ha, IO, "get_fatal_spcv: return4 0x%x\n", offset); return (char *)pm8001_ha->forensic_info.data_buf.direct_data - (char *)buf; } @@ -419,8 +408,7 @@ ssize_t pm80xx_get_non_fatal_dump(struct device *cdev, PAGE_SIZE, "Not supported for SPC controller"); return 0; } - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("forensic_info TYPE_NON_FATAL...\n")); + pm8001_dbg(pm8001_ha, IO, "forensic_info TYPE_NON_FATAL...\n"); /* * Step 1: Write the host buffer parameters in the MPI Fatal and * Non-Fatal Error Dump Capture Table.This is the buffer @@ -581,24 +569,24 @@ static void read_main_config_table(struct pm8001_hba_info *pm8001_ha) pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version = pm8001_mr32(address, MAIN_MPI_INACTIVE_FW_VERSION); - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "Main cfg table: sign:%x interface rev:%x fw_rev:%x\n", - pm8001_ha->main_cfg_tbl.pm80xx_tbl.signature, - pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev, - pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev)); - - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "table offset: gst:%x iq:%x oq:%x int vec:%x phy attr:%x\n", - pm8001_ha->main_cfg_tbl.pm80xx_tbl.gst_offset, - pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_queue_offset, - pm8001_ha->main_cfg_tbl.pm80xx_tbl.outbound_queue_offset, - pm8001_ha->main_cfg_tbl.pm80xx_tbl.int_vec_table_offset, - pm8001_ha->main_cfg_tbl.pm80xx_tbl.phy_attr_table_offset)); - - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "Main cfg table; ila rev:%x Inactive fw rev:%x\n", - pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version, - pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version)); + pm8001_dbg(pm8001_ha, DEV, + "Main cfg table: sign:%x interface rev:%x fw_rev:%x\n", + pm8001_ha->main_cfg_tbl.pm80xx_tbl.signature, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev); + + pm8001_dbg(pm8001_ha, DEV, + "table offset: gst:%x iq:%x oq:%x int vec:%x phy attr:%x\n", + pm8001_ha->main_cfg_tbl.pm80xx_tbl.gst_offset, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_queue_offset, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.outbound_queue_offset, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.int_vec_table_offset, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.phy_attr_table_offset); + + pm8001_dbg(pm8001_ha, DEV, + "Main cfg table; ila rev:%x Inactive fw rev:%x\n", + pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version, + pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version); } /** @@ -808,10 +796,10 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) pm8001_ha->inbnd_q_tbl[i].producer_idx = 0; pm8001_ha->inbnd_q_tbl[i].consumer_index = 0; - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "IQ %d pi_bar 0x%x pi_offset 0x%x\n", i, - pm8001_ha->inbnd_q_tbl[i].pi_pci_bar, - pm8001_ha->inbnd_q_tbl[i].pi_offset)); + pm8001_dbg(pm8001_ha, DEV, + "IQ %d pi_bar 0x%x pi_offset 0x%x\n", i, + pm8001_ha->inbnd_q_tbl[i].pi_pci_bar, + pm8001_ha->inbnd_q_tbl[i].pi_offset); } for (i = 0; i < pm8001_ha->max_q_num; i++) { pm8001_ha->outbnd_q_tbl[i].element_size_cnt = @@ -841,10 +829,10 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) pm8001_ha->outbnd_q_tbl[i].consumer_idx = 0; pm8001_ha->outbnd_q_tbl[i].producer_index = 0; - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "OQ %d ci_bar 0x%x ci_offset 0x%x\n", i, - pm8001_ha->outbnd_q_tbl[i].ci_pci_bar, - pm8001_ha->outbnd_q_tbl[i].ci_offset)); + pm8001_dbg(pm8001_ha, DEV, + "OQ %d ci_bar 0x%x ci_offset 0x%x\n", i, + pm8001_ha->outbnd_q_tbl[i].ci_pci_bar, + pm8001_ha->outbnd_q_tbl[i].ci_offset); } } @@ -878,9 +866,9 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha) ((pm8001_ha->max_q_num - 1) << 8); pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT, pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt); - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "Updated Fatal error interrupt vector 0x%x\n", - pm8001_mr32(address, MAIN_FATAL_ERROR_INTERRUPT))); + pm8001_dbg(pm8001_ha, DEV, + "Updated Fatal error interrupt vector 0x%x\n", + pm8001_mr32(address, MAIN_FATAL_ERROR_INTERRUPT)); pm8001_mw32(address, MAIN_EVENT_CRC_CHECK, pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump); @@ -891,9 +879,9 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha) pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping |= 0x20000000; pm8001_mw32(address, MAIN_GPIO_LED_FLAGS_OFFSET, pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping); - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "Programming DW 0x21 in main cfg table with 0x%x\n", - pm8001_mr32(address, MAIN_GPIO_LED_FLAGS_OFFSET))); + pm8001_dbg(pm8001_ha, DEV, + "Programming DW 0x21 in main cfg table with 0x%x\n", + pm8001_mr32(address, MAIN_GPIO_LED_FLAGS_OFFSET)); pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER, pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer); @@ -934,20 +922,20 @@ static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha, pm8001_mw32(address, offset + IB_CI_BASE_ADDR_LO_OFFSET, pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr); - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "IQ %d: Element pri size 0x%x\n", - number, - pm8001_ha->inbnd_q_tbl[number].element_pri_size_cnt)); + pm8001_dbg(pm8001_ha, DEV, + "IQ %d: Element pri size 0x%x\n", + number, + pm8001_ha->inbnd_q_tbl[number].element_pri_size_cnt); - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "IQ upr base addr 0x%x IQ lwr base addr 0x%x\n", - pm8001_ha->inbnd_q_tbl[number].upper_base_addr, - pm8001_ha->inbnd_q_tbl[number].lower_base_addr)); + pm8001_dbg(pm8001_ha, DEV, + "IQ upr base addr 0x%x IQ lwr base addr 0x%x\n", + pm8001_ha->inbnd_q_tbl[number].upper_base_addr, + pm8001_ha->inbnd_q_tbl[number].lower_base_addr); - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "CI upper base addr 0x%x CI lower base addr 0x%x\n", - pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr, - pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr)); + pm8001_dbg(pm8001_ha, DEV, + "CI upper base addr 0x%x CI lower base addr 0x%x\n", + pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr, + pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr); } /** @@ -973,20 +961,20 @@ static void update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha, pm8001_mw32(address, offset + OB_INTERRUPT_COALES_OFFSET, pm8001_ha->outbnd_q_tbl[number].interrup_vec_cnt_delay); - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "OQ %d: Element pri size 0x%x\n", - number, - pm8001_ha->outbnd_q_tbl[number].element_size_cnt)); + pm8001_dbg(pm8001_ha, DEV, + "OQ %d: Element pri size 0x%x\n", + number, + pm8001_ha->outbnd_q_tbl[number].element_size_cnt); - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "OQ upr base addr 0x%x OQ lwr base addr 0x%x\n", - pm8001_ha->outbnd_q_tbl[number].upper_base_addr, - pm8001_ha->outbnd_q_tbl[number].lower_base_addr)); + pm8001_dbg(pm8001_ha, DEV, + "OQ upr base addr 0x%x OQ lwr base addr 0x%x\n", + pm8001_ha->outbnd_q_tbl[number].upper_base_addr, + pm8001_ha->outbnd_q_tbl[number].lower_base_addr); - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "PI upper base addr 0x%x PI lower base addr 0x%x\n", - pm8001_ha->outbnd_q_tbl[number].pi_upper_base_addr, - pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr)); + pm8001_dbg(pm8001_ha, DEV, + "PI upper base addr 0x%x PI lower base addr 0x%x\n", + pm8001_ha->outbnd_q_tbl[number].pi_upper_base_addr, + pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr); } /** @@ -1016,8 +1004,9 @@ static int mpi_init_check(struct pm8001_hba_info *pm8001_ha) if (!max_wait_count) { /* additional check */ - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( - "Inb doorbell clear not toggled[value:%x]\n", value)); + pm8001_dbg(pm8001_ha, FAIL, + "Inb doorbell clear not toggled[value:%x]\n", + value); return -EBUSY; } /* check the MPI-State for initialization upto 100ms*/ @@ -1069,9 +1058,9 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha) if (!max_wait_count) ret = -1; else { - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" ila ready status in %d millisec\n", - (max_wait_time - max_wait_count))); + pm8001_dbg(pm8001_ha, MSG, + " ila ready status in %d millisec\n", + (max_wait_time - max_wait_count)); } /* check RAAE status */ @@ -1084,9 +1073,9 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha) if (!max_wait_count) ret = -1; else { - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" raae ready status in %d millisec\n", - (max_wait_time - max_wait_count))); + pm8001_dbg(pm8001_ha, MSG, + " raae ready status in %d millisec\n", + (max_wait_time - max_wait_count)); } /* check iop0 status */ @@ -1099,9 +1088,9 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha) if (!max_wait_count) ret = -1; else { - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" iop0 ready status in %d millisec\n", - (max_wait_time - max_wait_count))); + pm8001_dbg(pm8001_ha, MSG, + " iop0 ready status in %d millisec\n", + (max_wait_time - max_wait_count)); } /* check iop1 status only for 16 port controllers */ @@ -1117,9 +1106,9 @@ static int check_fw_ready(struct pm8001_hba_info *pm8001_ha) if (!max_wait_count) ret = -1; else { - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "iop1 ready status in %d millisec\n", - (max_wait_time - max_wait_count))); + pm8001_dbg(pm8001_ha, MSG, + "iop1 ready status in %d millisec\n", + (max_wait_time - max_wait_count)); } } @@ -1137,13 +1126,11 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha) value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0); offset = value & 0x03FFFFFF; /* scratch pad 0 TBL address */ - PM8001_DEV_DBG(pm8001_ha, - pm8001_printk("Scratchpad 0 Offset: 0x%x value 0x%x\n", - offset, value)); + pm8001_dbg(pm8001_ha, DEV, "Scratchpad 0 Offset: 0x%x value 0x%x\n", + offset, value); pcilogic = (value & 0xFC000000) >> 26; pcibar = get_pci_bar_index(pcilogic); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("Scratchpad 0 PCI BAR: %d\n", pcibar)); + pm8001_dbg(pm8001_ha, INIT, "Scratchpad 0 PCI BAR: %d\n", pcibar); pm8001_ha->main_cfg_tbl_addr = base_addr = pm8001_ha->io_mem[pcibar].memvirtaddr + offset; pm8001_ha->general_stat_tbl_addr = @@ -1165,33 +1152,25 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha) base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0xA0) & 0xFFFFFF); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("GST OFFSET 0x%x\n", - pm8001_cr32(pm8001_ha, pcibar, offset + 0x18))); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("INBND OFFSET 0x%x\n", - pm8001_cr32(pm8001_ha, pcibar, offset + 0x1C))); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("OBND OFFSET 0x%x\n", - pm8001_cr32(pm8001_ha, pcibar, offset + 0x20))); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("IVT OFFSET 0x%x\n", - pm8001_cr32(pm8001_ha, pcibar, offset + 0x8C))); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("PSPA OFFSET 0x%x\n", - pm8001_cr32(pm8001_ha, pcibar, offset + 0x90))); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("addr - main cfg %p general status %p\n", - pm8001_ha->main_cfg_tbl_addr, - pm8001_ha->general_stat_tbl_addr)); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("addr - inbnd %p obnd %p\n", - pm8001_ha->inbnd_q_tbl_addr, - pm8001_ha->outbnd_q_tbl_addr)); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("addr - pspa %p ivt %p\n", - pm8001_ha->pspa_q_tbl_addr, - pm8001_ha->ivt_tbl_addr)); + pm8001_dbg(pm8001_ha, INIT, "GST OFFSET 0x%x\n", + pm8001_cr32(pm8001_ha, pcibar, offset + 0x18)); + pm8001_dbg(pm8001_ha, INIT, "INBND OFFSET 0x%x\n", + pm8001_cr32(pm8001_ha, pcibar, offset + 0x1C)); + pm8001_dbg(pm8001_ha, INIT, "OBND OFFSET 0x%x\n", + pm8001_cr32(pm8001_ha, pcibar, offset + 0x20)); + pm8001_dbg(pm8001_ha, INIT, "IVT OFFSET 0x%x\n", + pm8001_cr32(pm8001_ha, pcibar, offset + 0x8C)); + pm8001_dbg(pm8001_ha, INIT, "PSPA OFFSET 0x%x\n", + pm8001_cr32(pm8001_ha, pcibar, offset + 0x90)); + pm8001_dbg(pm8001_ha, INIT, "addr - main cfg %p general status %p\n", + pm8001_ha->main_cfg_tbl_addr, + pm8001_ha->general_stat_tbl_addr); + pm8001_dbg(pm8001_ha, INIT, "addr - inbnd %p obnd %p\n", + pm8001_ha->inbnd_q_tbl_addr, + pm8001_ha->outbnd_q_tbl_addr); + pm8001_dbg(pm8001_ha, INIT, "addr - pspa %p ivt %p\n", + pm8001_ha->pspa_q_tbl_addr, + pm8001_ha->ivt_tbl_addr); } /** @@ -1225,9 +1204,9 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha) (THERMAL_ENABLE << 8) | page_code; payload.cfg_pg[1] = (LTEMPHIL << 24) | (RTEMPHIL << 8); - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "Setting up thermal config. cfg_pg 0 0x%x cfg_pg 1 0x%x\n", - payload.cfg_pg[0], payload.cfg_pg[1])); + pm8001_dbg(pm8001_ha, DEV, + "Setting up thermal config. cfg_pg 0 0x%x cfg_pg 1 0x%x\n", + payload.cfg_pg[0], payload.cfg_pg[1]); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, sizeof(payload), 0); @@ -1282,32 +1261,24 @@ pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha) | SAS_COPNRJT_RTRY_THR; SASConfigPage.MAX_AIP = SAS_MAX_AIP; - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("SASConfigPage.pageCode " - "0x%08x\n", SASConfigPage.pageCode)); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("SASConfigPage.MST_MSI " - " 0x%08x\n", SASConfigPage.MST_MSI)); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("SASConfigPage.STP_SSP_MCT_TMO " - " 0x%08x\n", SASConfigPage.STP_SSP_MCT_TMO)); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("SASConfigPage.STP_FRM_TMO " - " 0x%08x\n", SASConfigPage.STP_FRM_TMO)); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("SASConfigPage.STP_IDLE_TMO " - " 0x%08x\n", SASConfigPage.STP_IDLE_TMO)); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("SASConfigPage.OPNRJT_RTRY_INTVL " - " 0x%08x\n", SASConfigPage.OPNRJT_RTRY_INTVL)); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO " - " 0x%08x\n", SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO)); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR " - " 0x%08x\n", SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR)); - PM8001_INIT_DBG(pm8001_ha, pm8001_printk("SASConfigPage.MAX_AIP " - " 0x%08x\n", SASConfigPage.MAX_AIP)); + pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.pageCode 0x%08x\n", + SASConfigPage.pageCode); + pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.MST_MSI 0x%08x\n", + SASConfigPage.MST_MSI); + pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_SSP_MCT_TMO 0x%08x\n", + SASConfigPage.STP_SSP_MCT_TMO); + pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_FRM_TMO 0x%08x\n", + SASConfigPage.STP_FRM_TMO); + pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.STP_IDLE_TMO 0x%08x\n", + SASConfigPage.STP_IDLE_TMO); + pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.OPNRJT_RTRY_INTVL 0x%08x\n", + SASConfigPage.OPNRJT_RTRY_INTVL); + pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO 0x%08x\n", + SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO); + pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR 0x%08x\n", + SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR); + pm8001_dbg(pm8001_ha, INIT, "SASConfigPage.MAX_AIP 0x%08x\n", + SASConfigPage.MAX_AIP); memcpy(&payload.cfg_pg, &SASConfigPage, sizeof(SASProtocolTimerConfig_t)); @@ -1347,18 +1318,18 @@ pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha) SCRATCH_PAD3_SMB_ENABLED) pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB; pm8001_ha->encrypt_info.status = 0; - PM8001_INIT_DBG(pm8001_ha, pm8001_printk( - "Encryption: SCRATCH_PAD3_ENC_READY 0x%08X." - "Cipher mode 0x%x Sec mode 0x%x status 0x%x\n", - scratch3_value, pm8001_ha->encrypt_info.cipher_mode, - pm8001_ha->encrypt_info.sec_mode, - pm8001_ha->encrypt_info.status)); + pm8001_dbg(pm8001_ha, INIT, + "Encryption: SCRATCH_PAD3_ENC_READY 0x%08X.Cipher mode 0x%x Sec mode 0x%x status 0x%x\n", + scratch3_value, + pm8001_ha->encrypt_info.cipher_mode, + pm8001_ha->encrypt_info.sec_mode, + pm8001_ha->encrypt_info.status); ret = 0; } else if ((scratch3_value & SCRATCH_PAD3_ENC_READY) == SCRATCH_PAD3_ENC_DISABLED) { - PM8001_INIT_DBG(pm8001_ha, pm8001_printk( - "Encryption: SCRATCH_PAD3_ENC_DISABLED 0x%08X\n", - scratch3_value)); + pm8001_dbg(pm8001_ha, INIT, + "Encryption: SCRATCH_PAD3_ENC_DISABLED 0x%08X\n", + scratch3_value); pm8001_ha->encrypt_info.status = 0xFFFFFFFF; pm8001_ha->encrypt_info.cipher_mode = 0; pm8001_ha->encrypt_info.sec_mode = 0; @@ -1378,12 +1349,12 @@ pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha) if ((scratch3_value & SCRATCH_PAD3_SM_MASK) == SCRATCH_PAD3_SMB_ENABLED) pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB; - PM8001_INIT_DBG(pm8001_ha, pm8001_printk( - "Encryption: SCRATCH_PAD3_DIS_ERR 0x%08X." - "Cipher mode 0x%x sec mode 0x%x status 0x%x\n", - scratch3_value, pm8001_ha->encrypt_info.cipher_mode, - pm8001_ha->encrypt_info.sec_mode, - pm8001_ha->encrypt_info.status)); + pm8001_dbg(pm8001_ha, INIT, + "Encryption: SCRATCH_PAD3_DIS_ERR 0x%08X.Cipher mode 0x%x sec mode 0x%x status 0x%x\n", + scratch3_value, + pm8001_ha->encrypt_info.cipher_mode, + pm8001_ha->encrypt_info.sec_mode, + pm8001_ha->encrypt_info.status); } else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) == SCRATCH_PAD3_ENC_ENA_ERR) { @@ -1401,12 +1372,12 @@ pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha) SCRATCH_PAD3_SMB_ENABLED) pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB; - PM8001_INIT_DBG(pm8001_ha, pm8001_printk( - "Encryption: SCRATCH_PAD3_ENA_ERR 0x%08X." - "Cipher mode 0x%x sec mode 0x%x status 0x%x\n", - scratch3_value, pm8001_ha->encrypt_info.cipher_mode, - pm8001_ha->encrypt_info.sec_mode, - pm8001_ha->encrypt_info.status)); + pm8001_dbg(pm8001_ha, INIT, + "Encryption: SCRATCH_PAD3_ENA_ERR 0x%08X.Cipher mode 0x%x sec mode 0x%x status 0x%x\n", + scratch3_value, + pm8001_ha->encrypt_info.cipher_mode, + pm8001_ha->encrypt_info.sec_mode, + pm8001_ha->encrypt_info.status); } return ret; } @@ -1436,9 +1407,9 @@ static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha) payload.new_curidx_ksop = ((1 << 24) | (1 << 16) | (1 << 8) | KEK_MGMT_SUBOP_KEYCARDUPDATE); - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "Saving Encryption info to flash. payload 0x%x\n", - payload.new_curidx_ksop)); + pm8001_dbg(pm8001_ha, DEV, + "Saving Encryption info to flash. payload 0x%x\n", + payload.new_curidx_ksop); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, sizeof(payload), 0); @@ -1459,8 +1430,7 @@ static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha) /* check the firmware status */ if (-1 == check_fw_ready(pm8001_ha)) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Firmware is not ready!\n")); + pm8001_dbg(pm8001_ha, FAIL, "Firmware is not ready!\n"); return -EBUSY; } @@ -1484,8 +1454,7 @@ static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha) } /* notify firmware update finished and check initialization status */ if (0 == mpi_init_check(pm8001_ha)) { - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("MPI initialize successful!\n")); + pm8001_dbg(pm8001_ha, INIT, "MPI initialize successful!\n"); } else return -EBUSY; @@ -1494,16 +1463,13 @@ static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha) /* Check for encryption */ if (pm8001_ha->chip->encrypt) { - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("Checking for encryption\n")); + pm8001_dbg(pm8001_ha, INIT, "Checking for encryption\n"); ret = pm80xx_get_encrypt_info(pm8001_ha); if (ret == -1) { - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("Encryption error !!\n")); + pm8001_dbg(pm8001_ha, INIT, "Encryption error !!\n"); if (pm8001_ha->encrypt_info.status == 0x81) { - PM8001_INIT_DBG(pm8001_ha, pm8001_printk( - "Encryption enabled with error." - "Saving encryption key to flash\n")); + pm8001_dbg(pm8001_ha, INIT, + "Encryption enabled with error.Saving encryption key to flash\n"); pm80xx_encrypt_update(pm8001_ha); } } @@ -1534,8 +1500,7 @@ static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha) } while ((value != 0) && (--max_wait_count)); if (!max_wait_count) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("TIMEOUT:IBDB value/=%x\n", value)); + pm8001_dbg(pm8001_ha, FAIL, "TIMEOUT:IBDB value/=%x\n", value); return -1; } @@ -1552,9 +1517,8 @@ static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha) break; } while (--max_wait_count); if (!max_wait_count) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk(" TIME OUT MPI State = 0x%x\n", - gst_len_mpistate & GST_MPI_STATE_MASK)); + pm8001_dbg(pm8001_ha, FAIL, " TIME OUT MPI State = 0x%x\n", + gst_len_mpistate & GST_MPI_STATE_MASK); return -1; } @@ -1582,9 +1546,9 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) u32 r1 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); u32 r2 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2); u32 r3 = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3); - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( - "MPI state is not ready scratch: %x:%x:%x:%x\n", - r0, r1, r2, r3)); + pm8001_dbg(pm8001_ha, FAIL, + "MPI state is not ready scratch: %x:%x:%x:%x\n", + r0, r1, r2, r3); /* if things aren't ready but the bootloader is ok then * try the reset anyway. */ @@ -1594,25 +1558,25 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) } /* checked for reset register normal state; 0x0 */ regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("reset register before write : 0x%x\n", regval)); + pm8001_dbg(pm8001_ha, INIT, "reset register before write : 0x%x\n", + regval); pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, SPCv_NORMAL_RESET_VALUE); msleep(500); regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("reset register after write 0x%x\n", regval)); + pm8001_dbg(pm8001_ha, INIT, "reset register after write 0x%x\n", + regval); if ((regval & SPCv_SOFT_RESET_READ_MASK) == SPCv_SOFT_RESET_NORMAL_RESET_OCCURED) { - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" soft reset successful [regval: 0x%x]\n", - regval)); + pm8001_dbg(pm8001_ha, MSG, + " soft reset successful [regval: 0x%x]\n", + regval); } else { - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" soft reset failed [regval: 0x%x]\n", - regval)); + pm8001_dbg(pm8001_ha, MSG, + " soft reset failed [regval: 0x%x]\n", + regval); /* check bootloader is successfully executed or in HDA mode */ bootloader_state = @@ -1620,28 +1584,27 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) SCRATCH_PAD1_BOOTSTATE_MASK; if (bootloader_state == SCRATCH_PAD1_BOOTSTATE_HDA_SEEPROM) { - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "Bootloader state - HDA mode SEEPROM\n")); + pm8001_dbg(pm8001_ha, MSG, + "Bootloader state - HDA mode SEEPROM\n"); } else if (bootloader_state == SCRATCH_PAD1_BOOTSTATE_HDA_BOOTSTRAP) { - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "Bootloader state - HDA mode Bootstrap Pin\n")); + pm8001_dbg(pm8001_ha, MSG, + "Bootloader state - HDA mode Bootstrap Pin\n"); } else if (bootloader_state == SCRATCH_PAD1_BOOTSTATE_HDA_SOFTRESET) { - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "Bootloader state - HDA mode soft reset\n")); + pm8001_dbg(pm8001_ha, MSG, + "Bootloader state - HDA mode soft reset\n"); } else if (bootloader_state == SCRATCH_PAD1_BOOTSTATE_CRIT_ERROR) { - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "Bootloader state-HDA mode critical error\n")); + pm8001_dbg(pm8001_ha, MSG, + "Bootloader state-HDA mode critical error\n"); } return -EBUSY; } /* check the firmware status after reset */ if (-1 == check_fw_ready(pm8001_ha)) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Firmware is not ready!\n")); + pm8001_dbg(pm8001_ha, FAIL, "Firmware is not ready!\n"); /* check iButton feature support for motherboard controller */ if (pm8001_ha->pdev->subsystem_vendor != PCI_VENDOR_ID_ADAPTEC2 && @@ -1653,21 +1616,18 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) ibutton1 = pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_7); if (!ibutton0 && !ibutton1) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("iButton Feature is" - " not Available!!!\n")); + pm8001_dbg(pm8001_ha, FAIL, + "iButton Feature is not Available!!!\n"); return -EBUSY; } if (ibutton0 == 0xdeadbeef && ibutton1 == 0xdeadbeef) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("CRC Check for iButton" - " Feature Failed!!!\n")); + pm8001_dbg(pm8001_ha, FAIL, + "CRC Check for iButton Feature Failed!!!\n"); return -EBUSY; } } } - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("SPCv soft reset Complete\n")); + pm8001_dbg(pm8001_ha, INIT, "SPCv soft reset Complete\n"); return 0; } @@ -1675,13 +1635,11 @@ static void pm80xx_hw_chip_rst(struct pm8001_hba_info *pm8001_ha) { u32 i; - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("chip reset start\n")); + pm8001_dbg(pm8001_ha, INIT, "chip reset start\n"); /* do SPCv chip reset. */ pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, 0x11); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("SPC soft reset Complete\n")); + pm8001_dbg(pm8001_ha, INIT, "SPC soft reset Complete\n"); /* Check this ..whether delay is required or no */ /* delay 10 usec */ @@ -1693,8 +1651,7 @@ static void pm80xx_hw_chip_rst(struct pm8001_hba_info *pm8001_ha) mdelay(1); } while ((--i) != 0); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("chip reset finished\n")); + pm8001_dbg(pm8001_ha, INIT, "chip reset finished\n"); } /** @@ -1770,15 +1727,14 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha, int ret; if (!pm8001_ha_dev) { - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("dev is null\n")); + pm8001_dbg(pm8001_ha, FAIL, "dev is null\n"); return; } task = sas_alloc_slow_task(GFP_ATOMIC); if (!task) { - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot " - "allocate task\n")); + pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task\n"); return; } @@ -1804,8 +1760,7 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha, ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, sizeof(task_abort), 0); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Executing abort task end\n")); + pm8001_dbg(pm8001_ha, FAIL, "Executing abort task end\n"); if (ret) { sas_free_task(task); pm8001_tag_free(pm8001_ha, ccb_tag); @@ -1828,8 +1783,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, task = sas_alloc_slow_task(GFP_ATOMIC); if (!task) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("cannot allocate task !!!\n")); + pm8001_dbg(pm8001_ha, FAIL, "cannot allocate task !!!\n"); return; } task->task_done = pm8001_task_done; @@ -1837,8 +1791,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); if (res) { sas_free_task(task); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("cannot allocate tag !!!\n")); + pm8001_dbg(pm8001_ha, FAIL, "cannot allocate tag !!!\n"); return; } @@ -1849,8 +1802,8 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, if (!dev) { sas_free_task(task); pm8001_tag_free(pm8001_ha, ccb_tag); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Domain device cannot be allocated\n")); + pm8001_dbg(pm8001_ha, FAIL, + "Domain device cannot be allocated\n"); return; } @@ -1883,7 +1836,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, sizeof(sata_cmd), 0); - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Executing read log end\n")); + pm8001_dbg(pm8001_ha, FAIL, "Executing read log end\n"); if (res) { sas_free_task(task); pm8001_tag_free(pm8001_ha, ccb_tag); @@ -1929,27 +1882,24 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) t = ccb->task; if (status && status != IO_UNDERFLOW) - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("sas IO status 0x%x\n", status)); + pm8001_dbg(pm8001_ha, FAIL, "sas IO status 0x%x\n", status); if (unlikely(!t || !t->lldd_task || !t->dev)) return; ts = &t->task_status; - PM8001_DEV_DBG(pm8001_ha, pm8001_printk( - "tag::0x%x, status::0x%x task::0x%p\n", tag, status, t)); + pm8001_dbg(pm8001_ha, DEV, + "tag::0x%x, status::0x%x task::0x%p\n", tag, status, t); /* Print sas address of IO failed device */ if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && (status != IO_UNDERFLOW)) - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("SAS Address of IO Failure Drive" - ":%016llx", SAS_ADDR(t->dev->sas_addr))); + pm8001_dbg(pm8001_ha, FAIL, "SAS Address of IO Failure Drive:%016llx\n", + SAS_ADDR(t->dev->sas_addr)); switch (status) { case IO_SUCCESS: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_SUCCESS ,param = 0x%x\n", - param)); + pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS ,param = 0x%x\n", + param); if (param == 0) { ts->resp = SAS_TASK_COMPLETE; ts->stat = SAM_STAT_GOOD; @@ -1964,8 +1914,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_ABORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_ABORTED IOMB Tag\n")); + pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB Tag\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; if (pm8001_dev) @@ -1973,9 +1922,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) break; case IO_UNDERFLOW: /* SSP Completion with error */ - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_UNDERFLOW ,param = 0x%x\n", - param)); + pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW ,param = 0x%x\n", + param); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_UNDERRUN; ts->residual = param; @@ -1983,16 +1931,14 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_NO_DEVICE: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_NO_DEVICE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n"); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_PHY_DOWN; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; /* Force the midlayer to retry */ @@ -2001,8 +1947,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_PHY_NOT_READY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; @@ -2010,8 +1955,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_INVALID_SSP_RSP_FRAME: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_INVALID_SSP_RSP_FRAME\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_XFER_ERROR_INVALID_SSP_RSP_FRAME\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; @@ -2019,8 +1964,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_EPROTO; @@ -2028,8 +1973,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; @@ -2037,8 +1982,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; @@ -2051,8 +1995,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST: case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE: case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; @@ -2062,8 +2005,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); break; case IO_OPEN_CNX_ERROR_BAD_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_BAD_DEST; @@ -2071,8 +2014,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_CONN_RATE; @@ -2080,8 +2023,8 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_WRONG_DEST; @@ -2089,8 +2032,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_NAK_RECEIVED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; @@ -2098,24 +2040,21 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_ACK_NAK_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_DMA: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_DMA\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_DMA\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_OPEN_RETRY_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; @@ -2123,24 +2062,21 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_OFFSET_MISMATCH: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_PORT_IN_RESET: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_PORT_IN_RESET\n")); + pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_DS_NON_OPERATIONAL: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_DS_NON_OPERATIONAL\n")); + pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; if (!t->uldd_task) @@ -2149,32 +2085,29 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) IO_DS_NON_OPERATIONAL); break; case IO_DS_IN_RECOVERY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_DS_IN_RECOVERY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_TM_TAG_NOT_FOUND: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_TM_TAG_NOT_FOUND\n")); + pm8001_dbg(pm8001_ha, IO, "IO_TM_TAG_NOT_FOUND\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_SSP_EXT_IU_ZERO_LEN_ERROR: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_SSP_EXT_IU_ZERO_LEN_ERROR\n")); + pm8001_dbg(pm8001_ha, IO, "IO_SSP_EXT_IU_ZERO_LEN_ERROR\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; @@ -2182,8 +2115,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("Unknown status 0x%x\n", status)); + pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status); /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; @@ -2191,19 +2123,17 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; } - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("scsi_status = 0x%x\n ", - psspPayload->ssp_resp_iu.status)); + pm8001_dbg(pm8001_ha, IO, "scsi_status = 0x%x\n ", + psspPayload->ssp_resp_iu.status); spin_lock_irqsave(&t->task_state_lock, flags); t->task_state_flags &= ~SAS_TASK_STATE_PENDING; t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( - "task 0x%p done with io_status 0x%x resp 0x%x " - "stat 0x%x but aborted by upper layer!\n", - t, status, ts->resp, ts->stat)); + pm8001_dbg(pm8001_ha, FAIL, + "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", + t, status, ts->resp, ts->stat); if (t->slow_task) complete(&t->slow_task->completion); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); @@ -2233,17 +2163,15 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) t = ccb->task; pm8001_dev = ccb->device; if (event) - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("sas IO status 0x%x\n", event)); + pm8001_dbg(pm8001_ha, FAIL, "sas IO status 0x%x\n", event); if (unlikely(!t || !t->lldd_task || !t->dev)) return; ts = &t->task_status; - PM8001_IOERR_DBG(pm8001_ha, - pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n", - port_id, tag, event)); + pm8001_dbg(pm8001_ha, IOERR, "port_id:0x%x, tag:0x%x, event:0x%x\n", + port_id, tag, event); switch (event) { case IO_OVERFLOW: - PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n");) + pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; ts->residual = 0; @@ -2251,34 +2179,31 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); pm8001_handle_event(pm8001_ha, t, IO_XFER_ERROR_BREAK); return; case IO_XFER_ERROR_PHY_NOT_READY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_EPROTO; break; case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; break; case IO_OPEN_CNX_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; @@ -2289,8 +2214,7 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST: case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE: case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; @@ -2300,94 +2224,86 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); break; case IO_OPEN_CNX_ERROR_BAD_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_BAD_DEST; break; case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_CONN_RATE; break; case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_WRONG_DEST; break; case IO_XFER_ERROR_NAK_RECEIVED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_XFER_ERROR_ACK_NAK_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; break; case IO_XFER_OPEN_RETRY_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n"); pm8001_handle_event(pm8001_ha, t, IO_XFER_OPEN_RETRY_TIMEOUT); return; case IO_XFER_ERROR_UNEXPECTED_PHASE: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_UNEXPECTED_PHASE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_UNEXPECTED_PHASE\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; break; case IO_XFER_ERROR_XFER_RDY_OVERRUN: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_XFER_RDY_OVERRUN\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_XFER_RDY_OVERRUN\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; break; case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; break; case IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; break; case IO_XFER_ERROR_OFFSET_MISMATCH: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; break; case IO_XFER_ERROR_XFER_ZERO_DATA_LEN: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; break; case IO_XFER_ERROR_INTERNAL_CRC_ERROR: - PM8001_IOERR_DBG(pm8001_ha, - pm8001_printk("IO_XFR_ERROR_INTERNAL_CRC_ERROR\n")); + pm8001_dbg(pm8001_ha, IOERR, + "IO_XFR_ERROR_INTERNAL_CRC_ERROR\n"); /* TBC: used default set values */ ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; break; case IO_XFER_CMD_FRAME_ISSUED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_CMD_FRAME_ISSUED\n"); return; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("Unknown status 0x%x\n", event)); + pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", event); /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; @@ -2399,10 +2315,9 @@ static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( - "task 0x%p done with event 0x%x resp 0x%x " - "stat 0x%x but aborted by upper layer!\n", - t, event, ts->resp, ts->stat)); + pm8001_dbg(pm8001_ha, FAIL, + "task 0x%p done with event 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", + t, event, ts->resp, ts->stat); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); } else { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -2437,8 +2352,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) tag = le32_to_cpu(psataPayload->tag); if (!tag) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("tag null\n")); + pm8001_dbg(pm8001_ha, FAIL, "tag null\n"); return; } ccb = &pm8001_ha->ccb_info[tag]; @@ -2447,8 +2361,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) t = ccb->task; pm8001_dev = ccb->device; } else { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("ccb null\n")); + pm8001_dbg(pm8001_ha, FAIL, "ccb null\n"); return; } @@ -2456,29 +2369,26 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) if (t->dev && (t->dev->lldd_dev)) pm8001_dev = t->dev->lldd_dev; } else { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("task null\n")); + pm8001_dbg(pm8001_ha, FAIL, "task null\n"); return; } if ((pm8001_dev && !(pm8001_dev->id & NCQ_READ_LOG_FLAG)) && unlikely(!t || !t->lldd_task || !t->dev)) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("task or dev null\n")); + pm8001_dbg(pm8001_ha, FAIL, "task or dev null\n"); return; } ts = &t->task_status; if (!ts) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("ts null\n")); + pm8001_dbg(pm8001_ha, FAIL, "ts null\n"); return; } if (unlikely(status)) - PM8001_IOERR_DBG(pm8001_ha, pm8001_printk( - "status:0x%x, tag:0x%x, task::0x%p\n", - status, tag, t)); + pm8001_dbg(pm8001_ha, IOERR, + "status:0x%x, tag:0x%x, task::0x%p\n", + status, tag, t); /* Print sas address of IO failed device */ if ((status != IO_SUCCESS) && (status != IO_OVERFLOW) && @@ -2510,20 +2420,20 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) & 0xff000000)) + pm8001_dev->attached_phy + 0x10); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("SAS Address of IO Failure Drive:" - "%08x%08x", temp_sata_addr_hi, - temp_sata_addr_low)); + pm8001_dbg(pm8001_ha, FAIL, + "SAS Address of IO Failure Drive:%08x%08x\n", + temp_sata_addr_hi, + temp_sata_addr_low); } else { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("SAS Address of IO Failure Drive:" - "%016llx", SAS_ADDR(t->dev->sas_addr))); + pm8001_dbg(pm8001_ha, FAIL, + "SAS Address of IO Failure Drive:%016llx\n", + SAS_ADDR(t->dev->sas_addr)); } } switch (status) { case IO_SUCCESS: - PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); + pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS\n"); if (param == 0) { ts->resp = SAS_TASK_COMPLETE; ts->stat = SAM_STAT_GOOD; @@ -2545,39 +2455,38 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_PROTO_RESPONSE; ts->residual = param; - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("SAS_PROTO_RESPONSE len = %d\n", - param)); + pm8001_dbg(pm8001_ha, IO, + "SAS_PROTO_RESPONSE len = %d\n", + param); sata_resp = &psataPayload->sata_resp[0]; resp = (struct ata_task_resp *)ts->buf; if (t->ata_task.dma_xfer == 0 && t->data_dir == DMA_FROM_DEVICE) { len = sizeof(struct pio_setup_fis); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("PIO read len = %d\n", len)); + pm8001_dbg(pm8001_ha, IO, + "PIO read len = %d\n", len); } else if (t->ata_task.use_ncq) { len = sizeof(struct set_dev_bits_fis); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("FPDMA len = %d\n", len)); + pm8001_dbg(pm8001_ha, IO, "FPDMA len = %d\n", + len); } else { len = sizeof(struct dev_to_host_fis); - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("other len = %d\n", len)); + pm8001_dbg(pm8001_ha, IO, "other len = %d\n", + len); } if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) { resp->frame_len = len; memcpy(&resp->ending_fis[0], sata_resp, len); ts->buf_valid_size = sizeof(*resp); } else - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("response too large\n")); + pm8001_dbg(pm8001_ha, IO, + "response too large\n"); } if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_ABORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_ABORTED IOMB Tag\n")); + pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB Tag\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; if (pm8001_dev) @@ -2586,8 +2495,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) /* following cases are to do cases */ case IO_UNDERFLOW: /* SATA Completion with error */ - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_UNDERFLOW param = %d\n", param)); + pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW param = %d\n", param); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_UNDERRUN; ts->residual = param; @@ -2595,24 +2503,21 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_NO_DEVICE: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_NO_DEVICE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n"); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_PHY_DOWN; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_INTERRUPTED; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_PHY_NOT_READY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; @@ -2620,8 +2525,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_EPROTO; @@ -2629,8 +2534,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; @@ -2638,8 +2543,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; @@ -2652,8 +2556,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST: case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE: case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; if (!t->uldd_task) { @@ -2667,8 +2570,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case IO_OPEN_CNX_ERROR_BAD_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_BAD_DEST; @@ -2683,8 +2586,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_CONN_RATE; @@ -2692,8 +2595,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY: - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; if (!t->uldd_task) { @@ -2707,8 +2610,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_WRONG_DEST; @@ -2716,64 +2619,56 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_NAK_RECEIVED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_ACK_NAK_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_ACK_NAK_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_DMA: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_DMA\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_DMA\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_SATA_LINK_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_SATA_LINK_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_SATA_LINK_TIMEOUT\n"); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_DEV_NO_RESPONSE; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_REJECTED_NCQ_MODE: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_REJECTED_NCQ_MODE\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_UNDERRUN; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_OPEN_RETRY_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_PORT_IN_RESET: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_PORT_IN_RESET\n")); + pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_DS_NON_OPERATIONAL: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_DS_NON_OPERATIONAL\n")); + pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; if (!t->uldd_task) { @@ -2786,16 +2681,14 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case IO_DS_IN_RECOVERY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_DS_IN_RECOVERY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_DS_IN_ERROR: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_DS_IN_ERROR\n")); + pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_ERROR\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; if (!t->uldd_task) { @@ -2808,8 +2701,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; @@ -2817,8 +2710,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("Unknown status 0x%x\n", status)); + pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status); /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; @@ -2832,10 +2724,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("task 0x%p done with io_status 0x%x" - " resp 0x%x stat 0x%x but aborted by upper layer!\n", - t, status, ts->resp, ts->stat)); + pm8001_dbg(pm8001_ha, FAIL, + "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", + t, status, ts->resp, ts->stat); if (t->slow_task) complete(&t->slow_task->completion); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); @@ -2866,13 +2757,11 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) t = ccb->task; pm8001_dev = ccb->device; } else { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("No CCB !!!. returning\n")); + pm8001_dbg(pm8001_ha, FAIL, "No CCB !!!. returning\n"); return; } if (event) - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("SATA EVENT 0x%x\n", event)); + pm8001_dbg(pm8001_ha, FAIL, "SATA EVENT 0x%x\n", event); /* Check if this is NCQ error */ if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) { @@ -2885,18 +2774,16 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) } if (unlikely(!t || !t->lldd_task || !t->dev)) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("task or dev null\n")); + pm8001_dbg(pm8001_ha, FAIL, "task or dev null\n"); return; } ts = &t->task_status; - PM8001_IOERR_DBG(pm8001_ha, - pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n", - port_id, tag, event)); + pm8001_dbg(pm8001_ha, IOERR, "port_id:0x%x, tag:0x%x, event:0x%x\n", + port_id, tag, event); switch (event) { case IO_OVERFLOW: - PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n")); + pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; ts->residual = 0; @@ -2904,35 +2791,32 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_XFER_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_INTERRUPTED; break; case IO_XFER_ERROR_PHY_NOT_READY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_EPROTO; break; case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; break; case IO_OPEN_CNX_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; @@ -2943,8 +2827,8 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST: case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE: case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED: - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); + pm8001_dbg(pm8001_ha, FAIL, + "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_DEV_NO_RESPONSE; if (!t->uldd_task) { @@ -2958,107 +2842,96 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) } break; case IO_OPEN_CNX_ERROR_BAD_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_BAD_DEST; break; case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_CONN_RATE; break; case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_WRONG_DEST; break; case IO_XFER_ERROR_NAK_RECEIVED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_NAK_RECEIVED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; break; case IO_XFER_ERROR_PEER_ABORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_PEER_ABORTED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PEER_ABORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_NAK_R_ERR; break; case IO_XFER_ERROR_REJECTED_NCQ_MODE: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_REJECTED_NCQ_MODE\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_UNDERRUN; break; case IO_XFER_OPEN_RETRY_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; case IO_XFER_ERROR_UNEXPECTED_PHASE: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_UNEXPECTED_PHASE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_UNEXPECTED_PHASE\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; case IO_XFER_ERROR_XFER_RDY_OVERRUN: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_XFER_RDY_OVERRUN\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_XFER_RDY_OVERRUN\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; case IO_XFER_ERROR_OFFSET_MISMATCH: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_OFFSET_MISMATCH\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; case IO_XFER_ERROR_XFER_ZERO_DATA_LEN: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; case IO_XFER_CMD_FRAME_ISSUED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_CMD_FRAME_ISSUED\n"); break; case IO_XFER_PIO_SETUP_ERROR: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_PIO_SETUP_ERROR\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_PIO_SETUP_ERROR\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; case IO_XFER_ERROR_INTERNAL_CRC_ERROR: - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("IO_XFR_ERROR_INTERNAL_CRC_ERROR\n")); + pm8001_dbg(pm8001_ha, FAIL, + "IO_XFR_ERROR_INTERNAL_CRC_ERROR\n"); /* TBC: used default set values */ ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; case IO_XFER_DMA_ACTIVATE_TIMEOUT: - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("IO_XFR_DMA_ACTIVATE_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, FAIL, "IO_XFR_DMA_ACTIVATE_TIMEOUT\n"); /* TBC: used default set values */ ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; break; default: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("Unknown status 0x%x\n", event)); + pm8001_dbg(pm8001_ha, IO, "Unknown status 0x%x\n", event); /* not allowed case. Therefore, return failed status */ ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_TO; @@ -3070,10 +2943,9 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("task 0x%p done with io_status 0x%x" - " resp 0x%x stat 0x%x but aborted by upper layer!\n", - t, event, ts->resp, ts->stat)); + pm8001_dbg(pm8001_ha, FAIL, + "task 0x%p done with io_status 0x%x resp 0x%x stat 0x%x but aborted by upper layer!\n", + t, event, ts->resp, ts->stat); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); } else { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -3106,48 +2978,45 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts = &t->task_status; pm8001_dev = ccb->device; if (status) - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("smp IO status 0x%x\n", status)); + pm8001_dbg(pm8001_ha, FAIL, "smp IO status 0x%x\n", status); if (unlikely(!t || !t->lldd_task || !t->dev)) return; - PM8001_DEV_DBG(pm8001_ha, - pm8001_printk("tag::0x%x status::0x%x\n", tag, status)); + pm8001_dbg(pm8001_ha, DEV, "tag::0x%x status::0x%x\n", tag, status); switch (status) { case IO_SUCCESS: - PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); + pm8001_dbg(pm8001_ha, IO, "IO_SUCCESS\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAM_STAT_GOOD; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); if (pm8001_ha->smp_exp_mode == SMP_DIRECT) { - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("DIRECT RESPONSE Length:%d\n", - param)); + pm8001_dbg(pm8001_ha, IO, + "DIRECT RESPONSE Length:%d\n", + param); pdma_respaddr = (char *)(phys_to_virt(cpu_to_le64 ((u64)sg_dma_address (&t->smp_task.smp_resp)))); for (i = 0; i < param; i++) { *(pdma_respaddr+i) = psmpPayload->_r_a[i]; - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "SMP Byte%d DMA data 0x%x psmp 0x%x\n", - i, *(pdma_respaddr+i), - psmpPayload->_r_a[i])); + pm8001_dbg(pm8001_ha, IO, + "SMP Byte%d DMA data 0x%x psmp 0x%x\n", + i, *(pdma_respaddr + i), + psmpPayload->_r_a[i]); } } break; case IO_ABORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_ABORTED IOMB\n")); + pm8001_dbg(pm8001_ha, IO, "IO_ABORTED IOMB\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_ABORTED_TASK; if (pm8001_dev) atomic_dec(&pm8001_dev->running_req); break; case IO_OVERFLOW: - PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n")); + pm8001_dbg(pm8001_ha, IO, "IO_UNDERFLOW\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DATA_OVERRUN; ts->residual = 0; @@ -3155,45 +3024,41 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) atomic_dec(&pm8001_dev->running_req); break; case IO_NO_DEVICE: - PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_NO_DEVICE\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_PHY_DOWN; break; case IO_ERROR_HW_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_ERROR_HW_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_ERROR_HW_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAM_STAT_BUSY; break; case IO_XFER_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAM_STAT_BUSY; break; case IO_XFER_ERROR_PHY_NOT_READY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_PHY_NOT_READY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAM_STAT_BUSY; break; case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; break; case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; break; case IO_OPEN_CNX_ERROR_BREAK: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_BREAK\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; @@ -3204,8 +3069,7 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST: case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE: case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); + pm8001_dbg(pm8001_ha, IO, "IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_UNKNOWN; @@ -3214,75 +3078,68 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); break; case IO_OPEN_CNX_ERROR_BAD_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_BAD_DESTINATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_BAD_DEST; break; case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: - PM8001_IO_DBG(pm8001_ha, pm8001_printk(\ - "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_CONN_RATE; break; case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_WRONG_DEST; break; case IO_XFER_ERROR_RX_FRAME: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_ERROR_RX_FRAME\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_ERROR_RX_FRAME\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; break; case IO_XFER_OPEN_RETRY_TIMEOUT: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, IO, "IO_XFER_OPEN_RETRY_TIMEOUT\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_ERROR_INTERNAL_SMP_RESOURCE: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_ERROR_INTERNAL_SMP_RESOURCE\n")); + pm8001_dbg(pm8001_ha, IO, "IO_ERROR_INTERNAL_SMP_RESOURCE\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_QUEUE_FULL; break; case IO_PORT_IN_RESET: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_PORT_IN_RESET\n")); + pm8001_dbg(pm8001_ha, IO, "IO_PORT_IN_RESET\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_DS_NON_OPERATIONAL: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_DS_NON_OPERATIONAL\n")); + pm8001_dbg(pm8001_ha, IO, "IO_DS_NON_OPERATIONAL\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; break; case IO_DS_IN_RECOVERY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_DS_IN_RECOVERY\n")); + pm8001_dbg(pm8001_ha, IO, "IO_DS_IN_RECOVERY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY: - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n")); + pm8001_dbg(pm8001_ha, IO, + "IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n"); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_OPEN_REJECT; ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; break; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("Unknown status 0x%x\n", status)); + pm8001_dbg(pm8001_ha, DEVIO, "Unknown status 0x%x\n", status); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_DEV_NO_RESPONSE; /* not allowed case. Therefore, return failed status */ @@ -3294,10 +3151,9 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) t->task_state_flags |= SAS_TASK_STATE_DONE; if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&t->task_state_lock, flags); - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( - "task 0x%p done with io_status 0x%x resp 0x%x" - "stat 0x%x but aborted by upper layer!\n", - t, status, ts->resp, ts->stat)); + pm8001_dbg(pm8001_ha, FAIL, + "task 0x%p done with io_status 0x%x resp 0x%xstat 0x%x but aborted by upper layer!\n", + t, status, ts->resp, ts->stat); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); } else { spin_unlock_irqrestore(&t->task_state_lock, flags); @@ -3394,38 +3250,34 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) port->port_state = portstate; port->wide_port_phymap |= (1U << phy_id); phy->phy_state = PHY_STATE_LINK_UP_SPCV; - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "portid:%d; phyid:%d; linkrate:%d; " - "portstate:%x; devicetype:%x\n", - port_id, phy_id, link_rate, portstate, deviceType)); + pm8001_dbg(pm8001_ha, MSG, + "portid:%d; phyid:%d; linkrate:%d; portstate:%x; devicetype:%x\n", + port_id, phy_id, link_rate, portstate, deviceType); switch (deviceType) { case SAS_PHY_UNUSED: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("device type no device.\n")); + pm8001_dbg(pm8001_ha, MSG, "device type no device.\n"); break; case SAS_END_DEVICE: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk("end device.\n")); + pm8001_dbg(pm8001_ha, MSG, "end device.\n"); pm80xx_chip_phy_ctl_req(pm8001_ha, phy_id, PHY_NOTIFY_ENABLE_SPINUP); port->port_attached = 1; pm8001_get_lrate_mode(phy, link_rate); break; case SAS_EDGE_EXPANDER_DEVICE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("expander device.\n")); + pm8001_dbg(pm8001_ha, MSG, "expander device.\n"); port->port_attached = 1; pm8001_get_lrate_mode(phy, link_rate); break; case SAS_FANOUT_EXPANDER_DEVICE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("fanout expander device.\n")); + pm8001_dbg(pm8001_ha, MSG, "fanout expander device.\n"); port->port_attached = 1; pm8001_get_lrate_mode(phy, link_rate); break; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("unknown device type(%x)\n", deviceType)); + pm8001_dbg(pm8001_ha, DEVIO, "unknown device type(%x)\n", + deviceType); break; } phy->phy_type |= PORT_TYPE_SAS; @@ -3473,9 +3325,9 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) struct sas_ha_struct *sas_ha = pm8001_ha->sas; struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; unsigned long flags; - PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( - "port id %d, phy id %d link_rate %d portstate 0x%x\n", - port_id, phy_id, link_rate, portstate)); + pm8001_dbg(pm8001_ha, DEVIO, + "port id %d, phy id %d link_rate %d portstate 0x%x\n", + port_id, phy_id, link_rate, portstate); port->port_state = portstate; phy->phy_state = PHY_STATE_LINK_UP_SPCV; @@ -3525,10 +3377,10 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) case PORT_VALID: break; case PORT_INVALID: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" PortInvalid portID %d\n", port_id)); - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" Last phy Down and port invalid\n")); + pm8001_dbg(pm8001_ha, MSG, " PortInvalid portID %d\n", + port_id); + pm8001_dbg(pm8001_ha, MSG, + " Last phy Down and port invalid\n"); if (port_sata) { phy->phy_type = 0; port->port_attached = 0; @@ -3538,19 +3390,18 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) sas_phy_disconnected(&phy->sas_phy); break; case PORT_IN_RESET: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" Port In Reset portID %d\n", port_id)); + pm8001_dbg(pm8001_ha, MSG, " Port In Reset portID %d\n", + port_id); break; case PORT_NOT_ESTABLISHED: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" Phy Down and PORT_NOT_ESTABLISHED\n")); + pm8001_dbg(pm8001_ha, MSG, + " Phy Down and PORT_NOT_ESTABLISHED\n"); port->port_attached = 0; break; case PORT_LOSTCOMM: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" Phy Down and PORT_LOSTCOMM\n")); - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" Last phy Down and port invalid\n")); + pm8001_dbg(pm8001_ha, MSG, " Phy Down and PORT_LOSTCOMM\n"); + pm8001_dbg(pm8001_ha, MSG, + " Last phy Down and port invalid\n"); if (port_sata) { port->port_attached = 0; phy->phy_type = 0; @@ -3561,9 +3412,9 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) break; default: port->port_attached = 0; - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk(" Phy Down and(default) = 0x%x\n", - portstate)); + pm8001_dbg(pm8001_ha, DEVIO, + " Phy Down and(default) = 0x%x\n", + portstate); break; } @@ -3584,9 +3435,9 @@ static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) le32_to_cpu(pPayload->phyid); struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("phy start resp status:0x%x, phyid:0x%x\n", - status, phy_id)); + pm8001_dbg(pm8001_ha, INIT, + "phy start resp status:0x%x, phyid:0x%x\n", + status, phy_id); if (status == 0) { phy->phy_state = PHY_LINK_DOWN; if (pm8001_ha->flags == PM8001F_RUN_TIME && @@ -3613,18 +3464,18 @@ static int mpi_thermal_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) u32 rht_lht = le32_to_cpu(pPayload->rht_lht); if (thermal_event & 0x40) { - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "Thermal Event: Local high temperature violated!\n")); - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "Thermal Event: Measured local high temperature %d\n", - ((rht_lht & 0xFF00) >> 8))); + pm8001_dbg(pm8001_ha, IO, + "Thermal Event: Local high temperature violated!\n"); + pm8001_dbg(pm8001_ha, IO, + "Thermal Event: Measured local high temperature %d\n", + ((rht_lht & 0xFF00) >> 8)); } if (thermal_event & 0x10) { - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "Thermal Event: Remote high temperature violated!\n")); - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "Thermal Event: Measured remote high temperature %d\n", - ((rht_lht & 0xFF000000) >> 24))); + pm8001_dbg(pm8001_ha, IO, + "Thermal Event: Remote high temperature violated!\n"); + pm8001_dbg(pm8001_ha, IO, + "Thermal Event: Measured remote high temperature %d\n", + ((rht_lht & 0xFF000000) >> 24)); } return 0; } @@ -3653,42 +3504,36 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; struct pm8001_port *port = &pm8001_ha->port[port_id]; struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; - PM8001_DEV_DBG(pm8001_ha, - pm8001_printk("portid:%d phyid:%d event:0x%x status:0x%x\n", - port_id, phy_id, eventType, status)); + pm8001_dbg(pm8001_ha, DEV, + "portid:%d phyid:%d event:0x%x status:0x%x\n", + port_id, phy_id, eventType, status); switch (eventType) { case HW_EVENT_SAS_PHY_UP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PHY_START_STATUS\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_START_STATUS\n"); hw_event_sas_phy_up(pm8001_ha, piomb); break; case HW_EVENT_SATA_PHY_UP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_SATA_PHY_UP\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_PHY_UP\n"); hw_event_sata_phy_up(pm8001_ha, piomb); break; case HW_EVENT_SATA_SPINUP_HOLD: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_SATA_SPINUP_HOLD\n"); sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD); break; case HW_EVENT_PHY_DOWN: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PHY_DOWN\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_DOWN\n"); hw_event_phy_down(pm8001_ha, piomb); if (pm8001_ha->reset_in_progress) { - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("Reset in progress\n")); + pm8001_dbg(pm8001_ha, MSG, "Reset in progress\n"); return 0; } phy->phy_attached = 0; phy->phy_state = PHY_LINK_DISABLE; break; case HW_EVENT_PORT_INVALID: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PORT_INVALID\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_INVALID\n"); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); @@ -3696,8 +3541,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) /* the broadcast change primitive received, tell the LIBSAS this event to revalidate the sas domain*/ case HW_EVENT_BROADCAST_CHANGE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_BROADCAST_CHANGE\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_CHANGE\n"); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_BROADCAST_CHANGE, port_id, phy_id, 1, 0); spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); @@ -3706,81 +3550,74 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); break; case HW_EVENT_PHY_ERROR: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PHY_ERROR\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_ERROR\n"); sas_phy_disconnected(&phy->sas_phy); phy->phy_attached = 0; sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR); break; case HW_EVENT_BROADCAST_EXP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_BROADCAST_EXP\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_EXP\n"); spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); sas_phy->sas_prim = HW_EVENT_BROADCAST_EXP; spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); break; case HW_EVENT_LINK_ERR_INVALID_DWORD: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_LINK_ERR_INVALID_DWORD\n")); + pm8001_dbg(pm8001_ha, MSG, + "HW_EVENT_LINK_ERR_INVALID_DWORD\n"); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0); break; case HW_EVENT_LINK_ERR_DISPARITY_ERROR: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_LINK_ERR_DISPARITY_ERROR\n")); + pm8001_dbg(pm8001_ha, MSG, + "HW_EVENT_LINK_ERR_DISPARITY_ERROR\n"); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_DISPARITY_ERROR, port_id, phy_id, 0, 0); break; case HW_EVENT_LINK_ERR_CODE_VIOLATION: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_LINK_ERR_CODE_VIOLATION\n")); + pm8001_dbg(pm8001_ha, MSG, + "HW_EVENT_LINK_ERR_CODE_VIOLATION\n"); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_CODE_VIOLATION, port_id, phy_id, 0, 0); break; case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH\n")); + pm8001_dbg(pm8001_ha, MSG, + "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH\n"); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH, port_id, phy_id, 0, 0); break; case HW_EVENT_MALFUNCTION: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_MALFUNCTION\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_MALFUNCTION\n"); break; case HW_EVENT_BROADCAST_SES: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_BROADCAST_SES\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_BROADCAST_SES\n"); spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); sas_phy->sas_prim = HW_EVENT_BROADCAST_SES; spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); break; case HW_EVENT_INBOUND_CRC_ERROR: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_INBOUND_CRC_ERROR\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_INBOUND_CRC_ERROR\n"); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_INBOUND_CRC_ERROR, port_id, phy_id, 0, 0); break; case HW_EVENT_HARD_RESET_RECEIVED: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_HARD_RESET_RECEIVED\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_HARD_RESET_RECEIVED\n"); sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET); break; case HW_EVENT_ID_FRAME_TIMEOUT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_ID_FRAME_TIMEOUT\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_ID_FRAME_TIMEOUT\n"); sas_phy_disconnected(sas_phy); phy->phy_attached = 0; sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_LINK_ERR_PHY_RESET_FAILED: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n")); + pm8001_dbg(pm8001_ha, MSG, + "HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n"); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_LINK_ERR_PHY_RESET_FAILED, port_id, phy_id, 0, 0); @@ -3789,8 +3626,7 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); break; case HW_EVENT_PORT_RESET_TIMER_TMO: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PORT_RESET_TIMER_TMO\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_TIMER_TMO\n"); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN, port_id, phy_id, 0, 0); sas_phy_disconnected(sas_phy); @@ -3804,8 +3640,8 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case HW_EVENT_PORT_RECOVERY_TIMER_TMO: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PORT_RECOVERY_TIMER_TMO\n")); + pm8001_dbg(pm8001_ha, MSG, + "HW_EVENT_PORT_RECOVERY_TIMER_TMO\n"); pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PORT_RECOVERY_TIMER_TMO, port_id, phy_id, 0, 0); @@ -3819,13 +3655,11 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case HW_EVENT_PORT_RECOVER: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PORT_RECOVER\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RECOVER\n"); hw_event_port_recover(pm8001_ha, piomb); break; case HW_EVENT_PORT_RESET_COMPLETE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("HW_EVENT_PORT_RESET_COMPLETE\n")); + pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PORT_RESET_COMPLETE\n"); if (pm8001_ha->phy[phy_id].reset_completion) { pm8001_ha->phy[phy_id].port_reset_status = PORT_RESET_SUCCESS; @@ -3834,12 +3668,11 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) } break; case EVENT_BROADCAST_ASYNCH_EVENT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("EVENT_BROADCAST_ASYNCH_EVENT\n")); + pm8001_dbg(pm8001_ha, MSG, "EVENT_BROADCAST_ASYNCH_EVENT\n"); break; default: - PM8001_DEVIO_DBG(pm8001_ha, - pm8001_printk("Unknown event type 0x%x\n", eventType)); + pm8001_dbg(pm8001_ha, DEVIO, "Unknown event type 0x%x\n", + eventType); break; } return 0; @@ -3859,9 +3692,8 @@ static int mpi_phy_stop_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) u32 phyid = le32_to_cpu(pPayload->phyid) & 0xFF; struct pm8001_phy *phy = &pm8001_ha->phy[phyid]; - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("phy:0x%x status:0x%x\n", - phyid, status)); + pm8001_dbg(pm8001_ha, MSG, "phy:0x%x status:0x%x\n", + phyid, status); if (status == PHY_STOP_SUCCESS || status == PHY_STOP_ERR_DEVICE_ATTACHED) phy->phy_state = PHY_LINK_DISABLE; @@ -3881,9 +3713,9 @@ static int mpi_set_controller_config_resp(struct pm8001_hba_info *pm8001_ha, u32 status = le32_to_cpu(pPayload->status); u32 err_qlfr_pgcd = le32_to_cpu(pPayload->err_qlfr_pgcd); - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "SET CONTROLLER RESP: status 0x%x qlfr_pgcd 0x%x\n", - status, err_qlfr_pgcd)); + pm8001_dbg(pm8001_ha, MSG, + "SET CONTROLLER RESP: status 0x%x qlfr_pgcd 0x%x\n", + status, err_qlfr_pgcd); return 0; } @@ -3896,8 +3728,7 @@ static int mpi_set_controller_config_resp(struct pm8001_hba_info *pm8001_ha, static int mpi_get_controller_config_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) { - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" pm80xx_addition_functionality\n")); + pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n"); return 0; } @@ -3910,8 +3741,7 @@ static int mpi_get_controller_config_resp(struct pm8001_hba_info *pm8001_ha, static int mpi_get_phy_profile_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) { - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" pm80xx_addition_functionality\n")); + pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n"); return 0; } @@ -3923,8 +3753,7 @@ static int mpi_get_phy_profile_resp(struct pm8001_hba_info *pm8001_ha, */ static int mpi_flash_op_ext_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) { - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" pm80xx_addition_functionality\n")); + pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n"); return 0; } @@ -3949,15 +3778,14 @@ static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha, page_code = (u8)((ppc_phyid & 0xFF00) >> 8); if (status) { /* status is FAILED */ - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("PhyProfile command failed with status " - "0x%08X \n", status)); + pm8001_dbg(pm8001_ha, FAIL, + "PhyProfile command failed with status 0x%08X\n", + status); rc = -1; } else { if (page_code != SAS_PHY_ANALOG_SETTINGS_PAGE) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("Invalid page code 0x%X\n", - page_code)); + pm8001_dbg(pm8001_ha, FAIL, "Invalid page code 0x%X\n", + page_code); rc = -1; } } @@ -3979,9 +3807,9 @@ static int mpi_kek_management_resp(struct pm8001_hba_info *pm8001_ha, u32 kidx_new_curr_ksop = le32_to_cpu(pPayload->kidx_new_curr_ksop); u32 err_qlfr = le32_to_cpu(pPayload->err_qlfr); - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "KEK MGMT RESP. Status 0x%x idx_ksop 0x%x err_qlfr 0x%x\n", - status, kidx_new_curr_ksop, err_qlfr)); + pm8001_dbg(pm8001_ha, MSG, + "KEK MGMT RESP. Status 0x%x idx_ksop 0x%x err_qlfr 0x%x\n", + status, kidx_new_curr_ksop, err_qlfr); return 0; } @@ -3994,8 +3822,7 @@ static int mpi_kek_management_resp(struct pm8001_hba_info *pm8001_ha, static int mpi_dek_management_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) { - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" pm80xx_addition_functionality\n")); + pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n"); return 0; } @@ -4008,8 +3835,7 @@ static int mpi_dek_management_resp(struct pm8001_hba_info *pm8001_ha, static int ssp_coalesced_comp_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) { - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk(" pm80xx_addition_functionality\n")); + pm8001_dbg(pm8001_ha, MSG, " pm80xx_addition_functionality\n"); return 0; } @@ -4026,248 +3852,206 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) switch (opc) { case OPC_OUB_ECHO: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk("OPC_OUB_ECHO\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_ECHO\n"); break; case OPC_OUB_HW_EVENT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_HW_EVENT\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_HW_EVENT\n"); mpi_hw_event(pm8001_ha, piomb); break; case OPC_OUB_THERM_HW_EVENT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_THERMAL_EVENT\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_THERMAL_EVENT\n"); mpi_thermal_hw_event(pm8001_ha, piomb); break; case OPC_OUB_SSP_COMP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SSP_COMP\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_COMP\n"); mpi_ssp_completion(pm8001_ha, piomb); break; case OPC_OUB_SMP_COMP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SMP_COMP\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SMP_COMP\n"); mpi_smp_completion(pm8001_ha, piomb); break; case OPC_OUB_LOCAL_PHY_CNTRL: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_LOCAL_PHY_CNTRL\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_LOCAL_PHY_CNTRL\n"); pm8001_mpi_local_phy_ctl(pm8001_ha, piomb); break; case OPC_OUB_DEV_REGIST: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_DEV_REGIST\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEV_REGIST\n"); pm8001_mpi_reg_resp(pm8001_ha, piomb); break; case OPC_OUB_DEREG_DEV: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("unregister the device\n")); + pm8001_dbg(pm8001_ha, MSG, "unregister the device\n"); pm8001_mpi_dereg_resp(pm8001_ha, piomb); break; case OPC_OUB_GET_DEV_HANDLE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_GET_DEV_HANDLE\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_DEV_HANDLE\n"); break; case OPC_OUB_SATA_COMP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SATA_COMP\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_COMP\n"); mpi_sata_completion(pm8001_ha, piomb); break; case OPC_OUB_SATA_EVENT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SATA_EVENT\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_EVENT\n"); mpi_sata_event(pm8001_ha, piomb); break; case OPC_OUB_SSP_EVENT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SSP_EVENT\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_EVENT\n"); mpi_ssp_event(pm8001_ha, piomb); break; case OPC_OUB_DEV_HANDLE_ARRIV: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_DEV_HANDLE_ARRIV\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEV_HANDLE_ARRIV\n"); /*This is for target*/ break; case OPC_OUB_SSP_RECV_EVENT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SSP_RECV_EVENT\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_RECV_EVENT\n"); /*This is for target*/ break; case OPC_OUB_FW_FLASH_UPDATE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_FW_FLASH_UPDATE\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_FW_FLASH_UPDATE\n"); pm8001_mpi_fw_flash_update_resp(pm8001_ha, piomb); break; case OPC_OUB_GPIO_RESPONSE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_GPIO_RESPONSE\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GPIO_RESPONSE\n"); break; case OPC_OUB_GPIO_EVENT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_GPIO_EVENT\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GPIO_EVENT\n"); break; case OPC_OUB_GENERAL_EVENT: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_GENERAL_EVENT\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GENERAL_EVENT\n"); pm8001_mpi_general_event(pm8001_ha, piomb); break; case OPC_OUB_SSP_ABORT_RSP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SSP_ABORT_RSP\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SSP_ABORT_RSP\n"); pm8001_mpi_task_abort_resp(pm8001_ha, piomb); break; case OPC_OUB_SATA_ABORT_RSP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SATA_ABORT_RSP\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SATA_ABORT_RSP\n"); pm8001_mpi_task_abort_resp(pm8001_ha, piomb); break; case OPC_OUB_SAS_DIAG_MODE_START_END: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SAS_DIAG_MODE_START_END\n")); + pm8001_dbg(pm8001_ha, MSG, + "OPC_OUB_SAS_DIAG_MODE_START_END\n"); break; case OPC_OUB_SAS_DIAG_EXECUTE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SAS_DIAG_EXECUTE\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SAS_DIAG_EXECUTE\n"); break; case OPC_OUB_GET_TIME_STAMP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_GET_TIME_STAMP\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_TIME_STAMP\n"); break; case OPC_OUB_SAS_HW_EVENT_ACK: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SAS_HW_EVENT_ACK\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SAS_HW_EVENT_ACK\n"); break; case OPC_OUB_PORT_CONTROL: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_PORT_CONTROL\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_PORT_CONTROL\n"); break; case OPC_OUB_SMP_ABORT_RSP: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SMP_ABORT_RSP\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SMP_ABORT_RSP\n"); pm8001_mpi_task_abort_resp(pm8001_ha, piomb); break; case OPC_OUB_GET_NVMD_DATA: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_GET_NVMD_DATA\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_NVMD_DATA\n"); pm8001_mpi_get_nvmd_resp(pm8001_ha, piomb); break; case OPC_OUB_SET_NVMD_DATA: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SET_NVMD_DATA\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_NVMD_DATA\n"); pm8001_mpi_set_nvmd_resp(pm8001_ha, piomb); break; case OPC_OUB_DEVICE_HANDLE_REMOVAL: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_DEVICE_HANDLE_REMOVAL\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_DEVICE_HANDLE_REMOVAL\n"); break; case OPC_OUB_SET_DEVICE_STATE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SET_DEVICE_STATE\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_DEVICE_STATE\n"); pm8001_mpi_set_dev_state_resp(pm8001_ha, piomb); break; case OPC_OUB_GET_DEVICE_STATE: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_GET_DEVICE_STATE\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_GET_DEVICE_STATE\n"); break; case OPC_OUB_SET_DEV_INFO: - PM8001_MSG_DBG(pm8001_ha, - pm8001_printk("OPC_OUB_SET_DEV_INFO\n")); + pm8001_dbg(pm8001_ha, MSG, "OPC_OUB_SET_DEV_INFO\n"); break; /* spcv specifc commands */ case OPC_OUB_PHY_START_RESP: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "OPC_OUB_PHY_START_RESP opcode:%x\n", opc)); + pm8001_dbg(pm8001_ha, MSG, + "OPC_OUB_PHY_START_RESP opcode:%x\n", opc); mpi_phy_start_resp(pm8001_ha, piomb); break; case OPC_OUB_PHY_STOP_RESP: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "OPC_OUB_PHY_STOP_RESP opcode:%x\n", opc)); + pm8001_dbg(pm8001_ha, MSG, + "OPC_OUB_PHY_STOP_RESP opcode:%x\n", opc); mpi_phy_stop_resp(pm8001_ha, piomb); break; case OPC_OUB_SET_CONTROLLER_CONFIG: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "OPC_OUB_SET_CONTROLLER_CONFIG opcode:%x\n", opc)); + pm8001_dbg(pm8001_ha, MSG, + "OPC_OUB_SET_CONTROLLER_CONFIG opcode:%x\n", opc); mpi_set_controller_config_resp(pm8001_ha, piomb); break; case OPC_OUB_GET_CONTROLLER_CONFIG: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "OPC_OUB_GET_CONTROLLER_CONFIG opcode:%x\n", opc)); + pm8001_dbg(pm8001_ha, MSG, + "OPC_OUB_GET_CONTROLLER_CONFIG opcode:%x\n", opc); mpi_get_controller_config_resp(pm8001_ha, piomb); break; case OPC_OUB_GET_PHY_PROFILE: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "OPC_OUB_GET_PHY_PROFILE opcode:%x\n", opc)); + pm8001_dbg(pm8001_ha, MSG, + "OPC_OUB_GET_PHY_PROFILE opcode:%x\n", opc); mpi_get_phy_profile_resp(pm8001_ha, piomb); break; case OPC_OUB_FLASH_OP_EXT: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "OPC_OUB_FLASH_OP_EXT opcode:%x\n", opc)); + pm8001_dbg(pm8001_ha, MSG, + "OPC_OUB_FLASH_OP_EXT opcode:%x\n", opc); mpi_flash_op_ext_resp(pm8001_ha, piomb); break; case OPC_OUB_SET_PHY_PROFILE: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "OPC_OUB_SET_PHY_PROFILE opcode:%x\n", opc)); + pm8001_dbg(pm8001_ha, MSG, + "OPC_OUB_SET_PHY_PROFILE opcode:%x\n", opc); mpi_set_phy_profile_resp(pm8001_ha, piomb); break; case OPC_OUB_KEK_MANAGEMENT_RESP: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "OPC_OUB_KEK_MANAGEMENT_RESP opcode:%x\n", opc)); + pm8001_dbg(pm8001_ha, MSG, + "OPC_OUB_KEK_MANAGEMENT_RESP opcode:%x\n", opc); mpi_kek_management_resp(pm8001_ha, piomb); break; case OPC_OUB_DEK_MANAGEMENT_RESP: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "OPC_OUB_DEK_MANAGEMENT_RESP opcode:%x\n", opc)); + pm8001_dbg(pm8001_ha, MSG, + "OPC_OUB_DEK_MANAGEMENT_RESP opcode:%x\n", opc); mpi_dek_management_resp(pm8001_ha, piomb); break; case OPC_OUB_SSP_COALESCED_COMP_RESP: - PM8001_MSG_DBG(pm8001_ha, pm8001_printk( - "OPC_OUB_SSP_COALESCED_COMP_RESP opcode:%x\n", opc)); + pm8001_dbg(pm8001_ha, MSG, + "OPC_OUB_SSP_COALESCED_COMP_RESP opcode:%x\n", opc); ssp_coalesced_comp_resp(pm8001_ha, piomb); break; default: - PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( - "Unknown outbound Queue IOMB OPC = 0x%x\n", opc)); + pm8001_dbg(pm8001_ha, DEVIO, + "Unknown outbound Queue IOMB OPC = 0x%x\n", opc); break; } } static void print_scratchpad_registers(struct pm8001_hba_info *pm8001_ha) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("MSGU_SCRATCH_PAD_0: 0x%x\n", - pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0))); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("MSGU_SCRATCH_PAD_1:0x%x\n", - pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1))); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("MSGU_SCRATCH_PAD_2: 0x%x\n", - pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2))); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("MSGU_SCRATCH_PAD_3: 0x%x\n", - pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3))); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("MSGU_HOST_SCRATCH_PAD_0: 0x%x\n", - pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_0))); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("MSGU_HOST_SCRATCH_PAD_1: 0x%x\n", - pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_1))); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("MSGU_HOST_SCRATCH_PAD_2: 0x%x\n", - pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_2))); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("MSGU_HOST_SCRATCH_PAD_3: 0x%x\n", - pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_3))); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("MSGU_HOST_SCRATCH_PAD_4: 0x%x\n", - pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_4))); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("MSGU_HOST_SCRATCH_PAD_5: 0x%x\n", - pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_5))); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("MSGU_RSVD_SCRATCH_PAD_0: 0x%x\n", - pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_6))); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("MSGU_RSVD_SCRATCH_PAD_1: 0x%x\n", - pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_7))); + pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_0: 0x%x\n", + pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0)); + pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_1:0x%x\n", + pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1)); + pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_2: 0x%x\n", + pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_2)); + pm8001_dbg(pm8001_ha, FAIL, "MSGU_SCRATCH_PAD_3: 0x%x\n", + pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3)); + pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_0: 0x%x\n", + pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_0)); + pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_1: 0x%x\n", + pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_1)); + pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_2: 0x%x\n", + pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_2)); + pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_3: 0x%x\n", + pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_3)); + pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_4: 0x%x\n", + pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_4)); + pm8001_dbg(pm8001_ha, FAIL, "MSGU_HOST_SCRATCH_PAD_5: 0x%x\n", + pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_5)); + pm8001_dbg(pm8001_ha, FAIL, "MSGU_RSVD_SCRATCH_PAD_0: 0x%x\n", + pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_6)); + pm8001_dbg(pm8001_ha, FAIL, "MSGU_RSVD_SCRATCH_PAD_1: 0x%x\n", + pm8001_cr32(pm8001_ha, 0, MSGU_HOST_SCRATCH_PAD_7)); } static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) @@ -4284,8 +4068,9 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) if ((regval & SCRATCH_PAD_MIPSALL_READY) != SCRATCH_PAD_MIPSALL_READY) { pm8001_ha->controller_fatal_error = true; - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( - "Firmware Fatal error! Regval:0x%x\n", regval)); + pm8001_dbg(pm8001_ha, FAIL, + "Firmware Fatal error! Regval:0x%x\n", + regval); print_scratchpad_registers(pm8001_ha); return ret; } @@ -4391,8 +4176,7 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, smp_cmd.tag = cpu_to_le32(ccb->ccb_tag); length = sg_req->length; - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("SMP Frame Length %d\n", sg_req->length)); + pm8001_dbg(pm8001_ha, IO, "SMP Frame Length %d\n", sg_req->length); if (!(length - 8)) pm8001_ha->smp_exp_mode = SMP_DIRECT; else @@ -4404,8 +4188,7 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, /* INDIRECT MODE command settings. Use DMA */ if (pm8001_ha->smp_exp_mode == SMP_INDIRECT) { - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("SMP REQUEST INDIRECT MODE\n")); + pm8001_dbg(pm8001_ha, IO, "SMP REQUEST INDIRECT MODE\n"); /* for SPCv indirect mode. Place the top 4 bytes of * SMP Request header here. */ for (i = 0; i < 4; i++) @@ -4437,21 +4220,20 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, ((u32)sg_dma_len(&task->smp_task.smp_resp)-4); } if (pm8001_ha->smp_exp_mode == SMP_DIRECT) { - PM8001_IO_DBG(pm8001_ha, - pm8001_printk("SMP REQUEST DIRECT MODE\n")); + pm8001_dbg(pm8001_ha, IO, "SMP REQUEST DIRECT MODE\n"); for (i = 0; i < length; i++) if (i < 16) { smp_cmd.smp_req16[i] = *(preq_dma_addr+i); - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "Byte[%d]:%x (DMA data:%x)\n", - i, smp_cmd.smp_req16[i], - *(preq_dma_addr))); + pm8001_dbg(pm8001_ha, IO, + "Byte[%d]:%x (DMA data:%x)\n", + i, smp_cmd.smp_req16[i], + *(preq_dma_addr)); } else { smp_cmd.smp_req[i] = *(preq_dma_addr+i); - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "Byte[%d]:%x (DMA data:%x)\n", - i, smp_cmd.smp_req[i], - *(preq_dma_addr))); + pm8001_dbg(pm8001_ha, IO, + "Byte[%d]:%x (DMA data:%x)\n", + i, smp_cmd.smp_req[i], + *(preq_dma_addr)); } } @@ -4548,9 +4330,9 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, /* Check if encryption is set */ if (pm8001_ha->chip->encrypt && !(pm8001_ha->encrypt_info.status) && check_enc_sas_cmd(task)) { - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "Encryption enabled.Sending Encrypt SAS command 0x%x\n", - task->ssp_task.cmd->cmnd[0])); + pm8001_dbg(pm8001_ha, IO, + "Encryption enabled.Sending Encrypt SAS command 0x%x\n", + task->ssp_task.cmd->cmnd[0]); opc = OPC_INB_SSP_INI_DIF_ENC_IO; /* enable encryption. 0 for SAS 1.1 and SAS 2.0 compatible TLR*/ ssp_cmd.dad_dir_m_tlr = cpu_to_le32 @@ -4580,13 +4362,10 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); if (end_addr_high != ssp_cmd.enc_addr_high) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("The sg list address " - "start_addr=0x%016llx data_len=0x%x " - "end_addr_high=0x%08x end_addr_low=" - "0x%08x has crossed 4G boundary\n", - start_addr, ssp_cmd.enc_len, - end_addr_high, end_addr_low)); + pm8001_dbg(pm8001_ha, FAIL, + "The sg list address start_addr=0x%016llx data_len=0x%x end_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n", + start_addr, ssp_cmd.enc_len, + end_addr_high, end_addr_low); pm8001_chip_make_sg(task->scatter, 1, ccb->buf_prd); phys_addr = ccb->ccb_dma_handle; @@ -4610,9 +4389,9 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, (task->ssp_task.cmd->cmnd[4] << 8) | (task->ssp_task.cmd->cmnd[5])); } else { - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "Sending Normal SAS command 0x%x inb q %x\n", - task->ssp_task.cmd->cmnd[0], q_index)); + pm8001_dbg(pm8001_ha, IO, + "Sending Normal SAS command 0x%x inb q %x\n", + task->ssp_task.cmd->cmnd[0], q_index); /* fill in PRD (scatter/gather) table, if any */ if (task->num_scatter > 1) { pm8001_chip_make_sg(task->scatter, ccb->n_elem, @@ -4636,13 +4415,10 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); if (end_addr_high != ssp_cmd.addr_high) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("The sg list address " - "start_addr=0x%016llx data_len=0x%x " - "end_addr_high=0x%08x end_addr_low=" - "0x%08x has crossed 4G boundary\n", - start_addr, ssp_cmd.len, - end_addr_high, end_addr_low)); + pm8001_dbg(pm8001_ha, FAIL, + "The sg list address start_addr=0x%016llx data_len=0x%x end_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n", + start_addr, ssp_cmd.len, + end_addr_high, end_addr_low); pm8001_chip_make_sg(task->scatter, 1, ccb->buf_prd); phys_addr = ccb->ccb_dma_handle; @@ -4689,19 +4465,19 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, if (task->data_dir == DMA_NONE) { ATAP = 0x04; /* no data*/ - PM8001_IO_DBG(pm8001_ha, pm8001_printk("no data\n")); + pm8001_dbg(pm8001_ha, IO, "no data\n"); } else if (likely(!task->ata_task.device_control_reg_update)) { if (task->ata_task.dma_xfer) { ATAP = 0x06; /* DMA */ - PM8001_IO_DBG(pm8001_ha, pm8001_printk("DMA\n")); + pm8001_dbg(pm8001_ha, IO, "DMA\n"); } else { ATAP = 0x05; /* PIO*/ - PM8001_IO_DBG(pm8001_ha, pm8001_printk("PIO\n")); + pm8001_dbg(pm8001_ha, IO, "PIO\n"); } if (task->ata_task.use_ncq && dev->sata_dev.class != ATA_DEV_ATAPI) { ATAP = 0x07; /* FPDMA */ - PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n")); + pm8001_dbg(pm8001_ha, IO, "FPDMA\n"); } } if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) { @@ -4721,9 +4497,9 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, /* Check if encryption is set */ if (pm8001_ha->chip->encrypt && !(pm8001_ha->encrypt_info.status) && check_enc_sat_cmd(task)) { - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "Encryption enabled.Sending Encrypt SATA cmd 0x%x\n", - sata_cmd.sata_fis.command)); + pm8001_dbg(pm8001_ha, IO, + "Encryption enabled.Sending Encrypt SATA cmd 0x%x\n", + sata_cmd.sata_fis.command); opc = OPC_INB_SATA_DIF_ENC_IO; /* set encryption bit */ @@ -4751,13 +4527,10 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); if (end_addr_high != sata_cmd.enc_addr_high) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("The sg list address " - "start_addr=0x%016llx data_len=0x%x " - "end_addr_high=0x%08x end_addr_low" - "=0x%08x has crossed 4G boundary\n", - start_addr, sata_cmd.enc_len, - end_addr_high, end_addr_low)); + pm8001_dbg(pm8001_ha, FAIL, + "The sg list address start_addr=0x%016llx data_len=0x%x end_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n", + start_addr, sata_cmd.enc_len, + end_addr_high, end_addr_low); pm8001_chip_make_sg(task->scatter, 1, ccb->buf_prd); phys_addr = ccb->ccb_dma_handle; @@ -4786,9 +4559,9 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, cpu_to_le32((sata_cmd.sata_fis.lbah_exp << 8) | (sata_cmd.sata_fis.lbam_exp)); } else { - PM8001_IO_DBG(pm8001_ha, pm8001_printk( - "Sending Normal SATA command 0x%x inb %x\n", - sata_cmd.sata_fis.command, q_index)); + pm8001_dbg(pm8001_ha, IO, + "Sending Normal SATA command 0x%x inb %x\n", + sata_cmd.sata_fis.command, q_index); /* dad (bit 0-1) is 0 */ sata_cmd.ncqtag_atap_dir_m_dad = cpu_to_le32(((ncg_tag & 0xff)<<16) | @@ -4814,13 +4587,10 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, end_addr_low = cpu_to_le32(lower_32_bits(end_addr)); end_addr_high = cpu_to_le32(upper_32_bits(end_addr)); if (end_addr_high != sata_cmd.addr_high) { - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("The sg list address " - "start_addr=0x%016llx data_len=0x%x" - "end_addr_high=0x%08x end_addr_low=" - "0x%08x has crossed 4G boundary\n", - start_addr, sata_cmd.len, - end_addr_high, end_addr_low)); + pm8001_dbg(pm8001_ha, FAIL, + "The sg list address start_addr=0x%016llx data_len=0x%xend_addr_high=0x%08x end_addr_low=0x%08x has crossed 4G boundary\n", + start_addr, sata_cmd.len, + end_addr_high, end_addr_low); pm8001_chip_make_sg(task->scatter, 1, ccb->buf_prd); phys_addr = ccb->ccb_dma_handle; @@ -4879,10 +4649,10 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, SAS_TASK_STATE_ABORTED))) { spin_unlock_irqrestore(&task->task_state_lock, flags); - PM8001_FAIL_DBG(pm8001_ha, - pm8001_printk("task 0x%p resp 0x%x " - " stat 0x%x but aborted by upper layer " - "\n", task, ts->resp, ts->stat)); + pm8001_dbg(pm8001_ha, FAIL, + "task 0x%p resp 0x%x stat 0x%x but aborted by upper layer\n", + task, ts->resp, + ts->stat); pm8001_ccb_task_free(pm8001_ha, task, ccb, tag); return 0; } else { @@ -4917,8 +4687,7 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) memset(&payload, 0, sizeof(payload)); payload.tag = cpu_to_le32(tag); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("PHY START REQ for phy_id %d\n", phy_id)); + pm8001_dbg(pm8001_ha, INIT, "PHY START REQ for phy_id %d\n", phy_id); payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | LINKMODE_AUTO | pm8001_ha->link_rate | phy_id); @@ -5082,9 +4851,9 @@ static irqreturn_t pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec) { pm80xx_chip_interrupt_disable(pm8001_ha, vec); - PM8001_DEVIO_DBG(pm8001_ha, pm8001_printk( - "irq vec %d, ODMR:0x%x\n", - vec, pm8001_cr32(pm8001_ha, 0, 0x30))); + pm8001_dbg(pm8001_ha, DEVIO, + "irq vec %d, ODMR:0x%x\n", + vec, pm8001_cr32(pm8001_ha, 0, 0x30)); process_oq(pm8001_ha, vec); pm80xx_chip_interrupt_enable(pm8001_ha, vec); return IRQ_HANDLED; @@ -5103,13 +4872,13 @@ static void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha, memset(&payload, 0, sizeof(payload)); rc = pm8001_tag_alloc(pm8001_ha, &tag); if (rc) - PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Invalid tag\n")); + pm8001_dbg(pm8001_ha, FAIL, "Invalid tag\n"); circularQ = &pm8001_ha->inbnd_q_tbl[0]; payload.tag = cpu_to_le32(tag); payload.ppc_phyid = (((operation & 0xF) << 8) | (phyid & 0xFF)); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk(" phy profile command for phy %x ,length is %d\n", - payload.ppc_phyid, length)); + pm8001_dbg(pm8001_ha, INIT, + " phy profile command for phy %x ,length is %d\n", + payload.ppc_phyid, length); for (i = length; i < (length + PHY_DWORD_LENGTH - 1); i++) { payload.reserved[j] = cpu_to_le32(*((u32 *)buf + i)); j++; @@ -5130,7 +4899,7 @@ void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, SAS_PHY_ANALOG_SETTINGS_PAGE, i, length, (u32 *)buf); length = length + PHY_DWORD_LENGTH; } - PM8001_INIT_DBG(pm8001_ha, pm8001_printk("phy settings completed\n")); + pm8001_dbg(pm8001_ha, INIT, "phy settings completed\n"); } void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha, @@ -5145,7 +4914,7 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha, rc = pm8001_tag_alloc(pm8001_ha, &tag); if (rc) - PM8001_INIT_DBG(pm8001_ha, pm8001_printk("Invalid tag")); + pm8001_dbg(pm8001_ha, INIT, "Invalid tag\n"); circularQ = &pm8001_ha->inbnd_q_tbl[0]; opc = OPC_INB_SET_PHY_PROFILE; @@ -5162,8 +4931,7 @@ void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha, if (rc) pm8001_tag_free(pm8001_ha, tag); - PM8001_INIT_DBG(pm8001_ha, - pm8001_printk("PHY %d settings applied", phy)); + pm8001_dbg(pm8001_ha, INIT, "PHY %d settings applied\n", phy); } const struct pm8001_dispatch pm8001_80xx_dispatch = { .name = "pmc80xx", -- cgit v1.2.3 From 89eddb401080a1969f0ef67fbd19123062e64a0b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 20 Nov 2020 15:16:10 -0800 Subject: scsi: pm8001: Make implicit use of pm8001_ha in pm8001_printk() explicit Make the pm8001_printk() macro take an explicit HBA instead of assuming the existence of an unspecified pm8001_ha argument. Miscellanea: - Add pm8001_ha to the few uses of pm8001_printk() - Add HBA to the pm8001_dbg macro call to pm8001_printk() Link: https://lore.kernel.org/r/0e17a4c845f15e18f98b346ffb9b039584d21cdd.1605914030.git.joe@perches.com Acked-by: Jack Wang Signed-off-by: Joe Perches Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_init.c | 11 +++++------ drivers/scsi/pm8001/pm8001_sas.c | 4 ++-- drivers/scsi/pm8001/pm8001_sas.h | 6 +++--- 3 files changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 43ba55842602..a6b3f1f8c806 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -1293,9 +1293,8 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state) tasklet_kill(&pm8001_ha->tasklet[j]); #endif device_state = pci_choose_state(pdev, state); - pm8001_printk("pdev=0x%p, slot=%s, entering " - "operating state [D%d]\n", pdev, - pm8001_ha->name, device_state); + pm8001_printk(pm8001_ha, "pdev=0x%p, slot=%s, entering operating state [D%d]\n", + pdev, pm8001_ha->name, device_state); pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, device_state); @@ -1319,15 +1318,15 @@ static int pm8001_pci_resume(struct pci_dev *pdev) pm8001_ha = sha->lldd_ha; device_state = pdev->current_state; - pm8001_printk("pdev=0x%p, slot=%s, resuming from previous " - "operating state [D%d]\n", pdev, pm8001_ha->name, device_state); + pm8001_printk(pm8001_ha, "pdev=0x%p, slot=%s, resuming from previous operating state [D%d]\n", + pdev, pm8001_ha->name, device_state); pci_set_power_state(pdev, PCI_D0); pci_enable_wake(pdev, PCI_D0, 0); pci_restore_state(pdev); rc = pci_enable_device(pdev); if (rc) { - pm8001_printk("slot=%s Enable device failed during resume\n", + pm8001_printk(pm8001_ha, "slot=%s Enable device failed during resume\n", pm8001_ha->name); goto err_out_enable; } diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 505a885b4c77..4562b0a5062a 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -1191,7 +1191,7 @@ int pm8001_abort_task(struct sas_task *task) phy_id = pm8001_dev->attached_phy; ret = pm8001_find_tag(task, &tag); if (ret == 0) { - pm8001_printk("no tag for task:%p\n", task); + pm8001_printk(pm8001_ha, "no tag for task:%p\n", task); return TMF_RESP_FUNC_FAILED; } spin_lock_irqsave(&task->task_state_lock, flags); @@ -1313,7 +1313,7 @@ out: task->slow_task = NULL; spin_unlock_irqrestore(&task->task_state_lock, flags); if (rc != TMF_RESP_FUNC_COMPLETE) - pm8001_printk("rc= %d\n", rc); + pm8001_printk(pm8001_ha, "rc= %d\n", rc); return rc; } diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 5cd6fe6a7d2d..5266756a268b 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -70,14 +70,14 @@ #define PM8001_DEVIO_LOGGING 0x100 /* development io message logging */ #define PM8001_IOERR_LOGGING 0x200 /* development io err message logging */ -#define pm8001_printk(fmt, ...) \ +#define pm8001_printk(HBA, fmt, ...) \ pr_info("%s:: %s %d:" fmt, \ - pm8001_ha->name, __func__, __LINE__, ##__VA_ARGS__) + (HBA)->name, __func__, __LINE__, ##__VA_ARGS__) #define pm8001_dbg(HBA, level, fmt, ...) \ do { \ if (unlikely((HBA)->logging_level & PM8001_##level##_LOGGING)) \ - pm8001_printk(fmt, ##__VA_ARGS__); \ + pm8001_printk(HBA, fmt, ##__VA_ARGS__); \ } while (0) #define PM8001_USE_TASKLET -- cgit v1.2.3 From 90b3a938031fd2da2000f84e58223971ad8f6df3 Mon Sep 17 00:00:00 2001 From: Karan Tilak Kumar Date: Fri, 20 Nov 2020 14:07:12 -0800 Subject: scsi: fnic: Change shost_printk() to FNIC_FCS_DBG() Replacing shost_printk with FNIC_FCS_DBG() so that these log messages are controlled by fnic_log_level flag in fnic_fip_handler_timer. Bumping up version number from 47 to 49 to maintain same level as internal version. Link: https://lore.kernel.org/r/20201120220712.16708-1-kartilak@cisco.com Reviewed-by: Arulprabhu Ponnusamy Co-developed-by: Satish Kharat Signed-off-by: Satish Kharat Signed-off-by: Karan Tilak Kumar Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic.h | 2 +- drivers/scsi/fnic/fnic_fcs.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 477513dc23b7..ed00b6061e0c 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -39,7 +39,7 @@ #define DRV_NAME "fnic" #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" -#define DRV_VERSION "1.6.0.47" +#define DRV_VERSION "1.6.0.49" #define PFX DRV_NAME ": " #define DFX DRV_NAME "%d: " diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c index e3384afb7cbd..3fc3a7271dc1 100644 --- a/drivers/scsi/fnic/fnic_fcs.c +++ b/drivers/scsi/fnic/fnic_fcs.c @@ -1349,7 +1349,7 @@ void fnic_handle_fip_timer(struct fnic *fnic) } vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list); - shost_printk(KERN_DEBUG, fnic->lport->host, + FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "fip_timer: vlan %d state %d sol_count %d\n", vlan->vid, vlan->state, vlan->sol_count); switch (vlan->state) { @@ -1372,7 +1372,7 @@ void fnic_handle_fip_timer(struct fnic *fnic) * no response on this vlan, remove from the list. * Try the next vlan */ - shost_printk(KERN_INFO, fnic->lport->host, + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, "Dequeue this VLAN ID %d from list\n", vlan->vid); list_del(&vlan->list); @@ -1382,7 +1382,7 @@ void fnic_handle_fip_timer(struct fnic *fnic) /* we exhausted all vlans, restart vlan disc */ spin_unlock_irqrestore(&fnic->vlans_lock, flags); - shost_printk(KERN_INFO, fnic->lport->host, + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, "fip_timer: vlan list empty, " "trigger vlan disc\n"); fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC); -- cgit v1.2.3 From f9e2beb990f0836b642e5e7d1bed285bbc137c83 Mon Sep 17 00:00:00 2001 From: Karan Tilak Kumar Date: Fri, 20 Nov 2020 17:21:45 -0800 Subject: scsi: fnic: Avoid looping in TRANS ETH on unload Avoid looping in fnic_scsi_abort_io() before sending fw reset when fnic is in TRANS ETH state and when we have not received any link events. Link: https://lore.kernel.org/r/20201121012145.18522-1-kartilak@cisco.com Reviewed-by: Arulprabhu Ponnusamy Co-developed-by: Satish Kharat Signed-off-by: Satish Kharat Signed-off-by: Karan Tilak Kumar Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic.h | 3 ++- drivers/scsi/fnic/fnic_fcs.c | 2 ++ drivers/scsi/fnic/fnic_main.c | 2 ++ drivers/scsi/fnic/fnic_scsi.c | 3 ++- 4 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index ed00b6061e0c..6dc8c916de31 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -39,7 +39,7 @@ #define DRV_NAME "fnic" #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" -#define DRV_VERSION "1.6.0.49" +#define DRV_VERSION "1.6.0.50" #define PFX DRV_NAME ": " #define DFX DRV_NAME "%d: " @@ -245,6 +245,7 @@ struct fnic { u32 vlan_hw_insert:1; /* let hw insert the tag */ u32 in_remove:1; /* fnic device in removal */ u32 stop_rx_link_events:1; /* stop proc. rx frames, link events */ + u32 link_events:1; /* set when we get any link event*/ struct completion *remove_wait; /* device remove thread blocks */ diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c index 3fc3a7271dc1..3337d6627baf 100644 --- a/drivers/scsi/fnic/fnic_fcs.c +++ b/drivers/scsi/fnic/fnic_fcs.c @@ -56,6 +56,8 @@ void fnic_handle_link(struct work_struct *work) spin_lock_irqsave(&fnic->fnic_lock, flags); + fnic->link_events = 1; /* less work to just set everytime*/ + if (fnic->stop_rx_link_events) { spin_unlock_irqrestore(&fnic->fnic_lock, flags); return; diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index 5f8a7ef8f6a8..cad29679e90e 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c @@ -580,6 +580,8 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) fnic->lport = lp; fnic->ctlr.lp = lp; + fnic->link_events = 0; + snprintf(fnic->name, sizeof(fnic->name) - 1, "%s%d", DRV_NAME, host->host_no); diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index d1f7b84bbfe8..16e66f5b833a 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -2673,7 +2673,8 @@ void fnic_scsi_abort_io(struct fc_lport *lp) /* Issue firmware reset for fnic, wait for reset to complete */ retry_fw_reset: spin_lock_irqsave(&fnic->fnic_lock, flags); - if (unlikely(fnic->state == FNIC_IN_FC_TRANS_ETH_MODE)) { + if (unlikely(fnic->state == FNIC_IN_FC_TRANS_ETH_MODE) && + fnic->link_events) { /* fw reset is in progress, poll for its completion */ spin_unlock_irqrestore(&fnic->fnic_lock, flags); schedule_timeout(msecs_to_jiffies(100)); -- cgit v1.2.3 From 875d4eda3bd67315418f4e6f6725a877aa1786b5 Mon Sep 17 00:00:00 2001 From: Karan Tilak Kumar Date: Fri, 20 Nov 2020 17:37:39 -0800 Subject: scsi: fnic: Change shost_printk() to FNIC_MAIN_DBG() Replace shost_printk() with FNIC_MAIN_DBG() so that these log messages are controlled by fnic_log_level flag in fnic_handle_link. Link: https://lore.kernel.org/r/20201121013739.18701-1-kartilak@cisco.com Reviewed-by: Arulprabhu Ponnusamy Co-developed-by: Satish Kharat Signed-off-by: Satish Kharat Signed-off-by: Karan Tilak Kumar Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic.h | 2 +- drivers/scsi/fnic/fnic_fcs.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 6dc8c916de31..7c5c911b2673 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -39,7 +39,7 @@ #define DRV_NAME "fnic" #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" -#define DRV_VERSION "1.6.0.50" +#define DRV_VERSION "1.6.0.51" #define PFX DRV_NAME ": " #define DFX DRV_NAME "%d: " diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c index 3337d6627baf..e0cee4dcb439 100644 --- a/drivers/scsi/fnic/fnic_fcs.c +++ b/drivers/scsi/fnic/fnic_fcs.c @@ -75,7 +75,7 @@ void fnic_handle_link(struct work_struct *work) atomic64_set(&fnic->fnic_stats.misc_stats.current_port_speed, new_port_speed); if (old_port_speed != new_port_speed) - shost_printk(KERN_INFO, fnic->lport->host, + FNIC_MAIN_DBG(KERN_INFO, fnic->lport->host, "Current vnic speed set to : %llu\n", new_port_speed); -- cgit v1.2.3 From 74ae6d6a6805f9fe162e4527d8ff0f7d2f9bc0d0 Mon Sep 17 00:00:00 2001 From: Karan Tilak Kumar Date: Fri, 20 Nov 2020 17:51:34 -0800 Subject: scsi: fnic: Set scsi_set_resid() only for underflow Set scsi_set_resid() only if FCPIO_ICMND_CMPL_RESID_UNDER is set. Link: https://lore.kernel.org/r/20201121015134.18872-1-kartilak@cisco.com Reviewed-by: Arulprabhu Ponnusamy Co-developed-by: Satish Kharat Signed-off-by: Satish Kharat Signed-off-by: Karan Tilak Kumar Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic.h | 2 +- drivers/scsi/fnic/fnic_scsi.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 7c5c911b2673..e4d399f41a0a 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -39,7 +39,7 @@ #define DRV_NAME "fnic" #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" -#define DRV_VERSION "1.6.0.51" +#define DRV_VERSION "1.6.0.52" #define PFX DRV_NAME ": " #define DFX DRV_NAME "%d: " diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index 16e66f5b833a..532c3c7ae372 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -921,10 +921,11 @@ static void fnic_fcpio_icmnd_cmpl_handler(struct fnic *fnic, case FCPIO_SUCCESS: sc->result = (DID_OK << 16) | icmnd_cmpl->scsi_status; xfer_len = scsi_bufflen(sc); - scsi_set_resid(sc, icmnd_cmpl->residual); - if (icmnd_cmpl->flags & FCPIO_ICMND_CMPL_RESID_UNDER) + if (icmnd_cmpl->flags & FCPIO_ICMND_CMPL_RESID_UNDER) { xfer_len -= icmnd_cmpl->residual; + scsi_set_resid(sc, icmnd_cmpl->residual); + } if (icmnd_cmpl->scsi_status == SAM_STAT_CHECK_CONDITION) atomic64_inc(&fnic_stats->misc_stats.check_condition); -- cgit v1.2.3 From 3256b4682386298ec106c1d1896b064f6a291f88 Mon Sep 17 00:00:00 2001 From: Karan Tilak Kumar Date: Fri, 20 Nov 2020 18:33:37 -0800 Subject: scsi: fnic: Validate io_req before others We need to check for a valid io_req before we check other data. Also, remove redundant checks. Link: https://lore.kernel.org/r/20201121023337.19295-1-kartilak@cisco.com Reviewed-by: Arulprabhu Ponnusamy Co-developed-by: Satish Kharat Signed-off-by: Satish Kharat Signed-off-by: Karan Tilak Kumar Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic.h | 2 +- drivers/scsi/fnic/fnic_scsi.c | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index e4d399f41a0a..69f373b53132 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -39,7 +39,7 @@ #define DRV_NAME "fnic" #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" -#define DRV_VERSION "1.6.0.52" +#define DRV_VERSION "1.6.0.53" #define PFX DRV_NAME ": " #define DFX DRV_NAME "%d: " diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index 532c3c7ae372..36744968378f 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -1735,15 +1735,14 @@ void fnic_terminate_rport_io(struct fc_rport *rport) continue; } - cmd_rport = starget_to_rport(scsi_target(sc->device)); - if (rport != cmd_rport) { + io_req = (struct fnic_io_req *)CMD_SP(sc); + if (!io_req) { spin_unlock_irqrestore(io_lock, flags); continue; } - io_req = (struct fnic_io_req *)CMD_SP(sc); - - if (!io_req || rport != cmd_rport) { + cmd_rport = starget_to_rport(scsi_target(sc->device)); + if (rport != cmd_rport) { spin_unlock_irqrestore(io_lock, flags); continue; } -- cgit v1.2.3 From 8ed9d987c6d9c7f262a764c56c27d74a906475f0 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:02 +0530 Subject: scsi: megaraid_sas: Drop PCI wakeup calls from .resume The driver calls pci_enable_wake(...., false) in megasas_resume(), and there is no corresponding pci_enable_wake(...., true) in megasas_suspend(). Either it should do enable-wake the device in .suspend() or should not invoke pci_enable_wake() at all. Concluding that this driver doesn't support enable-wake and PCI core calls pci_enable_wake(pci_dev, PCI_D0, false) during resume, drop it from megasas_resume(). Link: https://lore.kernel.org/r/20201102164730.324035-2-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 242cefc61ca5..017f2540785a 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -7668,7 +7668,6 @@ megasas_resume(struct pci_dev *pdev) host = instance->host; pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); pci_restore_state(pdev); dev_info(&pdev->dev, "%s is called\n", __func__); -- cgit v1.2.3 From 977001df03683b0209e56324b51d96ca5362c019 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:03 +0530 Subject: scsi: megaraid_sas: Use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Link: https://lore.kernel.org/r/20201102164730.324035-3-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 51 ++++++++----------------------- 1 file changed, 13 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 017f2540785a..f8ec413d47a0 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -7593,25 +7593,23 @@ static void megasas_shutdown_controller(struct megasas_instance *instance, megasas_return_cmd(instance, cmd); } -#ifdef CONFIG_PM /** * megasas_suspend - driver suspend entry point - * @pdev: PCI device structure - * @state: PCI power state to suspend routine + * @dev: Device structure */ -static int -megasas_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused +megasas_suspend(struct device *dev) { struct megasas_instance *instance; - instance = pci_get_drvdata(pdev); + instance = dev_get_drvdata(dev); if (!instance) return 0; instance->unload = 1; - dev_info(&pdev->dev, "%s is called\n", __func__); + dev_info(dev, "%s is called\n", __func__); /* Shutdown SR-IOV heartbeat timer */ if (instance->requestorId && !instance->skip_heartbeat_timer_del) @@ -7641,47 +7639,29 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) if (instance->msix_vectors) pci_free_irq_vectors(instance->pdev); - pci_save_state(pdev); - pci_disable_device(pdev); - - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; } /** * megasas_resume- driver resume entry point - * @pdev: PCI device structure + * @dev: Device structure */ -static int -megasas_resume(struct pci_dev *pdev) +static int __maybe_unused +megasas_resume(struct device *dev) { int rval; struct Scsi_Host *host; struct megasas_instance *instance; u32 status_reg; - instance = pci_get_drvdata(pdev); + instance = dev_get_drvdata(dev); if (!instance) return 0; host = instance->host; - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - dev_info(&pdev->dev, "%s is called\n", __func__); - /* - * PCI prepping: enable device set bus mastering and dma mask - */ - rval = pci_enable_device_mem(pdev); - if (rval) { - dev_err(&pdev->dev, "Enable device failed\n"); - return rval; - } - - pci_set_master(pdev); + dev_info(dev, "%s is called\n", __func__); /* * We expect the FW state to be READY @@ -7807,14 +7787,8 @@ fail_reenable_msix: fail_set_dma_mask: fail_ready_state: - pci_disable_device(pdev); - return -ENODEV; } -#else -#define megasas_suspend NULL -#define megasas_resume NULL -#endif static inline int megasas_wait_for_adapter_operational(struct megasas_instance *instance) @@ -8552,6 +8526,8 @@ static const struct file_operations megasas_mgmt_fops = { .llseek = noop_llseek, }; +static SIMPLE_DEV_PM_OPS(megasas_pm_ops, megasas_suspend, megasas_resume); + /* * PCI hotplug support registration structure */ @@ -8561,8 +8537,7 @@ static struct pci_driver megasas_pci_driver = { .id_table = megasas_pci_table, .probe = megasas_probe_one, .remove = megasas_detach_one, - .suspend = megasas_suspend, - .resume = megasas_resume, + .driver.pm = &megasas_pm_ops, .shutdown = megasas_shutdown, }; -- cgit v1.2.3 From 498854102c1c14af20941c20d8ca996bdcf116f4 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:04 +0530 Subject: scsi: megaraid_sas: Update function description Function parameter 'pdev 'is described as Generic Device Structure. It is a PCI device structure. Link: https://lore.kernel.org/r/20201102164730.324035-4-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_sas_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index f8ec413d47a0..af192096a82b 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -7958,7 +7958,7 @@ skip_firing_dcmds: /** * megasas_shutdown - Shutdown entry point - * @pdev: Generic device structure + * @pdev: PCI device structure */ static void megasas_shutdown(struct pci_dev *pdev) { -- cgit v1.2.3 From 7dd2222180762656ccaf9e42ecc289f59fd43bc4 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:05 +0530 Subject: scsi: aacraid: Drop pci_enable_wake() from .resume The driver calls pci_enable_wake(...., false) in aac_resume(), and there is no corresponding pci_enable_wake(...., true) in aac_suspend(). Either it should do enable-wake the device in .suspend() or should not invoke pci_enable_wake() at all. Concluding that this is a bug and PCI core calls pci_enable_wake(pci_dev, PCI_D0, false) during resume, drop it from aac_resume(). Link: https://lore.kernel.org/r/20201102164730.324035-5-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/linit.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 0a82afaf4028..114690bef76a 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1881,7 +1881,6 @@ static int aac_resume(struct pci_dev *pdev) int r; pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); pci_restore_state(pdev); r = pci_enable_device(pdev); -- cgit v1.2.3 From 7e380b5c27ea3bab1175584c7763d616ecd6e0c5 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:06 +0530 Subject: scsi: aacraid: Use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Link: https://lore.kernel.org/r/20201102164730.324035-6-vaibhavgupta40@gmail.com Acked-by: Balsundar P Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/linit.c | 33 +++++++-------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 114690bef76a..3168915adaa7 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1853,11 +1853,9 @@ error_iounmap: } -#if (defined(CONFIG_PM)) -static int aac_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused aac_suspend(struct device *dev) { - - struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct Scsi_Host *shost = dev_get_drvdata(dev); struct aac_dev *aac = (struct aac_dev *)shost->hostdata; scsi_host_block(shost); @@ -1866,28 +1864,14 @@ static int aac_suspend(struct pci_dev *pdev, pm_message_t state) aac_release_resources(aac); - pci_set_drvdata(pdev, shost); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; } -static int aac_resume(struct pci_dev *pdev) +static int __maybe_unused aac_resume(struct device *dev) { - struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct Scsi_Host *shost = dev_get_drvdata(dev); struct aac_dev *aac = (struct aac_dev *)shost->hostdata; - int r; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - r = pci_enable_device(pdev); - - if (r) - goto fail_device; - pci_set_master(pdev); if (aac_acquire_resources(aac)) goto fail_device; /* @@ -1902,10 +1886,8 @@ static int aac_resume(struct pci_dev *pdev) fail_device: printk(KERN_INFO "%s%d: resume failed.\n", aac->name, aac->id); scsi_host_put(shost); - pci_disable_device(pdev); return -ENODEV; } -#endif static void aac_shutdown(struct pci_dev *dev) { @@ -2050,15 +2032,14 @@ static struct pci_error_handlers aac_pci_err_handler = { .resume = aac_pci_resume, }; +static SIMPLE_DEV_PM_OPS(aac_pm_ops, aac_suspend, aac_resume); + static struct pci_driver aac_pci_driver = { .name = AAC_DRIVERNAME, .id_table = aac_pci_tbl, .probe = aac_probe_one, .remove = aac_remove_one, -#if (defined(CONFIG_PM)) - .suspend = aac_suspend, - .resume = aac_resume, -#endif + .driver.pm = &aac_pm_ops, .shutdown = aac_shutdown, .err_handler = &aac_pci_err_handler, }; -- cgit v1.2.3 From 6897b9a177dfe38795bb4c086dc72edff7aba779 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:07 +0530 Subject: scsi: aic7xxx: Use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Link: https://lore.kernel.org/r/20201102164730.324035-7-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/aic7xxx/aic7xxx.h | 10 +++----- drivers/scsi/aic7xxx/aic7xxx_core.c | 6 ++--- drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 46 ++++++++-------------------------- drivers/scsi/aic7xxx/aic7xxx_pci.c | 4 +-- 4 files changed, 17 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index 88b90f9806c9..11a09798e6b5 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h @@ -1134,9 +1134,7 @@ const struct ahc_pci_identity *ahc_find_pci_device(ahc_dev_softc_t); int ahc_pci_config(struct ahc_softc *, const struct ahc_pci_identity *); int ahc_pci_test_register_access(struct ahc_softc *); -#ifdef CONFIG_PM -void ahc_pci_resume(struct ahc_softc *ahc); -#endif +void __maybe_unused ahc_pci_resume(struct ahc_softc *ahc); /*************************** EISA/VL Front End ********************************/ struct aic7770_identity *aic7770_find_device(uint32_t); @@ -1160,10 +1158,8 @@ int ahc_chip_init(struct ahc_softc *ahc); int ahc_init(struct ahc_softc *ahc); void ahc_intr_enable(struct ahc_softc *ahc, int enable); void ahc_pause_and_flushwork(struct ahc_softc *ahc); -#ifdef CONFIG_PM -int ahc_suspend(struct ahc_softc *ahc); -int ahc_resume(struct ahc_softc *ahc); -#endif +int __maybe_unused ahc_suspend(struct ahc_softc *ahc); +int __maybe_unused ahc_resume(struct ahc_softc *ahc); void ahc_set_unit(struct ahc_softc *, int); void ahc_set_name(struct ahc_softc *, char *); void ahc_free(struct ahc_softc *ahc); diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 725bb7f58054..4ef7af8c0f55 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -5590,8 +5590,7 @@ ahc_pause_and_flushwork(struct ahc_softc *ahc) ahc->flags &= ~AHC_ALL_INTERRUPTS; } -#ifdef CONFIG_PM -int +int __maybe_unused ahc_suspend(struct ahc_softc *ahc) { @@ -5617,7 +5616,7 @@ ahc_suspend(struct ahc_softc *ahc) return (0); } -int +int __maybe_unused ahc_resume(struct ahc_softc *ahc) { @@ -5626,7 +5625,6 @@ ahc_resume(struct ahc_softc *ahc) ahc_restart(ahc); return (0); } -#endif /************************** Busy Target Table *********************************/ /* * Return the untagged transaction id for a given target/channel lun. diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index 9b293b1f0b71..a07e94fac673 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -121,47 +121,23 @@ static const struct pci_device_id ahc_linux_pci_id_table[] = { MODULE_DEVICE_TABLE(pci, ahc_linux_pci_id_table); -#ifdef CONFIG_PM -static int -ahc_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg) +static int __maybe_unused +ahc_linux_pci_dev_suspend(struct device *dev) { - struct ahc_softc *ahc = pci_get_drvdata(pdev); - int rc; - - if ((rc = ahc_suspend(ahc))) - return rc; + struct ahc_softc *ahc = dev_get_drvdata(dev); - pci_save_state(pdev); - pci_disable_device(pdev); - - if (mesg.event & PM_EVENT_SLEEP) - pci_set_power_state(pdev, PCI_D3hot); - - return rc; + return ahc_suspend(ahc); } -static int -ahc_linux_pci_dev_resume(struct pci_dev *pdev) +static int __maybe_unused +ahc_linux_pci_dev_resume(struct device *dev) { - struct ahc_softc *ahc = pci_get_drvdata(pdev); - int rc; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - if ((rc = pci_enable_device(pdev))) { - dev_printk(KERN_ERR, &pdev->dev, - "failed to enable device after resume (%d)\n", rc); - return rc; - } - - pci_set_master(pdev); + struct ahc_softc *ahc = dev_get_drvdata(dev); ahc_pci_resume(ahc); return (ahc_resume(ahc)); } -#endif static void ahc_linux_pci_dev_remove(struct pci_dev *pdev) @@ -319,14 +295,14 @@ ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width) } } +static SIMPLE_DEV_PM_OPS(ahc_linux_pci_dev_pm_ops, + ahc_linux_pci_dev_suspend, + ahc_linux_pci_dev_resume); static struct pci_driver aic7xxx_pci_driver = { .name = "aic7xxx", .probe = ahc_linux_pci_dev_probe, -#ifdef CONFIG_PM - .suspend = ahc_linux_pci_dev_suspend, - .resume = ahc_linux_pci_dev_resume, -#endif + .driver.pm = &ahc_linux_pci_dev_pm_ops, .remove = ahc_linux_pci_dev_remove, .id_table = ahc_linux_pci_id_table }; diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c index 656f680c7802..dab3a6d12c4d 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c @@ -2008,8 +2008,7 @@ ahc_pci_chip_init(struct ahc_softc *ahc) return (ahc_chip_init(ahc)); } -#ifdef CONFIG_PM -void +void __maybe_unused ahc_pci_resume(struct ahc_softc *ahc) { /* @@ -2040,7 +2039,6 @@ ahc_pci_resume(struct ahc_softc *ahc) ahc_release_seeprom(&sd); } } -#endif static int ahc_aic785X_setup(struct ahc_softc *ahc) -- cgit v1.2.3 From ec199a8df6989915bd2f099e868f09d6ea6b7f06 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:08 +0530 Subject: scsi: aic79xx: Use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Link: https://lore.kernel.org/r/20201102164730.324035-8-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/aic7xxx/aic79xx.h | 12 ++++------ drivers/scsi/aic7xxx/aic79xx_core.c | 8 ++----- drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 43 ++++++++++------------------------ drivers/scsi/aic7xxx/aic79xx_pci.c | 6 ++--- 4 files changed, 20 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 9a515551641c..dd5dfd4f30a5 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -1330,10 +1330,8 @@ const struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t); int ahd_pci_config(struct ahd_softc *, const struct ahd_pci_identity *); int ahd_pci_test_register_access(struct ahd_softc *); -#ifdef CONFIG_PM -void ahd_pci_suspend(struct ahd_softc *); -void ahd_pci_resume(struct ahd_softc *); -#endif +void __maybe_unused ahd_pci_suspend(struct ahd_softc *); +void __maybe_unused ahd_pci_resume(struct ahd_softc *); /************************** SCB and SCB queue management **********************/ void ahd_qinfifo_requeue_tail(struct ahd_softc *ahd, @@ -1344,10 +1342,8 @@ struct ahd_softc *ahd_alloc(void *platform_arg, char *name); int ahd_softc_init(struct ahd_softc *); void ahd_controller_info(struct ahd_softc *ahd, char *buf); int ahd_init(struct ahd_softc *ahd); -#ifdef CONFIG_PM -int ahd_suspend(struct ahd_softc *ahd); -void ahd_resume(struct ahd_softc *ahd); -#endif +int __maybe_unused ahd_suspend(struct ahd_softc *ahd); +void __maybe_unused ahd_resume(struct ahd_softc *ahd); int ahd_default_config(struct ahd_softc *ahd); int ahd_parse_vpddata(struct ahd_softc *ahd, struct vpd_config *vpd); diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 98b02e7d38bb..78560a85b1e3 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -7866,11 +7866,9 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd) ahd->flags &= ~AHD_ALL_INTERRUPTS; } -#ifdef CONFIG_PM -int +int __maybe_unused ahd_suspend(struct ahd_softc *ahd) { - ahd_pause_and_flushwork(ahd); if (LIST_FIRST(&ahd->pending_scbs) != NULL) { @@ -7881,15 +7879,13 @@ ahd_suspend(struct ahd_softc *ahd) return (0); } -void +void __maybe_unused ahd_resume(struct ahd_softc *ahd) { - ahd_reset(ahd, /*reinit*/TRUE); ahd_intr_enable(ahd, TRUE); ahd_restart(ahd); } -#endif /************************** Busy Target Table *********************************/ /* diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index 8b891a05d9e7..07b670b80f1b 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -74,11 +74,10 @@ static const struct pci_device_id ahd_linux_pci_id_table[] = { MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table); -#ifdef CONFIG_PM -static int -ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg) +static int __maybe_unused +ahd_linux_pci_dev_suspend(struct device *dev) { - struct ahd_softc *ahd = pci_get_drvdata(pdev); + struct ahd_softc *ahd = dev_get_drvdata(dev); int rc; if ((rc = ahd_suspend(ahd))) @@ -86,39 +85,20 @@ ahd_linux_pci_dev_suspend(struct pci_dev *pdev, pm_message_t mesg) ahd_pci_suspend(ahd); - pci_save_state(pdev); - pci_disable_device(pdev); - - if (mesg.event & PM_EVENT_SLEEP) - pci_set_power_state(pdev, PCI_D3hot); - return rc; } -static int -ahd_linux_pci_dev_resume(struct pci_dev *pdev) +static int __maybe_unused +ahd_linux_pci_dev_resume(struct device *dev) { - struct ahd_softc *ahd = pci_get_drvdata(pdev); - int rc; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - if ((rc = pci_enable_device(pdev))) { - dev_printk(KERN_ERR, &pdev->dev, - "failed to enable device after resume (%d)\n", rc); - return rc; - } - - pci_set_master(pdev); + struct ahd_softc *ahd = dev_get_drvdata(dev); ahd_pci_resume(ahd); ahd_resume(ahd); - return rc; + return 0; } -#endif static void ahd_linux_pci_dev_remove(struct pci_dev *pdev) @@ -224,13 +204,14 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return (0); } +static SIMPLE_DEV_PM_OPS(ahd_linux_pci_dev_pm_ops, + ahd_linux_pci_dev_suspend, + ahd_linux_pci_dev_resume); + static struct pci_driver aic79xx_pci_driver = { .name = "aic79xx", .probe = ahd_linux_pci_dev_probe, -#ifdef CONFIG_PM - .suspend = ahd_linux_pci_dev_suspend, - .resume = ahd_linux_pci_dev_resume, -#endif + .driver.pm = &ahd_linux_pci_dev_pm_ops, .remove = ahd_linux_pci_dev_remove, .id_table = ahd_linux_pci_id_table }; diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 8397ae93f7dd..2f0bdb9225a4 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -377,8 +377,7 @@ ahd_pci_config(struct ahd_softc *ahd, const struct ahd_pci_identity *entry) return ahd_pci_map_int(ahd); } -#ifdef CONFIG_PM -void +void __maybe_unused ahd_pci_suspend(struct ahd_softc *ahd) { /* @@ -394,7 +393,7 @@ ahd_pci_suspend(struct ahd_softc *ahd) } -void +void __maybe_unused ahd_pci_resume(struct ahd_softc *ahd) { ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, @@ -404,7 +403,6 @@ ahd_pci_resume(struct ahd_softc *ahd) ahd_pci_write_config(ahd->dev_softc, CSIZE_LATTIME, ahd->suspend_state.pci_state.csize_lattime, /*bytes*/1); } -#endif /* * Perform some simple tests that should catch situations where -- cgit v1.2.3 From b7b862d75b49cc26038d03e9f723799b938d3bcf Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:09 +0530 Subject: scsi: arcmsr: Drop PCI wakeup calls from .resume The driver calls pci_enable_wake(...., false) in arcmsr_resume(), and there is no corresponding pci_enable_wake(...., true) in arcmsr_suspend(). Either it should do enable-wake the device in .suspend() or should not invoke pci_enable_wake() at all. Concluding that this driver doesn't support enable-wake and PCI core calls pci_enable_wake(pci_dev, PCI_D0, false) during resume, drop it from arcmsr_resume(). Link: https://lore.kernel.org/r/20201102164730.324035-9-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/arcmsr/arcmsr_hba.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index f241ae15496a..8d226ebfc204 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -1160,7 +1160,6 @@ static int arcmsr_resume(struct pci_dev *pdev) (struct AdapterControlBlock *)host->hostdata; pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); pci_restore_state(pdev); if (pci_enable_device(pdev)) { pr_warn("%s: pci_enable_device error\n", __func__); -- cgit v1.2.3 From 756ebbe73fc48fdcb588d38f8b8874591ed5ab90 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:10 +0530 Subject: scsi: arcmsr: Use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Link: https://lore.kernel.org/r/20201102164730.324035-10-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/arcmsr/arcmsr_hba.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 8d226ebfc204..4b79661275c9 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -117,8 +117,8 @@ static int arcmsr_bios_param(struct scsi_device *sdev, static int arcmsr_queue_command(struct Scsi_Host *h, struct scsi_cmnd *cmd); static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id); -static int arcmsr_suspend(struct pci_dev *pdev, pm_message_t state); -static int arcmsr_resume(struct pci_dev *pdev); +static int __maybe_unused arcmsr_suspend(struct device *dev); +static int __maybe_unused arcmsr_resume(struct device *dev); static void arcmsr_remove(struct pci_dev *pdev); static void arcmsr_shutdown(struct pci_dev *pdev); static void arcmsr_iop_init(struct AdapterControlBlock *acb); @@ -222,13 +222,14 @@ static struct pci_device_id arcmsr_device_id_table[] = { }; MODULE_DEVICE_TABLE(pci, arcmsr_device_id_table); +static SIMPLE_DEV_PM_OPS(arcmsr_pm_ops, arcmsr_suspend, arcmsr_resume); + static struct pci_driver arcmsr_pci_driver = { .name = "arcmsr", .id_table = arcmsr_device_id_table, .probe = arcmsr_probe, .remove = arcmsr_remove, - .suspend = arcmsr_suspend, - .resume = arcmsr_resume, + .driver.pm = &arcmsr_pm_ops, .shutdown = arcmsr_shutdown, }; /* @@ -1132,8 +1133,9 @@ static void arcmsr_free_irq(struct pci_dev *pdev, pci_free_irq_vectors(pdev); } -static int arcmsr_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused arcmsr_suspend(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct Scsi_Host *host = pci_get_drvdata(pdev); struct AdapterControlBlock *acb = (struct AdapterControlBlock *)host->hostdata; @@ -1146,28 +1148,18 @@ static int arcmsr_suspend(struct pci_dev *pdev, pm_message_t state) flush_work(&acb->arcmsr_do_message_isr_bh); arcmsr_stop_adapter_bgrb(acb); arcmsr_flush_adapter_cache(acb); - pci_set_drvdata(pdev, host); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } -static int arcmsr_resume(struct pci_dev *pdev) +static int __maybe_unused arcmsr_resume(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct Scsi_Host *host = pci_get_drvdata(pdev); struct AdapterControlBlock *acb = (struct AdapterControlBlock *)host->hostdata; - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - if (pci_enable_device(pdev)) { - pr_warn("%s: pci_enable_device error\n", __func__); - return -ENODEV; - } if (arcmsr_set_dma_mask(acb)) goto controller_unregister; - pci_set_master(pdev); if (arcmsr_request_irq(pdev, acb) == FAILED) goto controller_stop; switch (acb->adapter_type) { @@ -1212,9 +1204,7 @@ controller_unregister: if (acb->adapter_type == ACB_ADAPTER_TYPE_F) arcmsr_free_io_queue(acb); arcmsr_unmap_pciregion(acb); - pci_release_regions(pdev); scsi_host_put(host); - pci_disable_device(pdev); return -ENODEV; } -- cgit v1.2.3 From 996360c141a6097094ca80e50be695b61a63df3c Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:11 +0530 Subject: scsi: esas2r: Drop PCI Wakeup calls from .resume The driver calls pci_enable_wake(...., false) in esas2r_resume(), and there is no corresponding pci_enable_wake(...., true) in esas2r_suspend(). Either it should do enable-wake the device in .suspend() or should not invoke pci_enable_wake() at all. Concluding that this driver doesn't support enable-wake and PCI core calls pci_enable_wake(pci_dev, PCI_D0, false) during resume, drop it from esas2r_resume(). Link: https://lore.kernel.org/r/20201102164730.324035-11-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/esas2r/esas2r_init.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/esas2r/esas2r_init.c b/drivers/scsi/esas2r/esas2r_init.c index 4b91db7ba919..948bf33fb91b 100644 --- a/drivers/scsi/esas2r/esas2r_init.c +++ b/drivers/scsi/esas2r/esas2r_init.c @@ -677,10 +677,6 @@ int esas2r_resume(struct pci_dev *pdev) "pci_set_power_state(PCI_D0) " "called"); pci_set_power_state(pdev, PCI_D0); - esas2r_log_dev(ESAS2R_LOG_INFO, &(pdev->dev), - "pci_enable_wake(PCI_D0, 0) " - "called"); - pci_enable_wake(pdev, PCI_D0, 0); esas2r_log_dev(ESAS2R_LOG_INFO, &(pdev->dev), "pci_restore_state() called"); pci_restore_state(pdev); -- cgit v1.2.3 From 5f2d8c365050a53042cb0199caf04b63210c3da0 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:12 +0530 Subject: scsi: esas2r: Use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Link: https://lore.kernel.org/r/20201102164730.324035-12-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/esas2r/esas2r.h | 5 +++-- drivers/scsi/esas2r/esas2r_init.c | 44 +++++++++++---------------------------- drivers/scsi/esas2r/esas2r_main.c | 3 +-- 3 files changed, 16 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/esas2r/esas2r.h b/drivers/scsi/esas2r/esas2r.h index e30d2f1f5368..ed63f7a9ea54 100644 --- a/drivers/scsi/esas2r/esas2r.h +++ b/drivers/scsi/esas2r/esas2r.h @@ -996,8 +996,9 @@ void esas2r_adapter_tasklet(unsigned long context); irqreturn_t esas2r_interrupt(int irq, void *dev_id); irqreturn_t esas2r_msi_interrupt(int irq, void *dev_id); void esas2r_kickoff_timer(struct esas2r_adapter *a); -int esas2r_suspend(struct pci_dev *pcid, pm_message_t state); -int esas2r_resume(struct pci_dev *pcid); + +extern const struct dev_pm_ops esas2r_pm_ops; + void esas2r_fw_event_off(struct esas2r_adapter *a); void esas2r_fw_event_on(struct esas2r_adapter *a); bool esas2r_nvram_write(struct esas2r_adapter *a, struct esas2r_request *rq, diff --git a/drivers/scsi/esas2r/esas2r_init.c b/drivers/scsi/esas2r/esas2r_init.c index 948bf33fb91b..c1a5ab662dc8 100644 --- a/drivers/scsi/esas2r/esas2r_init.c +++ b/drivers/scsi/esas2r/esas2r_init.c @@ -641,49 +641,27 @@ void esas2r_kill_adapter(int i) } } -int esas2r_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused esas2r_suspend(struct device *dev) { - struct Scsi_Host *host = pci_get_drvdata(pdev); - u32 device_state; + struct Scsi_Host *host = dev_get_drvdata(dev); struct esas2r_adapter *a = (struct esas2r_adapter *)host->hostdata; - esas2r_log_dev(ESAS2R_LOG_INFO, &(pdev->dev), "suspending adapter()"); + esas2r_log_dev(ESAS2R_LOG_INFO, dev, "suspending adapter()"); if (!a) return -ENODEV; esas2r_adapter_power_down(a, 1); - device_state = pci_choose_state(pdev, state); - esas2r_log_dev(ESAS2R_LOG_INFO, &(pdev->dev), - "pci_save_state() called"); - pci_save_state(pdev); - esas2r_log_dev(ESAS2R_LOG_INFO, &(pdev->dev), - "pci_disable_device() called"); - pci_disable_device(pdev); - esas2r_log_dev(ESAS2R_LOG_INFO, &(pdev->dev), - "pci_set_power_state() called"); - pci_set_power_state(pdev, device_state); - esas2r_log_dev(ESAS2R_LOG_INFO, &(pdev->dev), "esas2r_suspend(): 0"); + esas2r_log_dev(ESAS2R_LOG_INFO, dev, "esas2r_suspend(): 0"); return 0; } -int esas2r_resume(struct pci_dev *pdev) +static int __maybe_unused esas2r_resume(struct device *dev) { - struct Scsi_Host *host = pci_get_drvdata(pdev); + struct Scsi_Host *host = dev_get_drvdata(dev); struct esas2r_adapter *a = (struct esas2r_adapter *)host->hostdata; - int rez; - - esas2r_log_dev(ESAS2R_LOG_INFO, &(pdev->dev), "resuming adapter()"); - esas2r_log_dev(ESAS2R_LOG_INFO, &(pdev->dev), - "pci_set_power_state(PCI_D0) " - "called"); - pci_set_power_state(pdev, PCI_D0); - esas2r_log_dev(ESAS2R_LOG_INFO, &(pdev->dev), - "pci_restore_state() called"); - pci_restore_state(pdev); - esas2r_log_dev(ESAS2R_LOG_INFO, &(pdev->dev), - "pci_enable_device() called"); - rez = pci_enable_device(pdev); - pci_set_master(pdev); + int rez = 0; + + esas2r_log_dev(ESAS2R_LOG_INFO, dev, "resuming adapter()"); if (!a) { rez = -ENODEV; @@ -727,11 +705,13 @@ int esas2r_resume(struct pci_dev *pdev) } error_exit: - esas2r_log_dev(ESAS2R_LOG_CRIT, &(pdev->dev), "esas2r_resume(): %d", + esas2r_log_dev(ESAS2R_LOG_CRIT, dev, "esas2r_resume(): %d", rez); return rez; } +SIMPLE_DEV_PM_OPS(esas2r_pm_ops, esas2r_suspend, esas2r_resume); + bool esas2r_set_degraded_mode(struct esas2r_adapter *a, char *error_str) { set_bit(AF_DEGRADED_MODE, &a->flags); diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c index 923e6e5ddbf9..a9dd6345f064 100644 --- a/drivers/scsi/esas2r/esas2r_main.c +++ b/drivers/scsi/esas2r/esas2r_main.c @@ -346,8 +346,7 @@ static struct pci_driver .id_table = esas2r_pci_table, .probe = esas2r_probe, .remove = esas2r_remove, - .suspend = esas2r_suspend, - .resume = esas2r_resume, + .driver.pm = &esas2r_pm_ops, }; static int esas2r_probe(struct pci_dev *pcid, -- cgit v1.2.3 From 17b5e4d14837b1f16d583cb66810d8f915ffbfd8 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:13 +0530 Subject: scsi: hisi_sas_v3_hw: Drop PCI Wakeup calls from .resume The driver calls pci_enable_wake(...., false) in hisi_sas_v3_resume(), and there is no corresponding pci_enable_wake(...., true) in hisi_sas_v3_suspend(). Either it should do enable-wake the device in .suspend() or should not invoke pci_enable_wake() at all. Concluding that this driver doesn't support enable-wake and PCI core calls pci_enable_wake(pci_dev, PCI_D0, false) during resume, drop it from hisi_sas_v3_resume(). Link: https://lore.kernel.org/r/20201102164730.324035-13-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 7133ca859b5e..f19f3db1ac6d 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -3492,7 +3492,6 @@ static int _resume_v3_hw(struct device *device) dev_warn(dev, "resuming from operating state [D%d]\n", device_state); pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); pci_restore_state(pdev); rc = pci_enable_device(pdev); if (rc) { -- cgit v1.2.3 From 027e508aea458719390eb6a83a297940e8ae79f1 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:14 +0530 Subject: scsi: hisi_sas_v3_hw: Don't use PCI helper functions Drivers using new-framework/generic-framework should not handle standard power management operations. These operations were performed by legacy framework through PCI helper functions like pci_save/restore_state(), pci_set_power_state(), etc. Drivers should not use them now. Link: https://lore.kernel.org/r/20201102164730.324035-14-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index f19f3db1ac6d..dfeb86c865d3 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -3440,7 +3440,6 @@ static int _suspend_v3_hw(struct device *device) struct hisi_hba *hisi_hba = sha->lldd_ha; struct device *dev = hisi_hba->dev; struct Scsi_Host *shost = hisi_hba->shost; - pci_power_t device_state; int rc; if (!pdev->pm_cap) { @@ -3466,12 +3465,7 @@ static int _suspend_v3_hw(struct device *device) hisi_sas_init_mem(hisi_hba); - device_state = pci_choose_state(pdev, PMSG_SUSPEND); - dev_warn(dev, "entering operating state [D%d]\n", - device_state); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, device_state); + dev_warn(dev, "entering suspend state\n"); hisi_sas_release_tasks(hisi_hba); @@ -3491,15 +3485,7 @@ static int _resume_v3_hw(struct device *device) dev_warn(dev, "resuming from operating state [D%d]\n", device_state); - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - rc = pci_enable_device(pdev); - if (rc) { - dev_err(dev, "enable device failed during resume (%d)\n", rc); - return rc; - } - pci_set_master(pdev); scsi_unblock_requests(shost); clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags); @@ -3507,7 +3493,6 @@ static int _resume_v3_hw(struct device *device) rc = hw_init_v3_hw(hisi_hba); if (rc) { scsi_remove_host(shost); - pci_disable_device(pdev); return rc; } hisi_hba->hw->phys_init(hisi_hba); -- cgit v1.2.3 From 71c8f15e1dbcd202f0b27d7560ce191c5a3b7286 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:15 +0530 Subject: scsi: hisi_sas_v3_hw: Remove extra function calls for runtime pm Both runtime_suspend_v3_hw() and runtime_resume_v3_hw() do nothing else but invoke suspend_v3_hw() and resume_v3_hw() respectively. This is the case of unnecessary function calls. To use those functions for runtime pm as well, simply use UNIVERSAL_DEV_PM_OPS. make -j$(nproc) W=1, with CONFIG_PM disabled, throws '-Wunused-function' warning for runtime_suspend_v3_hw() and runtime_resume_v3_hw(). After dropping those function definitions, the warning was thrown for suspend_v3_hw() and resume_v3_hw(). Hence, mark them as '__maybe_unused'. Link: https://lore.kernel.org/r/20201102164730.324035-15-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index dfeb86c865d3..9f0b4fe564cc 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -3502,7 +3502,7 @@ static int _resume_v3_hw(struct device *device) return 0; } -static int suspend_v3_hw(struct device *device) +static int __maybe_unused suspend_v3_hw(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct sas_ha_struct *sha = pci_get_drvdata(pdev); @@ -3518,7 +3518,7 @@ static int suspend_v3_hw(struct device *device) return rc; } -static int resume_v3_hw(struct device *device) +static int __maybe_unused resume_v3_hw(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct sas_ha_struct *sha = pci_get_drvdata(pdev); @@ -3541,21 +3541,10 @@ static const struct pci_error_handlers hisi_sas_err_handler = { .reset_done = hisi_sas_reset_done_v3_hw, }; -static int runtime_suspend_v3_hw(struct device *dev) -{ - return suspend_v3_hw(dev); -} - -static int runtime_resume_v3_hw(struct device *dev) -{ - return resume_v3_hw(dev); -} - -static const struct dev_pm_ops hisi_sas_v3_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(suspend_v3_hw, resume_v3_hw) - SET_RUNTIME_PM_OPS(runtime_suspend_v3_hw, - runtime_resume_v3_hw, NULL) -}; +static UNIVERSAL_DEV_PM_OPS(hisi_sas_v3_pm_ops, + suspend_v3_hw, + resume_v3_hw, + NULL); static struct pci_driver sas_v3_pci_driver = { .name = DRV_NAME, -- cgit v1.2.3 From eaf148359d009d70aec13ae3772675b25890822e Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:16 +0530 Subject: scsi: mpt3sas_scsih: Drop PCI Wakeup calls from .resume The driver calls pci_enable_wake(...., false) in scsih_resume(), and there is no corresponding pci_enable_wake(...., true) in scsih_suspend(). Either it should do enable-wake the device in .suspend() or should not invoke pci_enable_wake() at all. Concluding that this driver doesn't support enable-wake and PCI core calls pci_enable_wake(pci_dev, PCI_D0, false) during resume, drop it from scsih_resume(). Link: https://lore.kernel.org/r/20201102164730.324035-16-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index f081adb85add..5cea46c92ac1 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -12104,7 +12104,6 @@ scsih_resume(struct pci_dev *pdev) pdev, pci_name(pdev), device_state); pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); pci_restore_state(pdev); ioc->pdev = pdev; r = mpt3sas_base_map_resources(ioc); -- cgit v1.2.3 From 17287305a526fa3e3faae0d7c950f5b10df3fe9a Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:17 +0530 Subject: scsi: mpt3sas_scsih: Use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Link: https://lore.kernel.org/r/20201102164730.324035-17-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 5cea46c92ac1..a3ee5bf715f9 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -12048,20 +12048,18 @@ out_add_shost_fail: return rv; } -#ifdef CONFIG_PM /** * scsih_suspend - power management suspend main entry point - * @pdev: PCI device struct - * @state: PM state change to (usually PCI_D3) + * @dev: Device struct * * Return: 0 success, anything else error. */ -static int -scsih_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused +scsih_suspend(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct Scsi_Host *shost; struct MPT3SAS_ADAPTER *ioc; - pci_power_t device_state; int rc; rc = _scsih_get_shost_and_ioc(pdev, &shost, &ioc); @@ -12072,25 +12070,23 @@ scsih_suspend(struct pci_dev *pdev, pm_message_t state) flush_scheduled_work(); scsi_block_requests(shost); _scsih_nvme_shutdown(ioc); - device_state = pci_choose_state(pdev, state); - ioc_info(ioc, "pdev=0x%p, slot=%s, entering operating state [D%d]\n", - pdev, pci_name(pdev), device_state); + ioc_info(ioc, "pdev=0x%p, slot=%s, entering operating state\n", + pdev, pci_name(pdev)); - pci_save_state(pdev); mpt3sas_base_free_resources(ioc); - pci_set_power_state(pdev, device_state); return 0; } /** * scsih_resume - power management resume main entry point - * @pdev: PCI device struct + * @dev: Device struct * * Return: 0 success, anything else error. */ -static int -scsih_resume(struct pci_dev *pdev) +static int __maybe_unused +scsih_resume(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct Scsi_Host *shost; struct MPT3SAS_ADAPTER *ioc; pci_power_t device_state = pdev->current_state; @@ -12103,8 +12099,6 @@ scsih_resume(struct pci_dev *pdev) ioc_info(ioc, "pdev=0x%p, slot=%s, previous operating state [D%d]\n", pdev, pci_name(pdev), device_state); - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); ioc->pdev = pdev; r = mpt3sas_base_map_resources(ioc); if (r) @@ -12115,7 +12109,6 @@ scsih_resume(struct pci_dev *pdev) mpt3sas_base_start_watchdog(ioc); return 0; } -#endif /* CONFIG_PM */ /** * scsih_pci_error_detected - Called when a PCI error is detected. @@ -12417,6 +12410,8 @@ static struct pci_error_handlers _mpt3sas_err_handler = { .resume = scsih_pci_resume, }; +static SIMPLE_DEV_PM_OPS(scsih_pm_ops, scsih_suspend, scsih_resume); + static struct pci_driver mpt3sas_driver = { .name = MPT3SAS_DRIVER_NAME, .id_table = mpt3sas_pci_table, @@ -12424,10 +12419,7 @@ static struct pci_driver mpt3sas_driver = { .remove = scsih_remove, .shutdown = scsih_shutdown, .err_handler = &_mpt3sas_err_handler, -#ifdef CONFIG_PM - .suspend = scsih_suspend, - .resume = scsih_resume, -#endif + .driver.pm = &scsih_pm_ops, }; /** -- cgit v1.2.3 From ef6fa16b5d4a9d3f6ba839737b51d1b2f47259ea Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:18 +0530 Subject: scsi: lpfc: Use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Link: https://lore.kernel.org/r/20201102164730.324035-18-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_init.c | 100 ++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index f4cf60f125f5..ac67f420ec26 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -12576,8 +12576,7 @@ lpfc_pci_remove_one_s3(struct pci_dev *pdev) /** * lpfc_pci_suspend_one_s3 - PCI func to suspend SLI-3 device for power mgmnt - * @pdev: pointer to PCI device - * @msg: power management message + * @dev_d: pointer to device * * This routine is to be called from the kernel's PCI subsystem to support * system Power Management (PM) to device with SLI-3 interface spec. When @@ -12595,10 +12594,10 @@ lpfc_pci_remove_one_s3(struct pci_dev *pdev) * 0 - driver suspended the device * Error otherwise **/ -static int -lpfc_pci_suspend_one_s3(struct pci_dev *pdev, pm_message_t msg) +static int __maybe_unused +lpfc_pci_suspend_one_s3(struct device *dev_d) { - struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct Scsi_Host *shost = dev_get_drvdata(dev_d); struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; lpfc_printf_log(phba, KERN_INFO, LOG_INIT, @@ -12612,16 +12611,12 @@ lpfc_pci_suspend_one_s3(struct pci_dev *pdev, pm_message_t msg) /* Disable interrupt from device */ lpfc_sli_disable_intr(phba); - /* Save device state to PCI config space */ - pci_save_state(pdev); - pci_set_power_state(pdev, PCI_D3hot); - return 0; } /** * lpfc_pci_resume_one_s3 - PCI func to resume SLI-3 device for power mgmnt - * @pdev: pointer to PCI device + * @dev_d: pointer to device * * This routine is to be called from the kernel's PCI subsystem to support * system Power Management (PM) to device with SLI-3 interface spec. When PM @@ -12638,10 +12633,10 @@ lpfc_pci_suspend_one_s3(struct pci_dev *pdev, pm_message_t msg) * 0 - driver suspended the device * Error otherwise **/ -static int -lpfc_pci_resume_one_s3(struct pci_dev *pdev) +static int __maybe_unused +lpfc_pci_resume_one_s3(struct device *dev_d) { - struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct Scsi_Host *shost = dev_get_drvdata(dev_d); struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; uint32_t intr_mode; int error; @@ -12649,19 +12644,6 @@ lpfc_pci_resume_one_s3(struct pci_dev *pdev) lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "0452 PCI device Power Management resume.\n"); - /* Restore device state from PCI config space */ - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - /* - * As the new kernel behavior of pci_restore_state() API call clears - * device saved_state flag, need to save the restored state again. - */ - pci_save_state(pdev); - - if (pdev->is_busmaster) - pci_set_master(pdev); - /* Startup the kernel thread for this host adapter. */ phba->worker_thread = kthread_run(lpfc_do_work, phba, "lpfc_worker_%d", phba->brd_no); @@ -13417,8 +13399,7 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev) /** * lpfc_pci_suspend_one_s4 - PCI func to suspend SLI-4 device for power mgmnt - * @pdev: pointer to PCI device - * @msg: power management message + * @dev_d: pointer to device * * This routine is called from the kernel's PCI subsystem to support system * Power Management (PM) to device with SLI-4 interface spec. When PM invokes @@ -13436,10 +13417,10 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev) * 0 - driver suspended the device * Error otherwise **/ -static int -lpfc_pci_suspend_one_s4(struct pci_dev *pdev, pm_message_t msg) +static int __maybe_unused +lpfc_pci_suspend_one_s4(struct device *dev_d) { - struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct Scsi_Host *shost = dev_get_drvdata(dev_d); struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; lpfc_printf_log(phba, KERN_INFO, LOG_INIT, @@ -13454,16 +13435,12 @@ lpfc_pci_suspend_one_s4(struct pci_dev *pdev, pm_message_t msg) lpfc_sli4_disable_intr(phba); lpfc_sli4_queue_destroy(phba); - /* Save device state to PCI config space */ - pci_save_state(pdev); - pci_set_power_state(pdev, PCI_D3hot); - return 0; } /** * lpfc_pci_resume_one_s4 - PCI func to resume SLI-4 device for power mgmnt - * @pdev: pointer to PCI device + * @dev_d: pointer to device * * This routine is called from the kernel's PCI subsystem to support system * Power Management (PM) to device with SLI-4 interface spac. When PM invokes @@ -13480,10 +13457,10 @@ lpfc_pci_suspend_one_s4(struct pci_dev *pdev, pm_message_t msg) * 0 - driver suspended the device * Error otherwise **/ -static int -lpfc_pci_resume_one_s4(struct pci_dev *pdev) +static int __maybe_unused +lpfc_pci_resume_one_s4(struct device *dev_d) { - struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct Scsi_Host *shost = dev_get_drvdata(dev_d); struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; uint32_t intr_mode; int error; @@ -13491,19 +13468,6 @@ lpfc_pci_resume_one_s4(struct pci_dev *pdev) lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "0292 PCI device Power Management resume.\n"); - /* Restore device state from PCI config space */ - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - /* - * As the new kernel behavior of pci_restore_state() API call clears - * device saved_state flag, need to save the restored state again. - */ - pci_save_state(pdev); - - if (pdev->is_busmaster) - pci_set_master(pdev); - /* Startup the kernel thread for this host adapter. */ phba->worker_thread = kthread_run(lpfc_do_work, phba, "lpfc_worker_%d", phba->brd_no); @@ -13819,8 +13783,7 @@ lpfc_pci_remove_one(struct pci_dev *pdev) /** * lpfc_pci_suspend_one - lpfc PCI func to suspend dev for power management - * @pdev: pointer to PCI device - * @msg: power management message + * @dev: pointer to device * * This routine is to be registered to the kernel's PCI subsystem to support * system Power Management (PM). When PM invokes this method, it dispatches @@ -13831,19 +13794,19 @@ lpfc_pci_remove_one(struct pci_dev *pdev) * 0 - driver suspended the device * Error otherwise **/ -static int -lpfc_pci_suspend_one(struct pci_dev *pdev, pm_message_t msg) +static int __maybe_unused +lpfc_pci_suspend_one(struct device *dev) { - struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct Scsi_Host *shost = dev_get_drvdata(dev); struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; int rc = -ENODEV; switch (phba->pci_dev_grp) { case LPFC_PCI_DEV_LP: - rc = lpfc_pci_suspend_one_s3(pdev, msg); + rc = lpfc_pci_suspend_one_s3(dev); break; case LPFC_PCI_DEV_OC: - rc = lpfc_pci_suspend_one_s4(pdev, msg); + rc = lpfc_pci_suspend_one_s4(dev); break; default: lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, @@ -13856,7 +13819,7 @@ lpfc_pci_suspend_one(struct pci_dev *pdev, pm_message_t msg) /** * lpfc_pci_resume_one - lpfc PCI func to resume dev for power management - * @pdev: pointer to PCI device + * @dev: pointer to device * * This routine is to be registered to the kernel's PCI subsystem to support * system Power Management (PM). When PM invokes this method, it dispatches @@ -13867,19 +13830,19 @@ lpfc_pci_suspend_one(struct pci_dev *pdev, pm_message_t msg) * 0 - driver suspended the device * Error otherwise **/ -static int -lpfc_pci_resume_one(struct pci_dev *pdev) +static int __maybe_unused +lpfc_pci_resume_one(struct device *dev) { - struct Scsi_Host *shost = pci_get_drvdata(pdev); + struct Scsi_Host *shost = dev_get_drvdata(dev); struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; int rc = -ENODEV; switch (phba->pci_dev_grp) { case LPFC_PCI_DEV_LP: - rc = lpfc_pci_resume_one_s3(pdev); + rc = lpfc_pci_resume_one_s3(dev); break; case LPFC_PCI_DEV_OC: - rc = lpfc_pci_resume_one_s4(pdev); + rc = lpfc_pci_resume_one_s4(dev); break; default: lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, @@ -14059,14 +14022,17 @@ static const struct pci_error_handlers lpfc_err_handler = { .resume = lpfc_io_resume, }; +static SIMPLE_DEV_PM_OPS(lpfc_pci_pm_ops_one, + lpfc_pci_suspend_one, + lpfc_pci_resume_one); + static struct pci_driver lpfc_driver = { .name = LPFC_DRIVER_NAME, .id_table = lpfc_id_table, .probe = lpfc_pci_probe_one, .remove = lpfc_pci_remove_one, .shutdown = lpfc_pci_remove_one, - .suspend = lpfc_pci_suspend_one, - .resume = lpfc_pci_resume_one, + .driver.pm = &lpfc_pci_pm_ops_one, .err_handler = &lpfc_err_handler, }; -- cgit v1.2.3 From 66aea31a2d264cc4a6c0470103b313b7bd1600a5 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:19 +0530 Subject: scsi: pm_8001: Drop PCI Wakeup calls from .resume The driver calls pci_enable_wake(...., false) in pm8001_pci_resume(), and there is no corresponding pci_enable_wake(...., true) in pm8001_pci_suspend(). Either it should do enable-wake the device in .suspend() or should not invoke pci_enable_wake() at all. Concluding that this driver doesn't support enable-wake and PCI core calls pci_enable_wake(pci_dev, PCI_D0, false) during resume, drop it from pm8001_pci__resume(). Link: https://lore.kernel.org/r/20201102164730.324035-19-vaibhavgupta40@gmail.com Acked-by: Jack Wang Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_init.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index a6b3f1f8c806..9285a9a3557d 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -1322,7 +1322,6 @@ static int pm8001_pci_resume(struct pci_dev *pdev) pdev, pm8001_ha->name, device_state); pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); pci_restore_state(pdev); rc = pci_enable_device(pdev); if (rc) { -- cgit v1.2.3 From 47c37c4dbf93fb2f35b715f94baec779bd0b2500 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:20 +0530 Subject: scsi: pm_8001: Use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Link: https://lore.kernel.org/r/20201102164730.324035-20-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_init.c | 46 +++++++++++++++------------------------ 1 file changed, 17 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 9285a9a3557d..9627dcf5ffac 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -1253,23 +1253,21 @@ static void pm8001_pci_remove(struct pci_dev *pdev) /** * pm8001_pci_suspend - power management suspend main entry point - * @pdev: PCI device struct - * @state: PM state change to (usually PCI_D3) + * @dev: Device struct * * Returns 0 success, anything else error. */ -static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused pm8001_pci_suspend(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct sas_ha_struct *sha = pci_get_drvdata(pdev); - struct pm8001_hba_info *pm8001_ha; + struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; int i, j; - u32 device_state; - pm8001_ha = sha->lldd_ha; sas_suspend_ha(sha); flush_workqueue(pm8001_wq); scsi_block_requests(pm8001_ha->shost); if (!pdev->pm_cap) { - dev_err(&pdev->dev, " PCI PM not supported\n"); + dev_err(dev, " PCI PM not supported\n"); return -ENODEV; } PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF); @@ -1292,23 +1290,21 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state) for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) tasklet_kill(&pm8001_ha->tasklet[j]); #endif - device_state = pci_choose_state(pdev, state); - pm8001_printk(pm8001_ha, "pdev=0x%p, slot=%s, entering operating state [D%d]\n", - pdev, pm8001_ha->name, device_state); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, device_state); + pm8001_printk(pm8001_ha, "pdev=0x%p, slot=%s, entering " + "suspended state\n", pdev, + pm8001_ha->name); return 0; } /** * pm8001_pci_resume - power management resume main entry point - * @pdev: PCI device struct + * @dev: Device struct * * Returns 0 success, anything else error. */ -static int pm8001_pci_resume(struct pci_dev *pdev) +static int __maybe_unused pm8001_pci_resume(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct sas_ha_struct *sha = pci_get_drvdata(pdev); struct pm8001_hba_info *pm8001_ha; int rc; @@ -1321,16 +1317,6 @@ static int pm8001_pci_resume(struct pci_dev *pdev) pm8001_printk(pm8001_ha, "pdev=0x%p, slot=%s, resuming from previous operating state [D%d]\n", pdev, pm8001_ha->name, device_state); - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - rc = pci_enable_device(pdev); - if (rc) { - pm8001_printk(pm8001_ha, "slot=%s Enable device failed during resume\n", - pm8001_ha->name); - goto err_out_enable; - } - - pci_set_master(pdev); rc = pci_go_44(pdev); if (rc) goto err_out_disable; @@ -1390,8 +1376,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev) err_out_disable: scsi_remove_host(pm8001_ha->shost); - pci_disable_device(pdev); -err_out_enable: + return rc; } @@ -1474,13 +1459,16 @@ static struct pci_device_id pm8001_pci_table[] = { {} /* terminate list */ }; +static SIMPLE_DEV_PM_OPS(pm8001_pci_pm_ops, + pm8001_pci_suspend, + pm8001_pci_resume); + static struct pci_driver pm8001_pci_driver = { .name = DRV_NAME, .id_table = pm8001_pci_table, .probe = pm8001_pci_probe, .remove = pm8001_pci_remove, - .suspend = pm8001_pci_suspend, - .resume = pm8001_pci_resume, + .driver.pm = &pm8001_pci_pm_ops, }; /** -- cgit v1.2.3 From e5b79ebfb854a1b17a7dff1d3b00027363209e4f Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:21 +0530 Subject: scsi: hpsa: Use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Link: https://lore.kernel.org/r/20201102164730.324035-21-vaibhavgupta40@gmail.com Acked-by: Don Brace Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index f10489e4f804..353ba9268391 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -9079,25 +9079,27 @@ static void hpsa_remove_one(struct pci_dev *pdev) hpda_free_ctlr_info(h); /* init_one 1 */ } -static int hpsa_suspend(__attribute__((unused)) struct pci_dev *pdev, - __attribute__((unused)) pm_message_t state) +static int __maybe_unused hpsa_suspend( + __attribute__((unused)) struct device *dev) { return -ENOSYS; } -static int hpsa_resume(__attribute__((unused)) struct pci_dev *pdev) +static int __maybe_unused hpsa_resume + (__attribute__((unused)) struct device *dev) { return -ENOSYS; } +static SIMPLE_DEV_PM_OPS(hpsa_pm_ops, hpsa_suspend, hpsa_resume); + static struct pci_driver hpsa_pci_driver = { .name = HPSA, .probe = hpsa_init_one, .remove = hpsa_remove_one, .id_table = hpsa_pci_device_id, /* id_table */ .shutdown = hpsa_shutdown, - .suspend = hpsa_suspend, - .resume = hpsa_resume, + .driver.pm = &hpsa_pm_ops, }; /* Fill in bucket_map[], given nsgs (the max number of -- cgit v1.2.3 From 3a09951ae3661071a47fead76036d4530c91fd5e Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:22 +0530 Subject: scsi: 3w-9xxx: Drop PCI Wakeup calls from .resume The driver calls pci_enable_wake(...., false) in twa_resume(), and there is no corresponding pci_enable_wake(...., true) in twa_suspend(). Either it should do enable-wake the device in .suspend() or should not invoke pci_enable_wake() at all. Concluding that this driver doesn't support enable-wake and PCI core calls pci_enable_wake(pci_dev, PCI_D0, false) during resume, drop it from twa_resume(). Link: https://lore.kernel.org/r/20201102164730.324035-22-vaibhavgupta40@gmail.com Acked-by: Don Brace Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/3w-9xxx.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 3337b1e80412..e458e99ff161 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -2230,7 +2230,6 @@ static int twa_resume(struct pci_dev *pdev) printk(KERN_WARNING "3w-9xxx: Resuming host %d.\n", tw_dev->host->host_no); pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); pci_restore_state(pdev); retval = pci_enable_device(pdev); -- cgit v1.2.3 From d53ae6bbeb71e1d3c1b85e8befce6379642ed2d9 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:23 +0530 Subject: scsi: 3w-9xxx: Use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Link: https://lore.kernel.org/r/20201102164730.324035-23-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/3w-9xxx.c | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index e458e99ff161..b4718a1b2bd6 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -2191,10 +2191,10 @@ static void twa_remove(struct pci_dev *pdev) twa_device_extension_count--; } /* End twa_remove() */ -#ifdef CONFIG_PM /* This function is called on PCI suspend */ -static int twa_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused twa_suspend(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct Scsi_Host *host = pci_get_drvdata(pdev); TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; @@ -2214,31 +2214,19 @@ static int twa_suspend(struct pci_dev *pdev, pm_message_t state) } TW_CLEAR_ALL_INTERRUPTS(tw_dev); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; } /* End twa_suspend() */ /* This function is called on PCI resume */ -static int twa_resume(struct pci_dev *pdev) +static int __maybe_unused twa_resume(struct device *dev) { int retval = 0; + struct pci_dev *pdev = to_pci_dev(dev); struct Scsi_Host *host = pci_get_drvdata(pdev); TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; printk(KERN_WARNING "3w-9xxx: Resuming host %d.\n", tw_dev->host->host_no); - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - retval = pci_enable_device(pdev); - if (retval) { - TW_PRINTK(tw_dev->host, TW_DRIVER, 0x39, "Enable device failed during resume"); - return retval; - } - - pci_set_master(pdev); pci_try_set_mwi(pdev); retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); @@ -2276,11 +2264,9 @@ static int twa_resume(struct pci_dev *pdev) out_disable_device: scsi_remove_host(host); - pci_disable_device(pdev); return retval; } /* End twa_resume() */ -#endif /* PCI Devices supported by this driver */ static struct pci_device_id twa_pci_tbl[] = { @@ -2296,16 +2282,15 @@ static struct pci_device_id twa_pci_tbl[] = { }; MODULE_DEVICE_TABLE(pci, twa_pci_tbl); +static SIMPLE_DEV_PM_OPS(twa_pm_ops, twa_suspend, twa_resume); + /* pci_driver initializer */ static struct pci_driver twa_driver = { .name = "3w-9xxx", .id_table = twa_pci_tbl, .probe = twa_probe, .remove = twa_remove, -#ifdef CONFIG_PM - .suspend = twa_suspend, - .resume = twa_resume, -#endif + .driver.pm = &twa_pm_ops, .shutdown = twa_shutdown }; -- cgit v1.2.3 From 7ea03ab79e00fccd2a12c1526fb3c7703c8a7baa Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:24 +0530 Subject: scsi: 3w-sas: Drop PCI Wakeup calls from .resume The driver calls pci_enable_wake(...., false) in twl_resume(), and there is no corresponding pci_enable_wake(...., true) in twl_suspend(). Either it should do enable-wake the device in .suspend() or should not invoke pci_enable_wake() at all. Concluding that this driver doesn't support enable-wake and PCI core calls pci_enable_wake(pci_dev, PCI_D0, false) during resume, drop it from twl_resume(). Link: https://lore.kernel.org/r/20201102164730.324035-24-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/3w-sas.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c index dda6fa857709..0b4888199699 100644 --- a/drivers/scsi/3w-sas.c +++ b/drivers/scsi/3w-sas.c @@ -1795,7 +1795,6 @@ static int twl_resume(struct pci_dev *pdev) printk(KERN_WARNING "3w-sas: Resuming host %d.\n", tw_dev->host->host_no); pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); pci_restore_state(pdev); retval = pci_enable_device(pdev); -- cgit v1.2.3 From 99769d8d9109878d3f3e805dd21dfbb44aad035c Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:25 +0530 Subject: scsi: 3w-sas: Use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Link: https://lore.kernel.org/r/20201102164730.324035-25-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/3w-sas.c | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c index 0b4888199699..b8f1848ecef2 100644 --- a/drivers/scsi/3w-sas.c +++ b/drivers/scsi/3w-sas.c @@ -1756,11 +1756,10 @@ static void twl_remove(struct pci_dev *pdev) twl_device_extension_count--; } /* End twl_remove() */ -#ifdef CONFIG_PM /* This function is called on PCI suspend */ -static int twl_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused twl_suspend(struct device *dev) { - struct Scsi_Host *host = pci_get_drvdata(pdev); + struct Scsi_Host *host = dev_get_drvdata(dev); TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; printk(KERN_WARNING "3w-sas: Suspending host %d.\n", tw_dev->host->host_no); @@ -1779,31 +1778,18 @@ static int twl_suspend(struct pci_dev *pdev, pm_message_t state) /* Clear doorbell interrupt */ TWL_CLEAR_DB_INTERRUPT(tw_dev); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; } /* End twl_suspend() */ /* This function is called on PCI resume */ -static int twl_resume(struct pci_dev *pdev) +static int __maybe_unused twl_resume(struct device *dev) { int retval = 0; + struct pci_dev *pdev = to_pci_dev(dev); struct Scsi_Host *host = pci_get_drvdata(pdev); TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata; printk(KERN_WARNING "3w-sas: Resuming host %d.\n", tw_dev->host->host_no); - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - retval = pci_enable_device(pdev); - if (retval) { - TW_PRINTK(tw_dev->host, TW_DRIVER, 0x24, "Enable device failed during resume"); - return retval; - } - - pci_set_master(pdev); pci_try_set_mwi(pdev); retval = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); @@ -1841,11 +1827,9 @@ static int twl_resume(struct pci_dev *pdev) out_disable_device: scsi_remove_host(host); - pci_disable_device(pdev); return retval; } /* End twl_resume() */ -#endif /* PCI Devices supported by this driver */ static struct pci_device_id twl_pci_tbl[] = { @@ -1854,16 +1838,15 @@ static struct pci_device_id twl_pci_tbl[] = { }; MODULE_DEVICE_TABLE(pci, twl_pci_tbl); +static SIMPLE_DEV_PM_OPS(twl_pm_ops, twl_suspend, twl_resume); + /* pci_driver initializer */ static struct pci_driver twl_driver = { .name = "3w-sas", .id_table = twl_pci_tbl, .probe = twl_probe, .remove = twl_remove, -#ifdef CONFIG_PM - .suspend = twl_suspend, - .resume = twl_resume, -#endif + .driver.pm = &twl_pm_ops, .shutdown = twl_shutdown }; -- cgit v1.2.3 From bd7463cdbe1af0e6d120defcbe9cf0e6eb0729c7 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:26 +0530 Subject: scsi: mvumi: Drop PCI Wakeup calls from .resume The driver calls pci_enable_wake(...., false) in mvumi_resume(), and there is no corresponding pci_enable_wake(...., true) in mvumi_suspend(). Either it should do enable-wake the device in .suspend() or should not invoke pci_enable_wake() at all. Concluding that this driver doesn't support enable-wake and PCI core calls pci_enable_wake(pci_dev, PCI_D0, false) during resume, drop it from mvumi_resume(). Link: https://lore.kernel.org/r/20201102164730.324035-26-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/mvumi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c index 2f7a52bd653a..1d92c4da0c92 100644 --- a/drivers/scsi/mvumi.c +++ b/drivers/scsi/mvumi.c @@ -2594,7 +2594,6 @@ static int __maybe_unused mvumi_resume(struct pci_dev *pdev) mhba = pci_get_drvdata(pdev); pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); pci_restore_state(pdev); ret = pci_enable_device(pdev); -- cgit v1.2.3 From 0572edbc32c56ca8863e5849051f9dfd06fd38b9 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:27 +0530 Subject: scsi: mvumi: Use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Link: https://lore.kernel.org/r/20201102164730.324035-27-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/mvumi.c | 46 +++++++++------------------------------------- 1 file changed, 9 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c index 1d92c4da0c92..aa31ff7d8630 100644 --- a/drivers/scsi/mvumi.c +++ b/drivers/scsi/mvumi.c @@ -2567,46 +2567,26 @@ static void mvumi_shutdown(struct pci_dev *pdev) mvumi_flush_cache(mhba); } -static int __maybe_unused mvumi_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused mvumi_suspend(struct device *dev) { - struct mvumi_hba *mhba = NULL; + struct pci_dev *pdev = to_pci_dev(dev); + struct mvumi_hba *mhba = pci_get_drvdata(pdev); - mhba = pci_get_drvdata(pdev); mvumi_flush_cache(mhba); - pci_set_drvdata(pdev, mhba); mhba->instancet->disable_intr(mhba); - free_irq(mhba->pdev->irq, mhba); mvumi_unmap_pci_addr(pdev, mhba->base_addr); - pci_release_regions(pdev); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } -static int __maybe_unused mvumi_resume(struct pci_dev *pdev) +static int __maybe_unused mvumi_resume(struct device *dev) { int ret; - struct mvumi_hba *mhba = NULL; - - mhba = pci_get_drvdata(pdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - ret = pci_enable_device(pdev); - if (ret) { - dev_err(&pdev->dev, "enable device failed\n"); - return ret; - } + struct pci_dev *pdev = to_pci_dev(dev); + struct mvumi_hba *mhba = pci_get_drvdata(pdev); - ret = mvumi_pci_set_master(pdev); ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (ret) - goto fail; - ret = pci_request_regions(mhba->pdev, MV_DRIVER_NAME); if (ret) goto fail; ret = mvumi_map_pci_addr(mhba->pdev, mhba->base_addr); @@ -2626,12 +2606,6 @@ static int __maybe_unused mvumi_resume(struct pci_dev *pdev) goto unmap_pci_addr; } - ret = request_irq(mhba->pdev->irq, mvumi_isr_handler, IRQF_SHARED, - "mvumi", mhba); - if (ret) { - dev_err(&pdev->dev, "failed to register IRQ\n"); - goto unmap_pci_addr; - } mhba->instancet->enable_intr(mhba); return 0; @@ -2641,11 +2615,12 @@ unmap_pci_addr: release_regions: pci_release_regions(pdev); fail: - pci_disable_device(pdev); return ret; } +static SIMPLE_DEV_PM_OPS(mvumi_pm_ops, mvumi_suspend, mvumi_resume); + static struct pci_driver mvumi_pci_driver = { .name = MV_DRIVER_NAME, @@ -2653,10 +2628,7 @@ static struct pci_driver mvumi_pci_driver = { .probe = mvumi_probe_one, .remove = mvumi_detach_one, .shutdown = mvumi_shutdown, -#ifdef CONFIG_PM - .suspend = mvumi_suspend, - .resume = mvumi_resume, -#endif + .driver.pm = &mvumi_pm_ops, }; module_pci_driver(mvumi_pci_driver); -- cgit v1.2.3 From 53fdec73c14fdf8653f90078495ac13f7c171aa3 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:28 +0530 Subject: scsi: mvumi: Update function description There is no "device" parameter in mvumi_shutdown(). Instead there is "pdev" which is not described. Link: https://lore.kernel.org/r/20201102164730.324035-28-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/mvumi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c index aa31ff7d8630..71b6a1f834cd 100644 --- a/drivers/scsi/mvumi.c +++ b/drivers/scsi/mvumi.c @@ -2558,7 +2558,7 @@ static void mvumi_detach_one(struct pci_dev *pdev) /** * mvumi_shutdown - Shutdown entry point - * @device: Generic device structure + * @pdev: PCI device structure */ static void mvumi_shutdown(struct pci_dev *pdev) { -- cgit v1.2.3 From 0aea8a8f3a77d870a1e3312f561efbcf4907bcd5 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:29 +0530 Subject: scsi: pmcraid: Drop PCI Wakeup calls from .resume The driver calls pci_enable_wake(...., false) in pmcraid_resume(), and there is no corresponding pci_enable_wake(...., true) in pmcraid_suspend(). Either it should do enable-wake the device in .suspend() or should not invoke pci_enable_wake() at all. Concluding that this driver doesn't support enable-wake and PCI core calls pci_enable_wake(pci_dev, PCI_D0, false) during resume, drop it from pmcraid_resume(). Link: https://lore.kernel.org/r/20201102164730.324035-29-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/pmcraid.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index cbe5fab793eb..5c767cd8ffc3 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -5271,7 +5271,6 @@ static int pmcraid_resume(struct pci_dev *pdev) int rc; pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); pci_restore_state(pdev); rc = pci_enable_device(pdev); -- cgit v1.2.3 From ac85cca316370d897b5af0568d224410b027b5e4 Mon Sep 17 00:00:00 2001 From: Vaibhav Gupta Date: Mon, 2 Nov 2020 22:17:30 +0530 Subject: scsi: pmcraid: Use generic power management Drivers should do only device-specific jobs. But in general, drivers using legacy PCI PM framework for .suspend()/.resume() have to manage many PCI PM-related tasks themselves which can be done by PCI Core itself. This brings extra load on the driver and it directly calls PCI helper functions to handle them. Switch to the new generic framework by updating function signatures and define a "struct dev_pm_ops" variable to bind PM callbacks. Also, remove unnecessary calls to the PCI Helper functions along with the legacy .suspend & .resume bindings. Link: https://lore.kernel.org/r/20201102164730.324035-30-vaibhavgupta40@gmail.com Signed-off-by: Vaibhav Gupta Signed-off-by: Martin K. Petersen --- drivers/scsi/pmcraid.c | 43 ++++++++++--------------------------------- 1 file changed, 10 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 5c767cd8ffc3..834556ea21d2 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -5234,53 +5234,37 @@ static void pmcraid_remove(struct pci_dev *pdev) return; } -#ifdef CONFIG_PM /** * pmcraid_suspend - driver suspend entry point for power management - * @pdev: PCI device structure - * @state: PCI power state to suspend routine + * @dev: Device structure * * Return Value - 0 always */ -static int pmcraid_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused pmcraid_suspend(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct pmcraid_instance *pinstance = pci_get_drvdata(pdev); pmcraid_shutdown(pdev); pmcraid_disable_interrupts(pinstance, ~0); pmcraid_kill_tasklets(pinstance); - pci_set_drvdata(pinstance->pdev, pinstance); pmcraid_unregister_interrupt_handler(pinstance); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } /** * pmcraid_resume - driver resume entry point PCI power management - * @pdev: PCI device structure + * @dev: Device structure * * Return Value - 0 in case of success. Error code in case of any failure */ -static int pmcraid_resume(struct pci_dev *pdev) +static int __maybe_unused pmcraid_resume(struct device *dev) { + struct pci_dev *pdev = to_pci_dev(dev); struct pmcraid_instance *pinstance = pci_get_drvdata(pdev); struct Scsi_Host *host = pinstance->host; - int rc; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - rc = pci_enable_device(pdev); - - if (rc) { - dev_err(&pdev->dev, "resume: Enable device failed\n"); - return rc; - } - - pci_set_master(pdev); + int rc = 0; if (sizeof(dma_addr_t) == 4 || dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) @@ -5333,18 +5317,10 @@ release_host: scsi_host_put(host); disable_device: - pci_disable_device(pdev); return rc; } -#else - -#define pmcraid_suspend NULL -#define pmcraid_resume NULL - -#endif /* CONFIG_PM */ - /** * pmcraid_complete_ioa_reset - Called by either timer or tasklet during * completion of the ioa reset @@ -5832,6 +5808,8 @@ out_disable_device: return -ENODEV; } +static SIMPLE_DEV_PM_OPS(pmcraid_pm_ops, pmcraid_suspend, pmcraid_resume); + /* * PCI driver structure of pmcraid driver */ @@ -5840,8 +5818,7 @@ static struct pci_driver pmcraid_driver = { .id_table = pmcraid_pci_table, .probe = pmcraid_probe, .remove = pmcraid_remove, - .suspend = pmcraid_suspend, - .resume = pmcraid_resume, + .driver.pm = &pmcraid_pm_ops, .shutdown = pmcraid_shutdown }; -- cgit v1.2.3 From 2ce6e200a04c246a9a60ab3ee05506ed4d778c08 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Nov 2020 20:36:03 -0800 Subject: scsi: pm8001: Convert pm8001_printk() to pm8001_info() Use the more common logging style. [mkp: fixed a few conflicts] Link: https://lore.kernel.org/r/69dc34ff63adfa60b3f203ed2d58143b5692af57.1606192458.git.joe@perches.com Acked-by: Jack Wang Signed-off-by: Joe Perches Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_init.c | 4 ++-- drivers/scsi/pm8001/pm8001_sas.c | 4 ++-- drivers/scsi/pm8001/pm8001_sas.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 9627dcf5ffac..aaac12704475 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -1290,7 +1290,7 @@ static int __maybe_unused pm8001_pci_suspend(struct device *dev) for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) tasklet_kill(&pm8001_ha->tasklet[j]); #endif - pm8001_printk(pm8001_ha, "pdev=0x%p, slot=%s, entering " + pm8001_info(pm8001_ha, "pdev=0x%p, slot=%s, entering " "suspended state\n", pdev, pm8001_ha->name); return 0; @@ -1314,7 +1314,7 @@ static int __maybe_unused pm8001_pci_resume(struct device *dev) pm8001_ha = sha->lldd_ha; device_state = pdev->current_state; - pm8001_printk(pm8001_ha, "pdev=0x%p, slot=%s, resuming from previous operating state [D%d]\n", + pm8001_info(pm8001_ha, "pdev=0x%p, slot=%s, resuming from previous operating state [D%d]\n", pdev, pm8001_ha->name, device_state); rc = pci_go_44(pdev); diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 4562b0a5062a..d1e9dba2ef19 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -1191,7 +1191,7 @@ int pm8001_abort_task(struct sas_task *task) phy_id = pm8001_dev->attached_phy; ret = pm8001_find_tag(task, &tag); if (ret == 0) { - pm8001_printk(pm8001_ha, "no tag for task:%p\n", task); + pm8001_info(pm8001_ha, "no tag for task:%p\n", task); return TMF_RESP_FUNC_FAILED; } spin_lock_irqsave(&task->task_state_lock, flags); @@ -1313,7 +1313,7 @@ out: task->slow_task = NULL; spin_unlock_irqrestore(&task->task_state_lock, flags); if (rc != TMF_RESP_FUNC_COMPLETE) - pm8001_printk(pm8001_ha, "rc= %d\n", rc); + pm8001_info(pm8001_ha, "rc= %d\n", rc); return rc; } diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 5266756a268b..f2c8cbad3853 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -70,14 +70,14 @@ #define PM8001_DEVIO_LOGGING 0x100 /* development io message logging */ #define PM8001_IOERR_LOGGING 0x200 /* development io err message logging */ -#define pm8001_printk(HBA, fmt, ...) \ +#define pm8001_info(HBA, fmt, ...) \ pr_info("%s:: %s %d:" fmt, \ (HBA)->name, __func__, __LINE__, ##__VA_ARGS__) #define pm8001_dbg(HBA, level, fmt, ...) \ do { \ if (unlikely((HBA)->logging_level & PM8001_##level##_LOGGING)) \ - pm8001_printk(HBA, fmt, ##__VA_ARGS__); \ + pm8001_info(HBA, fmt, ##__VA_ARGS__); \ } while (0) #define PM8001_USE_TASKLET -- cgit v1.2.3 From 9aed578fba7839cab7a64a8184797e082ff759dd Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 23 Nov 2020 20:36:04 -0800 Subject: scsi: pm8001: Fix misindentation kernel robot reported a misindentation of a goto. Fix it. At the same time, use a temporary for a repeated entry in the same block to reduce visual noise. Link: https://lore.kernel.org/r/9542a8be9954c1dca744f93f53bb1af6dd1436e8.1606192458.git.joe@perches.com Reported-by: kernel test robot Acked-by: Jack Wang Signed-off-by: Joe Perches Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_init.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index aaac12704475..9a5d284f076a 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -386,17 +386,17 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, pm8001_ha->memoryMap.region[FORENSIC_MEM].element_size = 0x10000; pm8001_ha->memoryMap.region[FORENSIC_MEM].alignment = 0x10000; for (i = 0; i < pm8001_ha->max_memcnt; i++) { + struct mpi_mem *region = &pm8001_ha->memoryMap.region[i]; + if (pm8001_mem_alloc(pm8001_ha->pdev, - &pm8001_ha->memoryMap.region[i].virt_ptr, - &pm8001_ha->memoryMap.region[i].phys_addr, - &pm8001_ha->memoryMap.region[i].phys_addr_hi, - &pm8001_ha->memoryMap.region[i].phys_addr_lo, - pm8001_ha->memoryMap.region[i].total_len, - pm8001_ha->memoryMap.region[i].alignment) != 0) { - pm8001_dbg(pm8001_ha, FAIL, - "Mem%d alloc failed\n", - i); - goto err_out; + ®ion->virt_ptr, + ®ion->phys_addr, + ®ion->phys_addr_hi, + ®ion->phys_addr_lo, + region->total_len, + region->alignment) != 0) { + pm8001_dbg(pm8001_ha, FAIL, "Mem%d alloc failed\n", i); + goto err_out; } } -- cgit v1.2.3 From c6131854e28a50a7e3eaf7bc900d0780772b222b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 24 Nov 2020 09:38:28 +0000 Subject: scsi: pm8001: Remove space in a debug message There are two words that need separating with a space in a pm8001_dbg() message. Fix it. Link: https://lore.kernel.org/r/20201124093828.307709-1-colin.king@canonical.com Reviewed-by: Ewan D. Milne Acked-by: Jack Wang Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_hwi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 08d6cc9b50db..c8d4d87c5473 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -1031,7 +1031,7 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) regVal = pm8001_cr32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK); pm8001_cw32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK, regVal3); pm8001_dbg(pm8001_ha, INIT, - "GSM 0x700048 - Write Data Parity Check Enableis set to = 0x%x\n", + "GSM 0x700048 - Write Data Parity Check Enable is set to = 0x%x\n", pm8001_cr32(pm8001_ha, 2, GSM_WRITE_DATA_PARITY_CHECK)); /* step 13: bring the IOP and AAP1 out of reset */ -- cgit v1.2.3 From bec99e5250bfe1c575e72a971bc2b2b21cf6c8b4 Mon Sep 17 00:00:00 2001 From: John Garry Date: Tue, 24 Nov 2020 16:46:32 +0800 Subject: scsi: hisi_sas: Reduce some indirection in v3 hw driver Sometimes local functions are called indirectly from the hw driver, which only makes the code harder to follow. Remove these. Method .hw_init is only called from platform driver probe, which is not relevant, so don't set this either. Link: https://lore.kernel.org/r/1606207594-196362-2-git-send-email-john.garry@huawei.com Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 9f0b4fe564cc..82dc664d218b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -3142,7 +3142,6 @@ static struct scsi_host_template sht_v3_hw = { }; static const struct hisi_sas_hw hisi_sas_v3_hw = { - .hw_init = hisi_sas_v3_init, .setup_itct = setup_itct_v3_hw, .get_wideport_bitmap = get_wideport_bitmap_v3_hw, .complete_hdr_size = sizeof(struct hisi_sas_complete_v3_hdr), @@ -3322,7 +3321,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (rc) goto err_out_register_ha; - rc = hisi_hba->hw->hw_init(hisi_hba); + rc = hisi_sas_v3_init(hisi_hba); if (rc) goto err_out_register_ha; @@ -3495,7 +3494,7 @@ static int _resume_v3_hw(struct device *device) scsi_remove_host(shost); return rc; } - hisi_hba->hw->phys_init(hisi_hba); + phys_init_v3_hw(hisi_hba); sas_resume_ha(sha); clear_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags); -- cgit v1.2.3 From 2ebde94f2ea4cffd812ece2f318c2f4922239b1d Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Tue, 24 Nov 2020 16:46:33 +0800 Subject: scsi: hisi_sas: Fix up probe error handling for v3 hw Fix some rollbacks in function hisi_sas_v3_probe() and interrupt_init_v3_hw(). Link: https://lore.kernel.org/r/1606207594-196362-3-git-send-email-john.garry@huawei.com Fixes: 8d98416a55eb ("scsi: hisi_sas: Switch v3 hw to MQ") Signed-off-by: Xiang Chen Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 82dc664d218b..252d13e68341 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2409,8 +2409,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) DRV_NAME " phy", hisi_hba); if (rc) { dev_err(dev, "could not request phy interrupt, rc=%d\n", rc); - rc = -ENOENT; - goto free_irq_vectors; + return -ENOENT; } rc = devm_request_irq(dev, pci_irq_vector(pdev, 2), @@ -2418,8 +2417,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) DRV_NAME " channel", hisi_hba); if (rc) { dev_err(dev, "could not request chnl interrupt, rc=%d\n", rc); - rc = -ENOENT; - goto free_irq_vectors; + return -ENOENT; } rc = devm_request_irq(dev, pci_irq_vector(pdev, 11), @@ -2427,8 +2425,7 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) DRV_NAME " fatal", hisi_hba); if (rc) { dev_err(dev, "could not request fatal interrupt, rc=%d\n", rc); - rc = -ENOENT; - goto free_irq_vectors; + return -ENOENT; } if (hisi_sas_intr_conv) @@ -2449,16 +2446,11 @@ static int interrupt_init_v3_hw(struct hisi_hba *hisi_hba) if (rc) { dev_err(dev, "could not request cq%d interrupt, rc=%d\n", i, rc); - rc = -ENOENT; - goto free_irq_vectors; + return -ENOENT; } } return 0; - -free_irq_vectors: - pci_free_irq_vectors(pdev); - return rc; } static int hisi_sas_v3_init(struct hisi_hba *hisi_hba) @@ -3311,11 +3303,11 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) rc = interrupt_preinit_v3_hw(hisi_hba); if (rc) - goto err_out_ha; + goto err_out_debugfs; dev_err(dev, "%d hw queues\n", shost->nr_hw_queues); rc = scsi_add_host(shost, dev); if (rc) - goto err_out_ha; + goto err_out_free_irq_vectors; rc = sas_register_ha(sha); if (rc) @@ -3342,8 +3334,12 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) err_out_register_ha: scsi_remove_host(shost); -err_out_ha: +err_out_free_irq_vectors: + pci_free_irq_vectors(pdev); +err_out_debugfs: hisi_sas_debugfs_exit(hisi_hba); +err_out_ha: + hisi_sas_free(hisi_hba); scsi_host_put(shost); err_out_regions: pci_release_regions(pdev); -- cgit v1.2.3 From 623a4b6d5c2a7595f677fa17348dbca6b461f16a Mon Sep 17 00:00:00 2001 From: Luo Jiaxing Date: Tue, 24 Nov 2020 16:46:34 +0800 Subject: scsi: hisi_sas: Move debugfs code to v3 hw driver Relocate all the debugfs code for DFX to v3 hw since no other versions support it. Link: https://lore.kernel.org/r/1606207594-196362-4-git-send-email-john.garry@huawei.com Signed-off-by: Luo Jiaxing Signed-off-by: John Garry Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas.h | 28 - drivers/scsi/hisi_sas/hisi_sas_main.c | 1346 +------------------------------- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 1225 ++++++++++++++++++++++++++++- 3 files changed, 1212 insertions(+), 1387 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index a25cfc11c96d..2b28dd405600 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -243,24 +243,6 @@ struct hisi_sas_slot { u16 idx; }; -#define HISI_SAS_DEBUGFS_REG(x) {#x, x} - -struct hisi_sas_debugfs_reg_lu { - char *name; - int off; -}; - -struct hisi_sas_debugfs_reg { - const struct hisi_sas_debugfs_reg_lu *lu; - int count; - int base_off; - union { - u32 (*read_global_reg)(struct hisi_hba *hisi_hba, u32 off); - u32 (*read_port_reg)(struct hisi_hba *hisi_hba, int port, - u32 off); - }; -}; - struct hisi_sas_iost_itct_cache { u32 data[HISI_SAS_IOST_ITCT_CACHE_DW_SZ]; }; @@ -350,15 +332,8 @@ struct hisi_sas_hw { int delay_ms, int timeout_ms); void (*snapshot_prepare)(struct hisi_hba *hisi_hba); void (*snapshot_restore)(struct hisi_hba *hisi_hba); - int (*set_bist)(struct hisi_hba *hisi_hba, bool enable); - void (*read_iost_itct_cache)(struct hisi_hba *hisi_hba, - enum hisi_sas_debugfs_cache_type type, - u32 *cache); int complete_hdr_size; struct scsi_host_template *sht; - - const struct hisi_sas_debugfs_reg *debugfs_reg_array[DEBUGFS_REGS_NUM]; - const struct hisi_sas_debugfs_reg *debugfs_reg_port; }; #define HISI_SAS_MAX_DEBUGFS_DUMP (50) @@ -673,7 +648,4 @@ extern void hisi_sas_release_tasks(struct hisi_hba *hisi_hba); extern u8 hisi_sas_get_prog_phy_linkrate_mask(enum sas_linkrate max); extern void hisi_sas_controller_reset_prepare(struct hisi_hba *hisi_hba); extern void hisi_sas_controller_reset_done(struct hisi_hba *hisi_hba); -extern void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba); -extern void hisi_sas_debugfs_exit(struct hisi_hba *hisi_hba); -extern void hisi_sas_debugfs_work_handler(struct work_struct *work); #endif diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 128583dfccf2..e77c3e64a326 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -2690,1355 +2690,12 @@ int hisi_sas_probe(struct platform_device *pdev, err_out_register_ha: scsi_remove_host(shost); err_out_ha: - hisi_sas_debugfs_exit(hisi_hba); hisi_sas_free(hisi_hba); scsi_host_put(shost); return rc; } EXPORT_SYMBOL_GPL(hisi_sas_probe); -struct dentry *hisi_sas_debugfs_dir; - -static void hisi_sas_debugfs_snapshot_cq_reg(struct hisi_hba *hisi_hba) -{ - int queue_entry_size = hisi_hba->hw->complete_hdr_size; - int dump_index = hisi_hba->debugfs_dump_index; - int i; - - for (i = 0; i < hisi_hba->queue_count; i++) - memcpy(hisi_hba->debugfs_cq[dump_index][i].complete_hdr, - hisi_hba->complete_hdr[i], - HISI_SAS_QUEUE_SLOTS * queue_entry_size); -} - -static void hisi_sas_debugfs_snapshot_dq_reg(struct hisi_hba *hisi_hba) -{ - int queue_entry_size = sizeof(struct hisi_sas_cmd_hdr); - int dump_index = hisi_hba->debugfs_dump_index; - int i; - - for (i = 0; i < hisi_hba->queue_count; i++) { - struct hisi_sas_cmd_hdr *debugfs_cmd_hdr, *cmd_hdr; - int j; - - debugfs_cmd_hdr = hisi_hba->debugfs_dq[dump_index][i].hdr; - cmd_hdr = hisi_hba->cmd_hdr[i]; - - for (j = 0; j < HISI_SAS_QUEUE_SLOTS; j++) - memcpy(&debugfs_cmd_hdr[j], &cmd_hdr[j], - queue_entry_size); - } -} - -static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba) -{ - int dump_index = hisi_hba->debugfs_dump_index; - const struct hisi_sas_debugfs_reg *port = - hisi_hba->hw->debugfs_reg_port; - int i, phy_cnt; - u32 offset; - u32 *databuf; - - for (phy_cnt = 0; phy_cnt < hisi_hba->n_phy; phy_cnt++) { - databuf = hisi_hba->debugfs_port_reg[dump_index][phy_cnt].data; - for (i = 0; i < port->count; i++, databuf++) { - offset = port->base_off + 4 * i; - *databuf = port->read_port_reg(hisi_hba, phy_cnt, - offset); - } - } -} - -static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba) -{ - int dump_index = hisi_hba->debugfs_dump_index; - u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL].data; - const struct hisi_sas_hw *hw = hisi_hba->hw; - const struct hisi_sas_debugfs_reg *global = - hw->debugfs_reg_array[DEBUGFS_GLOBAL]; - int i; - - for (i = 0; i < global->count; i++, databuf++) - *databuf = global->read_global_reg(hisi_hba, 4 * i); -} - -static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba) -{ - int dump_index = hisi_hba->debugfs_dump_index; - u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI].data; - const struct hisi_sas_hw *hw = hisi_hba->hw; - const struct hisi_sas_debugfs_reg *axi = - hw->debugfs_reg_array[DEBUGFS_AXI]; - int i; - - for (i = 0; i < axi->count; i++, databuf++) - *databuf = axi->read_global_reg(hisi_hba, - 4 * i + axi->base_off); -} - -static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba) -{ - int dump_index = hisi_hba->debugfs_dump_index; - u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS].data; - const struct hisi_sas_hw *hw = hisi_hba->hw; - const struct hisi_sas_debugfs_reg *ras = - hw->debugfs_reg_array[DEBUGFS_RAS]; - int i; - - for (i = 0; i < ras->count; i++, databuf++) - *databuf = ras->read_global_reg(hisi_hba, - 4 * i + ras->base_off); -} - -static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba) -{ - int dump_index = hisi_hba->debugfs_dump_index; - void *cachebuf = hisi_hba->debugfs_itct_cache[dump_index].cache; - void *databuf = hisi_hba->debugfs_itct[dump_index].itct; - struct hisi_sas_itct *itct; - int i; - - hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_ITCT_CACHE, - cachebuf); - - itct = hisi_hba->itct; - - for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { - memcpy(databuf, itct, sizeof(struct hisi_sas_itct)); - databuf += sizeof(struct hisi_sas_itct); - } -} - -static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba) -{ - int dump_index = hisi_hba->debugfs_dump_index; - int max_command_entries = HISI_SAS_MAX_COMMANDS; - void *cachebuf = hisi_hba->debugfs_iost_cache[dump_index].cache; - void *databuf = hisi_hba->debugfs_iost[dump_index].iost; - struct hisi_sas_iost *iost; - int i; - - hisi_hba->hw->read_iost_itct_cache(hisi_hba, HISI_SAS_IOST_CACHE, - cachebuf); - - iost = hisi_hba->iost; - - for (i = 0; i < max_command_entries; i++, iost++) { - memcpy(databuf, iost, sizeof(struct hisi_sas_iost)); - databuf += sizeof(struct hisi_sas_iost); - } -} - -static const char * -hisi_sas_debugfs_to_reg_name(int off, int base_off, - const struct hisi_sas_debugfs_reg_lu *lu) -{ - for (; lu->name; lu++) { - if (off == lu->off - base_off) - return lu->name; - } - - return NULL; -} - -static void hisi_sas_debugfs_print_reg(u32 *regs_val, const void *ptr, - struct seq_file *s) -{ - const struct hisi_sas_debugfs_reg *reg = ptr; - int i; - - for (i = 0; i < reg->count; i++) { - int off = i * 4; - const char *name; - - name = hisi_sas_debugfs_to_reg_name(off, reg->base_off, - reg->lu); - - if (name) - seq_printf(s, "0x%08x 0x%08x %s\n", off, - regs_val[i], name); - else - seq_printf(s, "0x%08x 0x%08x\n", off, - regs_val[i]); - } -} - -static int hisi_sas_debugfs_global_show(struct seq_file *s, void *p) -{ - struct hisi_sas_debugfs_regs *global = s->private; - struct hisi_hba *hisi_hba = global->hisi_hba; - const struct hisi_sas_hw *hw = hisi_hba->hw; - const void *reg_global = hw->debugfs_reg_array[DEBUGFS_GLOBAL]; - - hisi_sas_debugfs_print_reg(global->data, - reg_global, s); - - return 0; -} - -static int hisi_sas_debugfs_global_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_global_show, - inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_global_fops = { - .open = hisi_sas_debugfs_global_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int hisi_sas_debugfs_axi_show(struct seq_file *s, void *p) -{ - struct hisi_sas_debugfs_regs *axi = s->private; - struct hisi_hba *hisi_hba = axi->hisi_hba; - const struct hisi_sas_hw *hw = hisi_hba->hw; - const void *reg_axi = hw->debugfs_reg_array[DEBUGFS_AXI]; - - hisi_sas_debugfs_print_reg(axi->data, - reg_axi, s); - - return 0; -} - -static int hisi_sas_debugfs_axi_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_axi_show, - inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_axi_fops = { - .open = hisi_sas_debugfs_axi_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int hisi_sas_debugfs_ras_show(struct seq_file *s, void *p) -{ - struct hisi_sas_debugfs_regs *ras = s->private; - struct hisi_hba *hisi_hba = ras->hisi_hba; - const struct hisi_sas_hw *hw = hisi_hba->hw; - const void *reg_ras = hw->debugfs_reg_array[DEBUGFS_RAS]; - - hisi_sas_debugfs_print_reg(ras->data, - reg_ras, s); - - return 0; -} - -static int hisi_sas_debugfs_ras_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_ras_show, - inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_ras_fops = { - .open = hisi_sas_debugfs_ras_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int hisi_sas_debugfs_port_show(struct seq_file *s, void *p) -{ - struct hisi_sas_debugfs_port *port = s->private; - struct hisi_sas_phy *phy = port->phy; - struct hisi_hba *hisi_hba = phy->hisi_hba; - const struct hisi_sas_hw *hw = hisi_hba->hw; - const struct hisi_sas_debugfs_reg *reg_port = hw->debugfs_reg_port; - - hisi_sas_debugfs_print_reg(port->data, reg_port, s); - - return 0; -} - -static int hisi_sas_debugfs_port_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_port_show, inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_port_fops = { - .open = hisi_sas_debugfs_port_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static void hisi_sas_show_row_64(struct seq_file *s, int index, - int sz, __le64 *ptr) -{ - int i; - - /* completion header size not fixed per HW version */ - seq_printf(s, "index %04d:\n\t", index); - for (i = 1; i <= sz / 8; i++, ptr++) { - seq_printf(s, " 0x%016llx", le64_to_cpu(*ptr)); - if (!(i % 2)) - seq_puts(s, "\n\t"); - } - - seq_puts(s, "\n"); -} - -static void hisi_sas_show_row_32(struct seq_file *s, int index, - int sz, __le32 *ptr) -{ - int i; - - /* completion header size not fixed per HW version */ - seq_printf(s, "index %04d:\n\t", index); - for (i = 1; i <= sz / 4; i++, ptr++) { - seq_printf(s, " 0x%08x", le32_to_cpu(*ptr)); - if (!(i % 4)) - seq_puts(s, "\n\t"); - } - seq_puts(s, "\n"); -} - -static void hisi_sas_cq_show_slot(struct seq_file *s, int slot, - struct hisi_sas_debugfs_cq *debugfs_cq) -{ - struct hisi_sas_cq *cq = debugfs_cq->cq; - struct hisi_hba *hisi_hba = cq->hisi_hba; - __le32 *complete_hdr = debugfs_cq->complete_hdr + - (hisi_hba->hw->complete_hdr_size * slot); - - hisi_sas_show_row_32(s, slot, - hisi_hba->hw->complete_hdr_size, - complete_hdr); -} - -static int hisi_sas_debugfs_cq_show(struct seq_file *s, void *p) -{ - struct hisi_sas_debugfs_cq *debugfs_cq = s->private; - int slot; - - for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) { - hisi_sas_cq_show_slot(s, slot, debugfs_cq); - } - return 0; -} - -static int hisi_sas_debugfs_cq_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_cq_show, inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_cq_fops = { - .open = hisi_sas_debugfs_cq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static void hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr) -{ - struct hisi_sas_debugfs_dq *debugfs_dq = dq_ptr; - void *cmd_queue = debugfs_dq->hdr; - __le32 *cmd_hdr = cmd_queue + - sizeof(struct hisi_sas_cmd_hdr) * slot; - - hisi_sas_show_row_32(s, slot, sizeof(struct hisi_sas_cmd_hdr), cmd_hdr); -} - -static int hisi_sas_debugfs_dq_show(struct seq_file *s, void *p) -{ - int slot; - - for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) { - hisi_sas_dq_show_slot(s, slot, s->private); - } - return 0; -} - -static int hisi_sas_debugfs_dq_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_dq_show, inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_dq_fops = { - .open = hisi_sas_debugfs_dq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p) -{ - struct hisi_sas_debugfs_iost *debugfs_iost = s->private; - struct hisi_sas_iost *iost = debugfs_iost->iost; - int i, max_command_entries = HISI_SAS_MAX_COMMANDS; - - for (i = 0; i < max_command_entries; i++, iost++) { - __le64 *data = &iost->qw0; - - hisi_sas_show_row_64(s, i, sizeof(*iost), data); - } - - return 0; -} - -static int hisi_sas_debugfs_iost_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_iost_show, inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_iost_fops = { - .open = hisi_sas_debugfs_iost_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int hisi_sas_debugfs_iost_cache_show(struct seq_file *s, void *p) -{ - struct hisi_sas_debugfs_iost_cache *debugfs_iost_cache = s->private; - struct hisi_sas_iost_itct_cache *iost_cache = debugfs_iost_cache->cache; - u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; - int i, tab_idx; - __le64 *iost; - - for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) { - /* - * Data struct of IOST cache: - * Data[1]: BIT0~15: Table index - * Bit16: Valid mask - * Data[2]~[9]: IOST table - */ - tab_idx = (iost_cache->data[1] & 0xffff); - iost = (__le64 *)iost_cache; - - hisi_sas_show_row_64(s, tab_idx, cache_size, iost); - } - - return 0; -} - -static int hisi_sas_debugfs_iost_cache_open(struct inode *inode, - struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_iost_cache_show, - inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_iost_cache_fops = { - .open = hisi_sas_debugfs_iost_cache_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p) -{ - int i; - struct hisi_sas_debugfs_itct *debugfs_itct = s->private; - struct hisi_sas_itct *itct = debugfs_itct->itct; - - for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { - __le64 *data = &itct->qw0; - - hisi_sas_show_row_64(s, i, sizeof(*itct), data); - } - - return 0; -} - -static int hisi_sas_debugfs_itct_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_itct_show, inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_itct_fops = { - .open = hisi_sas_debugfs_itct_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int hisi_sas_debugfs_itct_cache_show(struct seq_file *s, void *p) -{ - struct hisi_sas_debugfs_itct_cache *debugfs_itct_cache = s->private; - struct hisi_sas_iost_itct_cache *itct_cache = debugfs_itct_cache->cache; - u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; - int i, tab_idx; - __le64 *itct; - - for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) { - /* - * Data struct of ITCT cache: - * Data[1]: BIT0~15: Table index - * Bit16: Valid mask - * Data[2]~[9]: ITCT table - */ - tab_idx = itct_cache->data[1] & 0xffff; - itct = (__le64 *)itct_cache; - - hisi_sas_show_row_64(s, tab_idx, cache_size, itct); - } - - return 0; -} - -static int hisi_sas_debugfs_itct_cache_open(struct inode *inode, - struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_itct_cache_show, - inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_itct_cache_fops = { - .open = hisi_sas_debugfs_itct_cache_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba) -{ - u64 *debugfs_timestamp; - int dump_index = hisi_hba->debugfs_dump_index; - struct dentry *dump_dentry; - struct dentry *dentry; - char name[256]; - int p; - int c; - int d; - - snprintf(name, 256, "%d", dump_index); - - dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry); - - debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index]; - - debugfs_create_u64("timestamp", 0400, dump_dentry, - debugfs_timestamp); - - debugfs_create_file("global", 0400, dump_dentry, - &hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL], - &hisi_sas_debugfs_global_fops); - - /* Create port dir and files */ - dentry = debugfs_create_dir("port", dump_dentry); - for (p = 0; p < hisi_hba->n_phy; p++) { - snprintf(name, 256, "%d", p); - - debugfs_create_file(name, 0400, dentry, - &hisi_hba->debugfs_port_reg[dump_index][p], - &hisi_sas_debugfs_port_fops); - } - - /* Create CQ dir and files */ - dentry = debugfs_create_dir("cq", dump_dentry); - for (c = 0; c < hisi_hba->queue_count; c++) { - snprintf(name, 256, "%d", c); - - debugfs_create_file(name, 0400, dentry, - &hisi_hba->debugfs_cq[dump_index][c], - &hisi_sas_debugfs_cq_fops); - } - - /* Create DQ dir and files */ - dentry = debugfs_create_dir("dq", dump_dentry); - for (d = 0; d < hisi_hba->queue_count; d++) { - snprintf(name, 256, "%d", d); - - debugfs_create_file(name, 0400, dentry, - &hisi_hba->debugfs_dq[dump_index][d], - &hisi_sas_debugfs_dq_fops); - } - - debugfs_create_file("iost", 0400, dump_dentry, - &hisi_hba->debugfs_iost[dump_index], - &hisi_sas_debugfs_iost_fops); - - debugfs_create_file("iost_cache", 0400, dump_dentry, - &hisi_hba->debugfs_iost_cache[dump_index], - &hisi_sas_debugfs_iost_cache_fops); - - debugfs_create_file("itct", 0400, dump_dentry, - &hisi_hba->debugfs_itct[dump_index], - &hisi_sas_debugfs_itct_fops); - - debugfs_create_file("itct_cache", 0400, dump_dentry, - &hisi_hba->debugfs_itct_cache[dump_index], - &hisi_sas_debugfs_itct_cache_fops); - - debugfs_create_file("axi", 0400, dump_dentry, - &hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI], - &hisi_sas_debugfs_axi_fops); - - debugfs_create_file("ras", 0400, dump_dentry, - &hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS], - &hisi_sas_debugfs_ras_fops); - - return; -} - -static void hisi_sas_debugfs_snapshot_regs(struct hisi_hba *hisi_hba) -{ - hisi_hba->hw->snapshot_prepare(hisi_hba); - - hisi_sas_debugfs_snapshot_global_reg(hisi_hba); - hisi_sas_debugfs_snapshot_port_reg(hisi_hba); - hisi_sas_debugfs_snapshot_axi_reg(hisi_hba); - hisi_sas_debugfs_snapshot_ras_reg(hisi_hba); - hisi_sas_debugfs_snapshot_cq_reg(hisi_hba); - hisi_sas_debugfs_snapshot_dq_reg(hisi_hba); - hisi_sas_debugfs_snapshot_itct_reg(hisi_hba); - hisi_sas_debugfs_snapshot_iost_reg(hisi_hba); - - hisi_sas_debugfs_create_files(hisi_hba); - - hisi_hba->hw->snapshot_restore(hisi_hba); -} - -static ssize_t hisi_sas_debugfs_trigger_dump_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct hisi_hba *hisi_hba = file->f_inode->i_private; - char buf[8]; - - if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count) - return -EFAULT; - - if (count > 8) - return -EFAULT; - - if (copy_from_user(buf, user_buf, count)) - return -EFAULT; - - if (buf[0] != '1') - return -EFAULT; - - queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); - - return count; -} - -static const struct file_operations hisi_sas_debugfs_trigger_dump_fops = { - .write = &hisi_sas_debugfs_trigger_dump_write, - .owner = THIS_MODULE, -}; - -enum { - HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL = 0, - HISI_SAS_BIST_LOOPBACK_MODE_SERDES, - HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, -}; - -static const struct { - int value; - char *name; -} hisi_sas_debugfs_loop_linkrate[] = { - { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, - { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, - { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, - { SAS_LINK_RATE_12_0_GBPS, "12.0 Gbit" }, -}; - -static int hisi_sas_debugfs_bist_linkrate_show(struct seq_file *s, void *p) -{ - struct hisi_hba *hisi_hba = s->private; - int i; - - for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_linkrate); i++) { - int match = (hisi_hba->debugfs_bist_linkrate == - hisi_sas_debugfs_loop_linkrate[i].value); - - seq_printf(s, "%s%s%s ", match ? "[" : "", - hisi_sas_debugfs_loop_linkrate[i].name, - match ? "]" : ""); - } - seq_puts(s, "\n"); - - return 0; -} - -static ssize_t hisi_sas_debugfs_bist_linkrate_write(struct file *filp, - const char __user *buf, - size_t count, loff_t *ppos) -{ - struct seq_file *m = filp->private_data; - struct hisi_hba *hisi_hba = m->private; - char kbuf[16] = {}, *pkbuf; - bool found = false; - int i; - - if (hisi_hba->debugfs_bist_enable) - return -EPERM; - - if (count >= sizeof(kbuf)) - return -EOVERFLOW; - - if (copy_from_user(kbuf, buf, count)) - return -EINVAL; - - pkbuf = strstrip(kbuf); - - for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_linkrate); i++) { - if (!strncmp(hisi_sas_debugfs_loop_linkrate[i].name, - pkbuf, 16)) { - hisi_hba->debugfs_bist_linkrate = - hisi_sas_debugfs_loop_linkrate[i].value; - found = true; - break; - } - } - - if (!found) - return -EINVAL; - - return count; -} - -static int hisi_sas_debugfs_bist_linkrate_open(struct inode *inode, - struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_bist_linkrate_show, - inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_bist_linkrate_ops = { - .open = hisi_sas_debugfs_bist_linkrate_open, - .read = seq_read, - .write = hisi_sas_debugfs_bist_linkrate_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct { - int value; - char *name; -} hisi_sas_debugfs_loop_code_mode[] = { - { HISI_SAS_BIST_CODE_MODE_PRBS7, "PRBS7" }, - { HISI_SAS_BIST_CODE_MODE_PRBS23, "PRBS23" }, - { HISI_SAS_BIST_CODE_MODE_PRBS31, "PRBS31" }, - { HISI_SAS_BIST_CODE_MODE_JTPAT, "JTPAT" }, - { HISI_SAS_BIST_CODE_MODE_CJTPAT, "CJTPAT" }, - { HISI_SAS_BIST_CODE_MODE_SCRAMBED_0, "SCRAMBED_0" }, - { HISI_SAS_BIST_CODE_MODE_TRAIN, "TRAIN" }, - { HISI_SAS_BIST_CODE_MODE_TRAIN_DONE, "TRAIN_DONE" }, - { HISI_SAS_BIST_CODE_MODE_HFTP, "HFTP" }, - { HISI_SAS_BIST_CODE_MODE_MFTP, "MFTP" }, - { HISI_SAS_BIST_CODE_MODE_LFTP, "LFTP" }, - { HISI_SAS_BIST_CODE_MODE_FIXED_DATA, "FIXED_DATA" }, -}; - -static int hisi_sas_debugfs_bist_code_mode_show(struct seq_file *s, void *p) -{ - struct hisi_hba *hisi_hba = s->private; - int i; - - for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_code_mode); i++) { - int match = (hisi_hba->debugfs_bist_code_mode == - hisi_sas_debugfs_loop_code_mode[i].value); - - seq_printf(s, "%s%s%s ", match ? "[" : "", - hisi_sas_debugfs_loop_code_mode[i].name, - match ? "]" : ""); - } - seq_puts(s, "\n"); - - return 0; -} - -static ssize_t hisi_sas_debugfs_bist_code_mode_write(struct file *filp, - const char __user *buf, - size_t count, - loff_t *ppos) -{ - struct seq_file *m = filp->private_data; - struct hisi_hba *hisi_hba = m->private; - char kbuf[16] = {}, *pkbuf; - bool found = false; - int i; - - if (hisi_hba->debugfs_bist_enable) - return -EPERM; - - if (count >= sizeof(kbuf)) - return -EINVAL; - - if (copy_from_user(kbuf, buf, count)) - return -EOVERFLOW; - - pkbuf = strstrip(kbuf); - - for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_code_mode); i++) { - if (!strncmp(hisi_sas_debugfs_loop_code_mode[i].name, - pkbuf, 16)) { - hisi_hba->debugfs_bist_code_mode = - hisi_sas_debugfs_loop_code_mode[i].value; - found = true; - break; - } - } - - if (!found) - return -EINVAL; - - return count; -} - -static int hisi_sas_debugfs_bist_code_mode_open(struct inode *inode, - struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_bist_code_mode_show, - inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_bist_code_mode_ops = { - .open = hisi_sas_debugfs_bist_code_mode_open, - .read = seq_read, - .write = hisi_sas_debugfs_bist_code_mode_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static ssize_t hisi_sas_debugfs_bist_phy_write(struct file *filp, - const char __user *buf, - size_t count, loff_t *ppos) -{ - struct seq_file *m = filp->private_data; - struct hisi_hba *hisi_hba = m->private; - unsigned int phy_no; - int val; - - if (hisi_hba->debugfs_bist_enable) - return -EPERM; - - val = kstrtouint_from_user(buf, count, 0, &phy_no); - if (val) - return val; - - if (phy_no >= hisi_hba->n_phy) - return -EINVAL; - - hisi_hba->debugfs_bist_phy_no = phy_no; - - return count; -} - -static int hisi_sas_debugfs_bist_phy_show(struct seq_file *s, void *p) -{ - struct hisi_hba *hisi_hba = s->private; - - seq_printf(s, "%d\n", hisi_hba->debugfs_bist_phy_no); - - return 0; -} - -static int hisi_sas_debugfs_bist_phy_open(struct inode *inode, - struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_bist_phy_show, - inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_bist_phy_ops = { - .open = hisi_sas_debugfs_bist_phy_open, - .read = seq_read, - .write = hisi_sas_debugfs_bist_phy_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct { - int value; - char *name; -} hisi_sas_debugfs_loop_modes[] = { - { HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL, "digital" }, - { HISI_SAS_BIST_LOOPBACK_MODE_SERDES, "serdes" }, - { HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, "remote" }, -}; - -static int hisi_sas_debugfs_bist_mode_show(struct seq_file *s, void *p) -{ - struct hisi_hba *hisi_hba = s->private; - int i; - - for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_modes); i++) { - int match = (hisi_hba->debugfs_bist_mode == - hisi_sas_debugfs_loop_modes[i].value); - - seq_printf(s, "%s%s%s ", match ? "[" : "", - hisi_sas_debugfs_loop_modes[i].name, - match ? "]" : ""); - } - seq_puts(s, "\n"); - - return 0; -} - -static ssize_t hisi_sas_debugfs_bist_mode_write(struct file *filp, - const char __user *buf, - size_t count, loff_t *ppos) -{ - struct seq_file *m = filp->private_data; - struct hisi_hba *hisi_hba = m->private; - char kbuf[16] = {}, *pkbuf; - bool found = false; - int i; - - if (hisi_hba->debugfs_bist_enable) - return -EPERM; - - if (count >= sizeof(kbuf)) - return -EINVAL; - - if (copy_from_user(kbuf, buf, count)) - return -EOVERFLOW; - - pkbuf = strstrip(kbuf); - - for (i = 0; i < ARRAY_SIZE(hisi_sas_debugfs_loop_modes); i++) { - if (!strncmp(hisi_sas_debugfs_loop_modes[i].name, pkbuf, 16)) { - hisi_hba->debugfs_bist_mode = - hisi_sas_debugfs_loop_modes[i].value; - found = true; - break; - } - } - - if (!found) - return -EINVAL; - - return count; -} - -static int hisi_sas_debugfs_bist_mode_open(struct inode *inode, - struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_bist_mode_show, - inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_bist_mode_ops = { - .open = hisi_sas_debugfs_bist_mode_open, - .read = seq_read, - .write = hisi_sas_debugfs_bist_mode_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static ssize_t hisi_sas_debugfs_bist_enable_write(struct file *filp, - const char __user *buf, - size_t count, loff_t *ppos) -{ - struct seq_file *m = filp->private_data; - struct hisi_hba *hisi_hba = m->private; - unsigned int enable; - int val; - - val = kstrtouint_from_user(buf, count, 0, &enable); - if (val) - return val; - - if (enable > 1) - return -EINVAL; - - if (enable == hisi_hba->debugfs_bist_enable) - return count; - - if (!hisi_hba->hw->set_bist) - return -EPERM; - - val = hisi_hba->hw->set_bist(hisi_hba, enable); - if (val < 0) - return val; - - hisi_hba->debugfs_bist_enable = enable; - - return count; -} - -static int hisi_sas_debugfs_bist_enable_show(struct seq_file *s, void *p) -{ - struct hisi_hba *hisi_hba = s->private; - - seq_printf(s, "%d\n", hisi_hba->debugfs_bist_enable); - - return 0; -} - -static int hisi_sas_debugfs_bist_enable_open(struct inode *inode, - struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_bist_enable_show, - inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_bist_enable_ops = { - .open = hisi_sas_debugfs_bist_enable_open, - .read = seq_read, - .write = hisi_sas_debugfs_bist_enable_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct { - char *name; -} hisi_sas_debugfs_ffe_name[FFE_CFG_MAX] = { - { "SAS_1_5_GBPS" }, - { "SAS_3_0_GBPS" }, - { "SAS_6_0_GBPS" }, - { "SAS_12_0_GBPS" }, - { "FFE_RESV" }, - { "SATA_1_5_GBPS" }, - { "SATA_3_0_GBPS" }, - { "SATA_6_0_GBPS" }, -}; - -static ssize_t hisi_sas_debugfs_write(struct file *filp, - const char __user *buf, - size_t count, loff_t *ppos) -{ - struct seq_file *m = filp->private_data; - u32 *val = m->private; - int res; - - res = kstrtouint_from_user(buf, count, 0, val); - if (res) - return res; - - return count; -} - -static int hisi_sas_debugfs_show(struct seq_file *s, void *p) -{ - u32 *val = s->private; - - seq_printf(s, "0x%x\n", *val); - - return 0; -} - -static int hisi_sas_debugfs_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_show, - inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_ops = { - .open = hisi_sas_debugfs_open, - .read = seq_read, - .write = hisi_sas_debugfs_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static ssize_t hisi_sas_debugfs_phy_down_cnt_write(struct file *filp, - const char __user *buf, - size_t count, loff_t *ppos) -{ - struct seq_file *s = filp->private_data; - struct hisi_sas_phy *phy = s->private; - unsigned int set_val; - int res; - - res = kstrtouint_from_user(buf, count, 0, &set_val); - if (res) - return res; - - if (set_val > 0) - return -EINVAL; - - atomic_set(&phy->down_cnt, 0); - - return count; -} - -static int hisi_sas_debugfs_phy_down_cnt_show(struct seq_file *s, void *p) -{ - struct hisi_sas_phy *phy = s->private; - - seq_printf(s, "%d\n", atomic_read(&phy->down_cnt)); - - return 0; -} - -static int hisi_sas_debugfs_phy_down_cnt_open(struct inode *inode, - struct file *filp) -{ - return single_open(filp, hisi_sas_debugfs_phy_down_cnt_show, - inode->i_private); -} - -static const struct file_operations hisi_sas_debugfs_phy_down_cnt_ops = { - .open = hisi_sas_debugfs_phy_down_cnt_open, - .read = seq_read, - .write = hisi_sas_debugfs_phy_down_cnt_write, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -void hisi_sas_debugfs_work_handler(struct work_struct *work) -{ - struct hisi_hba *hisi_hba = - container_of(work, struct hisi_hba, debugfs_work); - int debugfs_dump_index = hisi_hba->debugfs_dump_index; - struct device *dev = hisi_hba->dev; - u64 timestamp = local_clock(); - - if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) { - dev_warn(dev, "dump count exceeded!\n"); - return; - } - - do_div(timestamp, NSEC_PER_MSEC); - hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp; - - hisi_sas_debugfs_snapshot_regs(hisi_hba); - hisi_hba->debugfs_dump_index++; -} -EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler); - -static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba, int dump_index) -{ - struct device *dev = hisi_hba->dev; - int i; - - devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache); - devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache); - devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost); - devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct); - - for (i = 0; i < hisi_hba->queue_count; i++) - devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr); - - for (i = 0; i < hisi_hba->queue_count; i++) - devm_kfree(dev, - hisi_hba->debugfs_cq[dump_index][i].complete_hdr); - - for (i = 0; i < DEBUGFS_REGS_NUM; i++) - devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data); - - for (i = 0; i < hisi_hba->n_phy; i++) - devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data); -} - -static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba, int dump_index) -{ - const struct hisi_sas_hw *hw = hisi_hba->hw; - struct device *dev = hisi_hba->dev; - int p, c, d, r, i; - size_t sz; - - for (r = 0; r < DEBUGFS_REGS_NUM; r++) { - struct hisi_sas_debugfs_regs *regs = - &hisi_hba->debugfs_regs[dump_index][r]; - - sz = hw->debugfs_reg_array[r]->count * 4; - regs->data = devm_kmalloc(dev, sz, GFP_KERNEL); - if (!regs->data) - goto fail; - regs->hisi_hba = hisi_hba; - } - - sz = hw->debugfs_reg_port->count * 4; - for (p = 0; p < hisi_hba->n_phy; p++) { - struct hisi_sas_debugfs_port *port = - &hisi_hba->debugfs_port_reg[dump_index][p]; - - port->data = devm_kmalloc(dev, sz, GFP_KERNEL); - if (!port->data) - goto fail; - port->phy = &hisi_hba->phy[p]; - } - - sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; - for (c = 0; c < hisi_hba->queue_count; c++) { - struct hisi_sas_debugfs_cq *cq = - &hisi_hba->debugfs_cq[dump_index][c]; - - cq->complete_hdr = devm_kmalloc(dev, sz, GFP_KERNEL); - if (!cq->complete_hdr) - goto fail; - cq->cq = &hisi_hba->cq[c]; - } - - sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; - for (d = 0; d < hisi_hba->queue_count; d++) { - struct hisi_sas_debugfs_dq *dq = - &hisi_hba->debugfs_dq[dump_index][d]; - - dq->hdr = devm_kmalloc(dev, sz, GFP_KERNEL); - if (!dq->hdr) - goto fail; - dq->dq = &hisi_hba->dq[d]; - } - - sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost); - - hisi_hba->debugfs_iost[dump_index].iost = - devm_kmalloc(dev, sz, GFP_KERNEL); - if (!hisi_hba->debugfs_iost[dump_index].iost) - goto fail; - - sz = HISI_SAS_IOST_ITCT_CACHE_NUM * - sizeof(struct hisi_sas_iost_itct_cache); - - hisi_hba->debugfs_iost_cache[dump_index].cache = - devm_kmalloc(dev, sz, GFP_KERNEL); - if (!hisi_hba->debugfs_iost_cache[dump_index].cache) - goto fail; - - sz = HISI_SAS_IOST_ITCT_CACHE_NUM * - sizeof(struct hisi_sas_iost_itct_cache); - - hisi_hba->debugfs_itct_cache[dump_index].cache = - devm_kmalloc(dev, sz, GFP_KERNEL); - if (!hisi_hba->debugfs_itct_cache[dump_index].cache) - goto fail; - - /* New memory allocation must be locate before itct */ - sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); - - hisi_hba->debugfs_itct[dump_index].itct = - devm_kmalloc(dev, sz, GFP_KERNEL); - if (!hisi_hba->debugfs_itct[dump_index].itct) - goto fail; - - return 0; -fail: - for (i = 0; i < hisi_sas_debugfs_dump_count; i++) - hisi_sas_debugfs_release(hisi_hba, i); - return -ENOMEM; -} - -static void hisi_sas_debugfs_phy_down_cnt_init(struct hisi_hba *hisi_hba) -{ - struct dentry *dir = debugfs_create_dir("phy_down_cnt", - hisi_hba->debugfs_dir); - char name[16]; - int phy_no; - - for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { - snprintf(name, 16, "%d", phy_no); - debugfs_create_file(name, 0600, dir, - &hisi_hba->phy[phy_no], - &hisi_sas_debugfs_phy_down_cnt_ops); - } -} - -static void hisi_sas_debugfs_bist_init(struct hisi_hba *hisi_hba) -{ - struct dentry *ports_dentry; - int phy_no; - - hisi_hba->debugfs_bist_dentry = - debugfs_create_dir("bist", hisi_hba->debugfs_dir); - debugfs_create_file("link_rate", 0600, - hisi_hba->debugfs_bist_dentry, hisi_hba, - &hisi_sas_debugfs_bist_linkrate_ops); - - debugfs_create_file("code_mode", 0600, - hisi_hba->debugfs_bist_dentry, hisi_hba, - &hisi_sas_debugfs_bist_code_mode_ops); - - debugfs_create_file("fixed_code", 0600, - hisi_hba->debugfs_bist_dentry, - &hisi_hba->debugfs_bist_fixed_code[0], - &hisi_sas_debugfs_ops); - - debugfs_create_file("fixed_code_1", 0600, - hisi_hba->debugfs_bist_dentry, - &hisi_hba->debugfs_bist_fixed_code[1], - &hisi_sas_debugfs_ops); - - debugfs_create_file("phy_id", 0600, hisi_hba->debugfs_bist_dentry, - hisi_hba, &hisi_sas_debugfs_bist_phy_ops); - - debugfs_create_u32("cnt", 0600, hisi_hba->debugfs_bist_dentry, - &hisi_hba->debugfs_bist_cnt); - - debugfs_create_file("loopback_mode", 0600, - hisi_hba->debugfs_bist_dentry, - hisi_hba, &hisi_sas_debugfs_bist_mode_ops); - - debugfs_create_file("enable", 0600, hisi_hba->debugfs_bist_dentry, - hisi_hba, &hisi_sas_debugfs_bist_enable_ops); - - ports_dentry = debugfs_create_dir("port", hisi_hba->debugfs_bist_dentry); - - for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { - struct dentry *port_dentry; - struct dentry *ffe_dentry; - char name[256]; - int i; - - snprintf(name, 256, "%d", phy_no); - port_dentry = debugfs_create_dir(name, ports_dentry); - ffe_dentry = debugfs_create_dir("ffe", port_dentry); - for (i = 0; i < FFE_CFG_MAX; i++) { - if (i == FFE_RESV) - continue; - debugfs_create_file(hisi_sas_debugfs_ffe_name[i].name, - 0600, ffe_dentry, - &hisi_hba->debugfs_bist_ffe[phy_no][i], - &hisi_sas_debugfs_ops); - } - } - - hisi_hba->debugfs_bist_linkrate = SAS_LINK_RATE_1_5_GBPS; -} - -void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba) -{ - struct device *dev = hisi_hba->dev; - int i; - - hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev), - hisi_sas_debugfs_dir); - debugfs_create_file("trigger_dump", 0200, - hisi_hba->debugfs_dir, - hisi_hba, - &hisi_sas_debugfs_trigger_dump_fops); - - /* create bist structures */ - hisi_sas_debugfs_bist_init(hisi_hba); - - hisi_hba->debugfs_dump_dentry = - debugfs_create_dir("dump", hisi_hba->debugfs_dir); - - hisi_sas_debugfs_phy_down_cnt_init(hisi_hba); - - for (i = 0; i < hisi_sas_debugfs_dump_count; i++) { - if (hisi_sas_debugfs_alloc(hisi_hba, i)) { - debugfs_remove_recursive(hisi_hba->debugfs_dir); - dev_dbg(dev, "failed to init debugfs!\n"); - break; - } - } -} -EXPORT_SYMBOL_GPL(hisi_sas_debugfs_init); - -void hisi_sas_debugfs_exit(struct hisi_hba *hisi_hba) -{ - debugfs_remove_recursive(hisi_hba->debugfs_dir); -} -EXPORT_SYMBOL_GPL(hisi_sas_debugfs_exit); - int hisi_sas_remove(struct platform_device *pdev) { struct sas_ha_struct *sha = platform_get_drvdata(pdev); @@ -4067,6 +2724,9 @@ EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dump_count); module_param_named(debugfs_dump_count, hisi_sas_debugfs_dump_count, uint, 0444); MODULE_PARM_DESC(hisi_sas_debugfs_dump_count, "Number of debugfs dumps to allow"); +struct dentry *hisi_sas_debugfs_dir; +EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dir); + static __init int hisi_sas_init(void) { hisi_sas_stt = sas_domain_attach_transport(&hisi_sas_transport_ops); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 252d13e68341..88f203f96280 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -522,6 +522,8 @@ module_param(auto_affine_msi_experimental, bool, 0444); MODULE_PARM_DESC(auto_affine_msi_experimental, "Enable auto-affinity of MSI IRQs as experimental:\n" "default is off"); +static void debugfs_work_handler_v3_hw(struct work_struct *work); + static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off) { void __iomem *regs = hisi_hba->regs + off; @@ -2753,6 +2755,19 @@ static struct device_attribute *host_attrs_v3_hw[] = { NULL }; +#define HISI_SAS_DEBUGFS_REG(x) {#x, x} + +struct hisi_sas_debugfs_reg_lu { + char *name; + int off; +}; + +struct hisi_sas_debugfs_reg { + const struct hisi_sas_debugfs_reg_lu *lu; + int count; + int base_off; +}; + static const struct hisi_sas_debugfs_reg_lu debugfs_port_reg_lu[] = { HISI_SAS_DEBUGFS_REG(PHY_CFG), HISI_SAS_DEBUGFS_REG(HARD_PHY_LINKRATE), @@ -2808,7 +2823,6 @@ static const struct hisi_sas_debugfs_reg debugfs_port_reg = { .lu = debugfs_port_reg_lu, .count = 0x100, .base_off = PORT_BASE, - .read_port_reg = hisi_sas_phy_read32, }; static const struct hisi_sas_debugfs_reg_lu debugfs_global_reg_lu[] = { @@ -2881,7 +2895,6 @@ static const struct hisi_sas_debugfs_reg_lu debugfs_global_reg_lu[] = { static const struct hisi_sas_debugfs_reg debugfs_global_reg = { .lu = debugfs_global_reg_lu, .count = 0x800, - .read_global_reg = hisi_sas_read32, }; static const struct hisi_sas_debugfs_reg_lu debugfs_axi_reg_lu[] = { @@ -2896,7 +2909,6 @@ static const struct hisi_sas_debugfs_reg debugfs_axi_reg = { .lu = debugfs_axi_reg_lu, .count = 0x61, .base_off = AXI_MASTER_CFG_BASE, - .read_global_reg = hisi_sas_read32, }; static const struct hisi_sas_debugfs_reg_lu debugfs_ras_reg_lu[] = { @@ -2914,7 +2926,6 @@ static const struct hisi_sas_debugfs_reg debugfs_ras_reg = { .lu = debugfs_ras_reg_lu, .count = 0x10, .base_off = RAS_BASE, - .read_global_reg = hisi_sas_read32, }; static void debugfs_snapshot_prepare_v3_hw(struct hisi_hba *hisi_hba) @@ -3156,14 +3167,6 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = { .get_events = phy_get_events_v3_hw, .write_gpio = write_gpio_v3_hw, .wait_cmds_complete_timeout = wait_cmds_complete_timeout_v3_hw, - .debugfs_reg_array[DEBUGFS_GLOBAL] = &debugfs_global_reg, - .debugfs_reg_array[DEBUGFS_AXI] = &debugfs_axi_reg, - .debugfs_reg_array[DEBUGFS_RAS] = &debugfs_ras_reg, - .debugfs_reg_port = &debugfs_port_reg, - .snapshot_prepare = debugfs_snapshot_prepare_v3_hw, - .snapshot_restore = debugfs_snapshot_restore_v3_hw, - .read_iost_itct_cache = read_iost_itct_cache_v3_hw, - .set_bist = debugfs_set_bist_v3_hw, }; static struct Scsi_Host * @@ -3181,7 +3184,7 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev) hisi_hba = shost_priv(shost); INIT_WORK(&hisi_hba->rst_work, hisi_sas_rst_work_handler); - INIT_WORK(&hisi_hba->debugfs_work, hisi_sas_debugfs_work_handler); + INIT_WORK(&hisi_hba->debugfs_work, debugfs_work_handler_v3_hw); hisi_hba->hw = &hisi_sas_v3_hw; hisi_hba->pci_dev = pdev; hisi_hba->dev = dev; @@ -3209,6 +3212,1196 @@ err_out: return NULL; } +static void debugfs_snapshot_cq_reg_v3_hw(struct hisi_hba *hisi_hba) +{ + int queue_entry_size = hisi_hba->hw->complete_hdr_size; + int dump_index = hisi_hba->debugfs_dump_index; + int i; + + for (i = 0; i < hisi_hba->queue_count; i++) + memcpy(hisi_hba->debugfs_cq[dump_index][i].complete_hdr, + hisi_hba->complete_hdr[i], + HISI_SAS_QUEUE_SLOTS * queue_entry_size); +} + +static void debugfs_snapshot_dq_reg_v3_hw(struct hisi_hba *hisi_hba) +{ + int queue_entry_size = sizeof(struct hisi_sas_cmd_hdr); + int dump_index = hisi_hba->debugfs_dump_index; + int i; + + for (i = 0; i < hisi_hba->queue_count; i++) { + struct hisi_sas_cmd_hdr *debugfs_cmd_hdr, *cmd_hdr; + int j; + + debugfs_cmd_hdr = hisi_hba->debugfs_dq[dump_index][i].hdr; + cmd_hdr = hisi_hba->cmd_hdr[i]; + + for (j = 0; j < HISI_SAS_QUEUE_SLOTS; j++) + memcpy(&debugfs_cmd_hdr[j], &cmd_hdr[j], + queue_entry_size); + } +} + +static void debugfs_snapshot_port_reg_v3_hw(struct hisi_hba *hisi_hba) +{ + int dump_index = hisi_hba->debugfs_dump_index; + const struct hisi_sas_debugfs_reg *port = &debugfs_port_reg; + int i, phy_cnt; + u32 offset; + u32 *databuf; + + for (phy_cnt = 0; phy_cnt < hisi_hba->n_phy; phy_cnt++) { + databuf = hisi_hba->debugfs_port_reg[dump_index][phy_cnt].data; + for (i = 0; i < port->count; i++, databuf++) { + offset = port->base_off + 4 * i; + *databuf = hisi_sas_phy_read32(hisi_hba, phy_cnt, + offset); + } + } +} + +static void debugfs_snapshot_global_reg_v3_hw(struct hisi_hba *hisi_hba) +{ + int dump_index = hisi_hba->debugfs_dump_index; + u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL].data; + int i; + + for (i = 0; i < debugfs_axi_reg.count; i++, databuf++) + *databuf = hisi_sas_read32(hisi_hba, 4 * i); +} + +static void debugfs_snapshot_axi_reg_v3_hw(struct hisi_hba *hisi_hba) +{ + int dump_index = hisi_hba->debugfs_dump_index; + u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI].data; + const struct hisi_sas_debugfs_reg *axi = &debugfs_axi_reg; + int i; + + for (i = 0; i < axi->count; i++, databuf++) + *databuf = hisi_sas_read32(hisi_hba, 4 * i + axi->base_off); +} + +static void debugfs_snapshot_ras_reg_v3_hw(struct hisi_hba *hisi_hba) +{ + int dump_index = hisi_hba->debugfs_dump_index; + u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS].data; + const struct hisi_sas_debugfs_reg *ras = &debugfs_ras_reg; + int i; + + for (i = 0; i < ras->count; i++, databuf++) + *databuf = hisi_sas_read32(hisi_hba, 4 * i + ras->base_off); +} + +static void debugfs_snapshot_itct_reg_v3_hw(struct hisi_hba *hisi_hba) +{ + int dump_index = hisi_hba->debugfs_dump_index; + void *cachebuf = hisi_hba->debugfs_itct_cache[dump_index].cache; + void *databuf = hisi_hba->debugfs_itct[dump_index].itct; + struct hisi_sas_itct *itct; + int i; + + read_iost_itct_cache_v3_hw(hisi_hba, HISI_SAS_ITCT_CACHE, cachebuf); + + itct = hisi_hba->itct; + + for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { + memcpy(databuf, itct, sizeof(struct hisi_sas_itct)); + databuf += sizeof(struct hisi_sas_itct); + } +} + +static void debugfs_snapshot_iost_reg_v3_hw(struct hisi_hba *hisi_hba) +{ + int dump_index = hisi_hba->debugfs_dump_index; + int max_command_entries = HISI_SAS_MAX_COMMANDS; + void *cachebuf = hisi_hba->debugfs_iost_cache[dump_index].cache; + void *databuf = hisi_hba->debugfs_iost[dump_index].iost; + struct hisi_sas_iost *iost; + int i; + + read_iost_itct_cache_v3_hw(hisi_hba, HISI_SAS_IOST_CACHE, cachebuf); + + iost = hisi_hba->iost; + + for (i = 0; i < max_command_entries; i++, iost++) { + memcpy(databuf, iost, sizeof(struct hisi_sas_iost)); + databuf += sizeof(struct hisi_sas_iost); + } +} + +static const char * +debugfs_to_reg_name_v3_hw(int off, int base_off, + const struct hisi_sas_debugfs_reg_lu *lu) +{ + for (; lu->name; lu++) { + if (off == lu->off - base_off) + return lu->name; + } + + return NULL; +} + +static void debugfs_print_reg_v3_hw(u32 *regs_val, struct seq_file *s, + const struct hisi_sas_debugfs_reg *reg) +{ + int i; + + for (i = 0; i < reg->count; i++) { + int off = i * 4; + const char *name; + + name = debugfs_to_reg_name_v3_hw(off, reg->base_off, + reg->lu); + + if (name) + seq_printf(s, "0x%08x 0x%08x %s\n", off, + regs_val[i], name); + else + seq_printf(s, "0x%08x 0x%08x\n", off, + regs_val[i]); + } +} + +static int debugfs_global_v3_hw_show(struct seq_file *s, void *p) +{ + struct hisi_sas_debugfs_regs *global = s->private; + + debugfs_print_reg_v3_hw(global->data, s, + &debugfs_global_reg); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(debugfs_global_v3_hw); + +static int debugfs_axi_v3_hw_show(struct seq_file *s, void *p) +{ + struct hisi_sas_debugfs_regs *axi = s->private; + + debugfs_print_reg_v3_hw(axi->data, s, + &debugfs_axi_reg); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(debugfs_axi_v3_hw); + +static int debugfs_ras_v3_hw_show(struct seq_file *s, void *p) +{ + struct hisi_sas_debugfs_regs *ras = s->private; + + debugfs_print_reg_v3_hw(ras->data, s, + &debugfs_ras_reg); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(debugfs_ras_v3_hw); + +static int debugfs_port_v3_hw_show(struct seq_file *s, void *p) +{ + struct hisi_sas_debugfs_port *port = s->private; + const struct hisi_sas_debugfs_reg *reg_port = &debugfs_port_reg; + + debugfs_print_reg_v3_hw(port->data, s, reg_port); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(debugfs_port_v3_hw); + +static void debugfs_show_row_64_v3_hw(struct seq_file *s, int index, + int sz, __le64 *ptr) +{ + int i; + + /* completion header size not fixed per HW version */ + seq_printf(s, "index %04d:\n\t", index); + for (i = 1; i <= sz / 8; i++, ptr++) { + seq_printf(s, " 0x%016llx", le64_to_cpu(*ptr)); + if (!(i % 2)) + seq_puts(s, "\n\t"); + } + + seq_puts(s, "\n"); +} + +static void debugfs_show_row_32_v3_hw(struct seq_file *s, int index, + int sz, __le32 *ptr) +{ + int i; + + /* completion header size not fixed per HW version */ + seq_printf(s, "index %04d:\n\t", index); + for (i = 1; i <= sz / 4; i++, ptr++) { + seq_printf(s, " 0x%08x", le32_to_cpu(*ptr)); + if (!(i % 4)) + seq_puts(s, "\n\t"); + } + seq_puts(s, "\n"); +} + +static void debugfs_cq_show_slot_v3_hw(struct seq_file *s, int slot, + struct hisi_sas_debugfs_cq *debugfs_cq) +{ + struct hisi_sas_cq *cq = debugfs_cq->cq; + struct hisi_hba *hisi_hba = cq->hisi_hba; + __le32 *complete_hdr = debugfs_cq->complete_hdr + + (hisi_hba->hw->complete_hdr_size * slot); + + debugfs_show_row_32_v3_hw(s, slot, + hisi_hba->hw->complete_hdr_size, + complete_hdr); +} + +static int debugfs_cq_v3_hw_show(struct seq_file *s, void *p) +{ + struct hisi_sas_debugfs_cq *debugfs_cq = s->private; + int slot; + + for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) + debugfs_cq_show_slot_v3_hw(s, slot, debugfs_cq); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(debugfs_cq_v3_hw); + +static void debugfs_dq_show_slot_v3_hw(struct seq_file *s, int slot, + void *dq_ptr) +{ + struct hisi_sas_debugfs_dq *debugfs_dq = dq_ptr; + void *cmd_queue = debugfs_dq->hdr; + __le32 *cmd_hdr = cmd_queue + + sizeof(struct hisi_sas_cmd_hdr) * slot; + + debugfs_show_row_32_v3_hw(s, slot, sizeof(struct hisi_sas_cmd_hdr), + cmd_hdr); +} + +static int debugfs_dq_v3_hw_show(struct seq_file *s, void *p) +{ + int slot; + + for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) + debugfs_dq_show_slot_v3_hw(s, slot, s->private); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(debugfs_dq_v3_hw); + +static int debugfs_iost_v3_hw_show(struct seq_file *s, void *p) +{ + struct hisi_sas_debugfs_iost *debugfs_iost = s->private; + struct hisi_sas_iost *iost = debugfs_iost->iost; + int i, max_command_entries = HISI_SAS_MAX_COMMANDS; + + for (i = 0; i < max_command_entries; i++, iost++) { + __le64 *data = &iost->qw0; + + debugfs_show_row_64_v3_hw(s, i, sizeof(*iost), data); + } + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(debugfs_iost_v3_hw); + +static int debugfs_iost_cache_v3_hw_show(struct seq_file *s, void *p) +{ + struct hisi_sas_debugfs_iost_cache *debugfs_iost_cache = s->private; + struct hisi_sas_iost_itct_cache *iost_cache = + debugfs_iost_cache->cache; + u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; + int i, tab_idx; + __le64 *iost; + + for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, iost_cache++) { + /* + * Data struct of IOST cache: + * Data[1]: BIT0~15: Table index + * Bit16: Valid mask + * Data[2]~[9]: IOST table + */ + tab_idx = (iost_cache->data[1] & 0xffff); + iost = (__le64 *)iost_cache; + + debugfs_show_row_64_v3_hw(s, tab_idx, cache_size, iost); + } + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(debugfs_iost_cache_v3_hw); + +static int debugfs_itct_v3_hw_show(struct seq_file *s, void *p) +{ + int i; + struct hisi_sas_debugfs_itct *debugfs_itct = s->private; + struct hisi_sas_itct *itct = debugfs_itct->itct; + + for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) { + __le64 *data = &itct->qw0; + + debugfs_show_row_64_v3_hw(s, i, sizeof(*itct), data); + } + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(debugfs_itct_v3_hw); + +static int debugfs_itct_cache_v3_hw_show(struct seq_file *s, void *p) +{ + struct hisi_sas_debugfs_itct_cache *debugfs_itct_cache = s->private; + struct hisi_sas_iost_itct_cache *itct_cache = + debugfs_itct_cache->cache; + u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4; + int i, tab_idx; + __le64 *itct; + + for (i = 0; i < HISI_SAS_IOST_ITCT_CACHE_NUM; i++, itct_cache++) { + /* + * Data struct of ITCT cache: + * Data[1]: BIT0~15: Table index + * Bit16: Valid mask + * Data[2]~[9]: ITCT table + */ + tab_idx = itct_cache->data[1] & 0xffff; + itct = (__le64 *)itct_cache; + + debugfs_show_row_64_v3_hw(s, tab_idx, cache_size, itct); + } + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(debugfs_itct_cache_v3_hw); + +static void debugfs_create_files_v3_hw(struct hisi_hba *hisi_hba) +{ + u64 *debugfs_timestamp; + int dump_index = hisi_hba->debugfs_dump_index; + struct dentry *dump_dentry; + struct dentry *dentry; + char name[256]; + int p; + int c; + int d; + + snprintf(name, 256, "%d", dump_index); + + dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry); + + debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index]; + + debugfs_create_u64("timestamp", 0400, dump_dentry, + debugfs_timestamp); + + debugfs_create_file("global", 0400, dump_dentry, + &hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL], + &debugfs_global_v3_hw_fops); + + /* Create port dir and files */ + dentry = debugfs_create_dir("port", dump_dentry); + for (p = 0; p < hisi_hba->n_phy; p++) { + snprintf(name, 256, "%d", p); + + debugfs_create_file(name, 0400, dentry, + &hisi_hba->debugfs_port_reg[dump_index][p], + &debugfs_port_v3_hw_fops); + } + + /* Create CQ dir and files */ + dentry = debugfs_create_dir("cq", dump_dentry); + for (c = 0; c < hisi_hba->queue_count; c++) { + snprintf(name, 256, "%d", c); + + debugfs_create_file(name, 0400, dentry, + &hisi_hba->debugfs_cq[dump_index][c], + &debugfs_cq_v3_hw_fops); + } + + /* Create DQ dir and files */ + dentry = debugfs_create_dir("dq", dump_dentry); + for (d = 0; d < hisi_hba->queue_count; d++) { + snprintf(name, 256, "%d", d); + + debugfs_create_file(name, 0400, dentry, + &hisi_hba->debugfs_dq[dump_index][d], + &debugfs_dq_v3_hw_fops); + } + + debugfs_create_file("iost", 0400, dump_dentry, + &hisi_hba->debugfs_iost[dump_index], + &debugfs_iost_v3_hw_fops); + + debugfs_create_file("iost_cache", 0400, dump_dentry, + &hisi_hba->debugfs_iost_cache[dump_index], + &debugfs_iost_cache_v3_hw_fops); + + debugfs_create_file("itct", 0400, dump_dentry, + &hisi_hba->debugfs_itct[dump_index], + &debugfs_itct_v3_hw_fops); + + debugfs_create_file("itct_cache", 0400, dump_dentry, + &hisi_hba->debugfs_itct_cache[dump_index], + &debugfs_itct_cache_v3_hw_fops); + + debugfs_create_file("axi", 0400, dump_dentry, + &hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI], + &debugfs_axi_v3_hw_fops); + + debugfs_create_file("ras", 0400, dump_dentry, + &hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS], + &debugfs_ras_v3_hw_fops); +} + +static void debugfs_snapshot_regs_v3_hw(struct hisi_hba *hisi_hba) +{ + debugfs_snapshot_prepare_v3_hw(hisi_hba); + + debugfs_snapshot_global_reg_v3_hw(hisi_hba); + debugfs_snapshot_port_reg_v3_hw(hisi_hba); + debugfs_snapshot_axi_reg_v3_hw(hisi_hba); + debugfs_snapshot_ras_reg_v3_hw(hisi_hba); + debugfs_snapshot_cq_reg_v3_hw(hisi_hba); + debugfs_snapshot_dq_reg_v3_hw(hisi_hba); + debugfs_snapshot_itct_reg_v3_hw(hisi_hba); + debugfs_snapshot_iost_reg_v3_hw(hisi_hba); + + debugfs_create_files_v3_hw(hisi_hba); + + debugfs_snapshot_restore_v3_hw(hisi_hba); +} + +static ssize_t debugfs_trigger_dump_v3_hw_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct hisi_hba *hisi_hba = file->f_inode->i_private; + char buf[8]; + + if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count) + return -EFAULT; + + if (count > 8) + return -EFAULT; + + if (copy_from_user(buf, user_buf, count)) + return -EFAULT; + + if (buf[0] != '1') + return -EFAULT; + + queue_work(hisi_hba->wq, &hisi_hba->debugfs_work); + + return count; +} + +static const struct file_operations debugfs_trigger_dump_v3_hw_fops = { + .write = &debugfs_trigger_dump_v3_hw_write, + .owner = THIS_MODULE, +}; + +enum { + HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL = 0, + HISI_SAS_BIST_LOOPBACK_MODE_SERDES, + HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, +}; + +static const struct { + int value; + char *name; +} debugfs_loop_linkrate_v3_hw[] = { + { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, + { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, + { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, + { SAS_LINK_RATE_12_0_GBPS, "12.0 Gbit" }, +}; + +static int debugfs_bist_linkrate_v3_hw_show(struct seq_file *s, void *p) +{ + struct hisi_hba *hisi_hba = s->private; + int i; + + for (i = 0; i < ARRAY_SIZE(debugfs_loop_linkrate_v3_hw); i++) { + int match = (hisi_hba->debugfs_bist_linkrate == + debugfs_loop_linkrate_v3_hw[i].value); + + seq_printf(s, "%s%s%s ", match ? "[" : "", + debugfs_loop_linkrate_v3_hw[i].name, + match ? "]" : ""); + } + seq_puts(s, "\n"); + + return 0; +} + +static ssize_t debugfs_bist_linkrate_v3_hw_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + char kbuf[16] = {}, *pkbuf; + bool found = false; + int i; + + if (hisi_hba->debugfs_bist_enable) + return -EPERM; + + if (count >= sizeof(kbuf)) + return -EOVERFLOW; + + if (copy_from_user(kbuf, buf, count)) + return -EINVAL; + + pkbuf = strstrip(kbuf); + + for (i = 0; i < ARRAY_SIZE(debugfs_loop_linkrate_v3_hw); i++) { + if (!strncmp(debugfs_loop_linkrate_v3_hw[i].name, + pkbuf, 16)) { + hisi_hba->debugfs_bist_linkrate = + debugfs_loop_linkrate_v3_hw[i].value; + found = true; + break; + } + } + + if (!found) + return -EINVAL; + + return count; +} + +static int debugfs_bist_linkrate_v3_hw_open(struct inode *inode, + struct file *filp) +{ + return single_open(filp, debugfs_bist_linkrate_v3_hw_show, + inode->i_private); +} + +static const struct file_operations debugfs_bist_linkrate_v3_hw_fops = { + .open = debugfs_bist_linkrate_v3_hw_open, + .read = seq_read, + .write = debugfs_bist_linkrate_v3_hw_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct { + int value; + char *name; +} debugfs_loop_code_mode_v3_hw[] = { + { HISI_SAS_BIST_CODE_MODE_PRBS7, "PRBS7" }, + { HISI_SAS_BIST_CODE_MODE_PRBS23, "PRBS23" }, + { HISI_SAS_BIST_CODE_MODE_PRBS31, "PRBS31" }, + { HISI_SAS_BIST_CODE_MODE_JTPAT, "JTPAT" }, + { HISI_SAS_BIST_CODE_MODE_CJTPAT, "CJTPAT" }, + { HISI_SAS_BIST_CODE_MODE_SCRAMBED_0, "SCRAMBED_0" }, + { HISI_SAS_BIST_CODE_MODE_TRAIN, "TRAIN" }, + { HISI_SAS_BIST_CODE_MODE_TRAIN_DONE, "TRAIN_DONE" }, + { HISI_SAS_BIST_CODE_MODE_HFTP, "HFTP" }, + { HISI_SAS_BIST_CODE_MODE_MFTP, "MFTP" }, + { HISI_SAS_BIST_CODE_MODE_LFTP, "LFTP" }, + { HISI_SAS_BIST_CODE_MODE_FIXED_DATA, "FIXED_DATA" }, +}; + +static int debugfs_bist_code_mode_v3_hw_show(struct seq_file *s, void *p) +{ + struct hisi_hba *hisi_hba = s->private; + int i; + + for (i = 0; i < ARRAY_SIZE(debugfs_loop_code_mode_v3_hw); i++) { + int match = (hisi_hba->debugfs_bist_code_mode == + debugfs_loop_code_mode_v3_hw[i].value); + + seq_printf(s, "%s%s%s ", match ? "[" : "", + debugfs_loop_code_mode_v3_hw[i].name, + match ? "]" : ""); + } + seq_puts(s, "\n"); + + return 0; +} + +static ssize_t debugfs_bist_code_mode_v3_hw_write(struct file *filp, + const char __user *buf, + size_t count, + loff_t *ppos) +{ + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + char kbuf[16] = {}, *pkbuf; + bool found = false; + int i; + + if (hisi_hba->debugfs_bist_enable) + return -EPERM; + + if (count >= sizeof(kbuf)) + return -EINVAL; + + if (copy_from_user(kbuf, buf, count)) + return -EOVERFLOW; + + pkbuf = strstrip(kbuf); + + for (i = 0; i < ARRAY_SIZE(debugfs_loop_code_mode_v3_hw); i++) { + if (!strncmp(debugfs_loop_code_mode_v3_hw[i].name, + pkbuf, 16)) { + hisi_hba->debugfs_bist_code_mode = + debugfs_loop_code_mode_v3_hw[i].value; + found = true; + break; + } + } + + if (!found) + return -EINVAL; + + return count; +} + +static int debugfs_bist_code_mode_v3_hw_open(struct inode *inode, + struct file *filp) +{ + return single_open(filp, debugfs_bist_code_mode_v3_hw_show, + inode->i_private); +} + +static const struct file_operations debugfs_bist_code_mode_v3_hw_fops = { + .open = debugfs_bist_code_mode_v3_hw_open, + .read = seq_read, + .write = debugfs_bist_code_mode_v3_hw_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static ssize_t debugfs_bist_phy_v3_hw_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + unsigned int phy_no; + int val; + + if (hisi_hba->debugfs_bist_enable) + return -EPERM; + + val = kstrtouint_from_user(buf, count, 0, &phy_no); + if (val) + return val; + + if (phy_no >= hisi_hba->n_phy) + return -EINVAL; + + hisi_hba->debugfs_bist_phy_no = phy_no; + + return count; +} + +static int debugfs_bist_phy_v3_hw_show(struct seq_file *s, void *p) +{ + struct hisi_hba *hisi_hba = s->private; + + seq_printf(s, "%d\n", hisi_hba->debugfs_bist_phy_no); + + return 0; +} + +static int debugfs_bist_phy_v3_hw_open(struct inode *inode, + struct file *filp) +{ + return single_open(filp, debugfs_bist_phy_v3_hw_show, + inode->i_private); +} + +static const struct file_operations debugfs_bist_phy_v3_hw_fops = { + .open = debugfs_bist_phy_v3_hw_open, + .read = seq_read, + .write = debugfs_bist_phy_v3_hw_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct { + int value; + char *name; +} debugfs_loop_modes_v3_hw[] = { + { HISI_SAS_BIST_LOOPBACK_MODE_DIGITAL, "digital" }, + { HISI_SAS_BIST_LOOPBACK_MODE_SERDES, "serdes" }, + { HISI_SAS_BIST_LOOPBACK_MODE_REMOTE, "remote" }, +}; + +static int debugfs_bist_mode_v3_hw_show(struct seq_file *s, void *p) +{ + struct hisi_hba *hisi_hba = s->private; + int i; + + for (i = 0; i < ARRAY_SIZE(debugfs_loop_modes_v3_hw); i++) { + int match = (hisi_hba->debugfs_bist_mode == + debugfs_loop_modes_v3_hw[i].value); + + seq_printf(s, "%s%s%s ", match ? "[" : "", + debugfs_loop_modes_v3_hw[i].name, + match ? "]" : ""); + } + seq_puts(s, "\n"); + + return 0; +} + +static ssize_t debugfs_bist_mode_v3_hw_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + char kbuf[16] = {}, *pkbuf; + bool found = false; + int i; + + if (hisi_hba->debugfs_bist_enable) + return -EPERM; + + if (count >= sizeof(kbuf)) + return -EINVAL; + + if (copy_from_user(kbuf, buf, count)) + return -EOVERFLOW; + + pkbuf = strstrip(kbuf); + + for (i = 0; i < ARRAY_SIZE(debugfs_loop_modes_v3_hw); i++) { + if (!strncmp(debugfs_loop_modes_v3_hw[i].name, pkbuf, 16)) { + hisi_hba->debugfs_bist_mode = + debugfs_loop_modes_v3_hw[i].value; + found = true; + break; + } + } + + if (!found) + return -EINVAL; + + return count; +} + +static int debugfs_bist_mode_v3_hw_open(struct inode *inode, + struct file *filp) +{ + return single_open(filp, debugfs_bist_mode_v3_hw_show, + inode->i_private); +} + +static const struct file_operations debugfs_bist_mode_v3_hw_fops = { + .open = debugfs_bist_mode_v3_hw_open, + .read = seq_read, + .write = debugfs_bist_mode_v3_hw_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static ssize_t debugfs_bist_enable_v3_hw_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + struct seq_file *m = filp->private_data; + struct hisi_hba *hisi_hba = m->private; + unsigned int enable; + int val; + + val = kstrtouint_from_user(buf, count, 0, &enable); + if (val) + return val; + + if (enable > 1) + return -EINVAL; + + if (enable == hisi_hba->debugfs_bist_enable) + return count; + + val = debugfs_set_bist_v3_hw(hisi_hba, enable); + if (val < 0) + return val; + + hisi_hba->debugfs_bist_enable = enable; + + return count; +} + +static int debugfs_bist_enable_v3_hw_show(struct seq_file *s, void *p) +{ + struct hisi_hba *hisi_hba = s->private; + + seq_printf(s, "%d\n", hisi_hba->debugfs_bist_enable); + + return 0; +} + +static int debugfs_bist_enable_v3_hw_open(struct inode *inode, + struct file *filp) +{ + return single_open(filp, debugfs_bist_enable_v3_hw_show, + inode->i_private); +} + +static const struct file_operations debugfs_bist_enable_v3_hw_fops = { + .open = debugfs_bist_enable_v3_hw_open, + .read = seq_read, + .write = debugfs_bist_enable_v3_hw_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static const struct { + char *name; +} debugfs_ffe_name_v3_hw[FFE_CFG_MAX] = { + { "SAS_1_5_GBPS" }, + { "SAS_3_0_GBPS" }, + { "SAS_6_0_GBPS" }, + { "SAS_12_0_GBPS" }, + { "FFE_RESV" }, + { "SATA_1_5_GBPS" }, + { "SATA_3_0_GBPS" }, + { "SATA_6_0_GBPS" }, +}; + +static ssize_t debugfs_v3_hw_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + struct seq_file *m = filp->private_data; + u32 *val = m->private; + int res; + + res = kstrtouint_from_user(buf, count, 0, val); + if (res) + return res; + + return count; +} + +static int debugfs_v3_hw_show(struct seq_file *s, void *p) +{ + u32 *val = s->private; + + seq_printf(s, "0x%x\n", *val); + + return 0; +} + +static int debugfs_v3_hw_open(struct inode *inode, struct file *filp) +{ + return single_open(filp, debugfs_v3_hw_show, + inode->i_private); +} + +static const struct file_operations debugfs_v3_hw_fops = { + .open = debugfs_v3_hw_open, + .read = seq_read, + .write = debugfs_v3_hw_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static ssize_t debugfs_phy_down_cnt_v3_hw_write(struct file *filp, + const char __user *buf, + size_t count, loff_t *ppos) +{ + struct seq_file *s = filp->private_data; + struct hisi_sas_phy *phy = s->private; + unsigned int set_val; + int res; + + res = kstrtouint_from_user(buf, count, 0, &set_val); + if (res) + return res; + + if (set_val > 0) + return -EINVAL; + + atomic_set(&phy->down_cnt, 0); + + return count; +} + +static int debugfs_phy_down_cnt_v3_hw_show(struct seq_file *s, void *p) +{ + struct hisi_sas_phy *phy = s->private; + + seq_printf(s, "%d\n", atomic_read(&phy->down_cnt)); + + return 0; +} + +static int debugfs_phy_down_cnt_v3_hw_open(struct inode *inode, + struct file *filp) +{ + return single_open(filp, debugfs_phy_down_cnt_v3_hw_show, + inode->i_private); +} + +static const struct file_operations debugfs_phy_down_cnt_v3_hw_fops = { + .open = debugfs_phy_down_cnt_v3_hw_open, + .read = seq_read, + .write = debugfs_phy_down_cnt_v3_hw_write, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static void debugfs_work_handler_v3_hw(struct work_struct *work) +{ + struct hisi_hba *hisi_hba = + container_of(work, struct hisi_hba, debugfs_work); + int debugfs_dump_index = hisi_hba->debugfs_dump_index; + struct device *dev = hisi_hba->dev; + u64 timestamp = local_clock(); + + if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) { + dev_warn(dev, "dump count exceeded!\n"); + return; + } + + do_div(timestamp, NSEC_PER_MSEC); + hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp; + + debugfs_snapshot_regs_v3_hw(hisi_hba); + hisi_hba->debugfs_dump_index++; +} + +static void debugfs_release_v3_hw(struct hisi_hba *hisi_hba, int dump_index) +{ + struct device *dev = hisi_hba->dev; + int i; + + devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache); + devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache); + devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost); + devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct); + + for (i = 0; i < hisi_hba->queue_count; i++) + devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr); + + for (i = 0; i < hisi_hba->queue_count; i++) + devm_kfree(dev, + hisi_hba->debugfs_cq[dump_index][i].complete_hdr); + + for (i = 0; i < DEBUGFS_REGS_NUM; i++) + devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data); + + for (i = 0; i < hisi_hba->n_phy; i++) + devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data); +} + +static const struct hisi_sas_debugfs_reg *debugfs_reg_array_v3_hw[DEBUGFS_REGS_NUM] = { + [DEBUGFS_GLOBAL] = &debugfs_global_reg, + [DEBUGFS_AXI] = &debugfs_axi_reg, + [DEBUGFS_RAS] = &debugfs_ras_reg, +}; + +static int debugfs_alloc_v3_hw(struct hisi_hba *hisi_hba, int dump_index) +{ + const struct hisi_sas_hw *hw = hisi_hba->hw; + struct device *dev = hisi_hba->dev; + int p, c, d, r, i; + size_t sz; + + for (r = 0; r < DEBUGFS_REGS_NUM; r++) { + struct hisi_sas_debugfs_regs *regs = + &hisi_hba->debugfs_regs[dump_index][r]; + + sz = debugfs_reg_array_v3_hw[r]->count * 4; + regs->data = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!regs->data) + goto fail; + regs->hisi_hba = hisi_hba; + } + + sz = debugfs_port_reg.count * 4; + for (p = 0; p < hisi_hba->n_phy; p++) { + struct hisi_sas_debugfs_port *port = + &hisi_hba->debugfs_port_reg[dump_index][p]; + + port->data = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!port->data) + goto fail; + port->phy = &hisi_hba->phy[p]; + } + + sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS; + for (c = 0; c < hisi_hba->queue_count; c++) { + struct hisi_sas_debugfs_cq *cq = + &hisi_hba->debugfs_cq[dump_index][c]; + + cq->complete_hdr = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!cq->complete_hdr) + goto fail; + cq->cq = &hisi_hba->cq[c]; + } + + sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS; + for (d = 0; d < hisi_hba->queue_count; d++) { + struct hisi_sas_debugfs_dq *dq = + &hisi_hba->debugfs_dq[dump_index][d]; + + dq->hdr = devm_kmalloc(dev, sz, GFP_KERNEL); + if (!dq->hdr) + goto fail; + dq->dq = &hisi_hba->dq[d]; + } + + sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost); + + hisi_hba->debugfs_iost[dump_index].iost = + devm_kmalloc(dev, sz, GFP_KERNEL); + if (!hisi_hba->debugfs_iost[dump_index].iost) + goto fail; + + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * + sizeof(struct hisi_sas_iost_itct_cache); + + hisi_hba->debugfs_iost_cache[dump_index].cache = + devm_kmalloc(dev, sz, GFP_KERNEL); + if (!hisi_hba->debugfs_iost_cache[dump_index].cache) + goto fail; + + sz = HISI_SAS_IOST_ITCT_CACHE_NUM * + sizeof(struct hisi_sas_iost_itct_cache); + + hisi_hba->debugfs_itct_cache[dump_index].cache = + devm_kmalloc(dev, sz, GFP_KERNEL); + if (!hisi_hba->debugfs_itct_cache[dump_index].cache) + goto fail; + + /* New memory allocation must be locate before itct */ + sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct); + + hisi_hba->debugfs_itct[dump_index].itct = + devm_kmalloc(dev, sz, GFP_KERNEL); + if (!hisi_hba->debugfs_itct[dump_index].itct) + goto fail; + + return 0; +fail: + for (i = 0; i < hisi_sas_debugfs_dump_count; i++) + debugfs_release_v3_hw(hisi_hba, i); + return -ENOMEM; +} + +static void debugfs_phy_down_cnt_init_v3_hw(struct hisi_hba *hisi_hba) +{ + struct dentry *dir = debugfs_create_dir("phy_down_cnt", + hisi_hba->debugfs_dir); + char name[16]; + int phy_no; + + for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { + snprintf(name, 16, "%d", phy_no); + debugfs_create_file(name, 0600, dir, + &hisi_hba->phy[phy_no], + &debugfs_phy_down_cnt_v3_hw_fops); + } +} + +static void debugfs_bist_init_v3_hw(struct hisi_hba *hisi_hba) +{ + struct dentry *ports_dentry; + int phy_no; + + hisi_hba->debugfs_bist_dentry = + debugfs_create_dir("bist", hisi_hba->debugfs_dir); + debugfs_create_file("link_rate", 0600, + hisi_hba->debugfs_bist_dentry, hisi_hba, + &debugfs_bist_linkrate_v3_hw_fops); + + debugfs_create_file("code_mode", 0600, + hisi_hba->debugfs_bist_dentry, hisi_hba, + &debugfs_bist_code_mode_v3_hw_fops); + + debugfs_create_file("fixed_code", 0600, + hisi_hba->debugfs_bist_dentry, + &hisi_hba->debugfs_bist_fixed_code[0], + &debugfs_v3_hw_fops); + + debugfs_create_file("fixed_code_1", 0600, + hisi_hba->debugfs_bist_dentry, + &hisi_hba->debugfs_bist_fixed_code[1], + &debugfs_v3_hw_fops); + + debugfs_create_file("phy_id", 0600, hisi_hba->debugfs_bist_dentry, + hisi_hba, &debugfs_bist_phy_v3_hw_fops); + + debugfs_create_u32("cnt", 0600, hisi_hba->debugfs_bist_dentry, + &hisi_hba->debugfs_bist_cnt); + + debugfs_create_file("loopback_mode", 0600, + hisi_hba->debugfs_bist_dentry, + hisi_hba, &debugfs_bist_mode_v3_hw_fops); + + debugfs_create_file("enable", 0600, hisi_hba->debugfs_bist_dentry, + hisi_hba, &debugfs_bist_enable_v3_hw_fops); + + ports_dentry = debugfs_create_dir("port", hisi_hba->debugfs_bist_dentry); + + for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) { + struct dentry *port_dentry; + struct dentry *ffe_dentry; + char name[256]; + int i; + + snprintf(name, 256, "%d", phy_no); + port_dentry = debugfs_create_dir(name, ports_dentry); + ffe_dentry = debugfs_create_dir("ffe", port_dentry); + for (i = 0; i < FFE_CFG_MAX; i++) { + if (i == FFE_RESV) + continue; + debugfs_create_file(debugfs_ffe_name_v3_hw[i].name, + 0600, ffe_dentry, + &hisi_hba->debugfs_bist_ffe[phy_no][i], + &debugfs_v3_hw_fops); + } + } + + hisi_hba->debugfs_bist_linkrate = SAS_LINK_RATE_1_5_GBPS; +} + +static void debugfs_init_v3_hw(struct hisi_hba *hisi_hba) +{ + struct device *dev = hisi_hba->dev; + int i; + + hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev), + hisi_sas_debugfs_dir); + debugfs_create_file("trigger_dump", 0200, + hisi_hba->debugfs_dir, + hisi_hba, + &debugfs_trigger_dump_v3_hw_fops); + + /* create bist structures */ + debugfs_bist_init_v3_hw(hisi_hba); + + hisi_hba->debugfs_dump_dentry = + debugfs_create_dir("dump", hisi_hba->debugfs_dir); + + debugfs_phy_down_cnt_init_v3_hw(hisi_hba); + + for (i = 0; i < hisi_sas_debugfs_dump_count; i++) { + if (debugfs_alloc_v3_hw(hisi_hba, i)) { + debugfs_remove_recursive(hisi_hba->debugfs_dir); + dev_dbg(dev, "failed to init debugfs!\n"); + break; + } + } +} + +static void debugfs_exit_v3_hw(struct hisi_hba *hisi_hba) +{ + debugfs_remove_recursive(hisi_hba->debugfs_dir); +} + static int hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -3299,7 +4492,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) } if (hisi_sas_debugfs_enable) - hisi_sas_debugfs_init(hisi_hba); + debugfs_init_v3_hw(hisi_hba); rc = interrupt_preinit_v3_hw(hisi_hba); if (rc) @@ -3337,7 +4530,7 @@ err_out_register_ha: err_out_free_irq_vectors: pci_free_irq_vectors(pdev); err_out_debugfs: - hisi_sas_debugfs_exit(hisi_hba); + debugfs_exit_v3_hw(hisi_hba); err_out_ha: hisi_sas_free(hisi_hba); scsi_host_put(shost); @@ -3384,7 +4577,7 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev) pci_release_regions(pdev); pci_disable_device(pdev); hisi_sas_free(hisi_hba); - hisi_sas_debugfs_exit(hisi_hba); + debugfs_exit_v3_hw(hisi_hba); scsi_host_put(shost); } -- cgit v1.2.3 From 939785d35def8d10e8ad312b252dbbecc8d41ca1 Mon Sep 17 00:00:00 2001 From: Bean Huo Date: Wed, 25 Nov 2020 19:53:00 +0100 Subject: scsi: ufs: Remove unnecessary if condition in ufshcd_suspend() In the case that auto_bkops_enable is false, which means auto bkops has been disabled, there is no need to call ufshcd_disable_auto_bkops(). Link: https://lore.kernel.org/r/20201125185300.3394-1-huobean@gmail.com Reviewed-by: Stanley Chu Reviewed-by: Can Guo Signed-off-by: Bean Huo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 92d433d5f3ca..93e15e829d1d 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -8609,11 +8609,9 @@ static int ufshcd_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) } if (req_dev_pwr_mode != hba->curr_dev_pwr_mode) { - if ((ufshcd_is_runtime_pm(pm_op) && !hba->auto_bkops_enabled) || - !ufshcd_is_runtime_pm(pm_op)) { + if (!ufshcd_is_runtime_pm(pm_op)) /* ensure that bkops is disabled */ ufshcd_disable_auto_bkops(hba); - } if (!hba->dev_info.b_rpm_dev_flush_capable) { ret = ufshcd_set_dev_pwr_mode(hba, req_dev_pwr_mode); -- cgit v1.2.3 From 4ba9e516573e60c471c01bb369144651f6f8d50b Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Thu, 26 Nov 2020 14:29:39 +0100 Subject: scsi: pm80xx: Do not sleep in atomic context hw_event_sas_phy_up() is used in hardirq/softirq context: pm8001_interrupt_handler_msix() || pm8001_interrupt_handler_intx() || pm8001_tasklet => PM8001_CHIP_DISP->isr() = pm80xx_chip_isr() => process_oq() [spin_lock_irqsave(&pm8001_ha->lock,)] => process_one_iomb() => mpi_hw_event() => hw_event_sas_phy_up() => msleep(200) Revert the msleep() back to an mdelay() to avoid sleeping in atomic context. Link: https://lore.kernel.org/r/20201126132952.2287996-2-bigeasy@linutronix.de Fixes: 4daf1ef3c681 ("scsi: pm80xx: Convert 'long' mdelay to msleep") Cc: Vikram Auradkar Cc: Jack Wang Acked-by: Jack Wang Signed-off-by: Ahmed S. Darwish Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm80xx_hwi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 69f8244539e0..6772b0924dac 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -3296,7 +3296,7 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr); spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags); if (pm8001_ha->flags == PM8001F_RUN_TIME) - msleep(200);/*delay a moment to wait disk to spinup*/ + mdelay(200); /* delay a moment to wait for disk to spin up */ pm8001_bytes_dmaed(pm8001_ha, phy_id); } -- cgit v1.2.3 From 18577cdcaeeb7a1ca5c3adc4d92ed2ba75699625 Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Thu, 26 Nov 2020 14:29:40 +0100 Subject: scsi: hisi_sas: Remove preemptible() hisi_sas_task_exec() uses preemptible() to see if it's safe to block. This does not work for CONFIG_PREEMPT_COUNT=n kernels in which preemptible() always returns 0. The problem is masked when enabling some of the common Kconfig.debug options (like CONFIG_DEBUG_ATOMIC_SLEEP), as they implicitly enable the preemption counter. In general, driver leaf functions should not make logic decisions based on the context they're called from. The caller should be the entity responsible for explicitly indicating context. Since hisi_sas_task_exec() already has a gfp_t flags parameter, use it as the explicit context marker. Link: https://lore.kernel.org/r/20201126132952.2287996-3-bigeasy@linutronix.de Fixes: 214e702d4b70 ("scsi: hisi_sas: Adjust task reject period during host reset") Fixes: 550c0d89d52d ("scsi: hisi_sas: Replace in_softirq() check in hisi_sas_task_exec()") Cc: Xiaofei Tan Cc: Xiang Chen Cc: John Garry Acked-by: John Garry Signed-off-by: Ahmed S. Darwish Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index e77c3e64a326..71ecfba996e4 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -585,13 +585,7 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags, dev = hisi_hba->dev; if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) { - /* - * For IOs from upper layer, it may already disable preempt - * in the IO path, if disable preempt again in down(), - * function schedule() will report schedule_bug(), so check - * preemptible() before goto down(). - */ - if (!preemptible()) + if (!gfpflags_allow_blocking(gfp_flags)) return -EINVAL; down(&hisi_hba->sem); -- cgit v1.2.3 From a93c3835319849f0226b9a7101284aeb60a5ed8e Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Thu, 26 Nov 2020 14:29:41 +0100 Subject: scsi: qla4xxx: Remove in_interrupt() qla4_82xx_crb_win_lock() spins on a certain hardware state until it's updated. At the end of each spin, if in_interrupt() is true, it does 20 loops of cpu_relax(). Otherwise, it yields the CPU. The in_interrupt() macro is ill-defined as it does not provide what the name suggests, and it does not catch the intended use-case here. qla4_82xx_crb_win_lock() is always invoked with scsi_qla_host::hw_lock acquired, with disabled interrupts. If the caller is in process context, as in qla4_82xx_need_reset_handler(), then in_interrupt() will return false even though it is not allowed to call schedule(). Remove the in_interrupt() check. Change qla4_82xx_crb_win_lock() specification to a purely atomic function. Mark it as static, remove its forward declaration, and move it above its callers. To avoid hammering the PCI bus while spinning, use a 10 micro-second delay instead of cpu_relax(). Link: https://lore.kernel.org/r/20201126132952.2287996-4-bigeasy@linutronix.de Fixes: f4f5df23bf72 ("[SCSI] qla4xxx: Added support for ISP82XX") Cc: Nilesh Javali Cc: Manish Rangankar Cc: Reviewed-by: Daniel Wagner Signed-off-by: Ahmed S. Darwish Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Martin K. Petersen --- drivers/scsi/qla4xxx/ql4_glbl.h | 1 - drivers/scsi/qla4xxx/ql4_nx.c | 63 +++++++++++++++++++---------------------- 2 files changed, 29 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index b8f02210aeb0..ea60057b2e20 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -114,7 +114,6 @@ irqreturn_t qla4_82xx_intr_handler(int irq, void *dev_id); void qla4_82xx_queue_iocb(struct scsi_qla_host *ha); void qla4_82xx_complete_iocb(struct scsi_qla_host *ha); -int qla4_82xx_crb_win_lock(struct scsi_qla_host *); void qla4_82xx_crb_win_unlock(struct scsi_qla_host *); int qla4_82xx_pci_get_crb_addr_2M(struct scsi_qla_host *, ulong *); void qla4_82xx_wr_32(struct scsi_qla_host *, ulong, u32); diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index f1767b21076f..da903a545b2c 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -375,6 +375,35 @@ qla4_82xx_pci_set_crbwindow_2M(struct scsi_qla_host *ha, ulong *off) *off = (*off & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase; } +#define CRB_WIN_LOCK_TIMEOUT 100000000 + +/* + * Context: atomic + */ +static int qla4_82xx_crb_win_lock(struct scsi_qla_host *ha) +{ + int done = 0, timeout = 0; + + while (!done) { + /* acquire semaphore3 from PCI HW block */ + done = qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK)); + if (done == 1) + break; + if (timeout >= CRB_WIN_LOCK_TIMEOUT) + return -1; + + timeout++; + udelay(10); + } + qla4_82xx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->func_num); + return 0; +} + +void qla4_82xx_crb_win_unlock(struct scsi_qla_host *ha) +{ + qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK)); +} + void qla4_82xx_wr_32(struct scsi_qla_host *ha, ulong off, u32 data) { @@ -475,40 +504,6 @@ int qla4_82xx_md_wr_32(struct scsi_qla_host *ha, uint32_t off, uint32_t data) return rval; } -#define CRB_WIN_LOCK_TIMEOUT 100000000 - -int qla4_82xx_crb_win_lock(struct scsi_qla_host *ha) -{ - int i; - int done = 0, timeout = 0; - - while (!done) { - /* acquire semaphore3 from PCI HW block */ - done = qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK)); - if (done == 1) - break; - if (timeout >= CRB_WIN_LOCK_TIMEOUT) - return -1; - - timeout++; - - /* Yield CPU */ - if (!in_interrupt()) - schedule(); - else { - for (i = 0; i < 20; i++) - cpu_relax(); /*This a nop instr on i386*/ - } - } - qla4_82xx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->func_num); - return 0; -} - -void qla4_82xx_crb_win_unlock(struct scsi_qla_host *ha) -{ - qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK)); -} - #define IDC_LOCK_TIMEOUT 100000000 /** -- cgit v1.2.3 From 8ac246bdd07a0f948f0e33eb4797bd2645cd8224 Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Thu, 26 Nov 2020 14:29:42 +0100 Subject: scsi: qla2xxx: Remove in_interrupt() from qla82xx-specific code qla82xx_idc_lock() spins on a certain hardware state until it's updated. At the end of each spin, if in_interrupt() is true, it does 20 loops of cpu_relax(). Otherwise, it yields the CPU. While in_interrupt() is ill-defined and does not provide what the name suggests, it is not needed here: qla82xx_idc_lock() is always called from process context. Below is an analysis of its callers, in order of appearance: - qla_nx.c: qla82xx_device_bootstrap(), only called by qla82xx_device_state_handler(), has multiple msleep()s. - qla_nx.c: qla82xx_need_qsnt_handler(), has one second msleep() - qla_nx.c: qla82xx_wait_for_state_change(), one second msleep() - qla_nx.c: qla82xx_need_reset_handler(), can sleep up to 10 seconds - qla_nx.c: qla82xx_device_state_handler(), has multiple msleep()s - qla_nx.c: qla82xx_abort_isp(), if it's a qla82xx controller, calls qla82xx_device_state_handler(), which sleeps. It's also bound to isp_operations ->abort_isp() hook, where all the callers are in process context. - qla_nx.c: qla82xx_beacon_on(), bound to isp_operations ->beacon_on() hook. That hook is only called once, in a mutex locked context, from qla2x00_beacon_store(). - qla_nx.c: qla82xx_beacon_off(), bound to isp_operations ->beacon_off() hook. Like ->beacon_on(), it's only called once, in a mutex locked context, from qla2x00_beacon_store(). - qla_nx.c: qla82xx_fw_dump(), calls qla2x00_wait_for_chip_reset(), which has msleep() in a loop. It is bound to isp_operations ->fw_dump() hook. That hook *is* called from atomic context at qla_isr.c by multiple interrupt handlers. Nonetheless, it's other controllers interrupt handlers, and not the qla82xx. - qla82xx_msix_default() and qla82xx_msix_rsp_q() call qla24xx_process_response_queue() which doesn't implement the firmware dumping. - qla_attr.c: qla2x00_sysfs_write_fw_dump(), and qla2x00_sysfs_write_reset(), process-context sysfs ->write() hooks. - qla_os.c: qla2x00_probe_one(). PCI ->probe(), process context. - qla_os.c: qla2x00_clear_drv_active(), called solely from qla2x00_remove_one(), which is PCI ->remove() hook, process context. - qla_os.c: qla2x00_do_dpc(), kthread function, process context. Remove the in_interrupt() check. Change qla82xx_idc_lock() specification to a purely process-context function. Mark it with "Context: task, might sleep". Change qla82xx_idc_lock() implementation to sleep 100ms, instead of a schedule(), for each spin. This is more deterministic, and it matches the other qla models idc_lock() functions. Link: https://lore.kernel.org/r/20201126132952.2287996-5-bigeasy@linutronix.de Cc: Nilesh Javali Cc: Reviewed-by: Himanshu Madhani Reviewed-by: Daniel Wagner Signed-off-by: Ahmed S. Darwish Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 5 +++++ drivers/scsi/qla2xxx/qla_nx.c | 25 +++++++++++-------------- 2 files changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index ed9b10f8537d..fe3c0e2f1ce8 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3296,8 +3296,10 @@ struct isp_operations { void (*fw_dump)(struct scsi_qla_host *vha); void (*mpi_fw_dump)(struct scsi_qla_host *, int); + /* Context: task, might sleep */ int (*beacon_on) (struct scsi_qla_host *); int (*beacon_off) (struct scsi_qla_host *); + void (*beacon_blink) (struct scsi_qla_host *); void *(*read_optrom)(struct scsi_qla_host *, void *, @@ -3308,7 +3310,10 @@ struct isp_operations { int (*get_flash_version) (struct scsi_qla_host *, void *); int (*start_scsi) (srb_t *); int (*start_scsi_mq) (srb_t *); + + /* Context: task, might sleep */ int (*abort_isp) (struct scsi_qla_host *); + int (*iospace_config)(struct qla_hw_data *); int (*initialize_adapter)(struct scsi_qla_host *); }; diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index b3ba0de5d4fb..b2017f1c3504 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -489,29 +489,26 @@ qla82xx_rd_32(struct qla_hw_data *ha, ulong off_in) return data; } -#define IDC_LOCK_TIMEOUT 100000000 +/* + * Context: task, might sleep + */ int qla82xx_idc_lock(struct qla_hw_data *ha) { - int i; - int done = 0, timeout = 0; + const int delay_ms = 100, timeout_ms = 2000; + int done, total = 0; - while (!done) { + might_sleep(); + + while (true) { /* acquire semaphore5 from PCI HW block */ done = qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_LOCK)); if (done == 1) break; - if (timeout >= IDC_LOCK_TIMEOUT) + if (WARN_ON_ONCE(total >= timeout_ms)) return -1; - timeout++; - - /* Yield CPU */ - if (!in_interrupt()) - schedule(); - else { - for (i = 0; i < 20; i++) - cpu_relax(); - } + total += delay_ms; + msleep(delay_ms); } return 0; -- cgit v1.2.3 From 9fef41f25d60d3cb22ee81d5d92cdea99a1b35ea Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Thu, 26 Nov 2020 14:29:43 +0100 Subject: scsi: target: tcm_qla2xxx: Remove BUG_ON(in_interrupt()) tcm_qla2xxx_free_session() has a BUG_ON(in_interrupt()). While in_interrupt() is ill-defined and does not provide what the name suggests, it is not needed here: the function is always invoked from workqueue context through "struct qla_tgt_func_tmpl" ->free_session() hook it is bound to. The function also calls wait_event_timeout() down the chain, which already has a might_sleep(). Remove the in_interrupt() check. Link: https://lore.kernel.org/r/20201126132952.2287996-6-bigeasy@linutronix.de Cc: Nilesh Javali Cc: Reviewed-by: Himanshu Madhani Reviewed-by: Daniel Wagner Signed-off-by: Ahmed S. Darwish Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/tcm_qla2xxx.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 784b43f18181..b55fc768a2a7 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -1400,8 +1400,6 @@ static void tcm_qla2xxx_free_session(struct fc_port *sess) struct se_session *se_sess; struct tcm_qla2xxx_lport *lport; - BUG_ON(in_interrupt()); - se_sess = sess->se_sess; if (!se_sess) { pr_err("struct fc_port->se_sess is NULL\n"); -- cgit v1.2.3 From 4f6a57c23b1e002487159791feef7d54b725bfa6 Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Thu, 26 Nov 2020 14:29:44 +0100 Subject: scsi: qla2xxx: Remove in_interrupt() from qla83xx-specific code qla83xx_wait_logic() is used to control the frequency of device IDC lock retries. If in_interrupt() is true, it does 20 loops of cpu_relax(). Otherwise, it sleeps for 100ms and yields the CPU. While in_interrupt() is ill-defined and does not provide what the name suggests, it is not needed here: that qla83xx_wait_logic() is exclusively called by qla83xx_idc_lock() / unlock(), and they always run from process context. Below is an analysis of all the idc lock/unlock callers, in order of appearance: - qla_os.c: qla83xx_nic_core_unrecoverable_work(), qla83xx_idc_state_handler_work(), qla83xx_nic_core_reset_work(), qla83xx_service_idc_aen(), all workqueue context - qla_os.c: qla83xx_check_nic_core_fw_alive(), has msleep() - qla_os.c: qla83xx_set_drv_presence(), called once from qla2x00_abort_isp(), which is bound to process-context ->abort_isp() hook. It also invokes wait_for_completion_timeout() through the chain qla2x00_configure_hba() => qla24xx_link_initialize() => qla2x00_mailbox_command(). - qla_os.c: qla83xx_clear_drv_presence(), which is called from qla2x00_abort_isp() discussed above, and from qla2x00_remove_one() which is PCI process-context ->remove() hook. - qla_os.c: qla83xx_need_reset_handler(), has a one second msleep() in a loop. - qla_os.c: qla83xx_device_bootstrap(), called only by qla83xx_idc_state_handler(), which has multiple msleep() invocations. - qla_os.c: qla83xx_idc_state_handler(), multiple msleep() invocations. - qla_attr.c: qla2x00_sysfs_write_reset(), sysfs bin_attribute ->write() hook, process context - qla_init.c: qla83xx_nic_core_fw_load() => qla_init.c: qla2x00_initialize_adapter() => bound to isp_operations ->initialize_adapter() hook ** => qla_os.c: qla2x00_probe_one(), PCI ->probe() process ctx - qla_init.c: qla83xx_initiating_reset(), msleep() in a loop. - qla_init.c: qla83xx_nic_core_reset(), called by qla83xx_nic_core_reset_work(), workqueue context. Remove the in_interrupt() check, and thus replace the entirety of qla83xx_wait_logic() with an msleep(QLA83XX_WAIT_LOGIC_MS). Mark qla83xx_idc_lock() / unlock() with "Context: task, can sleep". Link: https://lore.kernel.org/r/20201126132952.2287996-7-bigeasy@linutronix.de Cc: Nilesh Javali Cc: GR-QLogic-Storage-Upstream@marvell.com Reviewed-by: Himanshu Madhani Reviewed-by: Daniel Wagner Signed-off-by: Ahmed S. Darwish Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 43 +++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index f9c8ae9d669e..2a8e065b192c 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -5619,25 +5619,10 @@ qla83xx_service_idc_aen(struct work_struct *work) } } -static void -qla83xx_wait_logic(void) -{ - int i; - - /* Yield CPU */ - if (!in_interrupt()) { - /* - * Wait about 200ms before retrying again. - * This controls the number of retries for single - * lock operation. - */ - msleep(100); - schedule(); - } else { - for (i = 0; i < 20; i++) - cpu_relax(); /* This a nop instr on i386 */ - } -} +/* + * Control the frequency of IDC lock retries + */ +#define QLA83XX_WAIT_LOGIC_MS 100 static int qla83xx_force_lock_recovery(scsi_qla_host_t *base_vha) @@ -5727,7 +5712,7 @@ retry_lockid: goto exit; if (o_drv_lockid == n_drv_lockid) { - qla83xx_wait_logic(); + msleep(QLA83XX_WAIT_LOGIC_MS); goto retry_lockid; } else return QLA_SUCCESS; @@ -5736,6 +5721,9 @@ exit: return rval; } +/* + * Context: task, can sleep + */ void qla83xx_idc_lock(scsi_qla_host_t *base_vha, uint16_t requester_id) { @@ -5743,6 +5731,8 @@ qla83xx_idc_lock(scsi_qla_host_t *base_vha, uint16_t requester_id) uint32_t lock_owner; struct qla_hw_data *ha = base_vha->hw; + might_sleep(); + /* IDC-lock implementation using driver-lock/lock-id remote registers */ retry_lock: if (qla83xx_rd_reg(base_vha, QLA83XX_DRIVER_LOCK, &data) @@ -5761,7 +5751,7 @@ retry_lock: /* Retry/Perform IDC-Lock recovery */ if (qla83xx_idc_lock_recovery(base_vha) == QLA_SUCCESS) { - qla83xx_wait_logic(); + msleep(QLA83XX_WAIT_LOGIC_MS); goto retry_lock; } else ql_log(ql_log_warn, base_vha, 0xb075, @@ -6259,6 +6249,9 @@ void qla24xx_process_purex_list(struct purex_list *list) } } +/* + * Context: task, can sleep + */ void qla83xx_idc_unlock(scsi_qla_host_t *base_vha, uint16_t requester_id) { @@ -6269,6 +6262,8 @@ qla83xx_idc_unlock(scsi_qla_host_t *base_vha, uint16_t requester_id) uint32_t data; struct qla_hw_data *ha = base_vha->hw; + might_sleep(); + /* IDC-unlock implementation using driver-unlock/lock-id * remote registers */ @@ -6284,7 +6279,7 @@ retry_unlock: /* SV: XXX: IDC unlock retrying needed here? */ /* Retry for IDC-unlock */ - qla83xx_wait_logic(); + msleep(QLA83XX_WAIT_LOGIC_MS); retry++; ql_dbg(ql_dbg_p3p, base_vha, 0xb064, "Failed to release IDC lock, retrying=%d\n", retry); @@ -6292,7 +6287,7 @@ retry_unlock: } } else if (retry < 10) { /* Retry for IDC-unlock */ - qla83xx_wait_logic(); + msleep(QLA83XX_WAIT_LOGIC_MS); retry++; ql_dbg(ql_dbg_p3p, base_vha, 0xb065, "Failed to read drv-lockid, retrying=%d\n", retry); @@ -6308,7 +6303,7 @@ retry_unlock2: if (qla83xx_access_control(base_vha, options, 0, 0, NULL)) { if (retry < 10) { /* Retry for IDC-unlock */ - qla83xx_wait_logic(); + msleep(QLA83XX_WAIT_LOGIC_MS); retry++; ql_dbg(ql_dbg_p3p, base_vha, 0xb066, "Failed to release IDC lock, retrying=%d\n", retry); -- cgit v1.2.3 From 3627668c2e2c9459cff874ad34b82d251038da48 Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Thu, 26 Nov 2020 14:29:45 +0100 Subject: scsi: qla4xxx: Remove in_interrupt() from qla4_82xx_idc_lock() qla4_82xx_idc_lock() spins on a certain hardware state until it is updated. At the end of each spin, if in_interrupt() is true, it does 20 loops of cpu_relax(). Otherwise, it yields the CPU. While in_interrupt() is ill-defined and does not provide what the name suggests, it is not needed here: qla4_82xx_idc_lock() is always called from process context. Below is an analysis of its callers: - ql4_nx.c: qla4_82xx_need_reset_handler(), 1-second msleep() in a loop. - ql4_nx.c: qla4_82xx_isp_reset(), calls qla4_8xxx_device_state_handler(), which has multiple msleep()s. Beside direct calls, qla4_82xx_idc_lock() is also bound to isp_operations ->idc_lock() hook. Other functions which are bound to the same hook, e.g. qla4_83xx_drv_lock(), also have an msleep(). For completeness, below is an analysis of all callers of that hook: - ql4_83xx.c: qla4_83xx_need_reset_handler(), has an msleep() - ql4_83xx.c: qla4_83xx_isp_reset(), calls qla4_8xxx_device_state_handler(), which has multiple msleep()s. - ql4_83xx.c: qla4_83xx_disable_pause(), all process context callers: => ql4_mbx.c: qla4xxx_mailbox_command(), msleep(), mutex_lock() => ql4_os.c: qla4xxx_recover_adapter(), schedule_timeout() in loop => ql4_os.c: qla4xxx_do_dpc(), workqueue context - ql4_attr.c: qla4_8xxx_sysfs_write_fw_dump(), sysfs bin_attribute ->write() hook, process context - ql4_mbx.c: qla4xxx_mailbox_command(), earlier discussed - ql4_nx.c: qla4_8xxx_device_bootstrap(), callers: => ql4_83xx.c: qla4_83xx_need_reset_handler(), process, msleep() => ql4_nx.c: qla4_8xxx_device_state_handler(), earlier discussed - ql4_nx.c: qla4_8xxx_need_qsnt_handler(), callers: => ql4_nx.c: qla4_8xxx_device_state_handler(), multiple msleep()s => ql4_os.c: qla4xxx_do_dpc(), workqueue context - ql4_nx.c: qla4_8xxx_update_idc_reg(), callers: => ql4_nx.c: qla4_8xxx_device_state_handler(), earlier discussed => ql4_os.c: qla4_8xxx_error_recovery(), only called by qla4xxx_pci_slot_reset(), which is bound to PCI ->slot_reset() process-context hook - ql4_nx.c: qla4_8xxx_device_state_handler(), earlier discussed - ql4_os.c: qla4xxx_recover_adapter(), earlier discussed - ql4_os.c: qla4xxx_do_dpc(), earlier discussed Remove the in_interrupt() check. Mark, qla4_82xx_idc_lock(), and the ->idc_lock() hook itself, with "Context: task, can sleep". Change qla4_82xx_idc_lock() implementation to sleep 100ms, instead of a schedule(), for each spin. This is more deterministic, and it matches other PCI HW locking functions in the driver. Link: https://lore.kernel.org/r/20201126132952.2287996-8-bigeasy@linutronix.de Cc: Nilesh Javali Cc: Manish Rangankar Cc: Reviewed-by: Daniel Wagner Signed-off-by: Ahmed S. Darwish Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Martin K. Petersen --- drivers/scsi/qla4xxx/ql4_def.h | 2 +- drivers/scsi/qla4xxx/ql4_nx.c | 14 +++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index f5b382ed0a1b..921054748388 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -435,7 +435,7 @@ struct isp_operations { void (*wr_reg_direct) (struct scsi_qla_host *, ulong, uint32_t); int (*rd_reg_indirect) (struct scsi_qla_host *, uint32_t, uint32_t *); int (*wr_reg_indirect) (struct scsi_qla_host *, uint32_t, uint32_t); - int (*idc_lock) (struct scsi_qla_host *); + int (*idc_lock) (struct scsi_qla_host *); /* Context: task, can sleep */ void (*idc_unlock) (struct scsi_qla_host *); void (*rom_lock_recovery) (struct scsi_qla_host *); void (*queue_mailbox_command) (struct scsi_qla_host *, uint32_t *, int); diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index da903a545b2c..4362d0ebe0e1 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -512,12 +512,15 @@ int qla4_82xx_md_wr_32(struct scsi_qla_host *ha, uint32_t off, uint32_t data) * * General purpose lock used to synchronize access to * CRB_DEV_STATE, CRB_DEV_REF_COUNT, etc. + * + * Context: task, can sleep **/ int qla4_82xx_idc_lock(struct scsi_qla_host *ha) { - int i; int done = 0, timeout = 0; + might_sleep(); + while (!done) { /* acquire semaphore5 from PCI HW block */ done = qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM5_LOCK)); @@ -527,14 +530,7 @@ int qla4_82xx_idc_lock(struct scsi_qla_host *ha) return -1; timeout++; - - /* Yield CPU */ - if (!in_interrupt()) - schedule(); - else { - for (i = 0; i < 20; i++) - cpu_relax(); /*This a nop instr on i386*/ - } + msleep(100); } return 0; } -- cgit v1.2.3 From 014aced18aff34d3b3ed3735b094d538b8c9f66e Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Thu, 26 Nov 2020 14:29:46 +0100 Subject: scsi: qla4xxx: Remove in_interrupt() from qla4_82xx_rom_lock() qla4_82xx_rom_lock() spins on a certain hardware state until it is updated. At the end of each spin, if in_interrupt() is true, it does 20 loops of cpu_relax(). Otherwise, it yields the CPU. While in_interrupt() is ill-defined and does not provide what the name suggests, it is not needed here: qla4_82xx_rom_lock() is always called from process context. Below is an analysis of its callers: - ql4_nx.c: qla4_82xx_rom_fast_read(), all process context callers: => ql4_nx.c: qla4_82xx_pinit_from_rom(), GFP_KERNEL allocation => ql4_nx.c: qla4_82xx_load_from_flash(), msleep() in a loop - ql4_nx.c: qla4_82xx_pinit_from_rom(), earlier discussed - ql4_nx.c: qla4_82xx_rom_lock_recovery(), bound to "isp_operations" ->rom_lock_recovery() hook, which has one process context caller, qla4_8xxx_device_bootstrap(), with callers: => ql4_83xx.c: qla4_83xx_need_reset_handler(), process, msleep() => ql4_nx.c: qla4_8xxx_device_state_handler(), multiple msleep()s - ql4_nx.c: qla4_82xx_read_flash_data(), has cond_resched() Remove the in_interrupt() check. Mark, qla4_82xx_rom_lock(), and the ->rom_lock_recovery() hook, with "Context: task, can sleep". Change qla4_82xx_rom_lock() implementation to sleep 20ms, instead of a schedule(), for each spin. This is more deterministic, and it matches the other implementations bound to ->rom_lock_recovery(). Link: https://lore.kernel.org/r/20201126132952.2287996-9-bigeasy@linutronix.de Cc: Nilesh Javali Cc: Manish Rangankar Cc: Reviewed-by: Daniel Wagner Signed-off-by: Ahmed S. Darwish Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Martin K. Petersen --- drivers/scsi/qla4xxx/ql4_def.h | 2 +- drivers/scsi/qla4xxx/ql4_nx.c | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 921054748388..031569c496e5 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -437,7 +437,7 @@ struct isp_operations { int (*wr_reg_indirect) (struct scsi_qla_host *, uint32_t, uint32_t); int (*idc_lock) (struct scsi_qla_host *); /* Context: task, can sleep */ void (*idc_unlock) (struct scsi_qla_host *); - void (*rom_lock_recovery) (struct scsi_qla_host *); + void (*rom_lock_recovery) (struct scsi_qla_host *); /* Context: task, can sleep */ void (*queue_mailbox_command) (struct scsi_qla_host *, uint32_t *, int); void (*process_mailbox_interrupt) (struct scsi_qla_host *, int); }; diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 4362d0ebe0e1..fd30fbd0d33c 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -871,15 +871,18 @@ qla4_82xx_decode_crb_addr(unsigned long addr) static long rom_max_timeout = 100; static long qla4_82xx_rom_lock_timeout = 100; +/* + * Context: task, can_sleep + */ static int qla4_82xx_rom_lock(struct scsi_qla_host *ha) { - int i; int done = 0, timeout = 0; + might_sleep(); + while (!done) { /* acquire semaphore2 from PCI HW block */ - done = qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_LOCK)); if (done == 1) break; @@ -887,14 +890,7 @@ qla4_82xx_rom_lock(struct scsi_qla_host *ha) return -1; timeout++; - - /* Yield CPU */ - if (!in_interrupt()) - schedule(); - else { - for (i = 0; i < 20; i++) - cpu_relax(); /*This a nop instr on i386*/ - } + msleep(20); } qla4_82xx_wr_32(ha, QLA82XX_ROM_LOCK_ID, ROM_LOCK_DRIVER); return 0; -- cgit v1.2.3 From 547c0d1aeb76fead5177cc30b95e914b498675bd Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Thu, 26 Nov 2020 14:29:47 +0100 Subject: scsi: mpt3sas: Remove in_interrupt() _scsih_fw_event_cleanup_queue() waits for all outstanding firmware events wokrqueue handlers to finish. If in_interrupt() is true, it cancels itself and return early. That in_interrupt() check is ill-defined and does not provide what the name suggests: it does not cover all states in which it is safe to block and call functions like cancel_work_sync(). That check is also not needed: _scsih_fw_event_cleanup_queue() is always invoked from process context. Below is an analysis of its callers: - scsih_remove(), bound to PCI ->remove(), process context - scsih_shutdown(), bound to PCI ->shutdown(), process context - mpt3sas_scsih_clear_outstanding_scsi_tm_commands(), called by => _base_clear_outstanding_commands(), called by =>_base_fault_reset_work(), workqueue => mpt3sas_base_hard_reset_handler(), locks mutex Remove the in_interrupt() check. Change _scsih_fw_event_cleanup_queue() specification to a purely process-context function and mark it with "Context: task, can sleep". Link: https://lore.kernel.org/r/20201126132952.2287996-10-bigeasy@linutronix.de Cc: Sathya Prakash Cc: Sreekanth Reddy Cc: Suganath Prabu Subramani Cc: Reviewed-by: Daniel Wagner Signed-off-by: Ahmed S. Darwish Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index a3ee5bf715f9..c8b09a81834d 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -3673,6 +3673,8 @@ static struct fw_event_work *dequeue_next_fw_event(struct MPT3SAS_ADAPTER *ioc) * * Walk the firmware event queue, either killing timers, or waiting * for outstanding events to complete + * + * Context: task, can sleep */ static void _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc) @@ -3680,7 +3682,7 @@ _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc) struct fw_event_work *fw_event; if ((list_empty(&ioc->fw_event_list) && !ioc->current_event) || - !ioc->firmware_event_thread || in_interrupt()) + !ioc->firmware_event_thread) return; ioc->fw_events_cleanup = 1; -- cgit v1.2.3 From 3bc08b9545dab900bb5902459877bf6a0fb4ec8b Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Thu, 26 Nov 2020 14:29:48 +0100 Subject: scsi: myrb: Remove WARN_ON(in_interrupt()) The in_interrupt() macro is ill-defined and does not provide what the name suggests. The usage especially in driver code is deprecated and a tree-wide effort to clean up and consolidate the (ab)usage of in_interrupt() and related checks is happening. In this case the check covers only parts of the contexts in which these functions cannot be called. It fails to detect preemption or interrupt disabled invocations. As wait_for_completion() already contains a broad variety of checks (always enabled or debug option dependent) which cover all invalid conditions already, there is no point in having extra inconsistent warnings in drivers. Just remove it. Link: https://lore.kernel.org/r/20201126132952.2287996-11-bigeasy@linutronix.de Cc: Hannes Reinecke Reviewed-by: Daniel Wagner Signed-off-by: Ahmed S. Darwish Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Martin K. Petersen --- drivers/scsi/myrb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/myrb.c b/drivers/scsi/myrb.c index 5fa0f4ed6565..3d8e91c07dc7 100644 --- a/drivers/scsi/myrb.c +++ b/drivers/scsi/myrb.c @@ -194,7 +194,6 @@ static unsigned short myrb_exec_cmd(struct myrb_hba *cb, cb->qcmd(cb, cmd_blk); spin_unlock_irqrestore(&cb->queue_lock, flags); - WARN_ON(in_interrupt()); wait_for_completion(&cmpl); return cmd_blk->status; } -- cgit v1.2.3 From ca6853693cbdcc3f9a38f4544bd3d7b149509784 Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Thu, 26 Nov 2020 14:29:49 +0100 Subject: scsi: myrs: Remove WARN_ON(in_interrupt()) The in_interrupt() macro is ill-defined and does not provide what the name suggests. The usage especially in driver code is deprecated and a tree-wide effort to clean up and consolidate the (ab)usage of in_interrupt() and related checks is happening. In this case the check covers only parts of the contexts in which these functions cannot be called. It fails to detect preemption or interrupt disabled invocations. As wait_for_completion() already contains a broad variety of checks (always enabled or debug option dependent) which cover all invalid conditions already, there is no point in having extra inconsistent warnings in drivers. Just remove it. Link: https://lore.kernel.org/r/20201126132952.2287996-12-bigeasy@linutronix.de Cc: Hannes Reinecke Reviewed-by: Daniel Wagner Signed-off-by: Ahmed S. Darwish Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Martin K. Petersen --- drivers/scsi/myrs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/myrs.c b/drivers/scsi/myrs.c index 7a3ade765ce3..4adf9ded296a 100644 --- a/drivers/scsi/myrs.c +++ b/drivers/scsi/myrs.c @@ -136,7 +136,6 @@ static void myrs_exec_cmd(struct myrs_hba *cs, myrs_qcmd(cs, cmd_blk); spin_unlock_irqrestore(&cs->queue_lock, flags); - WARN_ON(in_interrupt()); wait_for_completion(&complete); } -- cgit v1.2.3 From b8a5144370bc59dbb192b8f29298920ceadc3d1e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 26 Nov 2020 14:29:51 +0100 Subject: scsi: message: fusion: Remove in_interrupt() usage in mpt_config() in_interrupt() is referenced all over the place in these drivers. Most of these references are comments which are outdated and wrong. Aside of that in_interrupt() is deprecated as it does not provide what the name suggests. It covers more than hard/soft interrupt servicing context and is semantically ill defined. >From reading the mpt_config() code and the history this is clearly a debug mechanism and should probably be replaced by might_sleep() or completely removed because such checks are already in the subsequent functions. Remove the in_interrupt() references and replace the usage in mpt_config() with might_sleep(). Link: https://lore.kernel.org/r/20201126132952.2287996-14-bigeasy@linutronix.de Cc: Sathya Prakash Cc: Sreekanth Reddy Cc: Suganath Prabu Subramani Cc: MPT-FusionLinux.pdl@broadcom.com Reviewed-by: Daniel Wagner Signed-off-by: Thomas Gleixner Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Martin K. Petersen --- drivers/message/fusion/mptbase.c | 14 ++------------ drivers/message/fusion/mptfc.c | 2 +- drivers/message/fusion/mptscsih.c | 2 +- drivers/message/fusion/mptspi.c | 2 +- 4 files changed, 5 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 3078fac34e51..549797d0301d 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -57,7 +57,7 @@ #include #include #include -#include /* needed for in_interrupt() proto */ +#include #include #include #include @@ -6335,7 +6335,6 @@ SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp) * Page header is updated. * * Returns 0 for success - * -EPERM if not allowed due to ISR context * -EAGAIN if no msg frames currently available * -EFAULT for non-successful reply or no reply (timeout) */ @@ -6353,19 +6352,10 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg) u8 page_type = 0, extend_page; unsigned long timeleft; unsigned long flags; - int in_isr; u8 issue_hard_reset = 0; u8 retry_count = 0; - /* Prevent calling wait_event() (below), if caller happens - * to be in ISR context, because that is fatal! - */ - in_isr = in_interrupt(); - if (in_isr) { - dcprintk(ioc, printk(MYIOC_s_WARN_FMT "Config request not allowed in ISR context!\n", - ioc->name)); - return -EPERM; - } + might_sleep(); /* don't send a config page during diag reset */ spin_lock_irqsave(&ioc->taskmgmt_lock, flags); diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index f92b0433f599..0484e9c15c09 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -50,7 +50,7 @@ #include #include #include /* for mdelay */ -#include /* needed for in_interrupt() proto */ +#include #include /* notifier code */ #include #include diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index a5ef9faf71c7..f441f433ad4d 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -52,7 +52,7 @@ #include #include #include /* for mdelay */ -#include /* needed for in_interrupt() proto */ +#include #include /* notifier code */ #include diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index eabc4de5816c..af0ce5611e4a 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -52,7 +52,7 @@ #include #include #include /* for mdelay */ -#include /* needed for in_interrupt() proto */ +#include #include /* notifier code */ #include #include -- cgit v1.2.3 From 817a7c996786f803a8b5528ca11a842eed88e01f Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 26 Nov 2020 14:29:52 +0100 Subject: scsi: message: fusion: Remove in_interrupt() usage in mptsas_cleanup_fw_event_q() mptsas_cleanup_fw_event_q() uses in_interrupt() to determine if it is safe to cancel a worker item. Aside of that in_interrupt() is deprecated as it does not provide what the name suggests. It covers more than hard/soft interrupt servicing context and is semantically ill defined. Looking closer there are a few problems with the current construct: - It could be invoked from an interrupt handler / non-blocking context because cancel_delayed_work() has no such restriction. Also, mptsas_free_fw_event() has no such restriction. - The list is accessed unlocked. It may dequeue a valid work-item but at the time of invoking cancel_delayed_work() the memory may be released or reused because the worker has already run. mptsas_cleanup_fw_event_q() is invoked via mptsas_shutdown() which is always invoked from preemtible context on device shutdown. It is also invoked via mptsas_ioc_reset(, MPT_IOC_POST_RESET) which is a MptResetHandlers callback. The only caller here are mpt_SoftResetHandler(), mpt_HardResetHandler() and mpt_Soft_Hard_ResetHandler(). All these functions have a `sleepFlag' argument and each caller uses caller uses `CAN_SLEEP' here and according to current documentation: | @sleepFlag: Indicates if sleep or schedule must be called So it is safe to sleep. Add mptsas_hotplug_event::users member. Initialize it to one by default so mptsas_free_fw_event() will free the memory. mptsas_cleanup_fw_event_q() will increment its value for items it dequeues and then it may keep a pointer after dropping the lock. Invoke cancel_delayed_work_sync() to cancel the work item and wait if the worker is currently busy. Free the memory afterwards since it owns the last reference to it. Link: https://lore.kernel.org/r/20201126132952.2287996-15-bigeasy@linutronix.de Cc: Sathya Prakash Cc: Sreekanth Reddy Cc: Suganath Prabu Subramani Cc: MPT-FusionLinux.pdl@broadcom.com Reviewed-by: Daniel Wagner Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Martin K. Petersen --- drivers/message/fusion/mptsas.c | 45 ++++++++++++++++++++++++++++++++--------- drivers/message/fusion/mptsas.h | 1 + 2 files changed, 36 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 18b91ea1a353..5eb0b3361e4e 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -289,6 +289,7 @@ mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event, spin_lock_irqsave(&ioc->fw_event_lock, flags); list_add_tail(&fw_event->list, &ioc->fw_event_list); + fw_event->users = 1; INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work); devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)" "on cpuid %d\n", ioc->name, __func__, @@ -314,6 +315,15 @@ mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event, spin_unlock_irqrestore(&ioc->fw_event_lock, flags); } +static void __mptsas_free_fw_event(MPT_ADAPTER *ioc, + struct fw_event_work *fw_event) +{ + devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: kfree (fw_event=0x%p)\n", + ioc->name, __func__, fw_event)); + list_del(&fw_event->list); + kfree(fw_event); +} + /* free memory associated to a sas firmware event */ static void mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event) @@ -321,10 +331,9 @@ mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event) unsigned long flags; spin_lock_irqsave(&ioc->fw_event_lock, flags); - devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: kfree (fw_event=0x%p)\n", - ioc->name, __func__, fw_event)); - list_del(&fw_event->list); - kfree(fw_event); + fw_event->users--; + if (!fw_event->users) + __mptsas_free_fw_event(ioc, fw_event); spin_unlock_irqrestore(&ioc->fw_event_lock, flags); } @@ -333,9 +342,10 @@ mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event) static void mptsas_cleanup_fw_event_q(MPT_ADAPTER *ioc) { - struct fw_event_work *fw_event, *next; + struct fw_event_work *fw_event; struct mptsas_target_reset_event *target_reset_list, *n; MPT_SCSI_HOST *hd = shost_priv(ioc->sh); + unsigned long flags; /* flush the target_reset_list */ if (!list_empty(&hd->target_reset_list)) { @@ -350,14 +360,29 @@ mptsas_cleanup_fw_event_q(MPT_ADAPTER *ioc) } } - if (list_empty(&ioc->fw_event_list) || - !ioc->fw_event_q || in_interrupt()) + if (list_empty(&ioc->fw_event_list) || !ioc->fw_event_q) return; - list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) { - if (cancel_delayed_work(&fw_event->work)) - mptsas_free_fw_event(ioc, fw_event); + spin_lock_irqsave(&ioc->fw_event_lock, flags); + + while (!list_empty(&ioc->fw_event_list)) { + bool canceled = false; + + fw_event = list_first_entry(&ioc->fw_event_list, + struct fw_event_work, list); + fw_event->users++; + spin_unlock_irqrestore(&ioc->fw_event_lock, flags); + if (cancel_delayed_work_sync(&fw_event->work)) + canceled = true; + + spin_lock_irqsave(&ioc->fw_event_lock, flags); + if (canceled) + fw_event->users--; + fw_event->users--; + WARN_ON_ONCE(fw_event->users); + __mptsas_free_fw_event(ioc, fw_event); } + spin_unlock_irqrestore(&ioc->fw_event_lock, flags); } diff --git a/drivers/message/fusion/mptsas.h b/drivers/message/fusion/mptsas.h index e35b13891fe4..71abf3477495 100644 --- a/drivers/message/fusion/mptsas.h +++ b/drivers/message/fusion/mptsas.h @@ -107,6 +107,7 @@ struct mptsas_hotplug_event { struct fw_event_work { struct list_head list; struct delayed_work work; + int users; MPT_ADAPTER *ioc; u32 event; u8 retries; -- cgit v1.2.3 From 81309c247a4dcd597cbda5254fd0afdd61b93f14 Mon Sep 17 00:00:00 2001 From: Can Guo Date: Wed, 25 Nov 2020 18:01:00 -0800 Subject: scsi: ufs: Refactor ufshcd_setup_clocks() to remove skip_ref_clk Remove the param skip_ref_clk from __ufshcd_setup_clocks(), but keep a flag in struct ufs_clk_info to tell whether a clock can be disabled or not while the link is active. Link: https://lore.kernel.org/r/1606356063-38380-2-git-send-email-cang@codeaurora.org Reviewed-by: Hongwu Su Reviewed-by: Bean Huo Reviewed-by: Stanley Chu Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd-pltfrm.c | 2 ++ drivers/scsi/ufs/ufshcd.c | 29 +++++++++-------------------- drivers/scsi/ufs/ufshcd.h | 3 +++ 3 files changed, 14 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index a6f76399b3ae..0619cfbfbdbb 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -92,6 +92,8 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba) clki->min_freq = clkfreq[i]; clki->max_freq = clkfreq[i+1]; clki->name = kstrdup(name, GFP_KERNEL); + if (!strcmp(name, "ref_clk")) + clki->keep_link_active = true; dev_dbg(dev, "%s: min %u max %u name %s\n", "freq-table-hz", clki->min_freq, clki->max_freq, clki->name); list_add_tail(&clki->list, &hba->clk_list_head); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 93e15e829d1d..17f4e632fa9a 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -226,8 +226,6 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd); static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag); static void ufshcd_hba_exit(struct ufs_hba *hba); static int ufshcd_probe_hba(struct ufs_hba *hba, bool async); -static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, - bool skip_ref_clk); static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on); static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba); static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba); @@ -1722,11 +1720,7 @@ static void ufshcd_gate_work(struct work_struct *work) ufshcd_disable_irq(hba); - if (!ufshcd_is_link_active(hba)) - ufshcd_setup_clocks(hba, false); - else - /* If link is active, device ref_clk can't be switched off */ - __ufshcd_setup_clocks(hba, false, true); + ufshcd_setup_clocks(hba, false); /* Put the host controller in low power mode if possible */ ufshcd_hba_vreg_set_lpm(hba); @@ -8052,8 +8046,7 @@ static int ufshcd_init_hba_vreg(struct ufs_hba *hba) return 0; } -static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, - bool skip_ref_clk) +static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on) { int ret = 0; struct ufs_clk_info *clki; @@ -8071,7 +8064,12 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, list_for_each_entry(clki, head, list) { if (!IS_ERR_OR_NULL(clki->clk)) { - if (skip_ref_clk && !strcmp(clki->name, "ref_clk")) + /* + * Don't disable clocks which are needed + * to keep the link active. + */ + if (ufshcd_is_link_active(hba) && + clki->keep_link_active) continue; clk_state_changed = on ^ clki->enabled; @@ -8116,11 +8114,6 @@ out: return ret; } -static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on) -{ - return __ufshcd_setup_clocks(hba, on, false); -} - static int ufshcd_init_clocks(struct ufs_hba *hba) { int ret = 0; @@ -8648,11 +8641,7 @@ disable_clks: */ ufshcd_disable_irq(hba); - if (!ufshcd_is_link_active(hba)) - ufshcd_setup_clocks(hba, false); - else - /* If link is active, device ref_clk can't be switched off */ - __ufshcd_setup_clocks(hba, false, true); + ufshcd_setup_clocks(hba, false); if (ufshcd_is_clkgating_allowed(hba)) { hba->clk_gating.state = CLKS_OFF; diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 61344c49c2cc..3a8bd7aa104d 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -234,6 +234,8 @@ struct ufs_dev_cmd { * @max_freq: maximum frequency supported by the clock * @min_freq: min frequency that can be used for clock scaling * @curr_freq: indicates the current frequency that it is set to + * @keep_link_active: indicates that the clk should not be disabled if + link is active * @enabled: variable to check against multiple enable/disable */ struct ufs_clk_info { @@ -243,6 +245,7 @@ struct ufs_clk_info { u32 max_freq; u32 min_freq; u32 curr_freq; + bool keep_link_active; bool enabled; }; -- cgit v1.2.3 From 96f08cc5943c0fe943ea10fdead6a80b73270046 Mon Sep 17 00:00:00 2001 From: Can Guo Date: Wed, 25 Nov 2020 18:01:01 -0800 Subject: scsi: ufs-qcom: Keep core_clk_unipro on while link is active If we want to disable clocks to save power but still keep the link active, core_clk_unipro, like ref_clk, should not be the one being disabled. Link: https://lore.kernel.org/r/1606356063-38380-3-git-send-email-cang@codeaurora.org Reviewed-by: Hongwu Su Reviewed-by: Asutosh Das Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-qcom.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 1e434cce0f79..2206b1e4b774 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -959,6 +959,7 @@ static int ufs_qcom_init(struct ufs_hba *hba) struct platform_device *pdev = to_platform_device(dev); struct ufs_qcom_host *host; struct resource *res; + struct ufs_clk_info *clki; if (strlen(android_boot_dev) && strcmp(android_boot_dev, dev_name(dev))) return -ENODEV; @@ -1057,6 +1058,11 @@ static int ufs_qcom_init(struct ufs_hba *hba) } } + list_for_each_entry(clki, &hba->clk_list_head, list) { + if (!strcmp(clki->name, "core_clk_unipro")) + clki->keep_link_active = true; + } + err = ufs_qcom_init_lane_clks(host); if (err) goto out_variant_clear; -- cgit v1.2.3 From 29b87e92a21605ed74888e4d2a31055d95dfafe1 Mon Sep 17 00:00:00 2001 From: Can Guo Date: Thu, 26 Nov 2020 17:58:48 -0800 Subject: scsi: ufs: Stop hardcoding the scale down gear Instead of hardcoding the scale down gear, make it a member of the ufs_clk_scaling struct. Link: https://lore.kernel.org/r/1606442334-22641-1-git-send-email-cang@codeaurora.org Reviewed-by: Stanley Chu Reviewed-by: Bean Huo Reviewed-by: Asutosh Das Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 12 +++++++----- drivers/scsi/ufs/ufshcd.h | 2 ++ 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 17f4e632fa9a..11a4aad09f3a 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1114,7 +1114,6 @@ out: */ static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up) { - #define UFS_MIN_GEAR_TO_SCALE_DOWN UFS_HS_G1 int ret = 0; struct ufs_pa_layer_attr new_pwr_info; @@ -1125,16 +1124,16 @@ static int ufshcd_scale_gear(struct ufs_hba *hba, bool scale_up) memcpy(&new_pwr_info, &hba->pwr_info, sizeof(struct ufs_pa_layer_attr)); - if (hba->pwr_info.gear_tx > UFS_MIN_GEAR_TO_SCALE_DOWN - || hba->pwr_info.gear_rx > UFS_MIN_GEAR_TO_SCALE_DOWN) { + if (hba->pwr_info.gear_tx > hba->clk_scaling.min_gear || + hba->pwr_info.gear_rx > hba->clk_scaling.min_gear) { /* save the current power mode */ memcpy(&hba->clk_scaling.saved_pwr_info.info, &hba->pwr_info, sizeof(struct ufs_pa_layer_attr)); /* scale down gear */ - new_pwr_info.gear_tx = UFS_MIN_GEAR_TO_SCALE_DOWN; - new_pwr_info.gear_rx = UFS_MIN_GEAR_TO_SCALE_DOWN; + new_pwr_info.gear_tx = hba->clk_scaling.min_gear; + new_pwr_info.gear_rx = hba->clk_scaling.min_gear; } } @@ -1842,6 +1841,9 @@ static void ufshcd_init_clk_scaling(struct ufs_hba *hba) if (!ufshcd_is_clkscaling_supported(hba)) return; + if (!hba->clk_scaling.min_gear) + hba->clk_scaling.min_gear = UFS_HS_G1; + INIT_WORK(&hba->clk_scaling.suspend_work, ufshcd_clk_scaling_suspend_work); INIT_WORK(&hba->clk_scaling.resume_work, diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 3a8bd7aa104d..7a7e056a33a9 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -390,6 +390,7 @@ struct ufs_saved_pwr_info { * @workq: workqueue to schedule devfreq suspend/resume work * @suspend_work: worker to suspend devfreq * @resume_work: worker to resume devfreq + * @min_gear: lowest HS gear to scale down to * @is_allowed: tracks if scaling is currently allowed or not * @is_busy_started: tracks if busy period has started or not * @is_suspended: tracks if devfreq is suspended or not @@ -404,6 +405,7 @@ struct ufs_clk_scaling { struct workqueue_struct *workq; struct work_struct suspend_work; struct work_struct resume_work; + u32 min_gear; bool is_allowed; bool is_busy_started; bool is_suspended; -- cgit v1.2.3 From 9d8de441db261dbb4abb989674a62d1c13fe4f93 Mon Sep 17 00:00:00 2001 From: James Smart Date: Mon, 30 Nov 2020 10:12:26 -0800 Subject: scsi: lpfc: Correct null ndlp reference on routine exit smatch correctly called out a logic error with accessing a pointer after checking it for null: drivers/scsi/lpfc/lpfc_els.c:2043 lpfc_cmpl_els_plogi() error: we previously assumed 'ndlp' could be null (see line 1942) Adjust the exit point to avoid the trace printf ndlp reference. A trace entry was already generated when the ndlp was checked for null. Link: https://lore.kernel.org/r/20201130181226.16675-1-james.smart@broadcom.com Fixes: 4430f7fd09ec ("scsi: lpfc: Rework locations of ndlp reference taking") Reported-by: Dan Carpenter Signed-off-by: James Smart Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_els.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index fd5c581cd67a..96c087b8b474 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1946,7 +1946,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, irsp->un.elsreq64.remoteID, irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpIoTag); - goto out; + goto out_freeiocb; } /* Since ndlp can be freed in the disc state machine, note if this node @@ -2042,6 +2042,7 @@ out: "PLOGI Cmpl PUT: did:x%x refcnt %d", ndlp->nlp_DID, kref_read(&ndlp->kref), 0); +out_freeiocb: /* Release the reference on the original I/O request. */ free_ndlp = (struct lpfc_nodelist *)cmdiocb->context1; -- cgit v1.2.3 From 995ae10f8000699b6ac8186489235bc9f0b8de34 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 20 Nov 2020 12:27:16 -0600 Subject: scsi: aic7xxx: Fix fall-through warnings for Clang In preparation to enable -Wimplicit-fallthrough for Clang, fix multiple warnings by explicitly adding multiple break statements instead of just letting the code fall through to the next case, and by adding fallthrough statements in places where the code is intended to fall through, and finally by replacing /* FALLTHROUGH */ comments with the new pseudo-keyword macro fallthrough. Link: https://github.com/KSPP/linux/issues/115 Link: https://lore.kernel.org/r/1a7cd2f77623e6ab46bbec0b6103b18491419206.1605896059.git.gustavoars@kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Martin K. Petersen --- drivers/scsi/aic7xxx/aic79xx_core.c | 4 +++- drivers/scsi/aic7xxx/aic7xxx_core.c | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 78560a85b1e3..c55b5880eb7e 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -6130,6 +6130,7 @@ ahd_free(struct ahd_softc *ahd) fallthrough; case 2: ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat); + break; case 1: break; case 0: @@ -6542,8 +6543,8 @@ ahd_fini_scbdata(struct ahd_softc *ahd) kfree(hscb_map); } ahd_dma_tag_destroy(ahd, scb_data->hscb_dmat); - /* FALLTHROUGH */ } + fallthrough; case 4: case 3: case 2: @@ -8907,6 +8908,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) break; case SIU_PFC_ILLEGAL_REQUEST: printk("Illegal request\n"); + break; default: break; } diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 4ef7af8c0f55..b1b852fe940b 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -4478,6 +4478,7 @@ ahc_free(struct ahc_softc *ahc) fallthrough; case 2: ahc_dma_tag_destroy(ahc, ahc->shared_data_dmat); + fallthrough; case 1: break; case 0: @@ -5865,9 +5866,8 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, if ((scb->flags & SCB_ACTIVE) == 0) printk("Inactive SCB in qinfifo\n"); ahc_done(ahc, scb); - - /* FALLTHROUGH */ } + fallthrough; case SEARCH_REMOVE: break; case SEARCH_COUNT: -- cgit v1.2.3 From 4886dd0a04b47a3da81b2d9c46c32c1035410ea2 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 20 Nov 2020 12:27:24 -0600 Subject: scsi: aic94xx: Fix fall-through warnings for Clang In preparation to enable -Wimplicit-fallthrough for Clang, fix multiple warnings by explicitly adding a couple of break and fallthrough statements instead of just letting the code fall through to the next case. Link: https://github.com/KSPP/linux/issues/115 Link: https://lore.kernel.org/r/9b58459045d303bbea0160f2e349f5799402a2bf.1605896059.git.gustavoars@kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Martin K. Petersen --- drivers/scsi/aic94xx/aic94xx_scb.c | 2 ++ drivers/scsi/aic94xx/aic94xx_task.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index e2d880a5f391..13677973da5c 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c @@ -721,6 +721,7 @@ static void set_speed_mask(u8 *speed_mask, struct asd_phy_desc *pd) fallthrough; case SAS_LINK_RATE_3_0_GBPS: *speed_mask |= SAS_SPEED_15_DIS; + fallthrough; default: case SAS_LINK_RATE_1_5_GBPS: /* nothing to do */ @@ -739,6 +740,7 @@ static void set_speed_mask(u8 *speed_mask, struct asd_phy_desc *pd) switch (pd->min_sata_lrate) { case SAS_LINK_RATE_3_0_GBPS: *speed_mask |= SATA_SPEED_15_DIS; + fallthrough; default: case SAS_LINK_RATE_1_5_GBPS: /* nothing to do */ diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c index ed034192b3c3..71d18f607dae 100644 --- a/drivers/scsi/aic94xx/aic94xx_task.c +++ b/drivers/scsi/aic94xx/aic94xx_task.c @@ -315,6 +315,7 @@ Again: break; case SAS_PROTOCOL_SSP: asd_unbuild_ssp_ascb(ascb); + break; default: break; } @@ -609,6 +610,7 @@ out_err_unmap: break; case SAS_PROTOCOL_SSP: asd_unbuild_ssp_ascb(a); + break; default: break; } -- cgit v1.2.3 From 4c7bd259d66c9f94d3937bce3de5f16a8fd812a1 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 20 Nov 2020 12:27:30 -0600 Subject: scsi: bfa: Fix fall-through warnings for Clang In preparation to enable -Wimplicit-fallthrough for Clang, fix multiple warnings by explicitly adding a couple break statements and replacing /* fall through */ comments with the new pseudo-keyword macro fallthrough; instead of just letting the code fall through to the next case. Notice that Clang doesn't recognize /* fall through */ comments as implicit fall-through markings. Link: https://github.com/KSPP/linux/issues/115 Link: https://lore.kernel.org/r/2ae1cafd858238b85fc5e7fe5cc183843e21ec9f.1605896059.git.gustavoars@kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Martin K. Petersen --- drivers/scsi/bfa/bfa_fcs_lport.c | 2 +- drivers/scsi/bfa/bfa_ioc.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index 3486e402bfc1..49a14157f123 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -5671,7 +5671,7 @@ bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port, bfa_fcs_lport_ms_fabric_rscn(port); break; } - /* !!!!!!!!! Fall Through !!!!!!!!!!!!! */ + fallthrough; case FC_RSCN_FORMAT_AREA: case FC_RSCN_FORMAT_DOMAIN: diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 325ad8a592bb..5740302d83ac 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -387,7 +387,7 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event) case IOC_E_PFFAILED: case IOC_E_HWERROR: bfa_ioc_timer_stop(ioc); - /* !!! fall through !!! */ + fallthrough; case IOC_E_TIMEOUT: ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); @@ -437,7 +437,7 @@ bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event) case IOC_E_PFFAILED: case IOC_E_HWERROR: bfa_hb_timer_stop(ioc); - /* !!! fall through !!! */ + fallthrough; case IOC_E_HBFAIL: if (ioc->iocpf.auto_recover) bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry); @@ -3299,6 +3299,7 @@ bfa_ablk_isr(void *cbarg, struct bfi_mbmsg_s *msg) case BFI_ABLK_I2H_PORT_CONFIG: /* update config port mode */ ablk->ioc->port_mode_cfg = rsp->port_mode; + break; case BFI_ABLK_I2H_PF_DELETE: case BFI_ABLK_I2H_PF_UPDATE: @@ -5871,6 +5872,7 @@ bfa_dconf_sm_uninit(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event) break; case BFA_DCONF_SM_EXIT: bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE); + break; case BFA_DCONF_SM_IOCDISABLE: case BFA_DCONF_SM_WR: case BFA_DCONF_SM_FLASH_COMP: -- cgit v1.2.3 From da38e8917d65edc8387a5154fff7366277c61783 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 20 Nov 2020 12:39:15 -0600 Subject: scsi: aacraid: Fix fall-through warnings for Clang In preparation to enable -Wimplicit-fallthrough for Clang, fix a warning by explicitly adding a break statement instead of letting the code fall through to the next case. Link: https://github.com/KSPP/linux/issues/115 Link: https://lore.kernel.org/r/e4e25e57964a69f7173f868ff93df9d6d08f360f.1605896060.git.gustavoars@kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Martin K. Petersen --- drivers/scsi/aacraid/commsup.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index b99ca1b0c553..0ae0d1fa2b50 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1448,6 +1448,7 @@ retry_next: break; } scsi_rescan_device(&device->sdev_gendev); + break; default: break; -- cgit v1.2.3 From 5133dc4764844575da10a7b6dc12cd87a0ca9d19 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 20 Nov 2020 12:39:21 -0600 Subject: scsi: aha1740: Fix fall-through warnings for Clang In preparation to enable -Wimplicit-fallthrough for Clang, fix a warning by explicitly adding a break statement instead of letting the code fall through to the next case. Link: https://github.com/KSPP/linux/issues/115 Link: https://lore.kernel.org/r/e9fc10eb7d843e6f31e50400d428bd7a217684ac.1605896060.git.gustavoars@kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Martin K. Petersen --- drivers/scsi/aha1740.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c index 5a227c03895f..0dc831026e9e 100644 --- a/drivers/scsi/aha1740.c +++ b/drivers/scsi/aha1740.c @@ -152,6 +152,7 @@ static int aha1740_makecode(unchar *sense, unchar *status) retval=DID_ERROR; /* It's an Overrun */ /* If not overrun, assume underrun and * ignore it! */ + break; case 0x00: /* No info, assume no error, should * not occur */ break; -- cgit v1.2.3 From 965077585513d83fd937bf788557af8cc48745c7 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 20 Nov 2020 12:39:26 -0600 Subject: scsi: csiostor: Fix fall-through warnings for Clang In preparation to enable -Wimplicit-fallthrough for Clang, fix a warning by explicitly adding a break statement instead of letting the code fall through to the next case. Link: https://github.com/KSPP/linux/issues/115 Link: https://lore.kernel.org/r/b77ee091548f16b52056c3b9ee8c76dc6691f868.1605896060.git.gustavoars@kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Martin K. Petersen --- drivers/scsi/csiostor/csio_wr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/csiostor/csio_wr.c b/drivers/scsi/csiostor/csio_wr.c index 9010cb6045dc..fe0355c964bc 100644 --- a/drivers/scsi/csiostor/csio_wr.c +++ b/drivers/scsi/csiostor/csio_wr.c @@ -830,6 +830,7 @@ csio_wr_destroy_queues(struct csio_hw *hw, bool cmd) if (flq_idx != -1) csio_q_flid(hw, flq_idx) = CSIO_MAX_QID; } + break; default: break; } -- cgit v1.2.3 From e9a7c7117103f6e8085ed3caecba6a1e6715e862 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 20 Nov 2020 12:39:31 -0600 Subject: scsi: lpfc: Fix fall-through warnings for Clang In preparation to enable -Wimplicit-fallthrough for Clang, fix a warning by explicitly adding a break statement instead of letting the code fall through to the next case. Link: https://github.com/KSPP/linux/issues/115 Link: https://lore.kernel.org/r/fff8d6f1d33b9e2c94dbe024a4f8df22866d3bf8.1605896060.git.gustavoars@kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Martin K. Petersen --- drivers/scsi/lpfc/lpfc_bsg.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 41e3657c2d8d..eed6ea5e0722 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -3519,6 +3519,7 @@ static int lpfc_bsg_check_cmd_access(struct lpfc_hba *phba, mb->mbxCommand); return -EPERM; } + break; case MBX_WRITE_NV: case MBX_WRITE_VPARMS: case MBX_LOAD_SM: -- cgit v1.2.3 From 8b185fc6e3fe5d16abcd2753f504d1c54134f03a Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 20 Nov 2020 12:39:36 -0600 Subject: scsi: stex: Fix fall-through warnings for Clang In preparation to enable -Wimplicit-fallthrough for Clang, fix a warning by explicitly adding a break statement instead of letting the code fall through to the next case. Link: https://github.com/KSPP/linux/issues/115 Link: https://lore.kernel.org/r/20a7bcc10af2b762325c7078a4f472121a4fabc7.1605896060.git.gustavoars@kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Martin K. Petersen --- drivers/scsi/stex.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index d4f10c0d813c..40473e4f850f 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -685,6 +685,7 @@ stex_queuecommand_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) done(cmd); return 0; } + break; default: break; } -- cgit v1.2.3 From 492096ecfa39d5b6a82a6959b848b78d0112bb09 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 20 Nov 2020 12:32:32 -0600 Subject: scsi: target: core: Fix fall-through warnings for Clang In preparation to enable -Wimplicit-fallthrough for Clang, fix a couple of warnings by explicitly adding a break statement and a fallthrough pseudo-keyword instead of letting the code fall through to the next case. Link: https://github.com/KSPP/linux/issues/115 Link: https://lore.kernel.org/r/761d6f755e8a6f8a6daebd1e5c1394167e5c780a.1605896059.git.gustavoars@kernel.org Signed-off-by: Gustavo A. R. Silva Signed-off-by: Martin K. Petersen --- drivers/target/target_core_iblock.c | 1 + drivers/target/target_core_pr.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index f2bd2e207e0b..8ed93fd205c7 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -211,6 +211,7 @@ static unsigned long long iblock_emulate_read_cap_with_block_size( break; case 512: blocks_long <<= 3; + break; default: break; } diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 5f79ea05f9b8..14db5e568f22 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -337,6 +337,7 @@ static int core_scsi3_pr_seq_non_holder(struct se_cmd *cmd, u32 pr_reg_type, switch (pr_reg_type) { case PR_TYPE_WRITE_EXCLUSIVE: we = 1; + fallthrough; case PR_TYPE_EXCLUSIVE_ACCESS: /* * Some commands are only allowed for the persistent reservation -- cgit v1.2.3 From 62eebd5247c4e4ce08826ad5995cf4dd7ce919dd Mon Sep 17 00:00:00 2001 From: Qinglang Miao Date: Mon, 9 Nov 2020 17:15:18 +0800 Subject: scsi: qedi: Fix missing destroy_workqueue() on error in __qedi_probe Add the missing destroy_workqueue() before return from __qedi_probe in the error handling case when fails to create workqueue qedi->offload_thread. Link: https://lore.kernel.org/r/20201109091518.55941-1-miaoqinglang@huawei.com Fixes: ace7f46ba5fd ("scsi: qedi: Add QLogic FastLinQ offload iSCSI driver framework.") Reviewed-by: Mike Christie Signed-off-by: Qinglang Miao Signed-off-by: Martin K. Petersen --- drivers/scsi/qedi/qedi_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index 61fab01d2d52..f5fc7f518f8a 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -2766,7 +2766,7 @@ retry_probe: QEDI_ERR(&qedi->dbg_ctx, "Unable to start offload thread!\n"); rc = -ENODEV; - goto free_cid_que; + goto free_tmf_thread; } INIT_DELAYED_WORK(&qedi->recovery_work, qedi_recovery_handler); @@ -2790,6 +2790,8 @@ retry_probe: return 0; +free_tmf_thread: + destroy_workqueue(qedi->tmf_thread); free_cid_que: qedi_release_cid_que(qedi); free_uio: -- cgit v1.2.3 From 97031ccffa4f62728602bfea8439dd045cd3aeb2 Mon Sep 17 00:00:00 2001 From: Zhang Qilong Date: Sat, 5 Dec 2020 19:55:51 +0800 Subject: scsi: pm80xx: Fix error return in pm8001_pci_probe() The driver did not return an error in the case where pm8001_configure_phy_settings() failed. Use rc to store the return value of pm8001_configure_phy_settings(). Link: https://lore.kernel.org/r/20201205115551.2079471-1-zhangqilong3@huawei.com Fixes: 279094079a44 ("[SCSI] pm80xx: Phy settings support for motherboard controller.") Acked-by: Jack Wang Signed-off-by: Zhang Qilong Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_init.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 9a5d284f076a..ee2de177d0d0 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -1127,7 +1127,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev, pm8001_init_sas_add(pm8001_ha); /* phy setting support for motherboard controller */ - if (pm8001_configure_phy_settings(pm8001_ha)) + rc = pm8001_configure_phy_settings(pm8001_ha); + if (rc) goto err_out_shost; pm8001_post_sas_ha_init(shost, chip); -- cgit v1.2.3 From 6dc1c7ab6f047f45b62986ffebc5324e86ed5f5a Mon Sep 17 00:00:00 2001 From: Qinglang Miao Date: Fri, 20 Nov 2020 15:48:52 +0800 Subject: scsi: iscsi: Fix inappropriate use of put_device() kfree(conn) is called inside put_device(&conn->dev) which could lead to use-after-free. In addition, device_unregister() should be used here rather than put_deviceO(). Link: https://lore.kernel.org/r/20201120074852.31658-1-miaoqinglang@huawei.com Fixes: f3c893e3dbb5 ("scsi: iscsi: Fail session and connection on transport registration failure") Reported-by: Hulk Robot Reviewed-by: Mike Christie Signed-off-by: Qinglang Miao Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_iscsi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 2eb3e4f9375a..2e68c0a87698 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2313,7 +2313,9 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid) return conn; release_conn_ref: - put_device(&conn->dev); + device_unregister(&conn->dev); + put_device(&session->dev); + return NULL; release_parent_ref: put_device(&session->dev); free_conn: -- cgit v1.2.3 From eb3d2611df2e37a5455818b72af3892f1209346b Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Sat, 5 Dec 2020 19:58:58 +0800 Subject: scsi: ufs: Add error history for abort event in UFS Device W-LUN Add error history for abort event in UFS Device W-LUN. Use specified value as parameter of ufshcd_update_reg_hist() to identify the aborted tag or LUNs. Link: https://lore.kernel.org/r/20201205115901.26815-2-stanley.chu@mediatek.com Reviewed-by: Asutosh Das Reviewed-by: Can Guo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 11a4aad09f3a..7067b86a8e08 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6738,8 +6738,10 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) * To avoid these unnecessary/illegal step we skip to the last error * handling stage: reset and restore. */ - if (lrbp->lun == UFS_UPIU_UFS_DEVICE_WLUN) + if (lrbp->lun == UFS_UPIU_UFS_DEVICE_WLUN) { + ufshcd_update_reg_hist(&hba->ufs_stats.task_abort, lrbp->lun); return ufshcd_eh_host_reset_handler(cmd); + } ufshcd_hold(hba, false); reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); @@ -6763,7 +6765,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) */ scsi_print_command(hba->lrb[tag].cmd); if (!hba->req_abort_count) { - ufshcd_update_reg_hist(&hba->ufs_stats.task_abort, 0); + ufshcd_update_reg_hist(&hba->ufs_stats.task_abort, tag); ufshcd_print_host_regs(hba); ufshcd_print_host_state(hba); ufshcd_print_pwr_info(hba); -- cgit v1.2.3 From e965e5e00b23c47b7a9834436972aa37c5baa708 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Sat, 5 Dec 2020 19:58:59 +0800 Subject: scsi: ufs: Refine error history functions The UFS error history does not only have "history of errors" but also a log of some other events which are not defined as errors. This patch fixes the confused naming of related functions and changes the approach for updating and printing history in preparation of next patch. This patch does not change any functionality. Link: https://lore.kernel.org/r/20201205115901.26815-3-stanley.chu@mediatek.com Reviewed-by: Asutosh Das Reviewed-by: Can Guo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 118 ++++++++++++++++++++++++++-------------------- drivers/scsi/ufs/ufshcd.h | 71 ++++++++++++---------------- 2 files changed, 97 insertions(+), 92 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 7067b86a8e08..f630955141df 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -411,20 +411,25 @@ static void ufshcd_print_clk_freqs(struct ufs_hba *hba) } } -static void ufshcd_print_err_hist(struct ufs_hba *hba, - struct ufs_err_reg_hist *err_hist, - char *err_name) +static void ufshcd_print_evt(struct ufs_hba *hba, u32 id, + char *err_name) { int i; bool found = false; + struct ufs_event_hist *e; - for (i = 0; i < UFS_ERR_REG_HIST_LENGTH; i++) { - int p = (i + err_hist->pos) % UFS_ERR_REG_HIST_LENGTH; + if (id >= UFS_EVT_CNT) + return; + + e = &hba->ufs_stats.event[id]; - if (err_hist->tstamp[p] == 0) + for (i = 0; i < UFS_EVENT_HIST_LENGTH; i++) { + int p = (i + e->pos) % UFS_EVENT_HIST_LENGTH; + + if (e->tstamp[p] == 0) continue; dev_err(hba->dev, "%s[%d] = 0x%x at %lld us\n", err_name, p, - err_hist->reg[p], ktime_to_us(err_hist->tstamp[p])); + e->val[p], ktime_to_us(e->tstamp[p])); found = true; } @@ -432,26 +437,26 @@ static void ufshcd_print_err_hist(struct ufs_hba *hba, dev_err(hba->dev, "No record of %s\n", err_name); } -static void ufshcd_print_host_regs(struct ufs_hba *hba) +static void ufshcd_print_evt_hist(struct ufs_hba *hba) { ufshcd_dump_regs(hba, 0, UFSHCI_REG_SPACE_SIZE, "host_regs: "); - ufshcd_print_err_hist(hba, &hba->ufs_stats.pa_err, "pa_err"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.dl_err, "dl_err"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.nl_err, "nl_err"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.tl_err, "tl_err"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.dme_err, "dme_err"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.auto_hibern8_err, - "auto_hibern8_err"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.fatal_err, "fatal_err"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.link_startup_err, - "link_startup_fail"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.resume_err, "resume_fail"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.suspend_err, - "suspend_fail"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.dev_reset, "dev_reset"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.host_reset, "host_reset"); - ufshcd_print_err_hist(hba, &hba->ufs_stats.task_abort, "task_abort"); + ufshcd_print_evt(hba, UFS_EVT_PA_ERR, "pa_err"); + ufshcd_print_evt(hba, UFS_EVT_DL_ERR, "dl_err"); + ufshcd_print_evt(hba, UFS_EVT_NL_ERR, "nl_err"); + ufshcd_print_evt(hba, UFS_EVT_TL_ERR, "tl_err"); + ufshcd_print_evt(hba, UFS_EVT_DME_ERR, "dme_err"); + ufshcd_print_evt(hba, UFS_EVT_AUTO_HIBERN8_ERR, + "auto_hibern8_err"); + ufshcd_print_evt(hba, UFS_EVT_FATAL_ERR, "fatal_err"); + ufshcd_print_evt(hba, UFS_EVT_LINK_STARTUP_FAIL, + "link_startup_fail"); + ufshcd_print_evt(hba, UFS_EVT_RESUME_ERR, "resume_fail"); + ufshcd_print_evt(hba, UFS_EVT_SUSPEND_ERR, + "suspend_fail"); + ufshcd_print_evt(hba, UFS_EVT_DEV_RESET, "dev_reset"); + ufshcd_print_evt(hba, UFS_EVT_HOST_RESET, "host_reset"); + ufshcd_print_evt(hba, UFS_EVT_ABORT, "task_abort"); ufshcd_vops_dbg_register_dump(hba); } @@ -3852,7 +3857,7 @@ out: if (ret) { ufshcd_print_host_state(hba); ufshcd_print_pwr_info(hba); - ufshcd_print_host_regs(hba); + ufshcd_print_evt_hist(hba); } spin_lock_irqsave(hba->host->host_lock, flags); @@ -4464,14 +4469,19 @@ static inline int ufshcd_disable_device_tx_lcc(struct ufs_hba *hba) return ufshcd_disable_tx_lcc(hba, true); } -void ufshcd_update_reg_hist(struct ufs_err_reg_hist *reg_hist, - u32 reg) +void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val) { - reg_hist->reg[reg_hist->pos] = reg; - reg_hist->tstamp[reg_hist->pos] = ktime_get(); - reg_hist->pos = (reg_hist->pos + 1) % UFS_ERR_REG_HIST_LENGTH; + struct ufs_event_hist *e; + + if (id >= UFS_EVT_CNT) + return; + + e = &hba->ufs_stats.event[id]; + e->val[e->pos] = val; + e->tstamp[e->pos] = ktime_get(); + e->pos = (e->pos + 1) % UFS_EVENT_HIST_LENGTH; } -EXPORT_SYMBOL_GPL(ufshcd_update_reg_hist); +EXPORT_SYMBOL_GPL(ufshcd_update_evt_hist); /** * ufshcd_link_startup - Initialize unipro link startup @@ -4500,7 +4510,8 @@ link_startup: /* check if device is detected by inter-connect layer */ if (!ret && !ufshcd_is_device_present(hba)) { - ufshcd_update_reg_hist(&hba->ufs_stats.link_startup_err, + ufshcd_update_evt_hist(hba, + UFS_EVT_LINK_STARTUP_FAIL, 0); dev_err(hba->dev, "%s: Device not present\n", __func__); ret = -ENXIO; @@ -4513,7 +4524,8 @@ link_startup: * succeeds. So reset the local Uni-Pro and try again. */ if (ret && ufshcd_hba_enable(hba)) { - ufshcd_update_reg_hist(&hba->ufs_stats.link_startup_err, + ufshcd_update_evt_hist(hba, + UFS_EVT_LINK_STARTUP_FAIL, (u32)ret); goto out; } @@ -4521,7 +4533,8 @@ link_startup: if (ret) { /* failed to get the link up... retire */ - ufshcd_update_reg_hist(&hba->ufs_stats.link_startup_err, + ufshcd_update_evt_hist(hba, + UFS_EVT_LINK_STARTUP_FAIL, (u32)ret); goto out; } @@ -4555,7 +4568,7 @@ out: dev_err(hba->dev, "link startup failed %d\n", ret); ufshcd_print_host_state(hba); ufshcd_print_pwr_info(hba); - ufshcd_print_host_regs(hba); + ufshcd_print_evt_hist(hba); } return ret; } @@ -4910,7 +4923,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) dev_err(hba->dev, "OCS error from controller = %x for tag %d\n", ocs, lrbp->task_tag); - ufshcd_print_host_regs(hba); + ufshcd_print_evt_hist(hba); ufshcd_print_host_state(hba); break; } /* end of switch */ @@ -5792,7 +5805,7 @@ static void ufshcd_err_handler(struct work_struct *work) spin_unlock_irqrestore(hba->host->host_lock, flags); ufshcd_print_host_state(hba); ufshcd_print_pwr_info(hba); - ufshcd_print_host_regs(hba); + ufshcd_print_evt_hist(hba); ufshcd_print_tmrs(hba, hba->outstanding_tasks); ufshcd_print_trs(hba, hba->outstanding_reqs, pr_prdt); spin_lock_irqsave(hba->host->host_lock, flags); @@ -5937,7 +5950,7 @@ static irqreturn_t ufshcd_update_uic_error(struct ufs_hba *hba) reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER); if ((reg & UIC_PHY_ADAPTER_LAYER_ERROR) && (reg & UIC_PHY_ADAPTER_LAYER_ERROR_CODE_MASK)) { - ufshcd_update_reg_hist(&hba->ufs_stats.pa_err, reg); + ufshcd_update_evt_hist(hba, UFS_EVT_PA_ERR, reg); /* * To know whether this error is fatal or not, DB timeout * must be checked but this error is handled separately. @@ -5967,7 +5980,7 @@ static irqreturn_t ufshcd_update_uic_error(struct ufs_hba *hba) reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_DATA_LINK_LAYER); if ((reg & UIC_DATA_LINK_LAYER_ERROR) && (reg & UIC_DATA_LINK_LAYER_ERROR_CODE_MASK)) { - ufshcd_update_reg_hist(&hba->ufs_stats.dl_err, reg); + ufshcd_update_evt_hist(hba, UFS_EVT_DL_ERR, reg); if (reg & UIC_DATA_LINK_LAYER_ERROR_PA_INIT) hba->uic_error |= UFSHCD_UIC_DL_PA_INIT_ERROR; @@ -5986,7 +5999,7 @@ static irqreturn_t ufshcd_update_uic_error(struct ufs_hba *hba) reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_NETWORK_LAYER); if ((reg & UIC_NETWORK_LAYER_ERROR) && (reg & UIC_NETWORK_LAYER_ERROR_CODE_MASK)) { - ufshcd_update_reg_hist(&hba->ufs_stats.nl_err, reg); + ufshcd_update_evt_hist(hba, UFS_EVT_NL_ERR, reg); hba->uic_error |= UFSHCD_UIC_NL_ERROR; retval |= IRQ_HANDLED; } @@ -5994,7 +6007,7 @@ static irqreturn_t ufshcd_update_uic_error(struct ufs_hba *hba) reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_TRANSPORT_LAYER); if ((reg & UIC_TRANSPORT_LAYER_ERROR) && (reg & UIC_TRANSPORT_LAYER_ERROR_CODE_MASK)) { - ufshcd_update_reg_hist(&hba->ufs_stats.tl_err, reg); + ufshcd_update_evt_hist(hba, UFS_EVT_TL_ERR, reg); hba->uic_error |= UFSHCD_UIC_TL_ERROR; retval |= IRQ_HANDLED; } @@ -6002,7 +6015,7 @@ static irqreturn_t ufshcd_update_uic_error(struct ufs_hba *hba) reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_DME); if ((reg & UIC_DME_ERROR) && (reg & UIC_DME_ERROR_CODE_MASK)) { - ufshcd_update_reg_hist(&hba->ufs_stats.dme_err, reg); + ufshcd_update_evt_hist(hba, UFS_EVT_DME_ERR, reg); hba->uic_error |= UFSHCD_UIC_DME_ERROR; retval |= IRQ_HANDLED; } @@ -6044,7 +6057,8 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba) irqreturn_t retval = IRQ_NONE; if (hba->errors & INT_FATAL_ERRORS) { - ufshcd_update_reg_hist(&hba->ufs_stats.fatal_err, hba->errors); + ufshcd_update_evt_hist(hba, UFS_EVT_FATAL_ERR, + hba->errors); queue_eh_work = true; } @@ -6061,7 +6075,7 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba) __func__, (hba->errors & UIC_HIBERNATE_ENTER) ? "Enter" : "Exit", hba->errors, ufshcd_get_upmcrs(hba)); - ufshcd_update_reg_hist(&hba->ufs_stats.auto_hibern8_err, + ufshcd_update_evt_hist(hba, UFS_EVT_AUTO_HIBERN8_ERR, hba->errors); ufshcd_set_link_broken(hba); queue_eh_work = true; @@ -6602,7 +6616,7 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd) out: hba->req_abort_count = 0; - ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, (u32)err); + ufshcd_update_evt_hist(hba, UFS_EVT_DEV_RESET, (u32)err); if (!err) { err = SUCCESS; } else { @@ -6739,7 +6753,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) * handling stage: reset and restore. */ if (lrbp->lun == UFS_UPIU_UFS_DEVICE_WLUN) { - ufshcd_update_reg_hist(&hba->ufs_stats.task_abort, lrbp->lun); + ufshcd_update_evt_hist(hba, UFS_EVT_ABORT, lrbp->lun); return ufshcd_eh_host_reset_handler(cmd); } @@ -6765,8 +6779,8 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) */ scsi_print_command(hba->lrb[tag].cmd); if (!hba->req_abort_count) { - ufshcd_update_reg_hist(&hba->ufs_stats.task_abort, tag); - ufshcd_print_host_regs(hba); + ufshcd_update_evt_hist(hba, UFS_EVT_ABORT, tag); + ufshcd_print_evt_hist(hba); ufshcd_print_host_state(hba); ufshcd_print_pwr_info(hba); ufshcd_print_trs(hba, 1 << tag, true); @@ -6849,7 +6863,7 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba) out: if (err) dev_err(hba->dev, "%s: Host init failed %d\n", __func__, err); - ufshcd_update_reg_hist(&hba->ufs_stats.host_reset, (u32)err); + ufshcd_update_evt_hist(hba, UFS_EVT_HOST_RESET, (u32)err); return err; } @@ -8697,7 +8711,7 @@ out: hba->pm_op_in_progress = 0; if (ret) - ufshcd_update_reg_hist(&hba->ufs_stats.suspend_err, (u32)ret); + ufshcd_update_evt_hist(hba, UFS_EVT_SUSPEND_ERR, (u32)ret); return ret; } @@ -8821,7 +8835,7 @@ disable_irq_and_vops_clks: out: hba->pm_op_in_progress = 0; if (ret) - ufshcd_update_reg_hist(&hba->ufs_stats.resume_err, (u32)ret); + ufshcd_update_evt_hist(hba, UFS_EVT_RESUME_ERR, (u32)ret); return ret; } @@ -9273,7 +9287,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) err = ufshcd_hba_enable(hba); if (err) { dev_err(hba->dev, "Host controller enable failed\n"); - ufshcd_print_host_regs(hba); + ufshcd_print_evt_hist(hba); ufshcd_print_host_state(hba); goto free_tmf_queue; } diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 7a7e056a33a9..b2eab23a17e8 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -58,6 +58,29 @@ enum dev_cmd_type { DEV_CMD_TYPE_QUERY = 0x1, }; +enum ufs_event_type { + /* uic specific errors */ + UFS_EVT_PA_ERR = 0, + UFS_EVT_DL_ERR, + UFS_EVT_NL_ERR, + UFS_EVT_TL_ERR, + UFS_EVT_DME_ERR, + + /* fatal errors */ + UFS_EVT_AUTO_HIBERN8_ERR, + UFS_EVT_FATAL_ERR, + UFS_EVT_LINK_STARTUP_FAIL, + UFS_EVT_RESUME_ERR, + UFS_EVT_SUSPEND_ERR, + + /* abnormal events */ + UFS_EVT_DEV_RESET, + UFS_EVT_HOST_RESET, + UFS_EVT_ABORT, + + UFS_EVT_CNT, +}; + /** * struct uic_command - UIC command structure * @command: UIC command @@ -411,17 +434,17 @@ struct ufs_clk_scaling { bool is_suspended; }; -#define UFS_ERR_REG_HIST_LENGTH 8 +#define UFS_EVENT_HIST_LENGTH 8 /** - * struct ufs_err_reg_hist - keeps history of errors + * struct ufs_event_hist - keeps history of errors * @pos: index to indicate cyclic buffer position * @reg: cyclic buffer for registers value * @tstamp: cyclic buffer for time stamp */ -struct ufs_err_reg_hist { +struct ufs_event_hist { int pos; - u32 reg[UFS_ERR_REG_HIST_LENGTH]; - ktime_t tstamp[UFS_ERR_REG_HIST_LENGTH]; + u32 val[UFS_EVENT_HIST_LENGTH]; + ktime_t tstamp[UFS_EVENT_HIST_LENGTH]; }; /** @@ -432,19 +455,6 @@ struct ufs_err_reg_hist { * reset this after link-startup. * @last_hibern8_exit_tstamp: Set time after the hibern8 exit. * Clear after the first successful command completion. - * @pa_err: tracks pa-uic errors - * @dl_err: tracks dl-uic errors - * @nl_err: tracks nl-uic errors - * @tl_err: tracks tl-uic errors - * @dme_err: tracks dme errors - * @auto_hibern8_err: tracks auto-hibernate errors - * @fatal_err: tracks fatal errors - * @linkup_err: tracks link-startup errors - * @resume_err: tracks resume errors - * @suspend_err: tracks suspend errors - * @dev_reset: tracks device reset events - * @host_reset: tracks host reset events - * @tsk_abort: tracks task abort events */ struct ufs_stats { u32 last_intr_status; @@ -452,25 +462,7 @@ struct ufs_stats { u32 hibern8_exit_cnt; ktime_t last_hibern8_exit_tstamp; - - /* uic specific errors */ - struct ufs_err_reg_hist pa_err; - struct ufs_err_reg_hist dl_err; - struct ufs_err_reg_hist nl_err; - struct ufs_err_reg_hist tl_err; - struct ufs_err_reg_hist dme_err; - - /* fatal errors */ - struct ufs_err_reg_hist auto_hibern8_err; - struct ufs_err_reg_hist fatal_err; - struct ufs_err_reg_hist link_startup_err; - struct ufs_err_reg_hist resume_err; - struct ufs_err_reg_hist suspend_err; - - /* abnormal events */ - struct ufs_err_reg_hist dev_reset; - struct ufs_err_reg_hist host_reset; - struct ufs_err_reg_hist task_abort; + struct ufs_event_hist event[UFS_EVT_CNT]; }; enum ufshcd_quirks { @@ -914,8 +906,7 @@ int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask, u32 val, unsigned long interval_us, unsigned long timeout_ms); void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba, struct clk *refclk); -void ufshcd_update_reg_hist(struct ufs_err_reg_hist *reg_hist, - u32 reg); +void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val); static inline void check_upiu_size(void) { @@ -1221,7 +1212,7 @@ static inline void ufshcd_vops_device_reset(struct ufs_hba *hba) if (!err) ufshcd_set_ufs_dev_active(hba); if (err != -EOPNOTSUPP) - ufshcd_update_reg_hist(&hba->ufs_stats.dev_reset, err); + ufshcd_update_evt_hist(hba, UFS_EVT_DEV_RESET, err); } } -- cgit v1.2.3 From 172614a9d0e861f8ad0e3165dd1d02bc63adaa1b Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Sat, 5 Dec 2020 19:59:00 +0800 Subject: scsi: ufs: Introduce event_notify variant function Introduce event_notify variant function to allow vendor to get notification of important events and connect to any proprietary debugging facilities. Link: https://lore.kernel.org/r/20201205115901.26815-4-stanley.chu@mediatek.com Reviewed-by: Asutosh Das Reviewed-by: Can Guo Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 2 ++ drivers/scsi/ufs/ufshcd.h | 11 +++++++++++ 2 files changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index f630955141df..308f624b3830 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -4480,6 +4480,8 @@ void ufshcd_update_evt_hist(struct ufs_hba *hba, u32 id, u32 val) e->val[e->pos] = val; e->tstamp[e->pos] = ktime_get(); e->pos = (e->pos + 1) % UFS_EVENT_HIST_LENGTH; + + ufshcd_vops_event_notify(hba, id, &val); } EXPORT_SYMBOL_GPL(ufshcd_update_evt_hist); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index b2eab23a17e8..815993239898 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -320,6 +320,7 @@ struct ufs_pwr_mode_info { * @phy_initialization: used to initialize phys * @device_reset: called to issue a reset pulse on the UFS device * @program_key: program or evict an inline encryption key + * @event_notify: called to notify important events */ struct ufs_hba_variant_ops { const char *name; @@ -355,6 +356,8 @@ struct ufs_hba_variant_ops { void *data); int (*program_key)(struct ufs_hba *hba, const union ufs_crypto_cfg_entry *cfg, int slot); + void (*event_notify)(struct ufs_hba *hba, + enum ufs_event_type evt, void *data); }; /* clock gating state */ @@ -1102,6 +1105,14 @@ static inline int ufshcd_vops_clk_scale_notify(struct ufs_hba *hba, return 0; } +static inline void ufshcd_vops_event_notify(struct ufs_hba *hba, + enum ufs_event_type evt, + void *data) +{ + if (hba->vops && hba->vops->event_notify) + hba->vops->event_notify(hba, evt, data); +} + static inline int ufshcd_vops_setup_clocks(struct ufs_hba *hba, bool on, enum ufs_notify_change_status status) { -- cgit v1.2.3 From ca1bb061d64499d8aa08b0987643928a924c30bc Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Sat, 5 Dec 2020 19:59:01 +0800 Subject: scsi: ufs-mediatek: Introduce event_notify implementation Introduce event_notify implementation on MediaTek UFS platform. A vendor-specific tracepoint is added that can be used for debugging purposes. Link: https://lore.kernel.org/r/20201205115901.26815-5-stanley.chu@mediatek.com Reviewed-by: Avri Altman Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufs-mediatek-trace.h | 36 +++++++++++++++++++++++++++++++++++ drivers/scsi/ufs/ufs-mediatek.c | 12 ++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 drivers/scsi/ufs/ufs-mediatek-trace.h (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufs-mediatek-trace.h b/drivers/scsi/ufs/ufs-mediatek-trace.h new file mode 100644 index 000000000000..fd6f84c1b4e2 --- /dev/null +++ b/drivers/scsi/ufs/ufs-mediatek-trace.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 MediaTek Inc. + */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM ufs_mtk + +#if !defined(_TRACE_EVENT_UFS_MEDIATEK_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_EVENT_UFS_MEDIATEK_H + +#include + +TRACE_EVENT(ufs_mtk_event, + TP_PROTO(unsigned int type, unsigned int data), + TP_ARGS(type, data), + + TP_STRUCT__entry( + __field(unsigned int, type) + __field(unsigned int, data) + ), + + TP_fast_assign( + __entry->type = type; + __entry->data = data; + ), + + TP_printk("ufs:event=%u data=%u", + __entry->type, __entry->data) + ); +#endif + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE ufs-mediatek-trace +#include diff --git a/drivers/scsi/ufs/ufs-mediatek.c b/drivers/scsi/ufs/ufs-mediatek.c index 1d3c5cd4592e..3522458db3bb 100644 --- a/drivers/scsi/ufs/ufs-mediatek.c +++ b/drivers/scsi/ufs/ufs-mediatek.c @@ -24,6 +24,9 @@ #include "unipro.h" #include "ufs-mediatek.h" +#define CREATE_TRACE_POINTS +#include "ufs-mediatek-trace.h" + #define ufs_mtk_smc(cmd, val, res) \ arm_smccc_smc(MTK_SIP_UFS_CONTROL, \ cmd, val, 0, 0, 0, 0, 0, &(res)) @@ -1002,6 +1005,14 @@ static void ufs_mtk_fixup_dev_quirks(struct ufs_hba *hba) ufshcd_fixup_dev_quirks(hba, ufs_mtk_dev_fixups); } +static void ufs_mtk_event_notify(struct ufs_hba *hba, + enum ufs_event_type evt, void *data) +{ + unsigned int val = *(u32 *)data; + + trace_ufs_mtk_event(evt, val); +} + /* * struct ufs_hba_mtk_vops - UFS MTK specific variant operations * @@ -1021,6 +1032,7 @@ static const struct ufs_hba_variant_ops ufs_hba_mtk_vops = { .resume = ufs_mtk_resume, .dbg_register_dump = ufs_mtk_dbg_register_dump, .device_reset = ufs_mtk_device_reset, + .event_notify = ufs_mtk_event_notify, }; /** -- cgit v1.2.3 From ade921a891de4c32ca31f5db95c2239ffb2b791d Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Sat, 5 Dec 2020 20:00:38 +0800 Subject: scsi: ufs: Remove unused setup_regulators variant function Since setup_regulators variant function is not used by any vendors, simply remove it. Link: https://lore.kernel.org/r/20201205120041.26869-2-stanley.chu@mediatek.com Reviewed-by: Avri Altman Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 10 +--------- drivers/scsi/ufs/ufshcd.h | 10 ---------- 2 files changed, 1 insertion(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 308f624b3830..6e72c0543c7b 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -8189,16 +8189,10 @@ static int ufshcd_variant_hba_init(struct ufs_hba *hba) goto out; err = ufshcd_vops_init(hba); - if (err) - goto out; - - err = ufshcd_vops_setup_regulators(hba, true); - if (err) - ufshcd_vops_exit(hba); -out: if (err) dev_err(hba->dev, "%s: variant %s init failed err %d\n", __func__, ufshcd_get_var_name(hba), err); +out: return err; } @@ -8207,8 +8201,6 @@ static void ufshcd_variant_hba_exit(struct ufs_hba *hba) if (!hba->vops) return; - ufshcd_vops_setup_regulators(hba, false); - ufshcd_vops_exit(hba); } diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 815993239898..f92be8aea7a8 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -300,7 +300,6 @@ struct ufs_pwr_mode_info { * @get_ufs_hci_version: called to get UFS HCI version * @clk_scale_notify: notifies that clks are scaled up/down * @setup_clocks: called before touching any of the controller registers - * @setup_regulators: called before accessing the host controller * @hce_enable_notify: called before and after HCE enable bit is set to allow * variant specific Uni-Pro initialization. * @link_startup_notify: called before and after Link startup is carried out @@ -331,7 +330,6 @@ struct ufs_hba_variant_ops { enum ufs_notify_change_status); int (*setup_clocks)(struct ufs_hba *, bool, enum ufs_notify_change_status); - int (*setup_regulators)(struct ufs_hba *, bool); int (*hce_enable_notify)(struct ufs_hba *, enum ufs_notify_change_status); int (*link_startup_notify)(struct ufs_hba *, @@ -1121,14 +1119,6 @@ static inline int ufshcd_vops_setup_clocks(struct ufs_hba *hba, bool on, return 0; } -static inline int ufshcd_vops_setup_regulators(struct ufs_hba *hba, bool status) -{ - if (hba->vops && hba->vops->setup_regulators) - return hba->vops->setup_regulators(hba, status); - - return 0; -} - static inline int ufshcd_vops_hce_enable_notify(struct ufs_hba *hba, bool status) { -- cgit v1.2.3 From 92bcebe4b6d652e98ca2667e8e43c3d0a08f6afc Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Sat, 5 Dec 2020 20:00:39 +0800 Subject: scsi: ufs: Introduce phy_initialization helper Introduce phy_initialization helper since this is the only one variant function without helper. Link: https://lore.kernel.org/r/20201205120041.26869-3-stanley.chu@mediatek.com Reviewed-by: Avri Altman Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index f92be8aea7a8..8c44929bed53 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -1136,6 +1136,14 @@ static inline int ufshcd_vops_link_startup_notify(struct ufs_hba *hba, return 0; } +static inline int ufshcd_vops_phy_initialization(struct ufs_hba *hba) +{ + if (hba->vops && hba->vops->phy_initialization) + return hba->vops->phy_initialization(hba); + + return 0; +} + static inline int ufshcd_vops_pwr_change_notify(struct ufs_hba *hba, bool status, struct ufs_pa_layer_attr *dev_max_params, -- cgit v1.2.3 From 885445736bc099430c0529eb85cd9cc8d12f4848 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Sat, 5 Dec 2020 20:00:40 +0800 Subject: scsi: ufs-cdns: Use phy_initialization helper Use phy_initialization helper instead of direct function invocation. Link: https://lore.kernel.org/r/20201205120041.26869-4-stanley.chu@mediatek.com Reviewed-by: Avri Altman Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/cdns-pltfrm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/cdns-pltfrm.c b/drivers/scsi/ufs/cdns-pltfrm.c index da065a259f6e..149391faa19c 100644 --- a/drivers/scsi/ufs/cdns-pltfrm.c +++ b/drivers/scsi/ufs/cdns-pltfrm.c @@ -221,8 +221,7 @@ static int cdns_ufs_init(struct ufs_hba *hba) return -ENOMEM; ufshcd_set_variant(hba, host); - if (hba->vops && hba->vops->phy_initialization) - status = hba->vops->phy_initialization(hba); + status = ufshcd_vops_phy_initialization(hba); return status; } -- cgit v1.2.3 From ab98105484fc83dfaafc2d6f6411cd4e2b39423d Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Sat, 5 Dec 2020 20:00:41 +0800 Subject: scsi: ufs-dwc: Use phy_initialization helper Use phy_initialization helper instead of direct invocation. Link: https://lore.kernel.org/r/20201205120041.26869-5-stanley.chu@mediatek.com Reviewed-by: Avri Altman Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd-dwc.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd-dwc.c b/drivers/scsi/ufs/ufshcd-dwc.c index 6a901da2d15a..5bb9d3a88795 100644 --- a/drivers/scsi/ufs/ufshcd-dwc.c +++ b/drivers/scsi/ufs/ufshcd-dwc.c @@ -120,13 +120,10 @@ int ufshcd_dwc_link_startup_notify(struct ufs_hba *hba, if (status == PRE_CHANGE) { ufshcd_dwc_program_clk_div(hba, DWC_UFS_REG_HCLKDIV_DIV_125); - if (hba->vops->phy_initialization) { - err = hba->vops->phy_initialization(hba); - if (err) { - dev_err(hba->dev, "Phy setup failed (%d)\n", - err); - goto out; - } + err = ufshcd_vops_phy_initialization(hba); + if (err) { + dev_err(hba->dev, "Phy setup failed (%d)\n", err); + goto out; } } else { /* POST_CHANGE */ err = ufshcd_dwc_link_is_up(hba); -- cgit v1.2.3 From 5b44a07b6bb2c26905b16deb479e9ba4e5605e97 Mon Sep 17 00:00:00 2001 From: Stanley Chu Date: Wed, 2 Dec 2020 17:18:19 +0800 Subject: scsi: ufs: Remove pre-defined initial voltage values of device power UFS specficication allows different VCC configurations for UFS devices, for example: (1). 2.70V - 3.60V (Activated by default in UFS core driver) (2). 1.70V - 1.95V (Activated if "vcc-supply-1p8" is declared in device tree) (3). 2.40V - 2.70V (Supported since UFS 3.x) With the introduction of UFS 3.x products, an issue is happening that UFS driver will use wrong "min_uV-max_uV" values to configure the voltage of VCC regulator on UFU 3.x products with the configuration (3) used. To solve this issue, we simply remove pre-defined initial VCC voltage values in UFS core driver with below reasons, 1. UFS specifications do not define how to detect the VCC configuration supported by attached device. 2. Device tree already supports standard regulator properties. Therefore VCC voltage shall be defined correctly in device tree, and shall not changed by UFS driver. What UFS driver needs to do is simply enable or disable the VCC regulator only. Similar change is applied to VCCQ and VCCQ2 as well. Note that we keep struct ufs_vreg unchanged. This allows vendors to configure proper min_uV and max_uV of any regulators to make regulator_set_voltage() works during regulator toggling flow in the future. Without specific vendor configurations, min_uV and max_uV will be NULL by default and UFS core driver will enable or disable the regulator only without adjusting its voltage. Link: https://lore.kernel.org/r/20201202091819.22363-1-stanley.chu@mediatek.com Reviewed-by: Asutosh Das Reviewed-by: Bjorn Andersson Reviewed-by: Can Guo Acked-by: Avri Altman Signed-off-by: Stanley Chu Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd-pltfrm.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index 0619cfbfbdbb..1a69949a4ea1 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -134,25 +134,6 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name, dev_info(dev, "%s: unable to find %s\n", __func__, prop_name); vreg->max_uA = 0; } - - if (!strcmp(name, "vcc")) { - if (of_property_read_bool(np, "vcc-supply-1p8")) { - vreg->min_uV = UFS_VREG_VCC_1P8_MIN_UV; - vreg->max_uV = UFS_VREG_VCC_1P8_MAX_UV; - } else { - vreg->min_uV = UFS_VREG_VCC_MIN_UV; - vreg->max_uV = UFS_VREG_VCC_MAX_UV; - } - } else if (!strcmp(name, "vccq")) { - vreg->min_uV = UFS_VREG_VCCQ_MIN_UV; - vreg->max_uV = UFS_VREG_VCCQ_MAX_UV; - } else if (!strcmp(name, "vccq2")) { - vreg->min_uV = UFS_VREG_VCCQ2_MIN_UV; - vreg->max_uV = UFS_VREG_VCCQ2_MAX_UV; - } - - goto out; - out: if (!ret) *out_vreg = vreg; -- cgit v1.2.3 From 88a92d6ae4fe09b2b27781178c5c9432d27b1ffb Mon Sep 17 00:00:00 2001 From: Can Guo Date: Wed, 2 Dec 2020 04:04:01 -0800 Subject: scsi: ufs: Serialize eh_work with system PM events and async scan Serialize eh_work with system PM events and async scan to make sure eh_work does not run in parallel with them. Link: https://lore.kernel.org/r/1606910644-21185-2-git-send-email-cang@codeaurora.org Reviewed-by: Stanley Chu Reviewed-by: Asutosh Das Reviewed-by: Hongwu Su Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 64 +++++++++++++++++++++++++++++------------------ drivers/scsi/ufs/ufshcd.h | 1 + 2 files changed, 41 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 6e72c0543c7b..b7a22a7c1aa0 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -5648,7 +5648,9 @@ static inline void ufshcd_schedule_eh_work(struct ufs_hba *hba) static void ufshcd_err_handling_prepare(struct ufs_hba *hba) { pm_runtime_get_sync(hba->dev); - if (pm_runtime_suspended(hba->dev)) { + if (pm_runtime_status_suspended(hba->dev) || hba->is_sys_suspended) { + enum ufs_pm_op pm_op; + /* * Don't assume anything of pm_runtime_get_sync(), if * resume fails, irq and clocks can be OFF, and powers @@ -5663,7 +5665,8 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba) if (!ufshcd_is_clkgating_allowed(hba)) ufshcd_setup_clocks(hba, true); ufshcd_release(hba); - ufshcd_vops_resume(hba, UFS_RUNTIME_PM); + pm_op = hba->is_sys_suspended ? UFS_SYSTEM_PM : UFS_RUNTIME_PM; + ufshcd_vops_resume(hba, pm_op); } else { ufshcd_hold(hba, false); if (hba->clk_scaling.is_allowed) { @@ -5684,7 +5687,7 @@ static void ufshcd_err_handling_unprepare(struct ufs_hba *hba) static inline bool ufshcd_err_handling_should_stop(struct ufs_hba *hba) { - return (hba->ufshcd_state == UFSHCD_STATE_ERROR || + return (!hba->is_powered || hba->ufshcd_state == UFSHCD_STATE_ERROR || (!(hba->saved_err || hba->saved_uic_err || hba->force_reset || ufshcd_is_link_broken(hba)))); } @@ -5697,6 +5700,7 @@ static void ufshcd_recover_pm_error(struct ufs_hba *hba) struct request_queue *q; int ret; + hba->is_sys_suspended = false; /* * Set RPM status of hba device to RPM_ACTIVE, * this also clears its runtime error. @@ -5755,11 +5759,13 @@ static void ufshcd_err_handler(struct work_struct *work) hba = container_of(work, struct ufs_hba, eh_work); + down(&hba->eh_sem); spin_lock_irqsave(hba->host->host_lock, flags); if (ufshcd_err_handling_should_stop(hba)) { if (hba->ufshcd_state != UFSHCD_STATE_ERROR) hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL; spin_unlock_irqrestore(hba->host->host_lock, flags); + up(&hba->eh_sem); return; } ufshcd_set_eh_in_progress(hba); @@ -5767,20 +5773,18 @@ static void ufshcd_err_handler(struct work_struct *work) ufshcd_err_handling_prepare(hba); spin_lock_irqsave(hba->host->host_lock, flags); ufshcd_scsi_block_requests(hba); - /* - * A full reset and restore might have happened after preparation - * is finished, double check whether we should stop. - */ - if (ufshcd_err_handling_should_stop(hba)) { - if (hba->ufshcd_state != UFSHCD_STATE_ERROR) - hba->ufshcd_state = UFSHCD_STATE_OPERATIONAL; - goto out; - } hba->ufshcd_state = UFSHCD_STATE_RESET; /* Complete requests that have door-bell cleared by h/w */ ufshcd_complete_requests(hba); + /* + * A full reset and restore might have happened after preparation + * is finished, double check whether we should stop. + */ + if (ufshcd_err_handling_should_stop(hba)) + goto skip_err_handling; + if (hba->dev_quirks & UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) { bool ret; @@ -5788,17 +5792,10 @@ static void ufshcd_err_handler(struct work_struct *work) /* release the lock as ufshcd_quirk_dl_nac_errors() may sleep */ ret = ufshcd_quirk_dl_nac_errors(hba); spin_lock_irqsave(hba->host->host_lock, flags); - if (!ret && !hba->force_reset && ufshcd_is_link_active(hba)) + if (!ret && ufshcd_err_handling_should_stop(hba)) goto skip_err_handling; } - if (hba->force_reset || ufshcd_is_link_broken(hba) || - ufshcd_is_saved_err_fatal(hba) || - ((hba->saved_err & UIC_ERROR) && - (hba->saved_uic_err & (UFSHCD_UIC_DL_NAC_RECEIVED_ERROR | - UFSHCD_UIC_DL_TCx_REPLAY_ERROR)))) - needs_reset = true; - if ((hba->saved_err & (INT_FATAL_ERRORS | UFSHCD_UIC_HIBERN8_MASK)) || (hba->saved_uic_err && (hba->saved_uic_err != UFSHCD_UIC_PA_GENERIC_ERROR))) { @@ -5818,8 +5815,14 @@ static void ufshcd_err_handler(struct work_struct *work) * transfers forcefully because they will get cleared during * host reset and restore */ - if (needs_reset) + if (hba->force_reset || ufshcd_is_link_broken(hba) || + ufshcd_is_saved_err_fatal(hba) || + ((hba->saved_err & UIC_ERROR) && + (hba->saved_uic_err & (UFSHCD_UIC_DL_NAC_RECEIVED_ERROR | + UFSHCD_UIC_DL_TCx_REPLAY_ERROR)))) { + needs_reset = true; goto do_reset; + } /* * If LINERESET was caught, UFS might have been put to PWM mode, @@ -5927,12 +5930,11 @@ skip_err_handling: dev_err_ratelimited(hba->dev, "%s: exit: saved_err 0x%x saved_uic_err 0x%x", __func__, hba->saved_err, hba->saved_uic_err); } - -out: ufshcd_clear_eh_in_progress(hba); spin_unlock_irqrestore(hba->host->host_lock, flags); ufshcd_scsi_unblock_requests(hba); ufshcd_err_handling_unprepare(hba); + up(&hba->eh_sem); } /** @@ -6911,6 +6913,7 @@ static int ufshcd_reset_and_restore(struct ufs_hba *hba) */ scsi_report_bus_reset(hba->host, 0); if (err) { + hba->ufshcd_state = UFSHCD_STATE_ERROR; hba->saved_err |= saved_err; hba->saved_uic_err |= saved_uic_err; } @@ -7815,8 +7818,10 @@ static void ufshcd_async_scan(void *data, async_cookie_t cookie) struct ufs_hba *hba = (struct ufs_hba *)data; int ret; + down(&hba->eh_sem); /* Initialize hba, detect and initialize UFS device */ ret = ufshcd_probe_hba(hba, true); + up(&hba->eh_sem); if (ret) goto out; @@ -8846,6 +8851,7 @@ int ufshcd_system_suspend(struct ufs_hba *hba) int ret = 0; ktime_t start = ktime_get(); + down(&hba->eh_sem); if (!hba || !hba->is_powered) return 0; @@ -8876,6 +8882,8 @@ out: hba->curr_dev_pwr_mode, hba->uic_link_state); if (!ret) hba->is_sys_suspended = true; + else + up(&hba->eh_sem); return ret; } EXPORT_SYMBOL(ufshcd_system_suspend); @@ -8892,8 +8900,10 @@ int ufshcd_system_resume(struct ufs_hba *hba) int ret = 0; ktime_t start = ktime_get(); - if (!hba) + if (!hba) { + up(&hba->eh_sem); return -EINVAL; + } if (!hba->is_powered || pm_runtime_suspended(hba->dev)) /* @@ -8909,6 +8919,7 @@ out: hba->curr_dev_pwr_mode, hba->uic_link_state); if (!ret) hba->is_sys_suspended = false; + up(&hba->eh_sem); return ret; } EXPORT_SYMBOL(ufshcd_system_resume); @@ -9000,6 +9011,7 @@ int ufshcd_shutdown(struct ufs_hba *hba) { int ret = 0; + down(&hba->eh_sem); if (!hba->is_powered) goto out; @@ -9016,6 +9028,8 @@ int ufshcd_shutdown(struct ufs_hba *hba) out: if (ret) dev_err(hba->dev, "%s failed, err %d\n", __func__, ret); + hba->is_powered = false; + up(&hba->eh_sem); /* allow force shutdown even in case of errors */ return 0; } @@ -9210,6 +9224,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) INIT_WORK(&hba->eh_work, ufshcd_err_handler); INIT_WORK(&hba->eeh_work, ufshcd_exception_event_handler); + sema_init(&hba->eh_sem, 1); + /* Initialize UIC command mutex */ mutex_init(&hba->uic_cmd_mutex); diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 8c44929bed53..1d4d3f80caa0 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -749,6 +749,7 @@ struct ufs_hba { u32 intr_mask; u16 ee_ctrl_mask; bool is_powered; + struct semaphore eh_sem; /* Work Queues */ struct workqueue_struct *eh_wq; -- cgit v1.2.3 From 7a7e66c65d4148fc3f23b058405bc9f102414fcb Mon Sep 17 00:00:00 2001 From: Can Guo Date: Wed, 2 Dec 2020 04:04:02 -0800 Subject: scsi: ufs: Fix a race condition between ufshcd_abort() and eh_work() In current task abort routine, if task abort happens to the device W-LUN, the code directly jumps to ufshcd_eh_host_reset_handler() to perform a full reset and restore then returns FAIL or SUCCESS. Commands sent to the device W-LUN are most likely the SSU cmds sent during UFS PM operations. If such SSU cmd enters task abort routine when ufshcd_eh_host_reset_handler() flushes eh_work, it will get stuck there since err_handler is serialized with PM operations. In order to unblock above call path, we merely clean up the lrb taken by this cmd, queue the eh_work and return SUCCESS. Once the cmd is aborted, the PM operation which sends out the cmd just errors out, then err_handler shall be able to proceed with the full reset and restore. In this scenario, the cmd is aborted even before it is actually cleared by HW, set the lrb->in_use flag to prevent subsequent cmds, including SCSI cmds and dev cmds, from taking the lrb released from abort. The flag shall evetually be cleared in __ufshcd_transfer_req_compl() invoked by the full reset and restore from err_handler. [mkp: conflict with event logging series] Link: https://lore.kernel.org/r/1606910644-21185-3-git-send-email-cang@codeaurora.org Reviewed-by: Asutosh Das Reviewed-by: Stanley Chu Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 64 ++++++++++++++++++++++++++++++++++++----------- drivers/scsi/ufs/ufshcd.h | 2 ++ 2 files changed, 51 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index b7a22a7c1aa0..d94a376bb194 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2558,6 +2558,14 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) (hba->clk_gating.state != CLKS_ON)); lrbp = &hba->lrb[tag]; + if (unlikely(lrbp->in_use)) { + if (hba->pm_op_in_progress) + set_host_byte(cmd, DID_BAD_TARGET); + else + err = SCSI_MLQUEUE_HOST_BUSY; + ufshcd_release(hba); + goto out; + } WARN_ON(lrbp->cmd); lrbp->cmd = cmd; @@ -2800,6 +2808,11 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, init_completion(&wait); lrbp = &hba->lrb[tag]; + if (unlikely(lrbp->in_use)) { + err = -EBUSY; + goto out; + } + WARN_ON(lrbp->cmd); err = ufshcd_compose_dev_cmd(hba, lrbp, cmd_type, tag); if (unlikely(err)) @@ -2816,6 +2829,7 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, err = ufshcd_wait_for_dev_cmd(hba, lrbp, timeout); +out: ufshcd_add_query_upiu_trace(hba, tag, err ? "query_complete_err" : "query_complete"); @@ -4980,9 +4994,11 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, struct scsi_cmnd *cmd; int result; int index; + bool update_scaling = false; for_each_set_bit(index, &completed_reqs, hba->nutrs) { lrbp = &hba->lrb[index]; + lrbp->in_use = false; lrbp->compl_time_stamp = ktime_get(); cmd = lrbp->cmd; if (cmd) { @@ -4995,15 +5011,17 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, /* Do not touch lrbp after scsi done */ cmd->scsi_done(cmd); __ufshcd_release(hba); + update_scaling = true; } else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE || lrbp->command_type == UTP_CMD_TYPE_UFS_STORAGE) { if (hba->dev_cmd.complete) { ufshcd_add_command_trace(hba, index, "dev_complete"); complete(hba->dev_cmd.complete); + update_scaling = true; } } - if (ufshcd_is_clkscaling_supported(hba)) + if (ufshcd_is_clkscaling_supported(hba) && update_scaling) hba->clk_scaling.active_reqs--; } @@ -6426,8 +6444,12 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba, init_completion(&wait); lrbp = &hba->lrb[tag]; - WARN_ON(lrbp->cmd); + if (unlikely(lrbp->in_use)) { + err = -EBUSY; + goto out; + } + WARN_ON(lrbp->cmd); lrbp->cmd = NULL; lrbp->sense_bufflen = 0; lrbp->sense_buffer = NULL; @@ -6499,6 +6521,7 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba, } } +out: blk_put_request(req); out_unlock: up_read(&hba->clk_scaling_lock); @@ -6749,18 +6772,6 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) BUG(); } - /* - * Task abort to the device W-LUN is illegal. When this command - * will fail, due to spec violation, scsi err handling next step - * will be to send LU reset which, again, is a spec violation. - * To avoid these unnecessary/illegal step we skip to the last error - * handling stage: reset and restore. - */ - if (lrbp->lun == UFS_UPIU_UFS_DEVICE_WLUN) { - ufshcd_update_evt_hist(hba, UFS_EVT_ABORT, lrbp->lun); - return ufshcd_eh_host_reset_handler(cmd); - } - ufshcd_hold(hba, false); reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); /* If command is already aborted/completed, return SUCCESS */ @@ -6781,7 +6792,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) * to reduce repeated printouts. For other aborted requests only print * basic details. */ - scsi_print_command(hba->lrb[tag].cmd); + scsi_print_command(cmd); if (!hba->req_abort_count) { ufshcd_update_evt_hist(hba, UFS_EVT_ABORT, tag); ufshcd_print_evt_hist(hba); @@ -6800,6 +6811,29 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) goto cleanup; } + /* + * Task abort to the device W-LUN is illegal. When this command + * will fail, due to spec violation, scsi err handling next step + * will be to send LU reset which, again, is a spec violation. + * To avoid these unnecessary/illegal steps, first we clean up + * the lrb taken by this cmd and mark the lrb as in_use, then + * queue the eh_work and bail. + */ + if (lrbp->lun == UFS_UPIU_UFS_DEVICE_WLUN) { + ufshcd_update_evt_hist(hba, UFS_EVT_ABORT, lrbp->lun); + spin_lock_irqsave(host->host_lock, flags); + if (lrbp->cmd) { + __ufshcd_transfer_req_compl(hba, (1UL << tag)); + __set_bit(tag, &hba->outstanding_reqs); + lrbp->in_use = true; + hba->force_reset = true; + ufshcd_schedule_eh_work(hba); + } + + spin_unlock_irqrestore(host->host_lock, flags); + goto out; + } + /* Skip task abort in case previous aborts failed and report failure */ if (lrbp->req_abort_skip) err = -EIO; diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 1d4d3f80caa0..08c8a591e6b0 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -193,6 +193,7 @@ struct ufs_pm_lvl_states { * @crypto_key_slot: the key slot to use for inline crypto (-1 if none) * @data_unit_num: the data unit number for the first block for inline crypto * @req_abort_skip: skip request abort task flag + * @in_use: indicates that this lrb is still in use */ struct ufshcd_lrb { struct utp_transfer_req_desc *utr_descriptor_ptr; @@ -222,6 +223,7 @@ struct ufshcd_lrb { #endif bool req_abort_skip; + bool in_use; }; /** -- cgit v1.2.3 From ace3804b69afa39d9445544843506eca59f3b4b2 Mon Sep 17 00:00:00 2001 From: Can Guo Date: Wed, 2 Dec 2020 04:04:03 -0800 Subject: scsi: ufs: Print host regs in IRQ handler when AH8 error happens Dump registers and states prior to leaving IRQ handler when an AH8 error occurs. Link: https://lore.kernel.org/r/1606910644-21185-4-git-send-email-cang@codeaurora.org Reviewed-by: Stanley Chu Reviewed-by: Bao D. Nguyen Reviewed-by: Asutosh Das Reviewed-by: Hongwu Su Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index d94a376bb194..e754191dbf5f 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6112,7 +6112,8 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba) hba->saved_uic_err |= hba->uic_error; /* dump controller state before resetting */ - if ((hba->saved_err & (INT_FATAL_ERRORS)) || + if ((hba->saved_err & + (INT_FATAL_ERRORS | UFSHCD_UIC_HIBERN8_MASK)) || (hba->saved_uic_err && (hba->saved_uic_err != UFSHCD_UIC_PA_GENERIC_ERROR))) { dev_err(hba->dev, "%s: saved_err 0x%x saved_uic_err 0x%x\n", -- cgit v1.2.3 From 8ca1a40b9f9defe7981ed9558b856a012e51b842 Mon Sep 17 00:00:00 2001 From: jintae jang Date: Thu, 3 Dec 2020 14:25:32 +0900 Subject: scsi: ufs: Adjust ufshcd_hold() during sending attribute requests Invalidation check of arguments should have been checked before ufshcd_hold(). This can help to prevent ufshcd_hold()/ ufshcd_release() from being invoked unnecessarily. [mkp: removed unused out: labels] Link: https://lore.kernel.org/r/1606973132-5937-1-git-send-email-user@jang-Samsung-DeskTop-System Reviewed-by: Stanley Chu Signed-off-by: jintae jang Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index e754191dbf5f..a41ee9cd26ba 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2975,14 +2975,14 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, BUG_ON(!hba); - ufshcd_hold(hba, false); if (!attr_val) { dev_err(hba->dev, "%s: attribute value required for opcode 0x%x\n", __func__, opcode); - err = -EINVAL; - goto out; + return -EINVAL; } + ufshcd_hold(hba, false); + mutex_lock(&hba->dev_cmd.lock); ufshcd_init_query(hba, &request, &response, opcode, idn, index, selector); @@ -3014,7 +3014,6 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, out_unlock: mutex_unlock(&hba->dev_cmd.lock); -out: ufshcd_release(hba); return err; } @@ -3066,21 +3065,20 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba, BUG_ON(!hba); - ufshcd_hold(hba, false); if (!desc_buf) { dev_err(hba->dev, "%s: descriptor buffer required for opcode 0x%x\n", __func__, opcode); - err = -EINVAL; - goto out; + return -EINVAL; } if (*buf_len < QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) { dev_err(hba->dev, "%s: descriptor buffer size (%d) is out of range\n", __func__, *buf_len); - err = -EINVAL; - goto out; + return -EINVAL; } + ufshcd_hold(hba, false); + mutex_lock(&hba->dev_cmd.lock); ufshcd_init_query(hba, &request, &response, opcode, idn, index, selector); @@ -3115,7 +3113,6 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba, out_unlock: hba->dev_cmd.query.descriptor = NULL; mutex_unlock(&hba->dev_cmd.lock); -out: ufshcd_release(hba); return err; } -- cgit v1.2.3 From e7734ef14ead1fd78dc28be3de7ab13128b5c315 Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Sun, 6 Dec 2020 08:51:57 +0100 Subject: scsi: NCR5380: Remove context check NCR5380_poll_politely2() uses in_interrupt() and irqs_disabled() to check if it is safe to sleep. Such usage in drivers is phased out and Linus clearly requested that code which changes behaviour depending on context should either be separated, or the context be explicitly conveyed in an argument passed by the caller. Below is a context analysis of NCR5380_poll_politely2() uppermost callers: - NCR5380_maybe_reset_bus(), task, invoked during device probe. -> NCR5380_poll_politely() -> do_abort() - NCR5380_select(), task, but can only sleep in the "release, then re-acquire" regions of the spinlock held by its caller. Sleeping invocations (lock released): -> NCR5380_poll_politely2() Atomic invocations (lock acquired): -> NCR5380_reselect() -> NCR5380_poll_politely() -> do_abort() -> NCR5380_transfer_pio() - NCR5380_intr(), interrupt handler -> NCR5380_dma_complete() -> NCR5380_transfer_pio() -> NCR5380_poll_politely() -> NCR5380_reselect() (see above) - NCR5380_information_transfer(), task, but can only sleep in the "release, then re-acquire" regions of the caller-held spinlock. Sleeping invocations (lock released): - NCR5380_transfer_pio() -> NCR5380_poll_politely() - NCR5380_poll_politely() Atomic invocations (lock acquired): - NCR5380_transfer_dma() -> NCR5380_dma_recv_setup() => generic_NCR5380_precv() -> NCR5380_poll_politely() => macscsi_pread() -> NCR5380_poll_politely() -> NCR5380_dma_send_setup() => generic_NCR5380_psend -> NCR5380_poll_politely2() => macscsi_pwrite() -> NCR5380_poll_politely() -> NCR5380_poll_politely2() -> NCR5380_dma_complete() -> NCR5380_transfer_pio() -> NCR5380_poll_politely() - NCR5380_transfer_pio() -> NCR5380_poll_politely - NCR5380_reselect(), atomic, always called with hostdata spinlock held. Since NCR5380_poll_politely2() already takes a "wait" argument in jiffies, use it to determine if the function can sleep. Modify atomic callers, which passed an unused wait value in terms of HZ, to pass zero. Link: https://lore.kernel.org/r/20201206075157.19067-1-a.darwish@linutronix.de Cc: Michael Schmitz Cc: Suggested-by: Finn Thain Co-developed-by: Sebastian Andrzej Siewior Acked-by: Finn Thain Signed-off-by: Ahmed S. Darwish Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 74 ++++++++++++++++++++++++++---------------------- drivers/scsi/NCR5380.h | 3 +- drivers/scsi/g_NCR5380.c | 12 ++++---- drivers/scsi/mac_scsi.c | 10 +++---- 4 files changed, 53 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index d597d7493a62..2ddbcaa667d1 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -132,7 +132,7 @@ static unsigned int disconnect_mask = ~0; module_param(disconnect_mask, int, 0444); -static int do_abort(struct Scsi_Host *); +static int do_abort(struct Scsi_Host *, unsigned int); static void do_reset(struct Scsi_Host *); static void bus_reset_cleanup(struct Scsi_Host *); @@ -197,7 +197,7 @@ static inline void set_resid_from_SCp(struct scsi_cmnd *cmd) * @reg2: Second 5380 register to poll * @bit2: Second bitmask to check * @val2: Second expected value - * @wait: Time-out in jiffies + * @wait: Time-out in jiffies, 0 if sleeping is not allowed * * Polls the chip in a reasonably efficient manner waiting for an * event to occur. After a short quick poll we begin to yield the CPU @@ -223,7 +223,7 @@ static int NCR5380_poll_politely2(struct NCR5380_hostdata *hostdata, cpu_relax(); } while (n--); - if (irqs_disabled() || in_interrupt()) + if (!wait) return -ETIMEDOUT; /* Repeatedly sleep for 1 ms until deadline */ @@ -486,7 +486,7 @@ static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance) break; case 2: shost_printk(KERN_ERR, instance, "bus busy, attempting abort\n"); - do_abort(instance); + do_abort(instance, 1); break; case 4: shost_printk(KERN_ERR, instance, "bus busy, attempting reset\n"); @@ -822,7 +822,7 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) if (toPIO > 0) { dsprintk(NDEBUG_DMA, instance, "Doing %d byte PIO to 0x%p\n", cnt, *data); - NCR5380_transfer_pio(instance, &p, &cnt, data); + NCR5380_transfer_pio(instance, &p, &cnt, data, 0); *count -= toPIO - cnt; } } @@ -1189,7 +1189,7 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) goto out; } if (!hostdata->selecting) { - do_abort(instance); + do_abort(instance, 0); return false; } @@ -1200,7 +1200,7 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) len = 1; data = tmp; phase = PHASE_MSGOUT; - NCR5380_transfer_pio(instance, &phase, &len, &data); + NCR5380_transfer_pio(instance, &phase, &len, &data, 0); if (len) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); cmd->result = DID_ERROR << 16; @@ -1238,7 +1238,8 @@ out: * * Inputs : instance - instance of driver, *phase - pointer to * what phase is expected, *count - pointer to number of - * bytes to transfer, **data - pointer to data pointer. + * bytes to transfer, **data - pointer to data pointer, + * can_sleep - 1 or 0 when sleeping is permitted or not, respectively. * * Returns : -1 when different phase is entered without transferring * maximum number of bytes, 0 if all bytes are transferred or exit @@ -1257,7 +1258,7 @@ out: static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, - unsigned char **data) + unsigned char **data, unsigned int can_sleep) { struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char p = *phase, tmp; @@ -1278,7 +1279,8 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, * valid */ - if (NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0) + if (NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, + HZ * can_sleep) < 0) break; dsprintk(NDEBUG_HANDSHAKE, instance, "REQ asserted\n"); @@ -1324,7 +1326,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, } if (NCR5380_poll_politely(hostdata, - STATUS_REG, SR_REQ, 0, 5 * HZ) < 0) + STATUS_REG, SR_REQ, 0, 5 * HZ * can_sleep) < 0) break; dsprintk(NDEBUG_HANDSHAKE, instance, "REQ negated, handshake complete\n"); @@ -1399,11 +1401,12 @@ static void do_reset(struct Scsi_Host *instance) * do_abort - abort the currently established nexus by going to * MESSAGE OUT phase and sending an ABORT message. * @instance: relevant scsi host instance + * @can_sleep: 1 or 0 when sleeping is permitted or not, respectively * * Returns 0 on success, negative error code on failure. */ -static int do_abort(struct Scsi_Host *instance) +static int do_abort(struct Scsi_Host *instance, unsigned int can_sleep) { struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char *msgptr, phase, tmp; @@ -1423,7 +1426,8 @@ static int do_abort(struct Scsi_Host *instance) * the target sees, so we just handshake. */ - rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, 10 * HZ); + rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, + 10 * HZ * can_sleep); if (rc < 0) goto out; @@ -1434,7 +1438,8 @@ static int do_abort(struct Scsi_Host *instance) if (tmp != PHASE_MSGOUT) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK); - rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, 0, 3 * HZ); + rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, 0, + 3 * HZ * can_sleep); if (rc < 0) goto out; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); @@ -1444,7 +1449,7 @@ static int do_abort(struct Scsi_Host *instance) msgptr = &tmp; len = 1; phase = PHASE_MSGOUT; - NCR5380_transfer_pio(instance, &phase, &len, &msgptr); + NCR5380_transfer_pio(instance, &phase, &len, &msgptr, can_sleep); if (len) rc = -ENXIO; @@ -1623,12 +1628,12 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, */ if (NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, - BASR_DRQ, BASR_DRQ, HZ) < 0) { + BASR_DRQ, BASR_DRQ, 0) < 0) { result = -1; shost_printk(KERN_ERR, instance, "PDMA read: DRQ timeout\n"); } if (NCR5380_poll_politely(hostdata, STATUS_REG, - SR_REQ, 0, HZ) < 0) { + SR_REQ, 0, 0) < 0) { result = -1; shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n"); } @@ -1640,7 +1645,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, */ if (NCR5380_poll_politely2(hostdata, BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ, - BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, HZ) < 0) { + BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, 0) < 0) { result = -1; shost_printk(KERN_ERR, instance, "PDMA write: DRQ and phase timeout\n"); } @@ -1737,7 +1742,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) #if (NDEBUG & NDEBUG_NO_DATAOUT) shost_printk(KERN_DEBUG, instance, "NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n"); sink = 1; - do_abort(instance); + do_abort(instance, 0); cmd->result = DID_ERROR << 16; complete_cmd(instance, cmd); hostdata->connected = NULL; @@ -1793,7 +1798,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) NCR5380_PIO_CHUNK_SIZE); len = transfersize; NCR5380_transfer_pio(instance, &phase, &len, - (unsigned char **)&cmd->SCp.ptr); + (unsigned char **)&cmd->SCp.ptr, + 0); cmd->SCp.this_residual -= transfersize - len; } #ifdef CONFIG_SUN3 @@ -1804,7 +1810,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) case PHASE_MSGIN: len = 1; data = &tmp; - NCR5380_transfer_pio(instance, &phase, &len, &data); + NCR5380_transfer_pio(instance, &phase, &len, &data, 0); cmd->SCp.Message = tmp; switch (tmp) { @@ -1910,7 +1916,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) len = 2; data = extended_msg + 1; phase = PHASE_MSGIN; - NCR5380_transfer_pio(instance, &phase, &len, &data); + NCR5380_transfer_pio(instance, &phase, &len, &data, 1); dsprintk(NDEBUG_EXTENDED, instance, "length %d, code 0x%02x\n", (int)extended_msg[1], (int)extended_msg[2]); @@ -1923,7 +1929,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) data = extended_msg + 3; phase = PHASE_MSGIN; - NCR5380_transfer_pio(instance, &phase, &len, &data); + NCR5380_transfer_pio(instance, &phase, &len, &data, 1); dsprintk(NDEBUG_EXTENDED, instance, "message received, residual %d\n", len); @@ -1970,7 +1976,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) len = 1; data = &msgout; hostdata->last_message = msgout; - NCR5380_transfer_pio(instance, &phase, &len, &data); + NCR5380_transfer_pio(instance, &phase, &len, &data, 0); if (msgout == ABORT) { hostdata->connected = NULL; hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun); @@ -1988,12 +1994,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) * PSEUDO-DMA architecture we should probably * use the dma transfer function. */ - NCR5380_transfer_pio(instance, &phase, &len, &data); + NCR5380_transfer_pio(instance, &phase, &len, &data, 0); break; case PHASE_STATIN: len = 1; data = &tmp; - NCR5380_transfer_pio(instance, &phase, &len, &data); + NCR5380_transfer_pio(instance, &phase, &len, &data, 0); cmd->SCp.Status = tmp; break; default: @@ -2052,7 +2058,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY); if (NCR5380_poll_politely(hostdata, - STATUS_REG, SR_SEL, 0, 2 * HZ) < 0) { + STATUS_REG, SR_SEL, 0, 0) < 0) { shost_printk(KERN_ERR, instance, "reselect: !SEL timeout\n"); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); return; @@ -2064,12 +2070,12 @@ static void NCR5380_reselect(struct Scsi_Host *instance) */ if (NCR5380_poll_politely(hostdata, - STATUS_REG, SR_REQ, SR_REQ, 2 * HZ) < 0) { + STATUS_REG, SR_REQ, SR_REQ, 0) < 0) { if ((NCR5380_read(STATUS_REG) & (SR_BSY | SR_SEL)) == 0) /* BUS FREE phase */ return; shost_printk(KERN_ERR, instance, "reselect: REQ timeout\n"); - do_abort(instance); + do_abort(instance, 0); return; } @@ -2085,10 +2091,10 @@ static void NCR5380_reselect(struct Scsi_Host *instance) unsigned char *data = msg; unsigned char phase = PHASE_MSGIN; - NCR5380_transfer_pio(instance, &phase, &len, &data); + NCR5380_transfer_pio(instance, &phase, &len, &data, 0); if (len) { - do_abort(instance); + do_abort(instance, 0); return; } } @@ -2098,7 +2104,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) shost_printk(KERN_ERR, instance, "expecting IDENTIFY message, got "); spi_print_msg(msg); printk("\n"); - do_abort(instance); + do_abort(instance, 0); return; } lun = msg[0] & 0x07; @@ -2138,7 +2144,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) * Since we have an established nexus that we can't do anything * with, we must abort it. */ - if (do_abort(instance) == 0) + if (do_abort(instance, 0) == 0) hostdata->busy[target] &= ~(1 << lun); return; } @@ -2285,7 +2291,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd); hostdata->connected = NULL; hostdata->dma_len = 0; - if (do_abort(instance) < 0) { + if (do_abort(instance, 0) < 0) { set_host_byte(cmd, DID_ERROR); complete_cmd(instance, cmd); result = FAILED; diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 5935fd6d1a05..8a3b41932288 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -277,7 +277,8 @@ static const char *NCR5380_info(struct Scsi_Host *instance); static void NCR5380_reselect(struct Scsi_Host *instance); static bool NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *); static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); -static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); +static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data, + unsigned int can_sleep); static int NCR5380_poll_politely2(struct NCR5380_hostdata *, unsigned int, u8, u8, unsigned int, u8, u8, unsigned long); diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 29e4cdcade72..2df2f38a9b12 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -529,14 +529,14 @@ static inline int generic_NCR5380_precv(struct NCR5380_hostdata *hostdata, if (start == len - 128) { /* Ignore End of DMA interrupt for the final buffer */ if (NCR5380_poll_politely(hostdata, hostdata->c400_ctl_status, - CSR_HOST_BUF_NOT_RDY, 0, HZ / 64) < 0) + CSR_HOST_BUF_NOT_RDY, 0, 0) < 0) break; } else { if (NCR5380_poll_politely2(hostdata, hostdata->c400_ctl_status, CSR_HOST_BUF_NOT_RDY, 0, hostdata->c400_ctl_status, CSR_GATED_53C80_IRQ, - CSR_GATED_53C80_IRQ, HZ / 64) < 0 || + CSR_GATED_53C80_IRQ, 0) < 0 || NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) break; } @@ -565,7 +565,7 @@ static inline int generic_NCR5380_precv(struct NCR5380_hostdata *hostdata, if (residual == 0 && NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_END_DMA_TRANSFER, BASR_END_DMA_TRANSFER, - HZ / 64) < 0) + 0) < 0) scmd_printk(KERN_ERR, hostdata->connected, "%s: End of DMA timeout\n", __func__); @@ -597,7 +597,7 @@ static inline int generic_NCR5380_psend(struct NCR5380_hostdata *hostdata, CSR_HOST_BUF_NOT_RDY, 0, hostdata->c400_ctl_status, CSR_GATED_53C80_IRQ, - CSR_GATED_53C80_IRQ, HZ / 64) < 0 || + CSR_GATED_53C80_IRQ, 0) < 0 || NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) { /* Both 128 B buffers are in use */ if (start >= 128) @@ -644,13 +644,13 @@ static inline int generic_NCR5380_psend(struct NCR5380_hostdata *hostdata, if (residual == 0) { if (NCR5380_poll_politely(hostdata, TARGET_COMMAND_REG, TCR_LAST_BYTE_SENT, TCR_LAST_BYTE_SENT, - HZ / 64) < 0) + 0) < 0) scmd_printk(KERN_ERR, hostdata->connected, "%s: Last Byte Sent timeout\n", __func__); if (NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_END_DMA_TRANSFER, BASR_END_DMA_TRANSFER, - HZ / 64) < 0) + 0) < 0) scmd_printk(KERN_ERR, hostdata->connected, "%s: End of DMA timeout\n", __func__); } diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index b5dde9d0d054..5c808fbc6ce2 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -285,7 +285,7 @@ static inline int macscsi_pread(struct NCR5380_hostdata *hostdata, while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_DRQ | BASR_PHASE_MATCH, - BASR_DRQ | BASR_PHASE_MATCH, HZ / 64)) { + BASR_DRQ | BASR_PHASE_MATCH, 0)) { int bytes; if (macintosh_config->ident == MAC_MODEL_IIFX) @@ -304,7 +304,7 @@ static inline int macscsi_pread(struct NCR5380_hostdata *hostdata, if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ, BUS_AND_STATUS_REG, BASR_ACK, - BASR_ACK, HZ / 64) < 0) + BASR_ACK, 0) < 0) scmd_printk(KERN_DEBUG, hostdata->connected, "%s: !REQ and !ACK\n", __func__); if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) @@ -344,7 +344,7 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata, while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_DRQ | BASR_PHASE_MATCH, - BASR_DRQ | BASR_PHASE_MATCH, HZ / 64)) { + BASR_DRQ | BASR_PHASE_MATCH, 0)) { int bytes; if (macintosh_config->ident == MAC_MODEL_IIFX) @@ -362,7 +362,7 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata, if (NCR5380_poll_politely(hostdata, TARGET_COMMAND_REG, TCR_LAST_BYTE_SENT, TCR_LAST_BYTE_SENT, - HZ / 64) < 0) { + 0) < 0) { scmd_printk(KERN_ERR, hostdata->connected, "%s: Last Byte Sent timeout\n", __func__); result = -1; @@ -372,7 +372,7 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata, if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ, BUS_AND_STATUS_REG, BASR_ACK, - BASR_ACK, HZ / 64) < 0) + BASR_ACK, 0) < 0) scmd_printk(KERN_DEBUG, hostdata->connected, "%s: !REQ and !ACK\n", __func__); if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) -- cgit v1.2.3 From 4c60244dc37262023d24b167e245055c06bc0b77 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 3 Dec 2020 23:31:26 +0100 Subject: scsi: ufs: Fix -Wsometimes-uninitialized warning clang complains about a possible code path in which a variable is used without an initialization: drivers/scsi/ufs/ufshcd.c:7690:3: error: variable 'sdp' is used uninitialized whenever 'if' condition is false [-Werror,-Wsometimes-uninitialized] BUG_ON(1); ^~~~~~~~~ include/asm-generic/bug.h:63:36: note: expanded from macro 'BUG_ON' #define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0) ^~~~~~~~~~~~~~~~~~~ Turn the BUG_ON(1) into an unconditional BUG() that makes it clear to clang that this code path is never hit. Link: https://lore.kernel.org/r/20201203223137.1205933-1-arnd@kernel.org Fixes: 4f3e900b6282 ("scsi: ufs: Clear UAC for FFU and RPMB LUNs") Reviewed-by: Avri Altman Signed-off-by: Arnd Bergmann Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index a41ee9cd26ba..c1c401b2b69d 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -7705,7 +7705,7 @@ static int ufshcd_clear_ua_wlun(struct ufs_hba *hba, u8 wlun) else if (wlun == UFS_UPIU_RPMB_WLUN) sdp = hba->sdev_rpmb; else - BUG_ON(1); + BUG(); if (sdp) { ret = scsi_device_get(sdp); if (!ret && !scsi_device_online(sdp)) { -- cgit v1.2.3 From d4fc94fe65578738ded138e9fce043db6bfc3241 Mon Sep 17 00:00:00 2001 From: Zhang Changzhong Date: Fri, 4 Dec 2020 15:47:39 +0800 Subject: scsi: fnic: Fix error return code in fnic_probe() Return a negative error code from the error handling case instead of 0 as done elsewhere in this function. Link: https://lore.kernel.org/r/1607068060-31203-1-git-send-email-zhangchangzhong@huawei.com Fixes: 5df6d737dd4b ("[SCSI] fnic: Add new Cisco PCI-Express FCoE HBA") Reported-by: Hulk Robot Reviewed-by: Karan Tilak Kumar Signed-off-by: Zhang Changzhong Signed-off-by: Martin K. Petersen --- drivers/scsi/fnic/fnic_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index cad29679e90e..186c3ab4456b 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c @@ -742,6 +742,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) for (i = 0; i < FNIC_IO_LOCKS; i++) spin_lock_init(&fnic->io_req_lock[i]); + err = -ENOMEM; fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache); if (!fnic->io_req_pool) goto err_out_free_resources; -- cgit v1.2.3 From 8f525bc2a7b296cf24cfa7e5186bc32dd8e766aa Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Mon, 30 Nov 2020 12:55:09 -0800 Subject: scsi: qla2xxx: Remove trailing semicolon in macro definition The macro use will already have a semicolon. Remove unneeded escaped newline. Link: https://lore.kernel.org/r/20201130205509.3447316-1-trix@redhat.com Reviewed-by: Daniel Wagner Signed-off-by: Tom Rix Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_def.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index fe3c0e2f1ce8..30c7e5e63851 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -4975,8 +4975,7 @@ struct secure_flash_update_block_pk { } while (0) #define QLA_QPAIR_MARK_NOT_BUSY(__qpair) \ - atomic_dec(&__qpair->ref_count); \ - + atomic_dec(&__qpair->ref_count) #define QLA_ENA_CONF(_ha) {\ int i;\ -- cgit v1.2.3 From 3a5b9fa2cc5fc0ddd86f03e28947e8b410622148 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 4 Dec 2020 19:18:10 +0000 Subject: scsi: qla4xxx: Remove redundant assignment to variable rval The variable rval is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Link: https://lore.kernel.org/r/20201204191810.1150995-1-colin.king@canonical.com Signed-off-by: Colin Ian King Signed-off-by: Martin K. Petersen Addresses-Coverity: ("Unused value") --- drivers/scsi/qla4xxx/ql4_nx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index fd30fbd0d33c..e6e35e6958f6 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -1767,7 +1767,7 @@ qla4_82xx_start_firmware(struct scsi_qla_host *ha, uint32_t image_start) int qla4_82xx_try_start_fw(struct scsi_qla_host *ha) { - int rval = QLA_ERROR; + int rval; /* * FW Load priority: -- cgit v1.2.3 From 305c16ce2632dca5056d7a1839c27f49c603f7f8 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 2 Dec 2020 05:22:58 -0800 Subject: scsi: qla2xxx: Return EBUSY on fcport deletion When the fcport is about to be deleted we should return EBUSY instead of ENODEV. Only for EBUSY will the request be requeued in a multipath setup. Also return EBUSY when the firmware has not yet started to avoid dropping the request. Link: https://lore.kernel.org/r/20201014073048.36219-1-dwagner@suse.de Link: https://lore.kernel.org/r/20201202132312.19966-2-njavali@marvell.com Reviewed-by: Arun Easi Reviewed-by: Himanshu Madhani Signed-off-by: Daniel Wagner Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nvme.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index 1f9005125313..b7a1dc24db38 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -554,10 +554,12 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, fcport = qla_rport->fcport; - if (!qpair || !fcport || (qpair && !qpair->fw_started) || - (fcport && fcport->deleted)) + if (!qpair || !fcport) return -ENODEV; + if (!qpair->fw_started || fcport->deleted) + return -EBUSY; + vha = fcport->vha; if (!(fcport->nvme_flag & NVME_FLAG_REGISTERED)) -- cgit v1.2.3 From c1599657d48ca65861408f9264e12c050ac9626b Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Wed, 2 Dec 2020 05:22:59 -0800 Subject: scsi: qla2xxx: Change post del message from debug level to log level Change the message debug level. Link: https://lore.kernel.org/r/20201202132312.19966-3-njavali@marvell.com Signed-off-by: Saurav Kashyap Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_gs.c | 8 ++++---- drivers/scsi/qla2xxx/qla_target.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index e28c4b7ec55f..391ac75e3de3 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -3558,10 +3558,10 @@ login_logout: if (fcport->flags & FCF_FCP2_DEVICE) fcport->logout_on_delete = 0; - ql_dbg(ql_dbg_disc, vha, 0x20f0, - "%s %d %8phC post del sess\n", - __func__, __LINE__, - fcport->port_name); + ql_log(ql_log_warn, vha, 0x20f0, + "%s %d %8phC post del sess\n", + __func__, __LINE__, + fcport->port_name); qlt_schedule_sess_for_deletion(fcport); continue; diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 6603caddc054..0d09480b66cd 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -1273,7 +1273,7 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess) qla24xx_chk_fcp_state(sess); - ql_dbg(ql_dbg_disc, sess->vha, 0xe001, + ql_dbg(ql_log_warn, sess->vha, 0xe001, "Scheduling sess %p for deletion %8phC\n", sess, sess->port_name); -- cgit v1.2.3 From a6dcfe08487e5e83b6b4214c959a9577a9ed2d9f Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Wed, 2 Dec 2020 05:23:00 -0800 Subject: scsi: qla2xxx: Limit interrupt vectors to number of CPUs Driver created too many QPairs(126) with 28xx adapter. Limit to the number of CPUs to minimize wasted resources. Link: https://lore.kernel.org/r/20201202132312.19966-4-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_isr.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index a24b82de4aab..77dd7630c3f8 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -3952,10 +3952,12 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) if (USER_CTRL_IRQ(ha) || !ha->mqiobase) { /* user wants to control IRQ setting for target mode */ ret = pci_alloc_irq_vectors(ha->pdev, min_vecs, - ha->msix_count, PCI_IRQ_MSIX); + min((u16)ha->msix_count, (u16)num_online_cpus()), + PCI_IRQ_MSIX); } else ret = pci_alloc_irq_vectors_affinity(ha->pdev, min_vecs, - ha->msix_count, PCI_IRQ_MSIX | PCI_IRQ_AFFINITY, + min((u16)ha->msix_count, (u16)num_online_cpus()), + PCI_IRQ_MSIX | PCI_IRQ_AFFINITY, &desc); if (ret < 0) { -- cgit v1.2.3 From e4fc78f48d3f8a9ea49e4b24878ac48dc9a58744 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Wed, 2 Dec 2020 05:23:01 -0800 Subject: scsi: qla2xxx: Tear down session if FW say it is down The completion status 0x28 (ppc = be = 0x2800) below indicates session is not there, trigger session deletion. qla2xxx [000b:04:00.1]-8009:8: DEVICE RESET ISSUED nexus=8:1:51 cmd=c000001432d0f600. qla2xxx [000b:04:00.1]-5039:8: Async-tmf error - hdl=67b completion status(2800). qla2xxx [000b:04:00.1]-8030:8: TM IOCB failed (102). qla2xxx [000b:04:00.1]-800c:8: do_reset failed for cmd=c000001432d0f600. qla2xxx [000b:04:00.1]-800f:8: DEVICE RESET FAILED: Task management failed nexus=8:1:51 cmd=c000001432d0f600. qla2xxx [000b:04:00.1]-8009:8: DEVICE RESET ISSUED nexus=8:1:52 cmd=c000001432d0c200. qla2xxx [000b:04:00.1]-5039:8: Async-tmf error - hdl=67c completion status(2800). qla2xxx [000b:04:00.1]-8030:8: TM IOCB failed (102). Link: https://lore.kernel.org/r/20201202132312.19966-5-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_isr.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 77dd7630c3f8..f9142dbec112 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -2226,11 +2226,13 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) srb_t *sp; struct srb_iocb *iocb; struct sts_entry_24xx *sts = (struct sts_entry_24xx *)tsk; + u16 comp_status; sp = qla2x00_get_sp_from_handle(vha, func, req, tsk); if (!sp) return; + comp_status = le16_to_cpu(sts->comp_status); iocb = &sp->u.iocb_cmd; type = sp->name; fcport = sp->fcport; @@ -2244,7 +2246,7 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) } else if (sts->comp_status != cpu_to_le16(CS_COMPLETE)) { ql_log(ql_log_warn, fcport->vha, 0x5039, "Async-%s error - hdl=%x completion status(%x).\n", - type, sp->handle, sts->comp_status); + type, sp->handle, comp_status); iocb->u.tmf.data = QLA_FUNCTION_FAILED; } else if ((le16_to_cpu(sts->scsi_status) & SS_RESPONSE_INFO_LEN_VALID)) { @@ -2260,6 +2262,30 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) } } + switch (comp_status) { + case CS_PORT_LOGGED_OUT: + case CS_PORT_CONFIG_CHG: + case CS_PORT_BUSY: + case CS_INCOMPLETE: + case CS_PORT_UNAVAILABLE: + case CS_TIMEOUT: + case CS_RESET: + if (atomic_read(&fcport->state) == FCS_ONLINE) { + ql_dbg(ql_dbg_disc, fcport->vha, 0x3021, + "-Port to be marked lost on fcport=%02x%02x%02x, current port state= %s comp_status %x.\n", + fcport->d_id.b.domain, fcport->d_id.b.area, + fcport->d_id.b.al_pa, + port_state_str[FCS_ONLINE], + comp_status); + + qlt_schedule_sess_for_deletion(fcport); + } + break; + + default: + break; + } + if (iocb->u.tmf.data != QLA_SUCCESS) ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, sp->vha, 0x5055, sts, sizeof(*sts)); -- cgit v1.2.3 From 0ce8ab50a6ed7c10bc3b7fc00d4aa5b67b5f9e2c Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Wed, 2 Dec 2020 05:23:02 -0800 Subject: scsi: qla2xxx: Don't check for fw_started while posting NVMe command NVMe commands can come only after successful addition of rport and NVMe connect, and rport is only registered after FW started bit is set. Remove the redundant check. Link: https://lore.kernel.org/r/20201202132312.19966-6-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Saurav Kashyap Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nvme.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index b7a1dc24db38..d4159d5a4ffd 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -554,19 +554,15 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport, fcport = qla_rport->fcport; - if (!qpair || !fcport) - return -ENODEV; - - if (!qpair->fw_started || fcport->deleted) + if (unlikely(!qpair || !fcport || fcport->deleted)) return -EBUSY; - vha = fcport->vha; - if (!(fcport->nvme_flag & NVME_FLAG_REGISTERED)) return -ENODEV; - if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) || - (qpair && !qpair->fw_started) || fcport->deleted) + vha = fcport->vha; + + if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) return -EBUSY; /* -- cgit v1.2.3 From aceba54ba0f998ed6bec88faaf94e7458f753399 Mon Sep 17 00:00:00 2001 From: Arun Easi Date: Wed, 2 Dec 2020 05:23:03 -0800 Subject: scsi: qla2xxx: Fix compilation issue in PPC systems MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix compile time errors reported on PPC systems, qla_gbl.h:991:20: error: inlining failed in call to always_inline ‘qla_nvme_abort_set_option’: function body not available Link: https://lore.kernel.org/r/20201202132312.19966-7-njavali@marvell.com Signed-off-by: Arun Easi Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nx.c | 2 +- drivers/scsi/qla2xxx/qla_nx2.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index b2017f1c3504..0677295957bc 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c @@ -962,7 +962,7 @@ qla82xx_read_status_reg(struct qla_hw_data *ha, uint32_t *val) static int qla82xx_flash_wait_write_finish(struct qla_hw_data *ha) { - uint32_t val; + uint32_t val = 0; int i, ret; scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c index 01ccd4526707..68a16c95dcb7 100644 --- a/drivers/scsi/qla2xxx/qla_nx2.c +++ b/drivers/scsi/qla2xxx/qla_nx2.c @@ -139,7 +139,7 @@ qla8044_poll_wait_for_ready(struct scsi_qla_host *vha, uint32_t addr1, uint32_t mask) { unsigned long timeout; - uint32_t temp; + uint32_t temp = 0; /* jiffies after 100ms */ timeout = jiffies + msecs_to_jiffies(TIMEOUT_100_MS); @@ -2594,7 +2594,7 @@ qla8044_minidump_process_rdmux(struct scsi_qla_host *vha, struct qla8044_minidump_entry_hdr *entry_hdr, uint32_t **d_ptr) { - uint32_t r_addr, s_stride, s_addr, s_value, loop_cnt, i, r_value; + uint32_t r_addr, s_stride, s_addr, s_value, loop_cnt, i, r_value = 0; struct qla8044_minidump_entry_mux *mux_hdr; uint32_t *data_ptr = *d_ptr; -- cgit v1.2.3 From 8de309e7299a00b3045fb274f82b326f356404f0 Mon Sep 17 00:00:00 2001 From: Arun Easi Date: Wed, 2 Dec 2020 05:23:04 -0800 Subject: scsi: qla2xxx: Fix crash during driver load on big endian machines Crash stack: [576544.715489] Unable to handle kernel paging request for data at address 0xd00000000f970000 [576544.715497] Faulting instruction address: 0xd00000000f880f64 [576544.715503] Oops: Kernel access of bad area, sig: 11 [#1] [576544.715506] SMP NR_CPUS=2048 NUMA pSeries : [576544.715703] NIP [d00000000f880f64] .qla27xx_fwdt_template_valid+0x94/0x100 [qla2xxx] [576544.715722] LR [d00000000f7952dc] .qla24xx_load_risc_flash+0x2fc/0x590 [qla2xxx] [576544.715726] Call Trace: [576544.715731] [c0000004d0ffb000] [c0000006fe02c350] 0xc0000006fe02c350 (unreliable) [576544.715750] [c0000004d0ffb080] [d00000000f7952dc] .qla24xx_load_risc_flash+0x2fc/0x590 [qla2xxx] [576544.715770] [c0000004d0ffb170] [d00000000f7aa034] .qla81xx_load_risc+0x84/0x1a0 [qla2xxx] [576544.715789] [c0000004d0ffb210] [d00000000f79f7c8] .qla2x00_setup_chip+0xc8/0x910 [qla2xxx] [576544.715808] [c0000004d0ffb300] [d00000000f7a631c] .qla2x00_initialize_adapter+0x4dc/0xb00 [qla2xxx] [576544.715826] [c0000004d0ffb3e0] [d00000000f78ce28] .qla2x00_probe_one+0xf08/0x2200 [qla2xxx] Link: https://lore.kernel.org/r/20201202132312.19966-8-njavali@marvell.com Fixes: f73cb695d3ec ("[SCSI] qla2xxx: Add support for ISP2071.") Cc: stable@vger.kernel.org Reviewed-by: Himanshu Madhani Signed-off-by: Arun Easi Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_tmpl.c | 9 +++++---- drivers/scsi/qla2xxx/qla_tmpl.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c index 84f4416d366f..a6bb1c0e2245 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.c +++ b/drivers/scsi/qla2xxx/qla_tmpl.c @@ -928,7 +928,8 @@ qla27xx_template_checksum(void *p, ulong size) static inline int qla27xx_verify_template_checksum(struct qla27xx_fwdt_template *tmp) { - return qla27xx_template_checksum(tmp, tmp->template_size) == 0; + return qla27xx_template_checksum(tmp, + le32_to_cpu(tmp->template_size)) == 0; } static inline int @@ -944,7 +945,7 @@ qla27xx_execute_fwdt_template(struct scsi_qla_host *vha, ulong len = 0; if (qla27xx_fwdt_template_valid(tmp)) { - len = tmp->template_size; + len = le32_to_cpu(tmp->template_size); tmp = memcpy(buf, tmp, len); ql27xx_edit_template(vha, tmp); qla27xx_walk_template(vha, tmp, buf, &len); @@ -960,7 +961,7 @@ qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *vha, void *p) ulong len = 0; if (qla27xx_fwdt_template_valid(tmp)) { - len = tmp->template_size; + len = le32_to_cpu(tmp->template_size); qla27xx_walk_template(vha, tmp, NULL, &len); } @@ -972,7 +973,7 @@ qla27xx_fwdt_template_size(void *p) { struct qla27xx_fwdt_template *tmp = p; - return tmp->template_size; + return le32_to_cpu(tmp->template_size); } int diff --git a/drivers/scsi/qla2xxx/qla_tmpl.h b/drivers/scsi/qla2xxx/qla_tmpl.h index c47184db5081..6e0987edfceb 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.h +++ b/drivers/scsi/qla2xxx/qla_tmpl.h @@ -12,7 +12,7 @@ struct __packed qla27xx_fwdt_template { __le32 template_type; __le32 entry_offset; - uint32_t template_size; + __le32 template_size; uint32_t count; /* borrow field for running/residual count */ __le32 entry_count; -- cgit v1.2.3 From 8a78dd6ed1af06bfa7b4ade81328ff7ea11b6947 Mon Sep 17 00:00:00 2001 From: Arun Easi Date: Wed, 2 Dec 2020 05:23:05 -0800 Subject: scsi: qla2xxx: Fix FW initialization error on big endian machines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some fields are not correctly byte swapped causing failure during initialization. As probe() returns failure, HBAs will not be claimed when this happens. qla2xxx [0007:01:00.0]-ffff:3: Secure Flash Update in FW: Supported qla2xxx [0007:01:00.0]-ffff:3: SCM in FW: Supported qla2xxx [0007:01:00.0]-00d2:3: Init Firmware **** FAILED ****. qla2xxx [0007:01:00.0]-00d6:3: Failed to initialize adapter - Adapter flags 2. qla2xxx 0007:01:00.1: enabling device (0140 -> 0142) qla2xxx [0007:01:00.1]-011c: : MSI-X vector count: 128. qla2xxx [0007:01:00.1]-001d: : Found an ISP2289 irq 18 iobase 0xd000080080004000. qla2xxx 0007:01:00.1: Using 64-bit direct DMA at offset 800000000000000 BUG: Bad page state in process insmod pfn:67118 page:f00000000168bd40 count:-1 mapcount:0 mapping: (null) index:0x0 page flags: 0x3ffff800000000() page dumped because: nonzero _count Modules linked in: qla2xxx(OE+) nvme_fc nvme_fabrics nvme_core scsi_transport_fc scsi_tgt nls_utf8 isofs ip6t_rpfilter ipt_REJECT nf_reject_ipv4 ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6 ip6table_mangle ip6table_security ip6table_raw iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack iptable_mangle iptable_security iptable_raw ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter nx_crypto ses enclosure scsi_transport_sas pseries_rng sg ip_tables xfs libcrc32c sr_mod cdrom sd_mod crc_t10dif crct10dif_generic crct10dif_common usb_storage ipr libata tg3 ptp pps_core dm_mirror dm_region_hash dm_log dm_mod CPU: 32 PID: 8560 Comm: insmod Kdump: loaded Tainted: G OE ------------ 3.10.0-957.el7.ppc64 #1 Call Trace: [c0000006dd7caa70] [c00000000001cca8] .show_stack+0x88/0x330 (unreliable) [c0000006dd7cab30] [c000000000ac3d88] .dump_stack+0x28/0x3c [c0000006dd7caba0] [c00000000029e48c] .bad_page+0x15c/0x1c0 [c0000006dd7cac40] [c00000000029f938] .get_page_from_freelist+0x11e8/0x1ea0 [c0000006dd7caf40] [c0000000002a1d30] .__alloc_pages_nodemask+0x1c0/0xc70 [c0000006dd7cb140] [c00000000002ba0c] .__dma_direct_alloc_coherent+0x8c/0x170 [c0000006dd7cb1e0] [d000000010a94688] .qla2x00_mem_alloc+0x10f8/0x1370 [qla2xxx] [c0000006dd7cb2d0] [d000000010a9c790] .qla2x00_probe_one+0xb60/0x22e0 [qla2xxx] [c0000006dd7cb540] [c0000000005de764] .pci_device_probe+0x204/0x300 [c0000006dd7cb600] [c0000000006ca61c] .driver_probe_device+0x2cc/0x6f0 [c0000006dd7cb6b0] [c0000000006cabec] .__driver_attach+0x10c/0x110 [c0000006dd7cb740] [c0000000006c5f04] .bus_for_each_dev+0x94/0x100 [c0000006dd7cb7e0] [c0000000006c94f4] .driver_attach+0x34/0x50 [c0000006dd7cb860] [c0000000006c8f58] .bus_add_driver+0x298/0x3b0 [c0000006dd7cb900] [c0000000006cb6e0] .driver_register+0xb0/0x1a0 [c0000006dd7cb980] [c0000000005dc474] .__pci_register_driver+0xc4/0xf0 [c0000006dd7cba10] [d000000010b94e20] .qla2x00_module_init+0x2a8/0x328 [qla2xxx] [c0000006dd7cbaa0] [c00000000000c130] .do_one_initcall+0x130/0x2e0 [c0000006dd7cbb50] [c0000000001b2e8c] .load_module+0x1afc/0x2340 [c0000006dd7cbd40] [c0000000001b3920] .SyS_finit_module+0xd0/0x130 [c0000006dd7cbe30] [c00000000000a284] system_call+0x38/0xfc Link: https://lore.kernel.org/r/20201202132312.19966-9-njavali@marvell.com Fixes: 9f2475fe7406 ("scsi: qla2xxx: SAN congestion management implementation") Fixes: cf3c54fb49a4 ("scsi: qla2xxx: Add SLER and PI control support”) Reviewed-by: Himanshu Madhani Signed-off-by: Arun Easi Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_mbx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 40af7f1524ce..1b4261c3c476 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1129,7 +1129,7 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) if (ha->flags.scm_supported_a && (ha->fw_attributes_ext[0] & FW_ATTR_EXT0_SCM_SUPPORTED)) { ha->flags.scm_supported_f = 1; - ha->sf_init_cb->flags |= BIT_13; + ha->sf_init_cb->flags |= cpu_to_le16(BIT_13); } ql_log(ql_log_info, vha, 0x11a3, "SCM in FW: %s\n", (ha->flags.scm_supported_f) ? "Supported" : @@ -1137,9 +1137,9 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha) if (vha->flags.nvme2_enabled) { /* set BIT_15 of special feature control block for SLER */ - ha->sf_init_cb->flags |= BIT_15; + ha->sf_init_cb->flags |= cpu_to_le16(BIT_15); /* set BIT_14 of special feature control block for PI CTRL*/ - ha->sf_init_cb->flags |= BIT_14; + ha->sf_init_cb->flags |= cpu_to_le16(BIT_14); } } -- cgit v1.2.3 From 07a5f69248e3486e387c40af64793466371c7d91 Mon Sep 17 00:00:00 2001 From: Quinn Tran Date: Wed, 2 Dec 2020 05:23:06 -0800 Subject: scsi: qla2xxx: Fix N2N and NVMe connect retry failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FC-NVMe target discovery failed when initiator wwpn < target wwpn in an N2N (Direct Attach) config, where the driver was stuck on FCP PRLI mode and failed to retry with NVMe PRLI. Link: https://lore.kernel.org/r/20201202132312.19966-10-njavali@marvell.com Fixes: 84ed362ac40c ("scsi: qla2xxx: Dual FCP-NVMe target port support”) Fixes: 983f127603fa ("scsi: qla2xxx: Retry PLOGI on FC-NVMe PRLI failure”) Signed-off-by: Quinn Tran Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 71 ++++++++++++++++++++++++++++++----------- drivers/scsi/qla2xxx/qla_mbx.c | 3 -- 2 files changed, 52 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 5626e9b6949f..12e3b05baf41 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1268,9 +1268,10 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport) lio->u.logio.flags |= SRB_LOGIN_NVME_PRLI; ql_dbg(ql_dbg_disc, vha, 0x211b, - "Async-prli - %8phC hdl=%x, loopid=%x portid=%06x retries=%d %s.\n", + "Async-prli - %8phC hdl=%x, loopid=%x portid=%06x retries=%d fc4type %x priority %x %s.\n", fcport->port_name, sp->handle, fcport->loop_id, fcport->d_id.b24, - fcport->login_retry, NVME_TARGET(vha->hw, fcport) ? "nvme" : "fc"); + fcport->login_retry, fcport->fc4_type, vha->hw->fc4_type_priority, + NVME_TARGET(vha->hw, fcport) ? "nvme" : "fcp"); rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) { @@ -1932,26 +1933,58 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea) break; } - /* - * Retry PRLI with other FC-4 type if failure occurred on dual - * FCP/NVMe port - */ - if (NVME_FCP_TARGET(ea->fcport)) { - ql_dbg(ql_dbg_disc, vha, 0x2118, - "%s %d %8phC post %s prli\n", - __func__, __LINE__, ea->fcport->port_name, - (ea->fcport->fc4_type & FS_FC4TYPE_NVME) ? - "NVMe" : "FCP"); - if (vha->hw->fc4_type_priority == FC4_PRIORITY_NVME) + ql_dbg(ql_dbg_disc, vha, 0x2118, + "%s %d %8phC priority %s, fc4type %x\n", + __func__, __LINE__, ea->fcport->port_name, + vha->hw->fc4_type_priority == FC4_PRIORITY_FCP ? + "FCP" : "NVMe", ea->fcport->fc4_type); + + if (N2N_TOPO(vha->hw)) { + if (vha->hw->fc4_type_priority == FC4_PRIORITY_NVME) { ea->fcport->fc4_type &= ~FS_FC4TYPE_NVME; - else + ea->fcport->fc4_type |= FS_FC4TYPE_FCP; + } else { ea->fcport->fc4_type &= ~FS_FC4TYPE_FCP; - } + ea->fcport->fc4_type |= FS_FC4TYPE_NVME; + } - ea->fcport->flags &= ~FCF_ASYNC_SENT; - ea->fcport->keep_nport_handle = 0; - ea->fcport->logout_on_delete = 1; - qlt_schedule_sess_for_deletion(ea->fcport); + if (ea->fcport->n2n_link_reset_cnt < 3) { + ea->fcport->n2n_link_reset_cnt++; + vha->relogin_jif = jiffies + 2 * HZ; + /* + * PRLI failed. Reset link to kick start + * state machine + */ + set_bit(N2N_LINK_RESET, &vha->dpc_flags); + } else { + ql_log(ql_log_warn, vha, 0x2119, + "%s %d %8phC Unable to reconnect\n", + __func__, __LINE__, + ea->fcport->port_name); + } + } else { + /* + * switch connect. login failed. Take connection down + * and allow relogin to retrigger + */ + if (NVME_FCP_TARGET(ea->fcport)) { + ql_dbg(ql_dbg_disc, vha, 0x2118, + "%s %d %8phC post %s prli\n", + __func__, __LINE__, + ea->fcport->port_name, + (ea->fcport->fc4_type & FS_FC4TYPE_NVME) + ? "NVMe" : "FCP"); + if (vha->hw->fc4_type_priority == FC4_PRIORITY_NVME) + ea->fcport->fc4_type &= ~FS_FC4TYPE_NVME; + else + ea->fcport->fc4_type &= ~FS_FC4TYPE_FCP; + } + + ea->fcport->flags &= ~FCF_ASYNC_SENT; + ea->fcport->keep_nport_handle = 0; + ea->fcport->logout_on_delete = 1; + qlt_schedule_sess_for_deletion(ea->fcport); + } break; } } diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 1b4261c3c476..d7d4ab65009c 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -3998,9 +3998,6 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, fcport->scan_state = QLA_FCPORT_FOUND; fcport->n2n_flag = 1; fcport->keep_nport_handle = 1; - fcport->fc4_type = FS_FC4TYPE_FCP; - if (vha->flags.nvme_enabled) - fcport->fc4_type |= FS_FC4TYPE_NVME; if (wwn_to_u64(vha->port_name) > wwn_to_u64(fcport->port_name)) { -- cgit v1.2.3 From f795f96e725b472de59db06a21a23e2285faaf14 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Wed, 2 Dec 2020 05:23:07 -0800 Subject: scsi: qla2xxx: Handle aborts correctly for port undergoing deletion Call trace observed while shutting down the adapter ports (LINK DOWN). Handle aborts correctly. localhost kernel: INFO: task nvme:44209 blocked for more than 120 seconds. localhost kernel: "echo 0 >/proc/sys/kernel/hung_task_timeout_secs" disables this message. localhost kernel: nvme D ffff88b45fb5acc0 0 44209 1 0x00000080 localhost kernel: Call Trace: localhost kernel: [] schedule+0x29/0x70 localhost kernel: [] schedule_timeout+0x221/0x2d0 localhost kernel: [] ? ttwu_do_wakeup+0x19/0xe0 localhost kernel: [] ? ttwu_do_activate+0x6f/0x80 localhost kernel: [] ? try_to_wake_up+0x190/0x390 localhost kernel: [] wait_for_completion+0xfd/0x140 localhost kernel: [] ? wake_up_state+0x20/0x20 localhost kernel: [] flush_work+0x10a/0x1b0 localhost kernel: [] ? move_linked_works+0x90/0x90 localhost kernel: [] flush_delayed_work+0x3f/0x50 localhost kernel: [] nvme_fc_init_ctrl+0x657/0x6a0 [nvme_fc] localhost kernel: [] nvme_fc_create_ctrl+0x18a/0x210 [nvme_fc] localhost kernel: [] nvmf_dev_write+0x98f/0xb35 [nvme_fabrics] localhost kernel: [] ? security_file_permission+0x27/0xa0 localhost kernel: [] vfs_write+0xc0/0x1f0 localhost kernel: [] SyS_write+0x7f/0xf0 localhost kernel: [] system_call_fastpath+0x25/0x2a Link: https://lore.kernel.org/r/20201202132312.19966-11-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Saurav Kashyap Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_nvme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c index d4159d5a4ffd..eab559b3b257 100644 --- a/drivers/scsi/qla2xxx/qla_nvme.c +++ b/drivers/scsi/qla2xxx/qla_nvme.c @@ -227,7 +227,7 @@ static void qla_nvme_abort_work(struct work_struct *work) "%s called for sp=%p, hndl=%x on fcport=%p deleted=%d\n", __func__, sp, sp->handle, fcport, fcport->deleted); - if (!ha->flags.fw_started && fcport->deleted) + if (!ha->flags.fw_started || fcport->deleted) goto out; if (ha->flags.host_shutting_down) { -- cgit v1.2.3 From 0bc17251dff432f2589d3d509fb4dc14912d4372 Mon Sep 17 00:00:00 2001 From: Arun Easi Date: Wed, 2 Dec 2020 05:23:08 -0800 Subject: scsi: qla2xxx: Fix flash update in 28XX adapters on big endian machines Flash update failed due to missing endian conversion in FLT region access as well as in checksum computation. Link: https://lore.kernel.org/r/20201202132312.19966-12-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Arun Easi Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_sup.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 0f92e9a044dc..f771fabcba59 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -2634,14 +2634,14 @@ qla28xx_extract_sfub_and_verify(struct scsi_qla_host *vha, uint32_t *buf, sizeof(struct secure_flash_update_block)); for (i = 0; i < (sizeof(struct secure_flash_update_block) >> 2); i++) - check_sum += p[i]; + check_sum += le32_to_cpu(p[i]); check_sum = (~check_sum) + 1; - if (check_sum != p[i]) { + if (check_sum != le32_to_cpu(p[i])) { ql_log(ql_log_warn, vha, 0x7097, "SFUB checksum failed, 0x%x, 0x%x\n", - check_sum, p[i]); + check_sum, le32_to_cpu(p[i])); return QLA_COMMAND_ERROR; } @@ -2721,7 +2721,7 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, if (ha->flags.secure_adapter && region.attribute) { ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, - "Region %x is secure\n", region.code); + "Region %x is secure\n", le16_to_cpu(region.code)); switch (le16_to_cpu(region.code)) { case FLT_REG_FW: @@ -2775,7 +2775,7 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr, default: ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff, "Secure region %x not supported\n", - region.code); + le16_to_cpu(region.code)); rval = QLA_COMMAND_ERROR; goto done; } -- cgit v1.2.3 From 0a6f4d762c6b8fd0d442db74c8d279744100ae25 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Wed, 2 Dec 2020 05:23:09 -0800 Subject: scsi: qla2xxx: Fix the call trace for flush workqueue The call trace was because workqueue was allocated without any flags, added WQ_MEM_RECLAIM as flag when allocating. kernel: workqueue: WQ_MEM_RECLAIM kblockd:blk_mq_run_work_fn is flushing !WQ_MEM_RECLAIM qla2xxx_wq:0x0 kernel: WARNING: CPU: 0 PID: 2475 at kernel/workqueue.c:2593 check_flush_dependency+0x110/0x130 kernel: CPU: 0 PID: 2475 Comm: kworker/0:1H Kdump: loaded Tainted: G OE --------- - - 4.18.0-193.el8.x86_64 #1 kernel: Hardware name: HPE ProLiant XL170r Gen10/ProLiant XL170r Gen10, BIOS U38 05/21/2019 kernel: Workqueue: kblockd blk_mq_run_work_fn kernel: RIP: 0010:check_flush_dependency+0x110/0x130 kernel: Code: ff ff 48 8b 50 18 48 8d 8b b0 00 00 00 49 89 e8 48 81 c6 b0 00 00 00 48 c7 c7 00 1e e9 95 c6 05 dc 9a 2f 01 01 e8 1a 42 fe ff <0f> 0b e9 0a ff ff ff 80 3d ca 9a 2f 01 0 0 75 95 e9 41 ff ff ff 90 kernel: RSP: 0018:ffffa40f48b2baf8 EFLAGS: 00010282 kernel: RAX: 0000000000000000 RBX: ffff946795282600 RCX: 0000000000000000 kernel: RDX: 000000000000005f RSI: ffffffff96a1af7f RDI: 0000000000000246 kernel: RBP: 0000000000000000 R08: ffffffff96a1af20 R09: 0000000000029480 kernel: R10: 00080c89bb3e7462 R11: 00000000000009ab R12: ffff946773628000 kernel: R13: 0000000000000282 R14: 0000000000000246 R15: ffffa40f48b2bb40 kernel: FS: 0000000000000000(0000) GS:ffff94679fa00000(0000) knlGS:0000000000000000 kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 kernel: CR2: 00005570c4b60110 CR3: 000000029140a005 CR4: 00000000007606f0 kernel: DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 kernel: DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 kernel: PKRU: 55555554 kernel: Call Trace: kernel: flush_workqueue+0x13a/0x440 kernel: qla2x00_wait_for_sess_deletion+0x1d6/0x200 [qla2xxx] kernel: ? finish_wait+0x80/0x80 kernel: qla2xxx_disable_port+0x2b/0x30 [qla2xxx] kernel: qla2x00_process_vendor_specific+0x1dc9/0x2d20 [qla2xxx] kernel: ? blk_rq_map_sg+0x195/0x570 kernel: qla24xx_bsg_request+0x1a3/0xf90 [qla2xxx] Link: https://lore.kernel.org/r/20201202132312.19966-13-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Saurav Kashyap Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2a8e065b192c..f102256391e7 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3265,7 +3265,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) "req->req_q_in=%p req->req_q_out=%p rsp->rsp_q_in=%p rsp->rsp_q_out=%p.\n", req->req_q_in, req->req_q_out, rsp->rsp_q_in, rsp->rsp_q_out); - ha->wq = alloc_workqueue("qla2xxx_wq", 0, 0); + ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 0); if (unlikely(!ha->wq)) { ret = -ENOMEM; goto probe_failed; -- cgit v1.2.3 From 707531bc2626c1959a03b93566ebb4e629c99276 Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Wed, 2 Dec 2020 05:23:10 -0800 Subject: scsi: qla2xxx: If fcport is undergoing deletion complete I/O with retry Driver unload with I/Os in flight causes server to crash. Complete I/O with DID_IMM_RETRY if fcport undergoing deletion. CPU: 44 PID: 35008 Comm: qla2xxx_4_dpc Kdump: loaded Tainted: G OE X 5.3.18-22-default #1 SLE15-SP2 (unreleased) Hardware name: HPE ProLiant DL380 Gen10/ProLiant DL380 Gen10, BIOS U30 07/16/2020 RIP: 0010:dma_direct_unmap_sg+0x24/0x60 Code: 4c 8b 04 24 eb b9 0f 1f 44 00 00 85 d2 7e 4e 41 57 4d 89 c7 41 56 41 89 ce 41 55 49 89 fd 41 54 41 89 d4 55 31 ed 53 48 89 f3 <8b> 53 18 48 8b 73 10 4d 89 f8 44 89 f1 4c 89 ef 83 c5 01 e8 44 ff RSP: 0018:ffffc0c661037d88 EFLAGS: 00010046 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000002 RDX: 000000000000001d RSI: 0000000000000000 RDI: ffff9a51ee53b0b0 RBP: 0000000000000000 R08: 0000000000000000 R09: ffff9a51ee53b0b0 R10: ffffc0c646463dc8 R11: ffff9a4a067087c8 R12: 000000000000001d R13: ffff9a51ee53b0b0 R14: 0000000000000002 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff9a523f800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000018 CR3: 000000043740a004 CR4: 00000000007606e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: qla2xxx_qpair_sp_free_dma+0x20d/0x3c0 [qla2xxx] qla2xxx_qpair_sp_compl+0x35/0x90 [qla2xxx] __qla2x00_abort_all_cmds+0x180/0x390 [qla2xxx] ? qla24xx_process_purex_list+0x100/0x100 [qla2xxx] qla2x00_abort_all_cmds+0x5e/0x80 [qla2xxx] qla2x00_do_dpc+0x317/0xa30 [qla2xxx] kthread+0x10d/0x130 ? kthread_park+0xa0/0xa0 ret_from_fork+0x35/0x40 Link: https://lore.kernel.org/r/20201202132312.19966-14-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Saurav Kashyap Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_os.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index f102256391e7..f80abe28f35a 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -884,8 +884,8 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) goto qc24_fail_command; } - if (!fcport) { - cmd->result = DID_NO_CONNECT << 16; + if (!fcport || fcport->deleted) { + cmd->result = DID_IMM_RETRY << 16; goto qc24_fail_command; } @@ -966,8 +966,8 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd, goto qc24_fail_command; } - if (!fcport) { - cmd->result = DID_NO_CONNECT << 16; + if (!fcport || fcport->deleted) { + cmd->result = DID_IMM_RETRY << 16; goto qc24_fail_command; } -- cgit v1.2.3 From abd9cae9bbae9f3a80dae82587b1f79161ad7836 Mon Sep 17 00:00:00 2001 From: Arun Easi Date: Wed, 2 Dec 2020 05:23:11 -0800 Subject: scsi: qla2xxx: Fix device loss on 4G and older HBAs Due to a bug in the older scan logic, when a once lost device re-appeared, it was not discovered. Fix this by resetting login_retry counter upon device discovery. This is applicable only for 4G and older HBAs. Link: https://lore.kernel.org/r/20201202132312.19966-15-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Arun Easi Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_init.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 12e3b05baf41..dcc0f0d823db 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -5982,6 +5982,9 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha) break; } + if (fcport->login_retry == 0) + fcport->login_retry = + vha->hw->login_retry_count; /* * If device was not a fabric device before. */ -- cgit v1.2.3 From afc516dcfe52802e0d29e37e3200c0f08583bd8f Mon Sep 17 00:00:00 2001 From: Nilesh Javali Date: Wed, 2 Dec 2020 05:23:12 -0800 Subject: scsi: qla2xxx: Update version to 10.02.00.104-k Link: https://lore.kernel.org/r/20201202132312.19966-16-njavali@marvell.com Reviewed-by: Himanshu Madhani Signed-off-by: Nilesh Javali Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_version.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index c2d4da52f4a9..ccec858875dd 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -6,9 +6,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "10.02.00.103-k" +#define QLA2XXX_VERSION "10.02.00.104-k" #define QLA_DRIVER_MAJOR_VER 10 #define QLA_DRIVER_MINOR_VER 2 #define QLA_DRIVER_PATCH_VER 0 -#define QLA_DRIVER_BETA_VER 103 +#define QLA_DRIVER_BETA_VER 104 -- cgit v1.2.3 From f98790c0037590cd7022ba9e22cf4ff90d3b2bb3 Mon Sep 17 00:00:00 2001 From: Suganath Prabu S Date: Thu, 26 Nov 2020 15:13:04 +0530 Subject: scsi: mpt3sas: Sync time periodically between driver and firmware The controller time currently gets updated with host time during driver load or when a controller reset is issued. I.e. when host issues the IOCInit request message to the HBA firmware. This IOCInit message has a field named 'TimeStamp' with which the host updates the controller time. Sometimes controller time drifts with respect to the host and it is difficult to correlate host logs with controller logs. Issuing a controller reset to sync the time would impact in-flight I/O and is not a viable option. Instead the driver now sends an IO_UNIT_CONTROL Request to sync the time periodically. This is done from the watchdog thread which gets invoked every second. The time synchronization interval is specified in the 'TimeSyncInterval' field in Manufacturing Page11 by the controller: TimeSyncInterval - 8 bits bits 0-6: Time stamp Synchronization interval value bit 7: Time stamp Synchronization interval unit, (if this bit is one then Timestamp Synchronization interval value is specified in terms of hours else Timestamp Synchronization interval value is specified in terms of minutes). The driver keeps track of the timer using IOC's timestamp_update_count field. This field value gets incremented whenever the watchdog thread gets invoked. And whenever this field value is greater than or equal to the Time Stamp Synchronization interval value, the driver sends the IO_UNIT_CONTROL Request message to controller to update the time and then it resets the timestamp_update_count field to zero. Link: https://lore.kernel.org/r/20201126094311.8686-2-suganath-prabu.subramani@broadcom.com Reported-by: kernel test robot Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 93 ++++++++++++++++++++++++++++++++++++- drivers/scsi/mpt3sas/mpt3sas_base.h | 14 +++++- 2 files changed, 104 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 93230cd1982f..8538c2ddbc68 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -596,6 +596,71 @@ static int mpt3sas_remove_dead_ioc_func(void *arg) return 0; } +/** + * _base_sync_drv_fw_timestamp - Sync Drive-Fw TimeStamp. + * @ioc: Per Adapter Object + * + * Return nothing. + */ +static void _base_sync_drv_fw_timestamp(struct MPT3SAS_ADAPTER *ioc) +{ + Mpi26IoUnitControlRequest_t *mpi_request; + Mpi26IoUnitControlReply_t *mpi_reply; + u16 smid; + ktime_t current_time; + u64 TimeStamp = 0; + u8 issue_reset = 0; + + mutex_lock(&ioc->scsih_cmds.mutex); + if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) { + ioc_err(ioc, "scsih_cmd in use %s\n", __func__); + goto out; + } + ioc->scsih_cmds.status = MPT3_CMD_PENDING; + smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx); + if (!smid) { + ioc_err(ioc, "Failed obtaining a smid %s\n", __func__); + ioc->scsih_cmds.status = MPT3_CMD_NOT_USED; + goto out; + } + mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); + ioc->scsih_cmds.smid = smid; + memset(mpi_request, 0, sizeof(Mpi26IoUnitControlRequest_t)); + mpi_request->Function = MPI2_FUNCTION_IO_UNIT_CONTROL; + mpi_request->Operation = MPI26_CTRL_OP_SET_IOC_PARAMETER; + mpi_request->IOCParameter = MPI26_SET_IOC_PARAMETER_SYNC_TIMESTAMP; + current_time = ktime_get_real(); + TimeStamp = ktime_to_ms(current_time); + mpi_request->Reserved7 = cpu_to_le32(TimeStamp & 0xFFFFFFFF); + mpi_request->IOCParameterValue = cpu_to_le32(TimeStamp >> 32); + init_completion(&ioc->scsih_cmds.done); + ioc->put_smid_default(ioc, smid); + dinitprintk(ioc, ioc_info(ioc, + "Io Unit Control Sync TimeStamp (sending), @time %lld ms\n", + TimeStamp)); + wait_for_completion_timeout(&ioc->scsih_cmds.done, + MPT3SAS_TIMESYNC_TIMEOUT_SECONDS*HZ); + if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) { + mpt3sas_check_cmd_timeout(ioc, + ioc->scsih_cmds.status, mpi_request, + sizeof(Mpi2SasIoUnitControlRequest_t)/4, issue_reset); + goto issue_host_reset; + } + if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) { + mpi_reply = ioc->scsih_cmds.reply; + dinitprintk(ioc, ioc_info(ioc, + "Io Unit Control sync timestamp (complete): ioc_status(0x%04x), loginfo(0x%08x)\n", + le16_to_cpu(mpi_reply->IOCStatus), + le32_to_cpu(mpi_reply->IOCLogInfo))); + } +issue_host_reset: + if (issue_reset) + mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER); + ioc->scsih_cmds.status = MPT3_CMD_NOT_USED; +out: + mutex_unlock(&ioc->scsih_cmds.mutex); +} + /** * _base_fault_reset_work - workq handling ioc fault conditions * @work: input argument, used to derive ioc @@ -720,7 +785,11 @@ _base_fault_reset_work(struct work_struct *work) return; /* don't rearm timer */ } ioc->ioc_coredump_loop = 0; - + if (ioc->time_sync_interval && + ++ioc->timestamp_update_count >= ioc->time_sync_interval) { + ioc->timestamp_update_count = 0; + _base_sync_drv_fw_timestamp(ioc); + } spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); rearm_timer: if (ioc->fault_reset_work_q) @@ -744,6 +813,7 @@ mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc) if (ioc->fault_reset_work_q) return; + ioc->timestamp_update_count = 0; /* initialize fault polling */ INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); @@ -4754,7 +4824,24 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) else ioc->nvme_abort_timeout = ioc->manu_pg11.NVMeAbortTO; } - + ioc->time_sync_interval = + ioc->manu_pg11.TimeSyncInterval & MPT3SAS_TIMESYNC_MASK; + if (ioc->time_sync_interval) { + if (ioc->manu_pg11.TimeSyncInterval & MPT3SAS_TIMESYNC_UNIT_MASK) + ioc->time_sync_interval = + ioc->time_sync_interval * SECONDS_PER_HOUR; + else + ioc->time_sync_interval = + ioc->time_sync_interval * SECONDS_PER_MIN; + dinitprintk(ioc, ioc_info(ioc, + "Driver-FW TimeSync interval is %d seconds. ManuPg11 TimeSync Unit is in %s\n", + ioc->time_sync_interval, (ioc->manu_pg11.TimeSyncInterval & + MPT3SAS_TIMESYNC_UNIT_MASK) ? "Hour" : "Minute")); + } else { + if (ioc->is_gen35_ioc) + ioc_warn(ioc, + "TimeSync Interval in Manuf page-11 is not enabled. Periodic Time-Sync will be disabled\n"); + } mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2); mpt3sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3); mpt3sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8); @@ -6466,6 +6553,8 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc) r = -EIO; } + /* Reset TimeSync Counter*/ + ioc->timestamp_update_count = 0; return r; } diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 7dab579dbc20..cc4815c74f69 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -93,6 +93,14 @@ /* CoreDump: Default timeout */ #define MPT3SAS_DEFAULT_COREDUMP_TIMEOUT_SECONDS (15) /*15 seconds*/ #define MPT3SAS_COREDUMP_LOOP_DONE (0xFF) +#define MPT3SAS_TIMESYNC_TIMEOUT_SECONDS (10) /* 10 seconds */ +#define MPT3SAS_TIMESYNC_UPDATE_INTERVAL (900) /* 15 minutes */ +#define MPT3SAS_TIMESYNC_UNIT_MASK (0x80) /* bit 7 */ +#define MPT3SAS_TIMESYNC_MASK (0x7F) /* 0 - 6 bits */ +#define SECONDS_PER_MIN (60) +#define SECONDS_PER_HOUR (3600) +#define MPT3SAS_COREDUMP_LOOP_DONE (0xFF) +#define MPI26_SET_IOC_PARAMETER_SYNC_TIMESTAMP (0x81) /* * Set MPT3SAS_SG_DEPTH value based on user input. @@ -405,7 +413,7 @@ struct Mpi2ManufacturingPage11_t { u16 HostTraceBufferMaxSizeKB; /* 50h */ u16 HostTraceBufferMinSizeKB; /* 52h */ u8 CoreDumpTOSec; /* 54h */ - u8 Reserved8; /* 55h */ + u8 TimeSyncInterval; /* 55h */ u16 Reserved9; /* 56h */ __le32 Reserved10; /* 58h */ }; @@ -1113,6 +1121,8 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); * @cpu_msix_table_sz: table size * @total_io_cnt: Gives total IO count, used to load balance the interrupts * @ioc_coredump_loop: will have non-zero value when FW is in CoreDump state + * @timestamp_update_count: Counter to fire timeSync command + * time_sync_interval: Time sync interval read from man page 11 * @high_iops_outstanding: used to load balance the interrupts * within high iops reply queues * @msix_load_balance: Enables load balancing of interrupts across @@ -1308,6 +1318,8 @@ struct MPT3SAS_ADAPTER { MPT3SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds; u32 non_operational_loop; u8 ioc_coredump_loop; + u32 timestamp_update_count; + u32 time_sync_interval; atomic64_t total_io_cnt; atomic64_t high_iops_outstanding; bool msix_load_balance; -- cgit v1.2.3 From aec93e8e238512689885c20c1af6e67747850341 Mon Sep 17 00:00:00 2001 From: Suganath Prabu S Date: Thu, 26 Nov 2020 15:13:05 +0530 Subject: scsi: mpt3sas: Add persistent trigger pages support The user can set trigger values in order to collect the IOC's host trace buffer automatically upon detecting certain conditions. However, the trigger values that the user sets are not persistent across system reboot or reload of the driver. In order to make the user trigger settings persistent, these trigger values need to be saved in the IOC's NVRAM pages: - Driver Persistent Trigger Page 0: This page is used to store list of trigger types that are enabled - Driver Persistent Trigger Page 1: This page stores the list of Master triggers that are enabled - Driver Persistent Trigger Page 2: This page stores the list of MPI Event Triggers that are enabled - Driver Persistent Trigger Page 3: This page stores the list of SCSI Sense Triggers that are enabled - Driver Persistent Trigger Page 4: This page stores the list of IOCStatus-LogInfo Triggers that are enabled. Whenever user configures triggers, the driver persists the values in the corresponding trigger pages. When the driver is subsequently reloaded, the driver reads the values from the trigger pages and configures the triggers accordingly. During firmware upload operation, if the newer firmware supports the trigger page feature, then driver persists the configured diag trigger values to NVRAM. Link: https://lore.kernel.org/r/20201126094311.8686-3-suganath-prabu.subramani@broadcom.com Reported-by: kernel test robot Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 70 ++++++++++++++ drivers/scsi/mpt3sas/mpt3sas_base.h | 5 + drivers/scsi/mpt3sas/mpt3sas_config.c | 134 +++++++++++++++++++++++++++ drivers/scsi/mpt3sas/mpt3sas_trigger_pages.h | 94 +++++++++++++++++++ 4 files changed, 303 insertions(+) create mode 100644 drivers/scsi/mpt3sas/mpt3sas_trigger_pages.h (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 8538c2ddbc68..4ccfcb36da0b 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -975,6 +975,20 @@ _base_sas_ioc_info(struct MPT3SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply, if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) return; + /* + * Older Firmware version doesn't support driver trigger pages. + * So, skip displaying 'config invalid type' type + * of error message. + */ + if (request_hdr->Function == MPI2_FUNCTION_CONFIG) { + Mpi2ConfigRequest_t *rqst = (Mpi2ConfigRequest_t *)request_hdr; + + if ((rqst->ExtPageType == + MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER) && + !(ioc->logging_level & MPT_DEBUG_CONFIG)) { + return; + } + } switch (ioc_status) { @@ -4783,6 +4797,58 @@ _base_update_ioc_page1_inlinewith_perf_mode(struct MPT3SAS_ADAPTER *ioc) } } +/** + * _base_check_for_trigger_pages_support - checks whether HBA FW supports + * driver trigger pages or not + * @ioc : per adapter object + * + * Returns trigger flags mask if HBA FW supports driver trigger pages, + * otherwise returns EFAULT. + */ +static int +_base_check_for_trigger_pages_support(struct MPT3SAS_ADAPTER *ioc) +{ + Mpi26DriverTriggerPage0_t trigger_pg0; + int r = 0; + Mpi2ConfigReply_t mpi_reply; + u16 ioc_status; + + r = mpt3sas_config_get_driver_trigger_pg0(ioc, &mpi_reply, + &trigger_pg0); + if (r) + return -EFAULT; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) + return -EFAULT; + + return le16_to_cpu(trigger_pg0.TriggerFlags); +} + +/** + * _base_get_diag_triggers - Retrieve diag trigger values from + * persistent pages. + * @ioc : per adapter object + * + * Return nothing. + */ +static void +_base_get_diag_triggers(struct MPT3SAS_ADAPTER *ioc) +{ + u16 trigger_flags; + + /* + * Default setting of master trigger. + */ + ioc->diag_trigger_master.MasterData = + (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET); + trigger_flags = _base_check_for_trigger_pages_support(ioc); + if (trigger_flags < 0) + return; + ioc->supports_trigger_pages = 1; +} + /** * _base_static_config_pages - static start of day config pages * @ioc: per adapter object @@ -4869,6 +4935,10 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) ioc->temp_sensors_count = ioc->iounit_pg8.NumSensors; if (ioc->is_aero_ioc) _base_update_ioc_page1_inlinewith_perf_mode(ioc); + if (ioc->is_gen35_ioc) { + if (ioc->is_driver_loading) + _base_get_diag_triggers(ioc); + } } /** diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index cc4815c74f69..83b630852ed3 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -71,6 +71,7 @@ #include "mpt3sas_debug.h" #include "mpt3sas_trigger_diag.h" +#include "mpt3sas_trigger_pages.h" /* driver versioning info */ #define MPT3SAS_DRIVER_NAME "mpt3sas" @@ -1541,6 +1542,7 @@ struct MPT3SAS_ADAPTER { struct SL_WH_EVENT_TRIGGERS_T diag_trigger_event; struct SL_WH_SCSI_TRIGGERS_T diag_trigger_scsi; struct SL_WH_MPI_TRIGGERS_T diag_trigger_mpi; + u8 supports_trigger_pages; void *device_remove_in_progress; u16 device_remove_in_progress_sz; u8 is_gen35_ioc; @@ -1817,6 +1819,9 @@ int mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle, u16 *volume_handle); int mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle, u64 *wwid); +int +mpt3sas_config_get_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page); /* ctl shared API */ extern struct device_attribute *mpt3sas_host_attrs[]; diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c index 4a0ddc7c95e4..2fa60c2e0b8e 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_config.c +++ b/drivers/scsi/mpt3sas/mpt3sas_config.c @@ -1742,6 +1742,140 @@ mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t return r; } +/** + * mpt3sas_config_get_driver_trigger_pg0 - obtain driver trigger page 0 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt3sas_config_get_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = + MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER; + mpi_request.Header.PageNumber = 0; + mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION; + ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + out: + return r; +} + +/** + * mpt3sas_config_set_driver_trigger_pg0 - write driver trigger page 0 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +static int +_config_set_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = + MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER; + mpi_request.Header.PageNumber = 0; + mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION; + ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; + _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + out: + return r; +} + +/** + * mpt3sas_config_update_driver_trigger_pg0 - update driver trigger page 0 + * @ioc: per adapter object + * @trigger_flag: trigger type bit map + * @set: set ot clear trigger values + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +static int +mpt3sas_config_update_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc, + u16 trigger_flag, bool set) +{ + Mpi26DriverTriggerPage0_t tg_pg0; + Mpi2ConfigReply_t mpi_reply; + int rc; + u16 flags, ioc_status; + + rc = mpt3sas_config_get_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0); + if (rc) + return rc; + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dcprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg0, ioc_status(0x%04x)\n", + __func__, ioc_status)); + return -EFAULT; + } + + if (set) + flags = le16_to_cpu(tg_pg0.TriggerFlags) | trigger_flag; + else + flags = le16_to_cpu(tg_pg0.TriggerFlags) & ~trigger_flag; + + tg_pg0.TriggerFlags = cpu_to_le16(flags); + + rc = _config_set_driver_trigger_pg0(ioc, &mpi_reply, &tg_pg0); + if (rc) + return rc; + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dcprintk(ioc, + ioc_err(ioc, + "%s: Failed to update trigger pg0, ioc_status(0x%04x)\n", + __func__, ioc_status)); + return -EFAULT; + } + + return 0; +} + /** * mpt3sas_config_get_volume_handle - returns volume handle for give hidden * raid components diff --git a/drivers/scsi/mpt3sas/mpt3sas_trigger_pages.h b/drivers/scsi/mpt3sas/mpt3sas_trigger_pages.h new file mode 100644 index 000000000000..5f3328f011a2 --- /dev/null +++ b/drivers/scsi/mpt3sas/mpt3sas_trigger_pages.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * This is the Fusion MPT base driver providing common API layer interface + * to store diag trigger values into persistent driver triggers pages + * for MPT (Message Passing Technology) based controllers. + * + * Copyright (C) 2020 Broadcom Inc. + * + * Authors: Broadcom Inc. + * Sreekanth Reddy + * + * Send feedback to : MPT-FusionLinux.pdl@broadcom.com) + */ + +#include "mpi/mpi2_cnfg.h" + +#ifndef MPI2_TRIGGER_PAGES_H +#define MPI2_TRIGGER_PAGES_H + +#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER (0xE0) +#define MPI26_DRIVER_TRIGGER_PAGE0_PAGEVERSION (0x01) +typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_0 { + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U16 TriggerFlags; /* 0x08 */ + U16 Reserved0xA; /* 0x0A */ + U32 Reserved0xC[61]; /* 0x0C */ +} _MPI26_CONFIG_PAGE_DRIVER_TIGGER_0, Mpi26DriverTriggerPage0_t; + +/* Trigger Flags */ +#define MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID (0x0001) +#define MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID (0x0002) +#define MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID (0x0004) +#define MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID (0x0008) + +#define MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION (0x01) +typedef struct _MPI26_DRIVER_MASTER_TIGGER_ENTRY { + U32 MasterTriggerFlags; +} MPI26_DRIVER_MASTER_TIGGER_ENTRY; + +#define MPI26_MAX_MASTER_TRIGGERS (1) +typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_1 { + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U16 NumMasterTrigger; /* 0x08 */ + U16 Reserved0xA; /* 0x0A */ + MPI26_DRIVER_MASTER_TIGGER_ENTRY MasterTriggers[MPI26_MAX_MASTER_TRIGGERS]; /* 0x0C */ +} MPI26_CONFIG_PAGE_DRIVER_TIGGER_1, Mpi26DriverTriggerPage1_t; + +#define MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION (0x01) +typedef struct _MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY { + U16 MPIEventCode; /* 0x00 */ + U16 MPIEventCodeSpecific; /* 0x02 */ +} MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY; + +#define MPI26_MAX_MPI_EVENT_TRIGGERS (20) +typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_2 { + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U16 NumMPIEventTrigger; /* 0x08 */ + U16 Reserved0xA; /* 0x0A */ + MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY MPIEventTriggers[MPI26_MAX_MPI_EVENT_TRIGGERS]; /* 0x0C */ +} MPI26_CONFIG_PAGE_DRIVER_TIGGER_2, Mpi26DriverTriggerPage2_t; + +#define MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION (0x01) +typedef struct _MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY { + U8 ASCQ; /* 0x00 */ + U8 ASC; /* 0x01 */ + U8 SenseKey; /* 0x02 */ + U8 Reserved; /* 0x03 */ +} MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY; + +#define MPI26_MAX_SCSI_SENSE_TRIGGERS (20) +typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_3 { + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U16 NumSCSISenseTrigger; /* 0x08 */ + U16 Reserved0xA; /* 0x0A */ + MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY SCSISenseTriggers[MPI26_MAX_SCSI_SENSE_TRIGGERS]; /* 0x0C */ +} MPI26_CONFIG_PAGE_DRIVER_TIGGER_3, Mpi26DriverTriggerPage3_t; + +#define MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION (0x01) +typedef struct _MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY { + U16 IOCStatus; /* 0x00 */ + U16 Reserved; /* 0x02 */ + U32 LogInfo; /* 0x04 */ +} MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY; + +#define MPI26_MAX_LOGINFO_TRIGGERS (20) +typedef struct _MPI26_CONFIG_PAGE_DRIVER_TIGGER_4 { + MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ + U16 NumIOCStatusLogInfoTrigger; /* 0x08 */ + U16 Reserved0xA; /* 0x0A */ + MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY IOCStatusLoginfoTriggers[MPI26_MAX_LOGINFO_TRIGGERS]; /* 0x0C */ +} MPI26_CONFIG_PAGE_DRIVER_TIGGER_4, Mpi26DriverTriggerPage4_t; + +#endif -- cgit v1.2.3 From bb855f2a5d7eb8f270eb30fda9b2b87cd682212c Mon Sep 17 00:00:00 2001 From: Suganath Prabu S Date: Thu, 26 Nov 2020 15:13:06 +0530 Subject: scsi: mpt3sas: Add persistent Master trigger page Trigger Page 1 is used to store information about Master triggers. Below are the Master trigger conditions: Bit[3] Trigger condition for Device Removal event Bit[2] Trigger condition for TM command issued by driver Bit[1] Trigger condition for Adapter reset issued by driver Bit[0] Trigger condition for IOC Fault state During driver load, if Master trigger type bit is enabled in the Persistent Trigger Page0, then read the Persistent Trigger Page1 and update the IOC instance's diag_trigger_master.MasterData with Persistent Trigger Page1's MasterTriggerFlags. Link: https://lore.kernel.org/r/20201126094311.8686-4-suganath-prabu.subramani@broadcom.com Reported-by: kernel test robot Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 46 +++++++++++ drivers/scsi/mpt3sas/mpt3sas_base.h | 6 ++ drivers/scsi/mpt3sas/mpt3sas_config.c | 151 ++++++++++++++++++++++++++++++++++ 3 files changed, 203 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 4ccfcb36da0b..332d304eefc5 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -4797,6 +4797,42 @@ _base_update_ioc_page1_inlinewith_perf_mode(struct MPT3SAS_ADAPTER *ioc) } } +/** + * _base_get_master_diag_triggers - get master diag trigger values from + * persistent pages + * @ioc : per adapter object + * + * Return nothing. + */ +static void +_base_get_master_diag_triggers(struct MPT3SAS_ADAPTER *ioc) +{ + Mpi26DriverTriggerPage1_t trigger_pg1; + Mpi2ConfigReply_t mpi_reply; + int r; + u16 ioc_status; + + r = mpt3sas_config_get_driver_trigger_pg1(ioc, &mpi_reply, + &trigger_pg1); + if (r) + return; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dinitprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n", + __func__, ioc_status)); + return; + } + + if (le16_to_cpu(trigger_pg1.NumMasterTrigger)) + ioc->diag_trigger_master.MasterData |= + le32_to_cpu( + trigger_pg1.MasterTriggers[0].MasterTriggerFlags); +} + /** * _base_check_for_trigger_pages_support - checks whether HBA FW supports * driver trigger pages or not @@ -4843,10 +4879,20 @@ _base_get_diag_triggers(struct MPT3SAS_ADAPTER *ioc) */ ioc->diag_trigger_master.MasterData = (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET); + trigger_flags = _base_check_for_trigger_pages_support(ioc); if (trigger_flags < 0) return; + ioc->supports_trigger_pages = 1; + + /* + * Retrieve master diag trigger values from driver trigger pg1 + * if master trigger bit enabled in TriggerFlags. + */ + if ((u16)trigger_flags & + MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID) + _base_get_master_diag_triggers(ioc); } /** diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 83b630852ed3..8215b0eb5e3f 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1822,6 +1822,12 @@ int mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, int mpt3sas_config_get_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage0_t *config_page); +int +mpt3sas_config_get_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page); +int +mpt3sas_config_update_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc, + struct SL_WH_MASTER_TRIGGER_T *master_tg, bool set); /* ctl shared API */ extern struct device_attribute *mpt3sas_host_attrs[]; diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c index 2fa60c2e0b8e..9eff6fd3055f 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_config.c +++ b/drivers/scsi/mpt3sas/mpt3sas_config.c @@ -1876,6 +1876,157 @@ mpt3sas_config_update_driver_trigger_pg0(struct MPT3SAS_ADAPTER *ioc, return 0; } +/** + * mpt3sas_config_get_driver_trigger_pg1 - obtain driver trigger page 1 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt3sas_config_get_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = + MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER; + mpi_request.Header.PageNumber = 1; + mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION; + ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + out: + return r; +} + +/** + * mpt3sas_config_set_driver_trigger_pg1 - write driver trigger page 1 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +static int +_config_set_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = + MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER; + mpi_request.Header.PageNumber = 1; + mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE1_PAGEVERSION; + ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; + _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + out: + return r; +} + +/** + * mpt3sas_config_update_driver_trigger_pg1 - update driver trigger page 1 + * @ioc: per adapter object + * @master_tg: Master trigger bit map + * @set: set ot clear trigger values + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt3sas_config_update_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc, + struct SL_WH_MASTER_TRIGGER_T *master_tg, bool set) +{ + Mpi26DriverTriggerPage1_t tg_pg1; + Mpi2ConfigReply_t mpi_reply; + int rc; + u16 ioc_status; + + rc = mpt3sas_config_update_driver_trigger_pg0(ioc, + MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, set); + if (rc) + return rc; + + rc = mpt3sas_config_get_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1); + if (rc) + goto out; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dcprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n", + __func__, ioc_status)); + rc = -EFAULT; + goto out; + } + + if (set) { + tg_pg1.NumMasterTrigger = cpu_to_le16(1); + tg_pg1.MasterTriggers[0].MasterTriggerFlags = cpu_to_le32( + master_tg->MasterData); + } else { + tg_pg1.NumMasterTrigger = 0; + tg_pg1.MasterTriggers[0].MasterTriggerFlags = 0; + } + + rc = _config_set_driver_trigger_pg1(ioc, &mpi_reply, &tg_pg1); + if (rc) + goto out; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dcprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg1, ioc_status(0x%04x)\n", + __func__, ioc_status)); + rc = -EFAULT; + goto out; + } + + return 0; + +out: + mpt3sas_config_update_driver_trigger_pg0(ioc, + MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID, !set); + + return rc; +} + /** * mpt3sas_config_get_volume_handle - returns volume handle for give hidden * raid components -- cgit v1.2.3 From 71b3fb8fe6dd6e8e8c296653e45ed6f1817e6dfc Mon Sep 17 00:00:00 2001 From: Suganath Prabu S Date: Thu, 26 Nov 2020 15:13:07 +0530 Subject: scsi: mpt3sas: Add persistent Event trigger page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trigger Page2 is used to store information about Event triggers: 31 24 23 16 15 8 7 0 Byte ----------------------------------------------- |PageType |PageNumber |Reserved |PageVersion| 0x00 ----------------------------------------------- |Reserved |ExtPageType | ExtPageLength | 0x04 ----------------------------------------------- | Reserved | NumMPIEventTriggers | 0x08 ----------------------------------------------- | MPIEventTriggerEntries | 0x0C | | 0xFC ----------------------------------------------- Number of MPI Event Trigger Entries currently stored in this page. If this is set to zero, there are no valid MPI-Event-Trigger entries available in this page. MPIEventTriggerEntry: - MPIEventCode [15:00] MPI Event code specified in MPI-Spec - MPIEventCodeSpecific [16:31] For Event Code “MPI2_EVENT_LOG_ENTRY_ADDED (0x0021)”, this field specifies the Log-Entry-Qualifier. For all other Event Codes, this field is reserved and not used Maximum of 20-event trigger entries can be stored in this page. Link: https://lore.kernel.org/r/20201126094311.8686-5-suganath-prabu.subramani@broadcom.com Reported-by: kernel test robot Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 60 +++++++++++++ drivers/scsi/mpt3sas/mpt3sas_base.h | 6 ++ drivers/scsi/mpt3sas/mpt3sas_config.c | 160 ++++++++++++++++++++++++++++++++++ 3 files changed, 226 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 332d304eefc5..1fd77aa34eed 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -4797,6 +4797,57 @@ _base_update_ioc_page1_inlinewith_perf_mode(struct MPT3SAS_ADAPTER *ioc) } } +/** + * _base_get_event_diag_triggers - get event diag trigger values from + * persistent pages + * @ioc : per adapter object + * + * Return nothing. + */ +static void +_base_get_event_diag_triggers(struct MPT3SAS_ADAPTER *ioc) +{ + Mpi26DriverTriggerPage2_t trigger_pg2; + struct SL_WH_EVENT_TRIGGER_T *event_tg; + MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY *mpi_event_tg; + Mpi2ConfigReply_t mpi_reply; + int r = 0, i = 0; + u16 count = 0; + u16 ioc_status; + + r = mpt3sas_config_get_driver_trigger_pg2(ioc, &mpi_reply, + &trigger_pg2); + if (r) + return; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dinitprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n", + __func__, ioc_status)); + return; + } + + if (le16_to_cpu(trigger_pg2.NumMPIEventTrigger)) { + count = le16_to_cpu(trigger_pg2.NumMPIEventTrigger); + count = min_t(u16, NUM_VALID_ENTRIES, count); + ioc->diag_trigger_event.ValidEntries = count; + + event_tg = &ioc->diag_trigger_event.EventTriggerEntry[0]; + mpi_event_tg = &trigger_pg2.MPIEventTriggers[0]; + for (i = 0; i < count; i++) { + event_tg->EventValue = le16_to_cpu( + mpi_event_tg->MPIEventCode); + event_tg->LogEntryQualifier = le16_to_cpu( + mpi_event_tg->MPIEventCodeSpecific); + event_tg++; + mpi_event_tg++; + } + } +} + /** * _base_get_master_diag_triggers - get master diag trigger values from * persistent pages @@ -4893,6 +4944,15 @@ _base_get_diag_triggers(struct MPT3SAS_ADAPTER *ioc) if ((u16)trigger_flags & MPI26_DRIVER_TRIGGER0_FLAG_MASTER_TRIGGER_VALID) _base_get_master_diag_triggers(ioc); + + /* + * Retrieve event diag trigger values from driver trigger pg2 + * if event trigger bit enabled in TriggerFlags. + */ + if ((u16)trigger_flags & + MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID) + _base_get_event_diag_triggers(ioc); + } /** diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 8215b0eb5e3f..1d381d7494e4 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1826,8 +1826,14 @@ int mpt3sas_config_get_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage1_t *config_page); int +mpt3sas_config_get_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page); +int mpt3sas_config_update_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc, struct SL_WH_MASTER_TRIGGER_T *master_tg, bool set); +int +mpt3sas_config_update_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc, + struct SL_WH_EVENT_TRIGGERS_T *event_tg, bool set); /* ctl shared API */ extern struct device_attribute *mpt3sas_host_attrs[]; diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c index 9eff6fd3055f..9bad6a8a8893 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_config.c +++ b/drivers/scsi/mpt3sas/mpt3sas_config.c @@ -2027,6 +2027,166 @@ out: return rc; } +/** + * mpt3sas_config_get_driver_trigger_pg2 - obtain driver trigger page 2 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt3sas_config_get_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = + MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER; + mpi_request.Header.PageNumber = 2; + mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION; + ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + out: + return r; +} + +/** + * mpt3sas_config_set_driver_trigger_pg2 - write driver trigger page 2 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +static int +_config_set_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = + MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER; + mpi_request.Header.PageNumber = 2; + mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE2_PAGEVERSION; + ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; + _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + out: + return r; +} + +/** + * mpt3sas_config_update_driver_trigger_pg2 - update driver trigger page 2 + * @ioc: per adapter object + * @event_tg: list of Event Triggers + * @set: set ot clear trigger values + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt3sas_config_update_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc, + struct SL_WH_EVENT_TRIGGERS_T *event_tg, bool set) +{ + Mpi26DriverTriggerPage2_t tg_pg2; + Mpi2ConfigReply_t mpi_reply; + int rc, i, count; + u16 ioc_status; + + rc = mpt3sas_config_update_driver_trigger_pg0(ioc, + MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, set); + if (rc) + return rc; + + rc = mpt3sas_config_get_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2); + if (rc) + goto out; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dcprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n", + __func__, ioc_status)); + rc = -EFAULT; + goto out; + } + + if (set) { + count = event_tg->ValidEntries; + tg_pg2.NumMPIEventTrigger = cpu_to_le16(count); + for (i = 0; i < count; i++) { + tg_pg2.MPIEventTriggers[i].MPIEventCode = + cpu_to_le16( + event_tg->EventTriggerEntry[i].EventValue); + tg_pg2.MPIEventTriggers[i].MPIEventCodeSpecific = + cpu_to_le16( + event_tg->EventTriggerEntry[i].LogEntryQualifier); + } + } else { + tg_pg2.NumMPIEventTrigger = 0; + memset(&tg_pg2.MPIEventTriggers[0], 0, + NUM_VALID_ENTRIES * sizeof( + MPI26_DRIVER_MPI_EVENT_TIGGER_ENTRY)); + } + + rc = _config_set_driver_trigger_pg2(ioc, &mpi_reply, &tg_pg2); + if (rc) + goto out; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dcprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg2, ioc_status(0x%04x)\n", + __func__, ioc_status)); + rc = -EFAULT; + goto out; + } + + return 0; + +out: + mpt3sas_config_update_driver_trigger_pg0(ioc, + MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID, !set); + + return rc; +} + /** * mpt3sas_config_get_volume_handle - returns volume handle for give hidden * raid components -- cgit v1.2.3 From 2a5c3a35c156efc9991dd3b9e46b1cc2653baa63 Mon Sep 17 00:00:00 2001 From: Suganath Prabu S Date: Thu, 26 Nov 2020 15:13:08 +0530 Subject: scsi: mpt3sas: Add persistent SCSI sense trigger page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trigger Page3 is used to store information about SCSI Sense triggers: Persistent Trigger Page-3 ------------------------------------------------------------------ | 31 24 23 16 15 8 7 0| Byte ------------------------------------------------------------------ | PageType | PageNumber | Reserved | PageVersion | 0x00 ------------------------------------------------------------------ | Reserved | ExtPageType | ExtPageLen | 0x04 ------------------------------------------------------------------ | Reserved | NumScsiSense | TriggerEntries | 0x08 ------------------------------------------------------------------ | ScsiSenseTriggerEntry[0] | 0x0C ------------------------------------------------------------------ | … … | ------------------------------------------------------------------ | ScsiSenseTriggerEntry[19] | 0x58 ------------------------------------------------------------------ NumScsiSenseTriggerEntries: This field indicates number of SCSI Sense trigger entries stored in this page. Currently driver is supporting a maximum of 20-SCSI Sense trigger entries. ScsiSenseTriggerEntry: ----------------------------------------------- | 31 24 23 16 15 8 7 0 | ----------------------------------------------- | Reserved | SenseKey | ASC | ASCQ | ----------------------------------------------- ASCQ => Additional Sense Code Qualifier ASC => Additional Sense Code SenseKey => Sense Key values ASCQ => Additional Sense Code Qualifier ASC => Additional Sense Code SenseKey => Sense Key values Link: https://lore.kernel.org/r/20201126094311.8686-6-suganath-prabu.subramani@broadcom.com Reported-by: kernel test robot Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 59 +++++++++++++ drivers/scsi/mpt3sas/mpt3sas_base.h | 6 ++ drivers/scsi/mpt3sas/mpt3sas_config.c | 157 ++++++++++++++++++++++++++++++++++ 3 files changed, 222 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 1fd77aa34eed..8c2ef565e8d7 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -4848,6 +4848,57 @@ _base_get_event_diag_triggers(struct MPT3SAS_ADAPTER *ioc) } } +/** + * _base_get_scsi_diag_triggers - get scsi diag trigger values from + * persistent pages + * @ioc : per adapter object + * + * Return nothing. + */ +static void +_base_get_scsi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) +{ + Mpi26DriverTriggerPage3_t trigger_pg3; + struct SL_WH_SCSI_TRIGGER_T *scsi_tg; + MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY *mpi_scsi_tg; + Mpi2ConfigReply_t mpi_reply; + int r = 0, i = 0; + u16 count = 0; + u16 ioc_status; + + r = mpt3sas_config_get_driver_trigger_pg3(ioc, &mpi_reply, + &trigger_pg3); + if (r) + return; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dinitprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n", + __func__, ioc_status)); + return; + } + + if (le16_to_cpu(trigger_pg3.NumSCSISenseTrigger)) { + count = le16_to_cpu(trigger_pg3.NumSCSISenseTrigger); + count = min_t(u16, NUM_VALID_ENTRIES, count); + ioc->diag_trigger_scsi.ValidEntries = count; + + scsi_tg = &ioc->diag_trigger_scsi.SCSITriggerEntry[0]; + mpi_scsi_tg = &trigger_pg3.SCSISenseTriggers[0]; + for (i = 0; i < count; i++) { + scsi_tg->ASCQ = mpi_scsi_tg->ASCQ; + scsi_tg->ASC = mpi_scsi_tg->ASC; + scsi_tg->SenseKey = mpi_scsi_tg->SenseKey; + + scsi_tg++; + mpi_scsi_tg++; + } + } +} + /** * _base_get_master_diag_triggers - get master diag trigger values from * persistent pages @@ -4953,6 +5004,14 @@ _base_get_diag_triggers(struct MPT3SAS_ADAPTER *ioc) MPI26_DRIVER_TRIGGER0_FLAG_MPI_EVENT_TRIGGER_VALID) _base_get_event_diag_triggers(ioc); + /* + * Retrieve scsi diag trigger values from driver trigger pg3 + * if scsi trigger bit enabled in TriggerFlags. + */ + if ((u16)trigger_flags & + MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID) + _base_get_scsi_diag_triggers(ioc); + } /** diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 1d381d7494e4..ffc04e6c9b26 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1829,11 +1829,17 @@ int mpt3sas_config_get_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage2_t *config_page); int +mpt3sas_config_get_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page); +int mpt3sas_config_update_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc, struct SL_WH_MASTER_TRIGGER_T *master_tg, bool set); int mpt3sas_config_update_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc, struct SL_WH_EVENT_TRIGGERS_T *event_tg, bool set); +int +mpt3sas_config_update_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc, + struct SL_WH_SCSI_TRIGGERS_T *scsi_tg, bool set); /* ctl shared API */ extern struct device_attribute *mpt3sas_host_attrs[]; diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c index 9bad6a8a8893..ae1caba662f3 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_config.c +++ b/drivers/scsi/mpt3sas/mpt3sas_config.c @@ -2187,6 +2187,163 @@ out: return rc; } +/** + * mpt3sas_config_get_driver_trigger_pg3 - obtain driver trigger page 3 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt3sas_config_get_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = + MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER; + mpi_request.Header.PageNumber = 3; + mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION; + ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + out: + return r; +} + +/** + * mpt3sas_config_set_driver_trigger_pg3 - write driver trigger page 3 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +static int +_config_set_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = + MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER; + mpi_request.Header.PageNumber = 3; + mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE3_PAGEVERSION; + ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; + _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + out: + return r; +} + +/** + * mpt3sas_config_update_driver_trigger_pg3 - update driver trigger page 3 + * @ioc: per adapter object + * @scsi_tg: scsi trigger list + * @set: set ot clear trigger values + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt3sas_config_update_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc, + struct SL_WH_SCSI_TRIGGERS_T *scsi_tg, bool set) +{ + Mpi26DriverTriggerPage3_t tg_pg3; + Mpi2ConfigReply_t mpi_reply; + int rc, i, count; + u16 ioc_status; + + rc = mpt3sas_config_update_driver_trigger_pg0(ioc, + MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, set); + if (rc) + return rc; + + rc = mpt3sas_config_get_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3); + if (rc) + goto out; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dcprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n", + __func__, ioc_status)); + return -EFAULT; + } + + if (set) { + count = scsi_tg->ValidEntries; + tg_pg3.NumSCSISenseTrigger = cpu_to_le16(count); + for (i = 0; i < count; i++) { + tg_pg3.SCSISenseTriggers[i].ASCQ = + scsi_tg->SCSITriggerEntry[i].ASCQ; + tg_pg3.SCSISenseTriggers[i].ASC = + scsi_tg->SCSITriggerEntry[i].ASC; + tg_pg3.SCSISenseTriggers[i].SenseKey = + scsi_tg->SCSITriggerEntry[i].SenseKey; + } + } else { + tg_pg3.NumSCSISenseTrigger = 0; + memset(&tg_pg3.SCSISenseTriggers[0], 0, + NUM_VALID_ENTRIES * sizeof( + MPI26_DRIVER_SCSI_SENSE_TIGGER_ENTRY)); + } + + rc = _config_set_driver_trigger_pg3(ioc, &mpi_reply, &tg_pg3); + if (rc) + goto out; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dcprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg3, ioc_status(0x%04x)\n", + __func__, ioc_status)); + return -EFAULT; + } + + return 0; +out: + mpt3sas_config_update_driver_trigger_pg0(ioc, + MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID, !set); + + return rc; +} + /** * mpt3sas_config_get_volume_handle - returns volume handle for give hidden * raid components -- cgit v1.2.3 From 0e17a87c5950b91aa5ed11ba569b46dea13b1e0d Mon Sep 17 00:00:00 2001 From: Suganath Prabu S Date: Thu, 26 Nov 2020 15:13:09 +0530 Subject: scsi: mpt3sas: Add persistent MPI trigger page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This page is used to store information about MPI (IOC Status & LogInfo) triggers. Driver Persistent Trigger Page-4 format: ------------------------------------------------------- | 31 24 23 16 15 8 7 0| Byte ------------------------------------------------------- | PageType | PageNumber | Reserved | PageVersion | 0x00 -------------------------------------------------------- | Reserved | ExtPageType | ExtPageLength | 0x04 -------------------------------------------------------- | Reserved | NumMpiTriggerEntries | 0x08 -------------------------------------------------------- | MPITriggerEntry[0] | 0x0C -------------------------------------------------------- | … | -------------------------------------------------------- | MPITriggerEntry[19] | 0xA4 -------------------------------------------------------- NumMpiTriggerEntries: This field indicates number of MPI (IOC Status & LogInfo) trigger entries stored in this page. Currently driver is supporting a maximum of 20-MPI trigger entries. MPITriggerEntry: ----------------------------------------------------- | 31 16 15 0 | ----------------------------------------------------- | Reserved | IOCStatus | ----------------------------------------------------- | IOCLogInfo | ----------------------------------------------------- IOCStatus => Status value from the IOC IOCLogInfo => Specific value that supplements the IOCStatus. Link: https://lore.kernel.org/r/20201126094311.8686-7-suganath-prabu.subramani@broadcom.com Reported-by: kernel test robot Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 61 ++++++++++++- drivers/scsi/mpt3sas/mpt3sas_base.h | 6 ++ drivers/scsi/mpt3sas/mpt3sas_config.c | 158 ++++++++++++++++++++++++++++++++++ 3 files changed, 224 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 8c2ef565e8d7..ce3ef9e2d6d1 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -4899,6 +4899,59 @@ _base_get_scsi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) } } +/** + * _base_get_mpi_diag_triggers - get mpi diag trigger values from + * persistent pages + * @ioc : per adapter object + * + * Return nothing. + */ +static void +_base_get_mpi_diag_triggers(struct MPT3SAS_ADAPTER *ioc) +{ + Mpi26DriverTriggerPage4_t trigger_pg4; + struct SL_WH_MPI_TRIGGER_T *status_tg; + MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY *mpi_status_tg; + Mpi2ConfigReply_t mpi_reply; + int r = 0, i = 0; + u16 count = 0; + u16 ioc_status; + + r = mpt3sas_config_get_driver_trigger_pg4(ioc, &mpi_reply, + &trigger_pg4); + if (r) + return; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dinitprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n", + __func__, ioc_status)); + return; + } + + if (le16_to_cpu(trigger_pg4.NumIOCStatusLogInfoTrigger)) { + count = le16_to_cpu(trigger_pg4.NumIOCStatusLogInfoTrigger); + count = min_t(u16, NUM_VALID_ENTRIES, count); + ioc->diag_trigger_mpi.ValidEntries = count; + + status_tg = &ioc->diag_trigger_mpi.MPITriggerEntry[0]; + mpi_status_tg = &trigger_pg4.IOCStatusLoginfoTriggers[0]; + + for (i = 0; i < count; i++) { + status_tg->IOCStatus = le16_to_cpu( + mpi_status_tg->IOCStatus); + status_tg->IocLogInfo = le32_to_cpu( + mpi_status_tg->LogInfo); + + status_tg++; + mpi_status_tg++; + } + } +} + /** * _base_get_master_diag_triggers - get master diag trigger values from * persistent pages @@ -5011,7 +5064,13 @@ _base_get_diag_triggers(struct MPT3SAS_ADAPTER *ioc) if ((u16)trigger_flags & MPI26_DRIVER_TRIGGER0_FLAG_SCSI_SENSE_TRIGGER_VALID) _base_get_scsi_diag_triggers(ioc); - + /* + * Retrieve mpi error diag trigger values from driver trigger pg4 + * if loginfo trigger bit enabled in TriggerFlags. + */ + if ((u16)trigger_flags & + MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID) + _base_get_mpi_diag_triggers(ioc); } /** diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index ffc04e6c9b26..352e6cd21388 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1832,6 +1832,9 @@ int mpt3sas_config_get_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage3_t *config_page); int +mpt3sas_config_get_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page); +int mpt3sas_config_update_driver_trigger_pg1(struct MPT3SAS_ADAPTER *ioc, struct SL_WH_MASTER_TRIGGER_T *master_tg, bool set); int @@ -1840,6 +1843,9 @@ mpt3sas_config_update_driver_trigger_pg2(struct MPT3SAS_ADAPTER *ioc, int mpt3sas_config_update_driver_trigger_pg3(struct MPT3SAS_ADAPTER *ioc, struct SL_WH_SCSI_TRIGGERS_T *scsi_tg, bool set); +int +mpt3sas_config_update_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc, + struct SL_WH_MPI_TRIGGERS_T *mpi_tg, bool set); /* ctl shared API */ extern struct device_attribute *mpt3sas_host_attrs[]; diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c index ae1caba662f3..8238843523b5 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_config.c +++ b/drivers/scsi/mpt3sas/mpt3sas_config.c @@ -2344,6 +2344,164 @@ out: return rc; } +/** + * mpt3sas_config_get_driver_trigger_pg4 - obtain driver trigger page 4 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt3sas_config_get_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = + MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER; + mpi_request.Header.PageNumber = 4; + mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION; + ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + out: + return r; +} + +/** + * mpt3sas_config_set_driver_trigger_pg4 - write driver trigger page 4 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +static int +_config_set_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26DriverTriggerPage4_t *config_page) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = + MPI2_CONFIG_EXTPAGETYPE_DRIVER_PERSISTENT_TRIGGER; + mpi_request.Header.PageNumber = 4; + mpi_request.Header.PageVersion = MPI26_DRIVER_TRIGGER_PAGE4_PAGEVERSION; + ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); + if (r) + goto out; + + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; + _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, + sizeof(*config_page)); + out: + return r; +} + +/** + * mpt3sas_config_update_driver_trigger_pg4 - update driver trigger page 4 + * @ioc: per adapter object + * @mpi_tg: mpi trigger list + * @set: set ot clear trigger values + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt3sas_config_update_driver_trigger_pg4(struct MPT3SAS_ADAPTER *ioc, + struct SL_WH_MPI_TRIGGERS_T *mpi_tg, bool set) +{ + Mpi26DriverTriggerPage4_t tg_pg4; + Mpi2ConfigReply_t mpi_reply; + int rc, i, count; + u16 ioc_status; + + rc = mpt3sas_config_update_driver_trigger_pg0(ioc, + MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, set); + if (rc) + return rc; + + rc = mpt3sas_config_get_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4); + if (rc) + goto out; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dcprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n", + __func__, ioc_status)); + rc = -EFAULT; + goto out; + } + + if (set) { + count = mpi_tg->ValidEntries; + tg_pg4.NumIOCStatusLogInfoTrigger = cpu_to_le16(count); + for (i = 0; i < count; i++) { + tg_pg4.IOCStatusLoginfoTriggers[i].IOCStatus = + cpu_to_le16(mpi_tg->MPITriggerEntry[i].IOCStatus); + tg_pg4.IOCStatusLoginfoTriggers[i].LogInfo = + cpu_to_le32(mpi_tg->MPITriggerEntry[i].IocLogInfo); + } + } else { + tg_pg4.NumIOCStatusLogInfoTrigger = 0; + memset(&tg_pg4.IOCStatusLoginfoTriggers[0], 0, + NUM_VALID_ENTRIES * sizeof( + MPI26_DRIVER_IOCSTATUS_LOGINFO_TIGGER_ENTRY)); + } + + rc = _config_set_driver_trigger_pg4(ioc, &mpi_reply, &tg_pg4); + if (rc) + goto out; + + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + dcprintk(ioc, + ioc_err(ioc, + "%s: Failed to get trigger pg4, ioc_status(0x%04x)\n", + __func__, ioc_status)); + rc = -EFAULT; + goto out; + } + + return 0; + +out: + mpt3sas_config_update_driver_trigger_pg0(ioc, + MPI26_DRIVER_TRIGGER0_FLAG_LOGINFO_TRIGGER_VALID, !set); + + return rc; +} + /** * mpt3sas_config_get_volume_handle - returns volume handle for give hidden * raid components -- cgit v1.2.3 From 9b271c69128b46e2735df732819c5a5b1f4252af Mon Sep 17 00:00:00 2001 From: Suganath Prabu S Date: Thu, 26 Nov 2020 15:13:10 +0530 Subject: scsi: mpt3sas: Handle trigger page after firmware update If a firmware update adds support for the trigger pages, then the driver should handle this by writing the existing trigger data from the driver's internal data structure to the corresponding trigger pages in NVRAM. Also handle the case where the trigger page capability is no longer present after a firmware downgrade. Link: https://lore.kernel.org/r/20201126094311.8686-8-suganath-prabu.subramani@broadcom.com Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.c | 50 ++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index ce3ef9e2d6d1..b129f3734ed0 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -5073,6 +5073,35 @@ _base_get_diag_triggers(struct MPT3SAS_ADAPTER *ioc) _base_get_mpi_diag_triggers(ioc); } +/** + * _base_update_diag_trigger_pages - Update the driver trigger pages after + * online FW update, incase updated FW supports driver + * trigger pages. + * @ioc : per adapter object + * + * Return nothing. + */ +static void +_base_update_diag_trigger_pages(struct MPT3SAS_ADAPTER *ioc) +{ + + if (ioc->diag_trigger_master.MasterData) + mpt3sas_config_update_driver_trigger_pg1(ioc, + &ioc->diag_trigger_master, 1); + + if (ioc->diag_trigger_event.ValidEntries) + mpt3sas_config_update_driver_trigger_pg2(ioc, + &ioc->diag_trigger_event, 1); + + if (ioc->diag_trigger_scsi.ValidEntries) + mpt3sas_config_update_driver_trigger_pg3(ioc, + &ioc->diag_trigger_scsi, 1); + + if (ioc->diag_trigger_mpi.ValidEntries) + mpt3sas_config_update_driver_trigger_pg4(ioc, + &ioc->diag_trigger_mpi, 1); +} + /** * _base_static_config_pages - static start of day config pages * @ioc: per adapter object @@ -5082,7 +5111,7 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) { Mpi2ConfigReply_t mpi_reply; u32 iounit_pg1_flags; - + int tg_flags = 0; ioc->nvme_abort_timeout = 30; mpt3sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0); if (ioc->ir_firmware) @@ -5162,6 +5191,25 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) if (ioc->is_gen35_ioc) { if (ioc->is_driver_loading) _base_get_diag_triggers(ioc); + else { + /* + * In case of online HBA FW update operation, + * check whether updated FW supports the driver trigger + * pages or not. + * - If previous FW has not supported driver trigger + * pages and newer FW supports them then update these + * pages with current diag trigger values. + * - If previous FW has supported driver trigger pages + * and new FW doesn't support them then disable + * support_trigger_pages flag. + */ + tg_flags = _base_check_for_trigger_pages_support(ioc); + if (!ioc->supports_trigger_pages && tg_flags != -EFAULT) + _base_update_diag_trigger_pages(ioc); + else if (ioc->supports_trigger_pages && + tg_flags == -EFAULT) + ioc->supports_trigger_pages = 0; + } } } -- cgit v1.2.3 From be1b500212541a70006887bae558ff834d7365d0 Mon Sep 17 00:00:00 2001 From: Suganath Prabu S Date: Thu, 26 Nov 2020 15:13:11 +0530 Subject: scsi: mpt3sas: Update driver version to 36.100.00.00 Update driver version to 36.100.00.00 Link: https://lore.kernel.org/r/20201126094311.8686-9-suganath-prabu.subramani@broadcom.com Signed-off-by: Suganath Prabu S Signed-off-by: Martin K. Petersen --- drivers/scsi/mpt3sas/mpt3sas_base.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 352e6cd21388..2def7a340616 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -77,9 +77,9 @@ #define MPT3SAS_DRIVER_NAME "mpt3sas" #define MPT3SAS_AUTHOR "Avago Technologies " #define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" -#define MPT3SAS_DRIVER_VERSION "35.101.00.00" -#define MPT3SAS_MAJOR_VERSION 35 -#define MPT3SAS_MINOR_VERSION 101 +#define MPT3SAS_DRIVER_VERSION "36.100.00.00" +#define MPT3SAS_MAJOR_VERSION 36 +#define MPT3SAS_MINOR_VERSION 100 #define MPT3SAS_BUILD_VERSION 0 #define MPT3SAS_RELEASE_VERSION 00 -- cgit v1.2.3