Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlaf Hering <ohering@suse.de>2019-10-01 11:09:31 +0200
committerOlaf Hering <ohering@suse.de>2019-10-01 11:09:31 +0200
commita902f2496bca36810eba2ad1be0ae0e1299970f0 (patch)
tree17dadc6968538177d27cb7d803f356d3388aab19
parentdc6001f5d87b47c2017b6e03aba547e0cae9a9fa (diff)
parentd6bc21fe5c71ddc763cde18c2231cf611af25cfe (diff)
Merge remote-tracking branch 'kerncvs/SLE12-SP4' into SLE12-SP4-AZURE
-rw-r--r--arch/x86/include/asm/fpu/types.h3
-rw-r--r--arch/x86/kernel/fpu/xstate.c36
-rw-r--r--arch/x86/kernel/tls.c9
-rw-r--r--drivers/edac/amd64_edac.c14
-rw-r--r--drivers/net/bonding/bond_main.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c97
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c3
-rw-r--r--drivers/net/team/team.c4
-rw-r--r--drivers/net/xen-netback/netback.c2
-rw-r--r--drivers/nvme/host/fc.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c10
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c447
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c110
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.h11
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c193
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.h10
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h440
-rw-r--r--drivers/scsi/qla2xxx/qla_dfs.c59
-rw-r--r--drivers/scsi/qla2xxx/qla_dsd.h32
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h106
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h146
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c470
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c2168
-rw-r--r--drivers/scsi/qla2xxx/qla_inline.h99
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c952
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c197
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c452
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c13
-rw-r--r--drivers/scsi/qla2xxx/qla_mr.c178
-rw-r--r--drivers/scsi/qla2xxx/qla_mr.h11
-rw-r--r--drivers/scsi/qla2xxx/qla_nvme.c342
-rw-r--r--drivers/scsi/qla2xxx/qla_nvme.h23
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.c60
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.h16
-rw-r--r--drivers/scsi/qla2xxx/qla_nx2.c15
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c1041
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c979
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c425
-rw-r--r--drivers/scsi/qla2xxx/qla_target.h70
-rw-r--r--drivers/scsi/qla2xxx/qla_tmpl.c651
-rw-r--r--drivers/scsi/qla2xxx/qla_tmpl.h80
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h4
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c129
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.h3
-rw-r--r--drivers/scsi/scsi_transport_fc.c3
-rw-r--r--include/linux/nvme-fc-driver.h8
-rw-r--r--include/scsi/scsi_transport_fc.h3
-rw-r--r--kernel/livepatch/core.c1
-rw-r--r--net/core/stream.c16
-rw-r--r--net/ipv6/addrconf.c3
-rw-r--r--net/packet/af_packet.c7
-rw-r--r--net/sctp/sm_sideeffect.c2
-rw-r--r--net/smc/smc_tx.c6
-rw-r--r--virt/kvm/coalesced_mmio.c17
54 files changed, 5739 insertions, 4445 deletions
diff --git a/arch/x86/include/asm/fpu/types.h b/arch/x86/include/asm/fpu/types.h
index 3c80f5b9c09d..7027dc882fe1 100644
--- a/arch/x86/include/asm/fpu/types.h
+++ b/arch/x86/include/asm/fpu/types.h
@@ -68,6 +68,9 @@ struct fxregs_state {
/* Default value for fxregs_state.mxcsr: */
#define MXCSR_DEFAULT 0x1f80
+/* Copy both mxcsr & mxcsr_flags with a single u64 memcpy: */
+#define MXCSR_AND_FLAGS_SIZE sizeof(u64)
+
/*
* Software based FPU emulation state. This is arbitrary really,
* it matches the x87 format to make it easier to understand:
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index fd6882c42246..da41179dd0cd 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -924,6 +924,23 @@ int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
#endif /* ! CONFIG_ARCH_HAS_PKEYS */
/*
+ * Weird legacy quirk: SSE and YMM states store information in the
+ * MXCSR and MXCSR_FLAGS fields of the FP area. That means if the FP
+ * area is marked as unused in the xfeatures header, we need to copy
+ * MXCSR and MXCSR_FLAGS if either SSE or YMM are in use.
+ */
+static inline bool xfeatures_mxcsr_quirk(u64 xfeatures)
+{
+ if (!(xfeatures & (XFEATURE_MASK_SSE|XFEATURE_MASK_YMM)))
+ return 0;
+
+ if (xfeatures & XFEATURE_MASK_FP)
+ return 0;
+
+ return 1;
+}
+
+/*
* This is similar to user_regset_copyout(), but will not add offset to
* the source data pointer or increment pos, count, kbuf, and ubuf.
*/
@@ -1003,7 +1020,15 @@ int copyout_from_xsaves(unsigned int pos, unsigned int count, void *kbuf,
if (offset + size >= count)
break;
}
+ }
+ if (xfeatures_mxcsr_quirk(header.xfeatures)) {
+ offset = offsetof(struct fxregs_state, mxcsr);
+ size = MXCSR_AND_FLAGS_SIZE;
+
+ ret = xstate_copyout(offset, size, kbuf, ubuf, &xsave->i387.mxcsr, 0, count);
+ if (ret)
+ return ret;
}
/*
@@ -1070,6 +1095,17 @@ int copyin_to_xsaves(const void *kbuf, const void __user *ubuf,
}
}
+ if (xfeatures_mxcsr_quirk(xfeatures)) {
+ offset = offsetof(struct fxregs_state, mxcsr);
+ size = MXCSR_AND_FLAGS_SIZE;
+
+ if (kbuf)
+ memcpy(&xsave->i387.mxcsr, kbuf + offset, size);
+ else
+ if (__copy_from_user(&xsave->i387.mxcsr, ubuf + offset, size))
+ return -EFAULT;
+ }
+
/*
* The state that came in from userspace was user-state only.
* Mask all the user states out of 'xfeatures':
diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c
index 6c8934406dc9..2a627dfb08a7 100644
--- a/arch/x86/kernel/tls.c
+++ b/arch/x86/kernel/tls.c
@@ -4,6 +4,7 @@
#include <linux/user.h>
#include <linux/regset.h>
#include <linux/syscalls.h>
+#include <linux/nospec.h>
#include <linux/uaccess.h>
#include <asm/desc.h>
@@ -219,6 +220,7 @@ int do_get_thread_area(struct task_struct *p, int idx,
struct user_desc __user *u_info)
{
struct user_desc info;
+ int index;
if (idx == -1 && get_user(idx, &u_info->entry_number))
return -EFAULT;
@@ -226,8 +228,11 @@ int do_get_thread_area(struct task_struct *p, int idx,
if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
return -EINVAL;
- fill_user_desc(&info, idx,
- &p->thread.tls_array[idx - GDT_ENTRY_TLS_MIN]);
+ index = idx - GDT_ENTRY_TLS_MIN;
+ index = array_index_nospec(index,
+ GDT_ENTRY_TLS_MAX - GDT_ENTRY_TLS_MIN + 1);
+
+ fill_user_desc(&info, idx, &p->thread.tls_array[index]);
if (copy_to_user(u_info, &info, sizeof(info)))
return -EFAULT;
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 26b6065c7950..9914336908f9 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -2512,13 +2512,6 @@ static void decode_umc_error(int node_id, struct mce *m)
goto log_error;
}
- if (umc_normaddr_to_sysaddr(m->addr, pvt->mc_node_id, err.channel, &sys_addr)) {
- err.err_code = ERR_NORM_ADDR;
- goto log_error;
- }
-
- error_address_to_page_and_offset(sys_addr, &err);
-
if (!(m->status & MCI_STATUS_SYNDV)) {
err.err_code = ERR_SYND;
goto log_error;
@@ -2535,6 +2528,13 @@ static void decode_umc_error(int node_id, struct mce *m)
err.csrow = m->synd & 0x7;
+ if (umc_normaddr_to_sysaddr(m->addr, pvt->mc_node_id, err.channel, &sys_addr)) {
+ err.err_code = ERR_NORM_ADDR;
+ goto log_error;
+ }
+
+ error_address_to_page_and_offset(sys_addr, &err);
+
log_error:
__log_ecc_error(mci, &err, ecc_type);
}
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index ae92f914fde7..d2480135d4d5 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1108,7 +1108,9 @@ static void bond_compute_features(struct bonding *bond)
done:
bond_dev->vlan_features = vlan_features;
- bond_dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL;
+ bond_dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
+ NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_STAG_TX;
bond_dev->gso_max_segs = gso_max_segs;
netif_set_gso_max_size(bond_dev, gso_max_size);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
index e87923e046c9..c567cff499d1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
@@ -439,12 +439,6 @@ arfs_hash_bucket(struct arfs_table *arfs_t, __be16 src_port,
return &arfs_t->rules_hash[bucket_idx];
}
-static u8 arfs_get_ip_proto(const struct sk_buff *skb)
-{
- return (skb->protocol == htons(ETH_P_IP)) ?
- ip_hdr(skb)->protocol : ipv6_hdr(skb)->nexthdr;
-}
-
static struct arfs_table *arfs_get_table(struct mlx5e_arfs_tables *arfs,
u8 ip_proto, __be16 etype)
{
@@ -601,31 +595,9 @@ out:
arfs_may_expire_flow(priv);
}
-/* return L4 destination port from ip4/6 packets */
-static __be16 arfs_get_dst_port(const struct sk_buff *skb)
-{
- char *transport_header;
-
- transport_header = skb_transport_header(skb);
- if (arfs_get_ip_proto(skb) == IPPROTO_TCP)
- return ((struct tcphdr *)transport_header)->dest;
- return ((struct udphdr *)transport_header)->dest;
-}
-
-/* return L4 source port from ip4/6 packets */
-static __be16 arfs_get_src_port(const struct sk_buff *skb)
-{
- char *transport_header;
-
- transport_header = skb_transport_header(skb);
- if (arfs_get_ip_proto(skb) == IPPROTO_TCP)
- return ((struct tcphdr *)transport_header)->source;
- return ((struct udphdr *)transport_header)->source;
-}
-
static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
struct arfs_table *arfs_t,
- const struct sk_buff *skb,
+ const struct flow_keys *fk,
u16 rxq, u32 flow_id)
{
struct arfs_rule *rule;
@@ -640,19 +612,19 @@ static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
INIT_WORK(&rule->arfs_work, arfs_handle_work);
tuple = &rule->tuple;
- tuple->etype = skb->protocol;
+ tuple->etype = fk->basic.n_proto;
+ tuple->ip_proto = fk->basic.ip_proto;
if (tuple->etype == htons(ETH_P_IP)) {
- tuple->src_ipv4 = ip_hdr(skb)->saddr;
- tuple->dst_ipv4 = ip_hdr(skb)->daddr;
+ tuple->src_ipv4 = fk->addrs.v4addrs.src;
+ tuple->dst_ipv4 = fk->addrs.v4addrs.dst;
} else {
- memcpy(&tuple->src_ipv6, &ipv6_hdr(skb)->saddr,
+ memcpy(&tuple->src_ipv6, &fk->addrs.v6addrs.src,
sizeof(struct in6_addr));
- memcpy(&tuple->dst_ipv6, &ipv6_hdr(skb)->daddr,
+ memcpy(&tuple->dst_ipv6, &fk->addrs.v6addrs.dst,
sizeof(struct in6_addr));
}
- tuple->ip_proto = arfs_get_ip_proto(skb);
- tuple->src_port = arfs_get_src_port(skb);
- tuple->dst_port = arfs_get_dst_port(skb);
+ tuple->src_port = fk->ports.src;
+ tuple->dst_port = fk->ports.dst;
rule->flow_id = flow_id;
rule->filter_id = priv->fs.arfs.last_filter_id++ % RPS_NO_FILTER;
@@ -663,37 +635,33 @@ static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
return rule;
}
-static bool arfs_cmp_ips(struct arfs_tuple *tuple,
- const struct sk_buff *skb)
+static bool arfs_cmp(const struct arfs_tuple *tuple, const struct flow_keys *fk)
{
- if (tuple->etype == htons(ETH_P_IP) &&
- tuple->src_ipv4 == ip_hdr(skb)->saddr &&
- tuple->dst_ipv4 == ip_hdr(skb)->daddr)
- return true;
- if (tuple->etype == htons(ETH_P_IPV6) &&
- (!memcmp(&tuple->src_ipv6, &ipv6_hdr(skb)->saddr,
- sizeof(struct in6_addr))) &&
- (!memcmp(&tuple->dst_ipv6, &ipv6_hdr(skb)->daddr,
- sizeof(struct in6_addr))))
- return true;
+ if (tuple->src_port != fk->ports.src || tuple->dst_port != fk->ports.dst)
+ return false;
+ if (tuple->etype != fk->basic.n_proto)
+ return false;
+ if (tuple->etype == htons(ETH_P_IP))
+ return tuple->src_ipv4 == fk->addrs.v4addrs.src &&
+ tuple->dst_ipv4 == fk->addrs.v4addrs.dst;
+ if (tuple->etype == htons(ETH_P_IPV6))
+ return !memcmp(&tuple->src_ipv6, &fk->addrs.v6addrs.src,
+ sizeof(struct in6_addr)) &&
+ !memcmp(&tuple->dst_ipv6, &fk->addrs.v6addrs.dst,
+ sizeof(struct in6_addr));
return false;
}
static struct arfs_rule *arfs_find_rule(struct arfs_table *arfs_t,
- const struct sk_buff *skb)
+ const struct flow_keys *fk)
{
struct arfs_rule *arfs_rule;
struct hlist_head *head;
- __be16 src_port = arfs_get_src_port(skb);
- __be16 dst_port = arfs_get_dst_port(skb);
- head = arfs_hash_bucket(arfs_t, src_port, dst_port);
+ head = arfs_hash_bucket(arfs_t, fk->ports.src, fk->ports.dst);
hlist_for_each_entry(arfs_rule, head, hlist) {
- if (arfs_rule->tuple.src_port == src_port &&
- arfs_rule->tuple.dst_port == dst_port &&
- arfs_cmp_ips(&arfs_rule->tuple, skb)) {
+ if (arfs_cmp(&arfs_rule->tuple, fk))
return arfs_rule;
- }
}
return NULL;
@@ -706,20 +674,24 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
struct mlx5e_arfs_tables *arfs = &priv->fs.arfs;
struct arfs_table *arfs_t;
struct arfs_rule *arfs_rule;
+ struct flow_keys fk;
+
+ if (!skb_flow_dissect_flow_keys(skb, &fk, 0))
+ return -EPROTONOSUPPORT;
- if (skb->protocol != htons(ETH_P_IP) &&
- skb->protocol != htons(ETH_P_IPV6))
+ if (fk.basic.n_proto != htons(ETH_P_IP) &&
+ fk.basic.n_proto != htons(ETH_P_IPV6))
return -EPROTONOSUPPORT;
if (skb->encapsulation)
return -EPROTONOSUPPORT;
- arfs_t = arfs_get_table(arfs, arfs_get_ip_proto(skb), skb->protocol);
+ arfs_t = arfs_get_table(arfs, fk.basic.ip_proto, fk.basic.n_proto);
if (!arfs_t)
return -EPROTONOSUPPORT;
spin_lock_bh(&arfs->arfs_lock);
- arfs_rule = arfs_find_rule(arfs_t, skb);
+ arfs_rule = arfs_find_rule(arfs_t, &fk);
if (arfs_rule) {
if (arfs_rule->rxq == rxq_index) {
spin_unlock_bh(&arfs->arfs_lock);
@@ -727,8 +699,7 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
}
arfs_rule->rxq = rxq_index;
} else {
- arfs_rule = arfs_alloc_rule(priv, arfs_t, skb,
- rxq_index, flow_id);
+ arfs_rule = arfs_alloc_rule(priv, arfs_t, &fk, rxq_index, flow_id);
if (!arfs_rule) {
spin_unlock_bh(&arfs->arfs_lock);
return -ENOMEM;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 90ac9a9fa28e..395d13d175cb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -1399,6 +1399,9 @@ static int mlx5e_set_pauseparam(struct net_device *netdev,
struct mlx5_core_dev *mdev = priv->mdev;
int err;
+ if (!MLX5_CAP_GEN(mdev, vport_group_manager))
+ return -EOPNOTSUPP;
+
if (pauseparam->autoneg)
return -EINVAL;
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index f8169fb7416e..e1a43169ca5b 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1014,7 +1014,9 @@ static void __team_compute_features(struct team *team)
}
team->dev->vlan_features = vlan_features;
- team->dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL;
+ team->dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
+ NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_STAG_TX;
team->dev->hard_header_len = max_hard_header_len;
team->dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index d09dea77c287..a871aa6418d0 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -927,6 +927,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
skb_shinfo(skb)->nr_frags = MAX_SKB_FRAGS;
nskb = xenvif_alloc_skb(0);
if (unlikely(nskb == NULL)) {
+ skb_shinfo(skb)->nr_frags = 0;
kfree_skb(skb);
xenvif_tx_err(queue, &txreq, extra_count, idx);
if (net_ratelimit())
@@ -942,6 +943,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
if (xenvif_set_skb_gso(queue->vif, skb, gso)) {
/* Failure in xenvif_set_skb_gso is fatal. */
+ skb_shinfo(skb)->nr_frags = 0;
kfree_skb(skb);
kfree_skb(nskb);
break;
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index 683b56bf77f3..cec823e72087 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -25,7 +25,9 @@
#include "fabrics.h"
#include <linux/nvme-fc-driver.h>
#include <linux/nvme-fc.h>
-
+#ifndef __GENKSYMS__
+#include <scsi/scsi_transport_fc.h>
+#endif
/* *************************** Data Structures/Defines ****************** */
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index a426f1ede107..2593f1224a65 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -4152,9 +4152,15 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
rdata->pnode = lpfc_nlp_get(ndlp);
if (ndlp->nlp_type & NLP_FCP_TARGET)
- rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
+ rport_ids.roles |= FC_PORT_ROLE_FCP_TARGET;
if (ndlp->nlp_type & NLP_FCP_INITIATOR)
- rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+ rport_ids.roles |= FC_PORT_ROLE_FCP_INITIATOR;
+ if (ndlp->nlp_type & NLP_NVME_INITIATOR)
+ rport_ids.roles |= FC_PORT_ROLE_NVME_INITIATOR;
+ if (ndlp->nlp_type & NLP_NVME_TARGET)
+ rport_ids.roles |= FC_PORT_ROLE_NVME_TARGET;
+ if (ndlp->nlp_type & NLP_NVME_DISCOVERY)
+ rport_ids.roles |= FC_PORT_ROLE_NVME_DISCOVERY;
if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN)
fc_remote_port_rolechg(rport, rport_ids.roles);
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 495999d2d73c..8f58ff57bf37 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -29,24 +29,27 @@ qla2x00_sysfs_read_fw_dump(struct file *filp, struct kobject *kobj,
if (!(ha->fw_dump_reading || ha->mctp_dump_reading))
return 0;
+ mutex_lock(&ha->optrom_mutex);
if (IS_P3P_TYPE(ha)) {
if (off < ha->md_template_size) {
rval = memory_read_from_buffer(buf, count,
&off, ha->md_tmplt_hdr, ha->md_template_size);
- return rval;
+ } else {
+ off -= ha->md_template_size;
+ rval = memory_read_from_buffer(buf, count,
+ &off, ha->md_dump, ha->md_dump_size);
}
- off -= ha->md_template_size;
- rval = memory_read_from_buffer(buf, count,
- &off, ha->md_dump, ha->md_dump_size);
- return rval;
- } else if (ha->mctp_dumped && ha->mctp_dump_reading)
- return memory_read_from_buffer(buf, count, &off, ha->mctp_dump,
+ } else if (ha->mctp_dumped && ha->mctp_dump_reading) {
+ rval = memory_read_from_buffer(buf, count, &off, ha->mctp_dump,
MCTP_DUMP_SIZE);
- else if (ha->fw_dump_reading)
- return memory_read_from_buffer(buf, count, &off, ha->fw_dump,
+ } else if (ha->fw_dump_reading) {
+ rval = memory_read_from_buffer(buf, count, &off, ha->fw_dump,
ha->fw_dump_len);
- else
- return 0;
+ } else {
+ rval = 0;
+ }
+ mutex_unlock(&ha->optrom_mutex);
+ return rval;
}
static ssize_t
@@ -154,6 +157,8 @@ qla2x00_sysfs_read_nvram(struct file *filp, struct kobject *kobj,
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
struct qla_hw_data *ha = vha->hw;
+ uint32_t faddr;
+ struct active_regions active_regions = { };
if (!capable(CAP_SYS_ADMIN))
return 0;
@@ -164,11 +169,21 @@ qla2x00_sysfs_read_nvram(struct file *filp, struct kobject *kobj,
return -EAGAIN;
}
- if (IS_NOCACHE_VPD_TYPE(ha))
- ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2,
- ha->nvram_size);
+ if (!IS_NOCACHE_VPD_TYPE(ha)) {
+ mutex_unlock(&ha->optrom_mutex);
+ goto skip;
+ }
+
+ faddr = ha->flt_region_nvram;
+ if (IS_QLA28XX(ha)) {
+ if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE)
+ faddr = ha->flt_region_nvram_sec;
+ }
+ ha->isp_ops->read_optrom(vha, ha->nvram, faddr << 2, ha->nvram_size);
+
mutex_unlock(&ha->optrom_mutex);
+skip:
return memory_read_from_buffer(buf, count, &off, ha->nvram,
ha->nvram_size);
}
@@ -223,9 +238,9 @@ qla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj,
}
/* Write NVRAM. */
- ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->nvram_base, count);
- ha->isp_ops->read_nvram(vha, (uint8_t *)ha->nvram, ha->nvram_base,
- count);
+ ha->isp_ops->write_nvram(vha, buf, ha->nvram_base, count);
+ ha->isp_ops->read_nvram(vha, ha->nvram, ha->nvram_base,
+ count);
mutex_unlock(&ha->optrom_mutex);
ql_dbg(ql_dbg_user, vha, 0x7060,
@@ -367,7 +382,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
ha->optrom_region_size = size;
ha->optrom_state = QLA_SREADING;
- ha->optrom_buffer = vmalloc(ha->optrom_region_size);
+ ha->optrom_buffer = vzalloc(ha->optrom_region_size);
if (ha->optrom_buffer == NULL) {
ql_log(ql_log_warn, vha, 0x7062,
"Unable to allocate memory for optrom retrieval "
@@ -389,7 +404,6 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
"Reading flash region -- 0x%x/0x%x.\n",
ha->optrom_region_start, ha->optrom_region_size);
- memset(ha->optrom_buffer, 0, ha->optrom_region_size);
ha->isp_ops->read_optrom(vha, ha->optrom_buffer,
ha->optrom_region_start, ha->optrom_region_size);
break;
@@ -418,6 +432,10 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
* 0x000000 -> 0x07ffff -- Boot code.
* 0x080000 -> 0x0fffff -- Firmware.
* 0x120000 -> 0x12ffff -- VPD and HBA parameters.
+ *
+ * > ISP25xx type boards:
+ *
+ * None -- should go through BSG.
*/
valid = 0;
if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
@@ -425,9 +443,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
else if (start == (ha->flt_region_boot * 4) ||
start == (ha->flt_region_fw * 4))
valid = 1;
- else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha)
- || IS_CNA_CAPABLE(ha) || IS_QLA2031(ha)
- || IS_QLA27XX(ha))
+ else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha))
valid = 1;
if (!valid) {
ql_log(ql_log_warn, vha, 0x7065,
@@ -440,7 +456,7 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
ha->optrom_region_size = size;
ha->optrom_state = QLA_SWRITING;
- ha->optrom_buffer = vmalloc(ha->optrom_region_size);
+ ha->optrom_buffer = vzalloc(ha->optrom_region_size);
if (ha->optrom_buffer == NULL) {
ql_log(ql_log_warn, vha, 0x7066,
"Unable to allocate memory for optrom update "
@@ -455,7 +471,6 @@ qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj,
"Staging flash region write -- 0x%x/0x%x.\n",
ha->optrom_region_start, ha->optrom_region_size);
- memset(ha->optrom_buffer, 0, ha->optrom_region_size);
break;
case 3:
if (ha->optrom_state != QLA_SWRITING) {
@@ -504,6 +519,7 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj,
struct device, kobj)));
struct qla_hw_data *ha = vha->hw;
uint32_t faddr;
+ struct active_regions active_regions = { };
if (unlikely(pci_channel_offline(ha->pdev)))
return -EAGAIN;
@@ -511,22 +527,33 @@ qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj,
if (!capable(CAP_SYS_ADMIN))
return -EINVAL;
- if (IS_NOCACHE_VPD_TYPE(ha)) {
- faddr = ha->flt_region_vpd << 2;
+ if (IS_NOCACHE_VPD_TYPE(ha))
+ goto skip;
+
+ faddr = ha->flt_region_vpd << 2;
- if (IS_QLA27XX(ha) &&
- qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
+ if (IS_QLA28XX(ha)) {
+ qla28xx_get_aux_images(vha, &active_regions);
+ if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE)
faddr = ha->flt_region_vpd_sec << 2;
- mutex_lock(&ha->optrom_mutex);
- if (qla2x00_chip_is_down(vha)) {
- mutex_unlock(&ha->optrom_mutex);
- return -EAGAIN;
- }
- ha->isp_ops->read_optrom(vha, ha->vpd, faddr,
- ha->vpd_size);
+ ql_dbg(ql_dbg_init, vha, 0x7070,
+ "Loading %s nvram image.\n",
+ active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ?
+ "primary" : "secondary");
+ }
+
+ mutex_lock(&ha->optrom_mutex);
+ if (qla2x00_chip_is_down(vha)) {
mutex_unlock(&ha->optrom_mutex);
+ return -EAGAIN;
}
+
+ ha->isp_ops->read_optrom(vha, ha->vpd, faddr, ha->vpd_size);
+ mutex_unlock(&ha->optrom_mutex);
+
+ ha->isp_ops->read_optrom(vha, ha->vpd, faddr, ha->vpd_size);
+skip:
return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size);
}
@@ -543,6 +570,9 @@ qla2x00_sysfs_write_vpd(struct file *filp, struct kobject *kobj,
if (unlikely(pci_channel_offline(ha->pdev)))
return 0;
+ if (qla2x00_chip_is_down(vha))
+ return 0;
+
if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size ||
!ha->isp_ops->write_nvram)
return 0;
@@ -560,8 +590,8 @@ qla2x00_sysfs_write_vpd(struct file *filp, struct kobject *kobj,
}
/* Write NVRAM. */
- ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->vpd_base, count);
- ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd, ha->vpd_base, count);
+ ha->isp_ops->write_nvram(vha, buf, ha->vpd_base, count);
+ ha->isp_ops->read_nvram(vha, ha->vpd, ha->vpd_base, count);
/* Update flash version information for 4Gb & above. */
if (!IS_FWI2_CAPABLE(ha)) {
@@ -642,6 +672,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
int type;
uint32_t idc_control;
uint8_t *tmp_data = NULL;
+
if (off != 0)
return -EINVAL;
@@ -679,7 +710,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
ql_log(ql_log_info, vha, 0x706f,
"Issuing MPI reset.\n");
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
uint32_t idc_control;
qla83xx_idc_lock(vha, 0);
@@ -693,7 +724,8 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
break;
} else {
/* Make sure FC side is not in reset */
- qla2x00_wait_for_hba_online(vha);
+ WARN_ON_ONCE(qla2x00_wait_for_hba_online(vha) !=
+ QLA_SUCCESS);
/* Issue MPI reset */
scsi_block_requests(vha->host);
@@ -855,7 +887,7 @@ do_read:
count = 0;
}
- count = actual_size > count ? count: actual_size;
+ count = actual_size > count ? count : actual_size;
memcpy(buf, ha->xgmac_data, count);
return count;
@@ -931,7 +963,7 @@ static struct bin_attribute sysfs_dcbx_tlv_attr = {
static struct sysfs_entry {
char *name;
struct bin_attribute *attr;
- int is4GBp_only;
+ int type;
} bin_file_entries[] = {
{ "fw_dump", &sysfs_fw_dump_attr, },
{ "nvram", &sysfs_nvram_attr, },
@@ -954,11 +986,11 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha)
int ret;
for (iter = bin_file_entries; iter->name; iter++) {
- if (iter->is4GBp_only && !IS_FWI2_CAPABLE(vha->hw))
+ if (iter->type && !IS_FWI2_CAPABLE(vha->hw))
continue;
- if (iter->is4GBp_only == 2 && !IS_QLA25XX(vha->hw))
+ if (iter->type == 2 && !IS_QLA25XX(vha->hw))
continue;
- if (iter->is4GBp_only == 3 && !(IS_CNA_CAPABLE(vha->hw)))
+ if (iter->type == 3 && !(IS_CNA_CAPABLE(vha->hw)))
continue;
ret = sysfs_create_bin_file(&host->shost_gendev.kobj,
@@ -982,13 +1014,14 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *vha, bool stop_beacon)
struct qla_hw_data *ha = vha->hw;
for (iter = bin_file_entries; iter->name; iter++) {
- if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha))
+ if (iter->type && !IS_FWI2_CAPABLE(ha))
continue;
- if (iter->is4GBp_only == 2 && !IS_QLA25XX(ha))
+ if (iter->type == 2 && !IS_QLA25XX(ha))
continue;
- if (iter->is4GBp_only == 3 && !(IS_CNA_CAPABLE(vha->hw)))
+ if (iter->type == 3 && !(IS_CNA_CAPABLE(ha)))
continue;
- if (iter->is4GBp_only == 0x27 && !IS_QLA27XX(vha->hw))
+ if (iter->type == 0x27 &&
+ (!IS_QLA27XX(ha) || !IS_QLA28XX(ha)))
continue;
sysfs_remove_bin_file(&host->shost_gendev.kobj,
@@ -1002,7 +1035,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *vha, bool stop_beacon)
/* Scsi_Host attributes. */
static ssize_t
-qla2x00_drvr_version_show(struct device *dev,
+qla2x00_driver_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%s\n", qla2x00_version_str);
@@ -1046,6 +1079,7 @@ qla2x00_isp_name_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+
return scnprintf(buf, PAGE_SIZE, "ISP%04X\n", vha->hw->pdev->device);
}
@@ -1079,6 +1113,7 @@ qla2x00_model_desc_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+
return scnprintf(buf, PAGE_SIZE, "%s\n", vha->hw->model_desc);
}
@@ -1090,7 +1125,8 @@ qla2x00_pci_info_show(struct device *dev, struct device_attribute *attr,
char pci_info[30];
return scnprintf(buf, PAGE_SIZE, "%s\n",
- vha->hw->isp_ops->pci_info_str(vha, pci_info));
+ vha->hw->isp_ops->pci_info_str(vha, pci_info,
+ sizeof(pci_info)));
}
static ssize_t
@@ -1291,6 +1327,7 @@ qla2x00_optrom_bios_version_show(struct device *dev,
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
struct qla_hw_data *ha = vha->hw;
+
return scnprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1],
ha->bios_revision[0]);
}
@@ -1301,6 +1338,7 @@ qla2x00_optrom_efi_version_show(struct device *dev,
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
struct qla_hw_data *ha = vha->hw;
+
return scnprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1],
ha->efi_revision[0]);
}
@@ -1311,6 +1349,7 @@ qla2x00_optrom_fcode_version_show(struct device *dev,
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
struct qla_hw_data *ha = vha->hw;
+
return scnprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1],
ha->fcode_revision[0]);
}
@@ -1321,6 +1360,7 @@ qla2x00_optrom_fw_version_show(struct device *dev,
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
struct qla_hw_data *ha = vha->hw;
+
return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n",
ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2],
ha->fw_revision[3]);
@@ -1333,7 +1373,8 @@ qla2x00_optrom_gold_fw_version_show(struct device *dev,
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
struct qla_hw_data *ha = vha->hw;
- if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+ if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
+ !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return scnprintf(buf, PAGE_SIZE, "\n");
return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%d)\n",
@@ -1346,6 +1387,7 @@ qla2x00_total_isp_aborts_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+
return scnprintf(buf, PAGE_SIZE, "%d\n",
vha->qla_stats.total_isp_aborts);
}
@@ -1355,24 +1397,40 @@ qla24xx_84xx_fw_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int rval = QLA_SUCCESS;
- uint16_t status[2] = {0, 0};
+ uint16_t status[2] = { 0 };
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
struct qla_hw_data *ha = vha->hw;
if (!IS_QLA84XX(ha))
return scnprintf(buf, PAGE_SIZE, "\n");
- if (ha->cs84xx->op_fw_version == 0)
+ if (!ha->cs84xx->op_fw_version) {
rval = qla84xx_verify_chip(vha, status);
- if ((rval == QLA_SUCCESS) && (status[0] == 0))
- return scnprintf(buf, PAGE_SIZE, "%u\n",
- (uint32_t)ha->cs84xx->op_fw_version);
+ if (!rval && !status[0])
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ (uint32_t)ha->cs84xx->op_fw_version);
+ }
return scnprintf(buf, PAGE_SIZE, "\n");
}
static ssize_t
+qla2x00_serdes_version_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ struct qla_hw_data *ha = vha->hw;
+
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+ return scnprintf(buf, PAGE_SIZE, "\n");
+
+ return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n",
+ ha->serdes_version[0], ha->serdes_version[1],
+ ha->serdes_version[2]);
+}
+
+static ssize_t
qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -1380,7 +1438,7 @@ qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr,
struct qla_hw_data *ha = vha->hw;
if (!IS_QLA81XX(ha) && !IS_QLA8031(ha) && !IS_QLA8044(ha) &&
- !IS_QLA27XX(ha))
+ !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return scnprintf(buf, PAGE_SIZE, "\n");
return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n",
@@ -1593,7 +1651,7 @@ qla2x00_pep_version_show(struct device *dev, struct device_attribute *attr,
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
struct qla_hw_data *ha = vha->hw;
- if (!IS_QLA27XX(ha))
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return scnprintf(buf, PAGE_SIZE, "\n");
return scnprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n",
@@ -1601,35 +1659,126 @@ qla2x00_pep_version_show(struct device *dev, struct device_attribute *attr,
}
static ssize_t
-qla2x00_min_link_speed_show(struct device *dev, struct device_attribute *attr,
- char *buf)
+qla2x00_min_supported_speed_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
struct qla_hw_data *ha = vha->hw;
- if (!IS_QLA27XX(ha))
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return scnprintf(buf, PAGE_SIZE, "\n");
return scnprintf(buf, PAGE_SIZE, "%s\n",
- ha->min_link_speed == 5 ? "32Gps" :
- ha->min_link_speed == 4 ? "16Gps" :
- ha->min_link_speed == 3 ? "8Gps" :
- ha->min_link_speed == 2 ? "4Gps" :
- ha->min_link_speed != 0 ? "unknown" : "");
+ ha->min_supported_speed == 6 ? "64Gps" :
+ ha->min_supported_speed == 5 ? "32Gps" :
+ ha->min_supported_speed == 4 ? "16Gps" :
+ ha->min_supported_speed == 3 ? "8Gps" :
+ ha->min_supported_speed == 2 ? "4Gps" :
+ ha->min_supported_speed != 0 ? "unknown" : "");
}
static ssize_t
-qla2x00_max_speed_sup_show(struct device *dev, struct device_attribute *attr,
- char *buf)
+qla2x00_max_supported_speed_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
struct qla_hw_data *ha = vha->hw;
- if (!IS_QLA27XX(ha))
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return scnprintf(buf, PAGE_SIZE, "\n");
return scnprintf(buf, PAGE_SIZE, "%s\n",
- ha->max_speed_sup ? "32Gps" : "16Gps");
+ ha->max_supported_speed == 2 ? "64Gps" :
+ ha->max_supported_speed == 1 ? "32Gps" :
+ ha->max_supported_speed == 0 ? "16Gps" : "unknown");
+}
+
+static ssize_t
+qla2x00_port_speed_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct scsi_qla_host *vha = shost_priv(dev_to_shost(dev));
+ ulong type, speed;
+ int oldspeed, rval;
+ int mode = QLA_SET_DATA_RATE_LR;
+ struct qla_hw_data *ha = vha->hw;
+
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) {
+ ql_log(ql_log_warn, vha, 0x70d8,
+ "Speed setting not supported \n");
+ return -EINVAL;
+ }
+
+ rval = kstrtol(buf, 10, &type);
+ if (rval)
+ return rval;
+ speed = type;
+ if (type == 40 || type == 80 || type == 160 ||
+ type == 320) {
+ ql_dbg(ql_dbg_user, vha, 0x70d9,
+ "Setting will be affected after a loss of sync\n");
+ type = type/10;
+ mode = QLA_SET_DATA_RATE_NOLR;
+ }
+
+ oldspeed = ha->set_data_rate;
+
+ switch (type) {
+ case 0:
+ ha->set_data_rate = PORT_SPEED_AUTO;
+ break;
+ case 4:
+ ha->set_data_rate = PORT_SPEED_4GB;
+ break;
+ case 8:
+ ha->set_data_rate = PORT_SPEED_8GB;
+ break;
+ case 16:
+ ha->set_data_rate = PORT_SPEED_16GB;
+ break;
+ case 32:
+ ha->set_data_rate = PORT_SPEED_32GB;
+ break;
+ default:
+ ql_log(ql_log_warn, vha, 0x1199,
+ "Unrecognized speed setting:%lx. Setting Autoneg\n",
+ speed);
+ ha->set_data_rate = PORT_SPEED_AUTO;
+ }
+
+ if (qla2x00_chip_is_down(vha) || (oldspeed == ha->set_data_rate))
+ return -EINVAL;
+
+ ql_log(ql_log_info, vha, 0x70da,
+ "Setting speed to %lx Gbps \n", type);
+
+ rval = qla2x00_set_data_rate(vha, mode);
+ if (rval != QLA_SUCCESS)
+ return -EIO;
+
+ return strlen(buf);
+}
+
+static ssize_t
+qla2x00_port_speed_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_qla_host *vha = shost_priv(dev_to_shost(dev));
+ struct qla_hw_data *ha = vha->hw;
+ ssize_t rval;
+ char *spd[7] = {"0", "0", "0", "4", "8", "16", "32"};
+
+ rval = qla2x00_get_data_rate(vha);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x70db,
+ "Unable to get port speed rval:%zd\n", rval);
+ return -EINVAL;
+ }
+
+ ql_log(ql_log_info, vha, 0x70d6,
+ "port speed:%d\n", ha->link_data_rate);
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n", spd[ha->link_data_rate]);
}
/* ----- */
@@ -2059,7 +2208,47 @@ ql2xiniexchg_store(struct device *dev, struct device_attribute *attr,
return strlen(buf);
}
-static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
+static ssize_t
+qla2x00_dif_bundle_statistics_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ struct qla_hw_data *ha = vha->hw;
+
+ return scnprintf(buf, PAGE_SIZE,
+ "cross=%llu read=%llu write=%llu kalloc=%llu dma_alloc=%llu unusable=%u\n",
+ ha->dif_bundle_crossed_pages, ha->dif_bundle_reads,
+ ha->dif_bundle_writes, ha->dif_bundle_kallocs,
+ ha->dif_bundle_dma_allocs, ha->pool.unusable.count);
+}
+
+static ssize_t
+qla2x00_fw_attr_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ struct qla_hw_data *ha = vha->hw;
+
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+ return scnprintf(buf, PAGE_SIZE, "\n");
+
+ return scnprintf(buf, PAGE_SIZE, "%llx\n",
+ (uint64_t)ha->fw_attributes_ext[1] << 48 |
+ (uint64_t)ha->fw_attributes_ext[0] << 32 |
+ (uint64_t)ha->fw_attributes_h << 16 |
+ (uint64_t)ha->fw_attributes);
+}
+
+static ssize_t
+qla2x00_port_no_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", vha->hw->port_no);
+}
+
+static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_driver_version_show, NULL);
static DEVICE_ATTR(fw_version, S_IRUGO, qla2x00_fw_version_show, NULL);
static DEVICE_ATTR(serial_num, S_IRUGO, qla2x00_serial_num_show, NULL);
static DEVICE_ATTR(isp_name, S_IRUGO, qla2x00_isp_name_show, NULL);
@@ -2087,6 +2276,7 @@ static DEVICE_ATTR(84xx_fw_version, S_IRUGO, qla24xx_84xx_fw_version_show,
NULL);
static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show,
NULL);
+static DEVICE_ATTR(serdes_version, 0444, qla2x00_serdes_version_show, NULL);
static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL);
static DEVICE_ATTR(phy_version, S_IRUGO, qla2x00_phy_version_show, NULL);
static DEVICE_ATTR(flash_block_size, S_IRUGO, qla2x00_flash_block_size_show,
@@ -2104,14 +2294,22 @@ static DEVICE_ATTR(allow_cna_fw_dump, S_IRUGO | S_IWUSR,
qla2x00_allow_cna_fw_dump_show,
qla2x00_allow_cna_fw_dump_store);
static DEVICE_ATTR(pep_version, S_IRUGO, qla2x00_pep_version_show, NULL);
-static DEVICE_ATTR(min_link_speed, S_IRUGO, qla2x00_min_link_speed_show, NULL);
-static DEVICE_ATTR(max_speed_sup, S_IRUGO, qla2x00_max_speed_sup_show, NULL);
+static DEVICE_ATTR(min_supported_speed, 0444,
+ qla2x00_min_supported_speed_show, NULL);
+static DEVICE_ATTR(max_supported_speed, 0444,
+ qla2x00_max_supported_speed_show, NULL);
static DEVICE_ATTR(zio_threshold, 0644,
qla_zio_threshold_show,
qla_zio_threshold_store);
static DEVICE_ATTR_RW(qlini_mode);
static DEVICE_ATTR_RW(ql2xexchoffld);
static DEVICE_ATTR_RW(ql2xiniexchg);
+static DEVICE_ATTR(dif_bundle_statistics, 0444,
+ qla2x00_dif_bundle_statistics_show, NULL);
+static DEVICE_ATTR(port_speed, 0644, qla2x00_port_speed_show,
+ qla2x00_port_speed_store);
+static DEVICE_ATTR(port_no, 0444, qla2x00_port_no_show, NULL);
+static DEVICE_ATTR(fw_attr, 0444, qla2x00_fw_attr_show, NULL);
struct device_attribute *qla2x00_host_attrs[] = {
@@ -2133,6 +2331,7 @@ struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_optrom_fw_version,
&dev_attr_84xx_fw_version,
&dev_attr_total_isp_aborts,
+ &dev_attr_serdes_version,
&dev_attr_mpi_version,
&dev_attr_phy_version,
&dev_attr_flash_block_size,
@@ -2147,9 +2346,13 @@ struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_fw_dump_size,
&dev_attr_allow_cna_fw_dump,
&dev_attr_pep_version,
- &dev_attr_min_link_speed,
- &dev_attr_max_speed_sup,
+ &dev_attr_min_supported_speed,
+ &dev_attr_max_supported_speed,
&dev_attr_zio_threshold,
+ &dev_attr_dif_bundle_statistics,
+ &dev_attr_port_speed,
+ &dev_attr_port_no,
+ &dev_attr_fw_attr,
NULL, /* reserve for qlini_mode */
NULL, /* reserve for ql2xiniexchg */
NULL, /* reserve for ql2xexchoffld */
@@ -2185,16 +2388,15 @@ qla2x00_get_host_port_id(struct Scsi_Host *shost)
static void
qla2x00_get_host_speed(struct Scsi_Host *shost)
{
- struct qla_hw_data *ha = ((struct scsi_qla_host *)
- (shost_priv(shost)))->hw;
- u32 speed = FC_PORTSPEED_UNKNOWN;
+ scsi_qla_host_t *vha = shost_priv(shost);
+ u32 speed;
- if (IS_QLAFX00(ha)) {
+ if (IS_QLAFX00(vha->hw)) {
qlafx00_get_host_speed(shost);
return;
}
- switch (ha->link_data_rate) {
+ switch (vha->hw->link_data_rate) {
case PORT_SPEED_1GB:
speed = FC_PORTSPEED_1GBIT;
break;
@@ -2216,7 +2418,14 @@ qla2x00_get_host_speed(struct Scsi_Host *shost)
case PORT_SPEED_32GB:
speed = FC_PORTSPEED_32GBIT;
break;
+ case PORT_SPEED_64GB:
+ speed = FC_PORTSPEED_64GBIT;
+ break;
+ default:
+ speed = FC_PORTSPEED_UNKNOWN;
+ break;
}
+
fc_host_speed(shost) = speed;
}
@@ -2224,7 +2433,7 @@ static void
qla2x00_get_host_port_type(struct Scsi_Host *shost)
{
scsi_qla_host_t *vha = shost_priv(shost);
- uint32_t port_type = FC_PORTTYPE_UNKNOWN;
+ uint32_t port_type;
if (vha->vp_idx) {
fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
@@ -2243,7 +2452,11 @@ qla2x00_get_host_port_type(struct Scsi_Host *shost)
case ISP_CFG_F:
port_type = FC_PORTTYPE_NPORT;
break;
+ default:
+ port_type = FC_PORTTYPE_UNKNOWN;
+ break;
}
+
fc_host_port_type(shost) = port_type;
}
@@ -2305,13 +2518,10 @@ qla2x00_get_starget_port_id(struct scsi_target *starget)
fc_starget_port_id(starget) = port_id;
}
-static void
+static inline void
qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
{
- if (timeout)
- rport->dev_loss_tmo = timeout;
- else
- rport->dev_loss_tmo = 1;
+ rport->dev_loss_tmo = timeout ? timeout : 1;
}
static void
@@ -2600,8 +2810,8 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
/* initialized vport states */
atomic_set(&vha->loop_state, LOOP_DOWN);
- vha->vp_err_state= VP_ERR_PORTDWN;
- vha->vp_prev_err_state= VP_ERR_UNKWN;
+ vha->vp_err_state = VP_ERR_PORTDWN;
+ vha->vp_prev_err_state = VP_ERR_UNKWN;
/* Check if physical ha port is Up */
if (atomic_read(&base_vha->loop_state) == LOOP_DOWN ||
atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
@@ -2616,6 +2826,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif && !ql2xnvmeenable) {
if (ha->fw_attributes & BIT_4) {
int prot = 0, guard;
+
vha->flags.difdix_supported = 1;
ql_dbg(ql_dbg_user, vha, 0x7082,
"Registered for DIF/DIX type 1 and 3 protection.\n");
@@ -2744,6 +2955,8 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
dma_free_coherent(&ha->pdev->dev, vha->gnl.size, vha->gnl.l,
vha->gnl.ldma);
+ vha->gnl.l = NULL;
+
vfree(vha->scan.l);
if (vha->qpair && vha->qpair->vp_idx == vha->vp_idx) {
@@ -2866,7 +3079,7 @@ void
qla2x00_init_host_attr(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
- u32 speed = FC_PORTSPEED_UNKNOWN;
+ u32 speeds = FC_PORTSPEED_UNKNOWN;
fc_host_dev_loss_tmo(vha->host) = ha->port_down_retry_count;
fc_host_node_name(vha->host) = wwn_to_u64(vha->node_name);
@@ -2877,25 +3090,45 @@ qla2x00_init_host_attr(scsi_qla_host_t *vha)
fc_host_npiv_vports_inuse(vha->host) = ha->cur_vport_count;
if (IS_CNA_CAPABLE(ha))
- speed = FC_PORTSPEED_10GBIT;
- else if (IS_QLA2031(ha))
- speed = FC_PORTSPEED_16GBIT | FC_PORTSPEED_8GBIT |
- FC_PORTSPEED_4GBIT;
- else if (IS_QLA25XX(ha))
- speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT |
- FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
+ speeds = FC_PORTSPEED_10GBIT;
+ else if (IS_QLA28XX(ha) || IS_QLA27XX(ha)) {
+ if (ha->max_supported_speed == 2) {
+ if (ha->min_supported_speed <= 6)
+ speeds |= FC_PORTSPEED_64GBIT;
+ }
+ if (ha->max_supported_speed == 2 ||
+ ha->max_supported_speed == 1) {
+ if (ha->min_supported_speed <= 5)
+ speeds |= FC_PORTSPEED_32GBIT;
+ }
+ if (ha->max_supported_speed == 2 ||
+ ha->max_supported_speed == 1 ||
+ ha->max_supported_speed == 0) {
+ if (ha->min_supported_speed <= 4)
+ speeds |= FC_PORTSPEED_16GBIT;
+ }
+ if (ha->max_supported_speed == 1 ||
+ ha->max_supported_speed == 0) {
+ if (ha->min_supported_speed <= 3)
+ speeds |= FC_PORTSPEED_8GBIT;
+ }
+ if (ha->max_supported_speed == 0) {
+ if (ha->min_supported_speed <= 2)
+ speeds |= FC_PORTSPEED_4GBIT;
+ }
+ } else if (IS_QLA2031(ha))
+ speeds = FC_PORTSPEED_16GBIT|FC_PORTSPEED_8GBIT|
+ FC_PORTSPEED_4GBIT;
+ else if (IS_QLA25XX(ha) || IS_QLAFX00(ha))
+ speeds = FC_PORTSPEED_8GBIT|FC_PORTSPEED_4GBIT|
+ FC_PORTSPEED_2GBIT|FC_PORTSPEED_1GBIT;
else if (IS_QLA24XX_TYPE(ha))
- speed = FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT |
- FC_PORTSPEED_1GBIT;
+ speeds = FC_PORTSPEED_4GBIT|FC_PORTSPEED_2GBIT|
+ FC_PORTSPEED_1GBIT;
else if (IS_QLA23XX(ha))
- speed = FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
- else if (IS_QLAFX00(ha))
- speed = FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT |
- FC_PORTSPEED_2GBIT | FC_PORTSPEED_1GBIT;
- else if (IS_QLA27XX(ha))
- speed = FC_PORTSPEED_32GBIT | FC_PORTSPEED_16GBIT |
- FC_PORTSPEED_8GBIT;
+ speeds = FC_PORTSPEED_2GBIT|FC_PORTSPEED_1GBIT;
else
- speed = FC_PORTSPEED_1GBIT;
- fc_host_supported_speeds(vha->host) = speed;
+ speeds = FC_PORTSPEED_1GBIT;
+
+ fc_host_supported_speeds(vha->host) = speeds;
}
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index ff294092b6a4..a0d10d63a00b 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -1,4 +1,4 @@
- /*
+/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2014 QLogic Corporation
*
@@ -12,10 +12,8 @@
#include <linux/bsg-lib.h>
/* BSG support for ELS/CT pass through */
-void
-qla2x00_bsg_job_done(void *ptr, int res)
+void qla2x00_bsg_job_done(srb_t *sp, int res)
{
- srb_t *sp = ptr;
struct bsg_job *bsg_job = sp->u.bsg_job;
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
@@ -25,10 +23,8 @@ qla2x00_bsg_job_done(void *ptr, int res)
sp->free(sp);
}
-void
-qla2x00_bsg_sp_free(void *ptr)
+void qla2x00_bsg_sp_free(srb_t *sp)
{
- srb_t *sp = ptr;
struct qla_hw_data *ha = sp->vha->hw;
struct bsg_job *bsg_job = sp->u.bsg_job;
struct fc_bsg_request *bsg_request = bsg_job->request;
@@ -84,8 +80,7 @@ qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *vha,
return 0;
}
- if (bcode[0] != 'H' || bcode[1] != 'Q' || bcode[2] != 'O' ||
- bcode[3] != 'S') {
+ if (memcmp(bcode, "HQOS", 4)) {
/* Invalid FCP priority data header*/
ql_dbg(ql_dbg_user, vha, 0x7052,
"Invalid FCP Priority data header. bcode=0x%x.\n",
@@ -342,6 +337,8 @@ qla2x00_process_els(struct bsg_job *bsg_job)
dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
if (!req_sg_cnt) {
+ dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
+ bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
rval = -ENOMEM;
goto done_free_fcport;
}
@@ -349,6 +346,8 @@ qla2x00_process_els(struct bsg_job *bsg_job)
rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
if (!rsp_sg_cnt) {
+ dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
rval = -ENOMEM;
goto done_free_fcport;
}
@@ -1035,7 +1034,7 @@ qla84xx_updatefw(struct bsg_job *bsg_job)
sg_copy_to_buffer(bsg_job->request_payload.sg_list,
bsg_job->request_payload.sg_cnt, fw_buf, data_len);
- mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
+ mn = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
if (!mn) {
ql_log(ql_log_warn, vha, 0x7036,
"DMA alloc failed for fw buffer.\n");
@@ -1044,9 +1043,8 @@ qla84xx_updatefw(struct bsg_job *bsg_job)
}
flag = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
- fw_ver = le32_to_cpu(*((uint32_t *)((uint32_t *)fw_buf + 2)));
+ fw_ver = get_unaligned_le32((uint32_t *)fw_buf + 2);
- memset(mn, 0, sizeof(struct access_chip_84xx));
mn->entry_type = VERIFY_CHIP_IOCB_TYPE;
mn->entry_count = 1;
@@ -1058,9 +1056,8 @@ qla84xx_updatefw(struct bsg_job *bsg_job)
mn->fw_ver = cpu_to_le32(fw_ver);
mn->fw_size = cpu_to_le32(data_len);
mn->fw_seq_size = cpu_to_le32(data_len);
- mn->dseg_address[0] = cpu_to_le32(LSD(fw_dma));
- mn->dseg_address[1] = cpu_to_le32(MSD(fw_dma));
- mn->dseg_length = cpu_to_le32(data_len);
+ put_unaligned_le64(fw_dma, &mn->dsd.address);
+ mn->dsd.length = cpu_to_le32(data_len);
mn->data_seg_cnt = cpu_to_le16(1);
rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120);
@@ -1239,9 +1236,8 @@ qla84xx_mgmt_cmd(struct bsg_job *bsg_job)
if (ql84_mgmt->mgmt.cmd != QLA84_MGMT_CHNG_CONFIG) {
mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->mgmt.len);
mn->dseg_count = cpu_to_le16(1);
- mn->dseg_address[0] = cpu_to_le32(LSD(mgmt_dma));
- mn->dseg_address[1] = cpu_to_le32(MSD(mgmt_dma));
- mn->dseg_length = cpu_to_le32(ql84_mgmt->mgmt.len);
+ put_unaligned_le64(mgmt_dma, &mn->dsd.address);
+ mn->dsd.length = cpu_to_le32(ql84_mgmt->mgmt.len);
}
rval = qla2x00_issue_iocb(vha, mn, mn_dma, 0);
@@ -1355,7 +1351,7 @@ qla24xx_iidma(struct bsg_job *bsg_job)
if (rval) {
ql_log(ql_log_warn, vha, 0x704c,
- "iIDMA cmd failed for %8phN -- "
+ "iiDMA cmd failed for %8phN -- "
"%04x %x %04x %04x.\n", fcport->port_name,
rval, fcport->fp_speed, mb[0], mb[1]);
rval = (DID_ERROR << 16);
@@ -1413,7 +1409,8 @@ qla2x00_optrom_setup(struct bsg_job *bsg_job, scsi_qla_host_t *vha,
start == (ha->flt_region_fw * 4))
valid = 1;
else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) ||
- IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha))
+ IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha))
valid = 1;
if (!valid) {
ql_log(ql_log_warn, vha, 0x7058,
@@ -1535,6 +1532,7 @@ qla2x00_update_fru_versions(struct bsg_job *bsg_job)
uint32_t count;
dma_addr_t sfp_dma;
void *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
+
if (!sfp) {
bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
EXT_STATUS_NO_MEMORY;
@@ -1585,6 +1583,7 @@ qla2x00_read_fru_status(struct bsg_job *bsg_job)
struct qla_status_reg *sr = (void *)bsg;
dma_addr_t sfp_dma;
uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
+
if (!sfp) {
bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
EXT_STATUS_NO_MEMORY;
@@ -1635,6 +1634,7 @@ qla2x00_write_fru_status(struct bsg_job *bsg_job)
struct qla_status_reg *sr = (void *)bsg;
dma_addr_t sfp_dma;
uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
+
if (!sfp) {
bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
EXT_STATUS_NO_MEMORY;
@@ -1681,6 +1681,7 @@ qla2x00_write_i2c(struct bsg_job *bsg_job)
struct qla_i2c_access *i2c = (void *)bsg;
dma_addr_t sfp_dma;
uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
+
if (!sfp) {
bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
EXT_STATUS_NO_MEMORY;
@@ -1726,6 +1727,7 @@ qla2x00_read_i2c(struct bsg_job *bsg_job)
struct qla_i2c_access *i2c = (void *)bsg;
dma_addr_t sfp_dma;
uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
+
if (!sfp) {
bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
EXT_STATUS_NO_MEMORY;
@@ -1776,8 +1778,8 @@ qla24xx_process_bidir_cmd(struct bsg_job *bsg_job)
uint16_t nextlid = 0;
uint32_t tot_dsds;
srb_t *sp = NULL;
- uint32_t req_data_len = 0;
- uint32_t rsp_data_len = 0;
+ uint32_t req_data_len;
+ uint32_t rsp_data_len;
/* Check the type of the adapter */
if (!IS_BIDI_CAPABLE(ha)) {
@@ -1882,6 +1884,9 @@ qla24xx_process_bidir_cmd(struct bsg_job *bsg_job)
goto done_unmap_sg;
}
+ req_data_len = bsg_job->request_payload.payload_len;
+ rsp_data_len = bsg_job->reply_payload.payload_len;
+
if (req_data_len != rsp_data_len) {
rval = EXT_STATUS_BUSY;
ql_log(ql_log_warn, vha, 0x70aa,
@@ -1889,10 +1894,6 @@ qla24xx_process_bidir_cmd(struct bsg_job *bsg_job)
goto done_unmap_sg;
}
- req_data_len = bsg_job->request_payload.payload_len;
- rsp_data_len = bsg_job->reply_payload.payload_len;
-
-
/* Alloc SRB structure */
sp = qla2x00_get_sp(vha, &(vha->bidir_fcport), GFP_KERNEL);
if (!sp) {
@@ -1962,7 +1963,7 @@ qlafx00_mgmt_cmd(struct bsg_job *bsg_job)
/* Dump the vendor information */
ql_dump_buffer(ql_dbg_user + ql_dbg_verbose , vha, 0x70cf,
- (uint8_t *)piocb_rqst, sizeof(struct qla_mt_iocb_rqst_fx00));
+ piocb_rqst, sizeof(*piocb_rqst));
if (!vha->flags.online) {
ql_log(ql_log_warn, vha, 0x70d0,
@@ -2158,7 +2159,7 @@ qla27xx_get_flash_upd_cap(struct bsg_job *bsg_job)
struct qla_hw_data *ha = vha->hw;
struct qla_flash_update_caps cap;
- if (!(IS_QLA27XX(ha)))
+ if (!(IS_QLA27XX(ha)) && !IS_QLA28XX(ha))
return -EPERM;
memset(&cap, 0, sizeof(cap));
@@ -2191,7 +2192,7 @@ qla27xx_set_flash_upd_cap(struct bsg_job *bsg_job)
uint64_t online_fw_attr = 0;
struct qla_flash_update_caps cap;
- if (!(IS_QLA27XX(ha)))
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return -EPERM;
memset(&cap, 0, sizeof(cap));
@@ -2239,7 +2240,7 @@ qla27xx_get_bbcr_data(struct bsg_job *bsg_job)
uint8_t domain, area, al_pa, state;
int rval;
- if (!(IS_QLA27XX(ha)))
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return -EPERM;
memset(&bbcr, 0, sizeof(bbcr));
@@ -2324,8 +2325,8 @@ qla2x00_get_priv_stats(struct bsg_job *bsg_job)
rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma, options);
if (rval == QLA_SUCCESS) {
- ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e3,
- (uint8_t *)stats, sizeof(*stats));
+ ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e5,
+ stats, sizeof(*stats));
sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
bsg_job->reply_payload.sg_cnt, stats, sizeof(*stats));
}
@@ -2354,7 +2355,8 @@ qla2x00_do_dport_diagnostics(struct bsg_job *bsg_job)
int rval;
struct qla_dport_diag *dd;
- if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw))
+ if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) &&
+ !IS_QLA28XX(vha->hw))
return -EPERM;
dd = kmalloc(sizeof(*dd), GFP_KERNEL);
@@ -2389,6 +2391,45 @@ qla2x00_do_dport_diagnostics(struct bsg_job *bsg_job)
}
static int
+qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
+{
+ scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
+ struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+ struct qla_hw_data *ha = vha->hw;
+ struct qla_active_regions regions = { };
+ struct active_regions active_regions = { };
+
+ qla28xx_get_aux_images(vha, &active_regions);
+ regions.global_image = active_regions.global;
+
+ if (IS_QLA28XX(ha)) {
+ qla27xx_get_active_image(vha, &active_regions);
+ regions.board_config = active_regions.aux.board_config;
+ regions.vpd_nvram = active_regions.aux.vpd_nvram;
+ regions.npiv_config_0_1 = active_regions.aux.npiv_config_0_1;
+ regions.npiv_config_2_3 = active_regions.aux.npiv_config_2_3;
+ }
+
+ ql_dbg(ql_dbg_user, vha, 0x70e1,
+ "%s(%lu): FW=%u BCFG=%u VPDNVR=%u NPIV01=%u NPIV02=%u\n",
+ __func__, vha->host_no, regions.global_image,
+ regions.board_config, regions.vpd_nvram,
+ regions.npiv_config_0_1, regions.npiv_config_2_3);
+
+ sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+ bsg_job->reply_payload.sg_cnt, &regions, sizeof(regions));
+
+ bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
+ bsg_reply->reply_payload_rcv_len = sizeof(regions);
+ bsg_reply->result = DID_OK << 16;
+ bsg_job->reply_len = sizeof(struct fc_bsg_reply);
+ bsg_job_done(bsg_job, bsg_reply->result,
+ bsg_reply->reply_payload_rcv_len);
+
+ return 0;
+}
+
+static int
qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
{
struct fc_bsg_request *bsg_request = bsg_job->request;
@@ -2461,6 +2502,9 @@ qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
case QL_VND_DPORT_DIAGNOSTICS:
return qla2x00_do_dport_diagnostics(bsg_job);
+ case QL_VND_SS_GET_FLASH_IMAGE_STATUS:
+ return qla2x00_get_flash_image_status(bsg_job);
+
default:
return -ENOSYS;
}
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
index d97dfd521356..7594fad7b5b5 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.h
+++ b/drivers/scsi/qla2xxx/qla_bsg.h
@@ -31,6 +31,7 @@
#define QL_VND_GET_PRIV_STATS 0x18
#define QL_VND_DPORT_DIAGNOSTICS 0x19
#define QL_VND_GET_PRIV_STATS_EX 0x1A
+#define QL_VND_SS_GET_FLASH_IMAGE_STATUS 0x1E
/* BSG Vendor specific subcode returns */
#define EXT_STATUS_OK 0
@@ -279,4 +280,14 @@ struct qla_dport_diag {
#define QLA_DPORT_RESULT 0x0
#define QLA_DPORT_START 0x2
+/* active images in flash */
+struct qla_active_regions {
+ uint8_t global_image;
+ uint8_t board_config;
+ uint8_t vpd_nvram;
+ uint8_t npiv_config_0_1;
+ uint8_t npiv_config_2_3;
+ uint8_t reserved[32];
+} __packed;
+
#endif
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index c7533fa7f46e..30afc59c1870 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -111,30 +111,25 @@ int
qla27xx_dump_mpi_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram,
uint32_t ram_dwords, void **nxt)
{
- int rval;
- uint32_t cnt, stat, timer, dwords, idx;
- uint16_t mb0;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
dma_addr_t dump_dma = ha->gid_list_dma;
- uint32_t *dump = (uint32_t *)ha->gid_list;
-
- rval = QLA_SUCCESS;
- mb0 = 0;
+ uint32_t *chunk = (void *)ha->gid_list;
+ uint32_t dwords = qla2x00_gid_list_size(ha) / 4;
+ uint32_t stat;
+ ulong i, j, timer = 6000000;
+ int rval = QLA_FUNCTION_FAILED;
- WRT_REG_WORD(&reg->mailbox0, MBC_LOAD_DUMP_MPI_RAM);
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+ for (i = 0; i < ram_dwords; i += dwords, addr += dwords) {
+ if (i + dwords > ram_dwords)
+ dwords = ram_dwords - i;
- dwords = qla2x00_gid_list_size(ha) / 4;
- for (cnt = 0; cnt < ram_dwords && rval == QLA_SUCCESS;
- cnt += dwords, addr += dwords) {
- if (cnt + dwords > ram_dwords)
- dwords = ram_dwords - cnt;
-
+ WRT_REG_WORD(&reg->mailbox0, MBC_LOAD_DUMP_MPI_RAM);
WRT_REG_WORD(&reg->mailbox1, LSW(addr));
WRT_REG_WORD(&reg->mailbox8, MSW(addr));
- WRT_REG_WORD(&reg->mailbox2, MSW(dump_dma));
- WRT_REG_WORD(&reg->mailbox3, LSW(dump_dma));
+ WRT_REG_WORD(&reg->mailbox2, MSW(LSD(dump_dma)));
+ WRT_REG_WORD(&reg->mailbox3, LSW(LSD(dump_dma)));
WRT_REG_WORD(&reg->mailbox6, MSW(MSD(dump_dma)));
WRT_REG_WORD(&reg->mailbox7, LSW(MSD(dump_dma)));
@@ -145,76 +140,76 @@ qla27xx_dump_mpi_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram,
WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);
ha->flags.mbox_int = 0;
- for (timer = 6000000; timer; timer--) {
- /* Check for pending interrupts. */
- stat = RD_REG_DWORD(&reg->host_status);
- if (stat & HSRX_RISC_INT) {
- stat &= 0xff;
-
- if (stat == 0x1 || stat == 0x2 ||
- stat == 0x10 || stat == 0x11) {
- set_bit(MBX_INTERRUPT,
- &ha->mbx_cmd_flags);
+ while (timer--) {
+ udelay(5);
- mb0 = RD_REG_WORD(&reg->mailbox0);
- RD_REG_WORD(&reg->mailbox1);
+ stat = RD_REG_DWORD(&reg->host_status);
+ /* Check for pending interrupts. */
+ if (!(stat & HSRX_RISC_INT))
+ continue;
- WRT_REG_DWORD(&reg->hccr,
- HCCRX_CLR_RISC_INT);
- RD_REG_DWORD(&reg->hccr);
- break;
- }
+ stat &= 0xff;
+ if (stat != 0x1 && stat != 0x2 &&
+ stat != 0x10 && stat != 0x11) {
/* Clear this intr; it wasn't a mailbox intr */
WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
RD_REG_DWORD(&reg->hccr);
+ continue;
}
- udelay(5);
+
+ set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+ rval = RD_REG_WORD(&reg->mailbox0) & MBS_MASK;
+ WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
+ RD_REG_DWORD(&reg->hccr);
+ break;
}
ha->flags.mbox_int = 1;
+ *nxt = ram + i;
- if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
- rval = mb0 & MBS_MASK;
- for (idx = 0; idx < dwords; idx++)
- ram[cnt + idx] = IS_QLA27XX(ha) ?
- le32_to_cpu(dump[idx]) : swab32(dump[idx]);
- } else {
- rval = QLA_FUNCTION_FAILED;
+ if (!test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
+ /* no interrupt, timed out*/
+ return rval;
+ }
+ if (rval) {
+ /* error completion status */
+ return rval;
+ }
+ for (j = 0; j < dwords; j++) {
+ ram[i + j] =
+ (IS_QLA27XX(ha) || IS_QLA28XX(ha)) ?
+ chunk[j] : swab32(chunk[j]);
}
}
- *nxt = rval == QLA_SUCCESS ? &ram[cnt] : NULL;
- return rval;
+ *nxt = ram + i;
+ return QLA_SUCCESS;
}
int
qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram,
uint32_t ram_dwords, void **nxt)
{
- int rval;
- uint32_t cnt, stat, timer, dwords, idx;
- uint16_t mb0;
+ int rval = QLA_FUNCTION_FAILED;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
dma_addr_t dump_dma = ha->gid_list_dma;
- uint32_t *dump = (uint32_t *)ha->gid_list;
+ uint32_t *chunk = (void *)ha->gid_list;
+ uint32_t dwords = qla2x00_gid_list_size(ha) / 4;
+ uint32_t stat;
+ ulong i, j, timer = 6000000;
- rval = QLA_SUCCESS;
- mb0 = 0;
-
- WRT_REG_WORD(&reg->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED);
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
- dwords = qla2x00_gid_list_size(ha) / 4;
- for (cnt = 0; cnt < ram_dwords && rval == QLA_SUCCESS;
- cnt += dwords, addr += dwords) {
- if (cnt + dwords > ram_dwords)
- dwords = ram_dwords - cnt;
+ for (i = 0; i < ram_dwords; i += dwords, addr += dwords) {
+ if (i + dwords > ram_dwords)
+ dwords = ram_dwords - i;
+ WRT_REG_WORD(&reg->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED);
WRT_REG_WORD(&reg->mailbox1, LSW(addr));
WRT_REG_WORD(&reg->mailbox8, MSW(addr));
- WRT_REG_WORD(&reg->mailbox2, MSW(dump_dma));
- WRT_REG_WORD(&reg->mailbox3, LSW(dump_dma));
+ WRT_REG_WORD(&reg->mailbox2, MSW(LSD(dump_dma)));
+ WRT_REG_WORD(&reg->mailbox3, LSW(LSD(dump_dma)));
WRT_REG_WORD(&reg->mailbox6, MSW(MSD(dump_dma)));
WRT_REG_WORD(&reg->mailbox7, LSW(MSD(dump_dma)));
@@ -223,45 +218,48 @@ qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram,
WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);
ha->flags.mbox_int = 0;
- for (timer = 6000000; timer; timer--) {
- /* Check for pending interrupts. */
+ while (timer--) {
+ udelay(5);
stat = RD_REG_DWORD(&reg->host_status);
- if (stat & HSRX_RISC_INT) {
- stat &= 0xff;
- if (stat == 0x1 || stat == 0x2 ||
- stat == 0x10 || stat == 0x11) {
- set_bit(MBX_INTERRUPT,
- &ha->mbx_cmd_flags);
-
- mb0 = RD_REG_WORD(&reg->mailbox0);
-
- WRT_REG_DWORD(&reg->hccr,
- HCCRX_CLR_RISC_INT);
- RD_REG_DWORD(&reg->hccr);
- break;
- }
+ /* Check for pending interrupts. */
+ if (!(stat & HSRX_RISC_INT))
+ continue;
- /* Clear this intr; it wasn't a mailbox intr */
+ stat &= 0xff;
+ if (stat != 0x1 && stat != 0x2 &&
+ stat != 0x10 && stat != 0x11) {
WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
RD_REG_DWORD(&reg->hccr);
+ continue;
}
- udelay(5);
+
+ set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
+ rval = RD_REG_WORD(&reg->mailbox0) & MBS_MASK;
+ WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
+ RD_REG_DWORD(&reg->hccr);
+ break;
}
ha->flags.mbox_int = 1;
+ *nxt = ram + i;
- if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
- rval = mb0 & MBS_MASK;
- for (idx = 0; idx < dwords; idx++)
- ram[cnt + idx] = IS_QLA27XX(ha) ?
- le32_to_cpu(dump[idx]) : swab32(dump[idx]);
- } else {
- rval = QLA_FUNCTION_FAILED;
+ if (!test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
+ /* no interrupt, timed out*/
+ return rval;
+ }
+ if (rval) {
+ /* error completion status */
+ return rval;
+ }
+ for (j = 0; j < dwords; j++) {
+ ram[i + j] =
+ (IS_QLA27XX(ha) || IS_QLA28XX(ha)) ?
+ chunk[j] : swab32(chunk[j]);
}
}
- *nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL;
- return rval;
+ *nxt = ram + i;
+ return QLA_SUCCESS;
}
static int
@@ -447,7 +445,7 @@ qla2xxx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint16_t *ram,
}
}
- *nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL;
+ *nxt = rval == QLA_SUCCESS ? &ram[cnt] : NULL;
return rval;
}
@@ -669,7 +667,8 @@ qla25xx_copy_mq(struct qla_hw_data *ha, void *ptr, uint32_t **last_chain)
struct qla2xxx_mq_chain *mq = ptr;
device_reg_t *reg;
- if (!ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+ if (!ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha))
return ptr;
mq = ptr;
@@ -2521,7 +2520,7 @@ qla83xx_fw_dump_failed:
/****************************************************************************/
static inline int
-ql_mask_match(uint32_t level)
+ql_mask_match(uint level)
{
return (level & ql2xextended_error_logging) == level;
}
@@ -2540,7 +2539,7 @@ ql_mask_match(uint32_t level)
* msg: The message to be displayed.
*/
void
-ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...)
+ql_dbg(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...)
{
va_list va;
struct va_format vaf;
@@ -2583,8 +2582,7 @@ ql_dbg(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...)
* msg: The message to be displayed.
*/
void
-ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id,
- const char *fmt, ...)
+ql_dbg_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...)
{
va_list va;
struct va_format vaf;
@@ -2620,7 +2618,7 @@ ql_dbg_pci(uint32_t level, struct pci_dev *pdev, int32_t id,
* msg: The message to be displayed.
*/
void
-ql_log(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...)
+ql_log(uint level, scsi_qla_host_t *vha, uint id, const char *fmt, ...)
{
va_list va;
struct va_format vaf;
@@ -2678,8 +2676,7 @@ ql_log(uint32_t level, scsi_qla_host_t *vha, int32_t id, const char *fmt, ...)
* msg: The message to be displayed.
*/
void
-ql_log_pci(uint32_t level, struct pci_dev *pdev, int32_t id,
- const char *fmt, ...)
+ql_log_pci(uint level, struct pci_dev *pdev, uint id, const char *fmt, ...)
{
va_list va;
struct va_format vaf;
@@ -2719,7 +2716,7 @@ ql_log_pci(uint32_t level, struct pci_dev *pdev, int32_t id,
}
void
-ql_dump_regs(uint32_t level, scsi_qla_host_t *vha, int32_t id)
+ql_dump_regs(uint level, scsi_qla_host_t *vha, uint id)
{
int i;
struct qla_hw_data *ha = vha->hw;
@@ -2741,13 +2738,13 @@ ql_dump_regs(uint32_t level, scsi_qla_host_t *vha, int32_t id)
ql_dbg(level, vha, id, "Mailbox registers:\n");
for (i = 0; i < 6; i++, mbx_reg++)
ql_dbg(level, vha, id,
- "mbox[%d] 0x%04x\n", i, RD_REG_WORD(mbx_reg));
+ "mbox[%d] %#04x\n", i, RD_REG_WORD(mbx_reg));
}
void
-ql_dump_buffer(uint32_t level, scsi_qla_host_t *vha, int32_t id,
- uint8_t *buf, uint size)
+ql_dump_buffer(uint level, scsi_qla_host_t *vha, uint id, const void *buf,
+ uint size)
{
uint cnt;
diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h
index 8877aa97d829..bb01b680ce9f 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.h
+++ b/drivers/scsi/qla2xxx/qla_dbg.h
@@ -318,20 +318,20 @@ struct qla2xxx_fw_dump {
* as compared to other log levels.
*/
-extern int ql_errlev;
+extern uint ql_errlev;
void __attribute__((format (printf, 4, 5)))
-ql_dbg(uint32_t, scsi_qla_host_t *vha, int32_t, const char *fmt, ...);
+ql_dbg(uint, scsi_qla_host_t *vha, uint, const char *fmt, ...);
void __attribute__((format (printf, 4, 5)))
-ql_dbg_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...);
+ql_dbg_pci(uint, struct pci_dev *pdev, uint, const char *fmt, ...);
void __attribute__((format (printf, 4, 5)))
ql_dbg_qp(uint32_t, struct qla_qpair *, int32_t, const char *fmt, ...);
void __attribute__((format (printf, 4, 5)))
-ql_log(uint32_t, scsi_qla_host_t *vha, int32_t, const char *fmt, ...);
+ql_log(uint, scsi_qla_host_t *vha, uint, const char *fmt, ...);
void __attribute__((format (printf, 4, 5)))
-ql_log_pci(uint32_t, struct pci_dev *pdev, int32_t, const char *fmt, ...);
+ql_log_pci(uint, struct pci_dev *pdev, uint, const char *fmt, ...);
void __attribute__((format (printf, 4, 5)))
ql_log_qp(uint32_t, struct qla_qpair *, int32_t, const char *fmt, ...);
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index a6ea6cf784dd..b4936de72201 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -34,7 +34,22 @@
#include <scsi/scsi_transport_fc.h>
#include <scsi/scsi_bsg_fc.h>
+/* Big endian Fibre Channel S_ID (source ID) or D_ID (destination ID). */
+typedef struct {
+ uint8_t domain;
+ uint8_t area;
+ uint8_t al_pa;
+} be_id_t;
+
+/* Little endian Fibre Channel S_ID (source ID) or D_ID (destination ID). */
+typedef struct {
+ uint8_t al_pa;
+ uint8_t area;
+ uint8_t domain;
+} le_id_t;
+
#include "qla_bsg.h"
+#include "qla_dsd.h"
#include "qla_nx.h"
#include "qla_nx2.h"
#include "qla_nvme.h"
@@ -116,9 +131,9 @@
#define RD_REG_BYTE_RELAXED(addr) readb_relaxed(addr)
#define RD_REG_WORD_RELAXED(addr) readw_relaxed(addr)
#define RD_REG_DWORD_RELAXED(addr) readl_relaxed(addr)
-#define WRT_REG_BYTE(addr, data) writeb(data,addr)
-#define WRT_REG_WORD(addr, data) writew(data,addr)
-#define WRT_REG_DWORD(addr, data) writel(data,addr)
+#define WRT_REG_BYTE(addr, data) writeb(data, addr)
+#define WRT_REG_WORD(addr, data) writew(data, addr)
+#define WRT_REG_DWORD(addr, data) writel(data, addr)
/*
* ISP83XX specific remote register addresses
@@ -206,7 +221,7 @@
* 133Mhz slot.
*/
#define RD_REG_WORD_PIO(addr) (inw((unsigned long)addr))
-#define WRT_REG_WORD_PIO(addr, data) (outw(data,(unsigned long)addr))
+#define WRT_REG_WORD_PIO(addr, data) (outw(data, (unsigned long)addr))
/*
* Fibre Channel device definitions.
@@ -302,7 +317,8 @@ struct srb_cmd {
uint32_t request_sense_length;
uint32_t fw_sense_length;
uint8_t *request_sense_ptr;
- void *ctx;
+ struct ct6_dsd *ct6_ctx;
+ struct crc_context *crc_ctx;
};
/*
@@ -314,6 +330,7 @@ struct srb_cmd {
#define SRB_CRC_PROT_DMA_VALID BIT_4 /* DIF: prot DMA valid */
#define SRB_CRC_CTX_DSD_VALID BIT_5 /* DIF: dsd_list valid */
#define SRB_WAKEUP_ON_COMP BIT_6
+#define SRB_DIF_BUNDL_DMA_VALID BIT_7 /* DIF: DMA list valid */
/* To identify if a srb is of T10-CRC type. @sp => srb_t pointer */
#define IS_PROT_IO(sp) (sp->flags & SRB_CRC_CTX_DSD_VALID)
@@ -341,6 +358,51 @@ typedef union {
} port_id_t;
#define INVALID_PORT_ID 0xFFFFFF
+static inline le_id_t be_id_to_le(be_id_t id)
+{
+ le_id_t res;
+
+ res.domain = id.domain;
+ res.area = id.area;
+ res.al_pa = id.al_pa;
+
+ return res;
+}
+
+static inline be_id_t le_id_to_be(le_id_t id)
+{
+ be_id_t res;
+
+ res.domain = id.domain;
+ res.area = id.area;
+ res.al_pa = id.al_pa;
+
+ return res;
+}
+
+static inline port_id_t be_to_port_id(be_id_t id)
+{
+ port_id_t res;
+
+ res.b.domain = id.domain;
+ res.b.area = id.area;
+ res.b.al_pa = id.al_pa;
+ res.b.rsvd_1 = 0;
+
+ return res;
+}
+
+static inline be_id_t port_id_to_be_id(port_id_t port_id)
+{
+ be_id_t res;
+
+ res.domain = port_id.b.domain;
+ res.area = port_id.b.area;
+ res.al_pa = port_id.b.al_pa;
+
+ return res;
+}
+
struct els_logo_payload {
uint8_t opcode;
uint8_t rsvd[3];
@@ -393,7 +455,7 @@ struct srb_iocb {
struct els_logo_payload *els_logo_pyld;
dma_addr_t els_logo_pyld_dma;
} els_logo;
- struct {
+ struct els_plogi {
#define ELS_DCMD_PLOGI 0x3
uint32_t flags;
uint32_t els_cmd;
@@ -530,9 +592,12 @@ typedef struct srb {
uint8_t cmd_type;
uint8_t pad[3];
atomic_t ref_count;
+ struct kref cmd_kref; /* need to migrate ref_count over to this */
+ void *priv;
wait_queue_head_t nvme_ls_waitq;
struct fc_port *fcport;
struct scsi_qla_host *vha;
+ unsigned int start_timer:1;
uint32_t handle;
uint16_t flags;
uint16_t type;
@@ -544,19 +609,28 @@ typedef struct srb {
u32 gen2; /* scratch */
int rc;
int retry_count;
- struct completion comp;
+ struct completion *comp;
union {
struct srb_iocb iocb_cmd;
struct bsg_job *bsg_job;
struct srb_cmd scmd;
} u;
- void (*done)(void *, int);
- void (*free)(void *);
+ /*
+ * Report completion status @res and call sp_put(@sp). @res is
+ * an NVMe status code, a SCSI result (e.g. DID_OK << 16) or a
+ * QLA_* status value.
+ */
+ void (*done)(struct srb *sp, int res);
+ /* Stop the timer and free @sp. Only used by the FCP code. */
+ void (*free)(struct srb *sp);
+ /*
+ * Call nvme_private->fd->done() and free @sp. Only used by the NVMe
+ * code.
+ */
+ void (*put_fn)(struct kref *kref);
} srb_t;
#define GET_CMD_SP(sp) (sp->u.scmd.cmd)
-#define SET_CMD_SP(sp, cmd) (sp->u.scmd.cmd = cmd)
-#define GET_CMD_CTX_SP(sp) (sp->u.scmd.ctx)
#define GET_CMD_SENSE_LEN(sp) \
(sp->u.scmd.request_sense_length)
@@ -916,6 +990,11 @@ struct mbx_cmd_32 {
#define MBS_LINK_DOWN_ERROR 0x400B
#define MBS_DIAG_ECHO_TEST_ERROR 0x400C
+static inline bool qla2xxx_is_valid_mbs(unsigned int mbs)
+{
+ return MBS_COMMAND_COMPLETE <= mbs && mbs <= MBS_DIAG_ECHO_TEST_ERROR;
+}
+
/*
* ISP mailbox asynchronous event status codes
*/
@@ -1032,6 +1111,7 @@ struct mbx_cmd_32 {
#define MBC_GET_FIRMWARE_VERSION 8 /* Get firmware revision. */
#define MBC_LOAD_RISC_RAM 9 /* Load RAM command. */
#define MBC_DUMP_RISC_RAM 0xa /* Dump RAM command. */
+#define MBC_SECURE_FLASH_UPDATE 0xa /* Secure Flash Update(28xx) */
#define MBC_LOAD_RISC_RAM_EXTENDED 0xb /* Load RAM extended. */
#define MBC_DUMP_RISC_RAM_EXTENDED 0xc /* Dump RAM extended. */
#define MBC_WRITE_RAM_WORD_EXTENDED 0xd /* Write RAM word extended */
@@ -1202,6 +1282,10 @@ struct mbx_cmd_32 {
#define QLA27XX_IMG_STATUS_VER_MAJOR 0x01
#define QLA27XX_IMG_STATUS_VER_MINOR 0x00
#define QLA27XX_IMG_STATUS_SIGN 0xFACEFADE
+#define QLA28XX_IMG_STATUS_SIGN 0xFACEFADF
+#define QLA28XX_IMG_STATUS_SIGN 0xFACEFADF
+#define QLA28XX_AUX_IMG_STATUS_SIGN 0xFACEFAED
+#define QLA27XX_DEFAULT_IMAGE 0
#define QLA27XX_PRIMARY_IMAGE 1
#define QLA27XX_SECONDARY_IMAGE 2
@@ -1322,8 +1406,8 @@ typedef struct {
uint16_t response_q_inpointer;
uint16_t request_q_length;
uint16_t response_q_length;
- uint32_t request_q_address[2];
- uint32_t response_q_address[2];
+ __le64 request_q_address __packed;
+ __le64 response_q_address __packed;
uint16_t lun_enables;
uint8_t command_resource_count;
@@ -1748,12 +1832,10 @@ typedef struct {
uint16_t dseg_count; /* Data segment count. */
uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */
uint32_t byte_count; /* Total byte count. */
- uint32_t dseg_0_address; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
- uint32_t dseg_2_address; /* Data segment 2 address. */
- uint32_t dseg_2_length; /* Data segment 2 length. */
+ union {
+ struct dsd32 dsd32[3];
+ struct dsd64 dsd64[2];
+ };
} cmd_entry_t;
/*
@@ -1774,10 +1856,7 @@ typedef struct {
uint16_t dseg_count; /* Data segment count. */
uint8_t scsi_cdb[MAX_CMDSZ]; /* SCSI command words. */
uint32_t byte_count; /* Total byte count. */
- uint32_t dseg_0_address[2]; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address[2]; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
+ struct dsd64 dsd[2];
} cmd_a64_entry_t, request_t;
/*
@@ -1790,20 +1869,7 @@ typedef struct {
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
uint32_t reserved;
- uint32_t dseg_0_address; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
- uint32_t dseg_2_address; /* Data segment 2 address. */
- uint32_t dseg_2_length; /* Data segment 2 length. */
- uint32_t dseg_3_address; /* Data segment 3 address. */
- uint32_t dseg_3_length; /* Data segment 3 length. */
- uint32_t dseg_4_address; /* Data segment 4 address. */
- uint32_t dseg_4_length; /* Data segment 4 length. */
- uint32_t dseg_5_address; /* Data segment 5 address. */
- uint32_t dseg_5_length; /* Data segment 5 length. */
- uint32_t dseg_6_address; /* Data segment 6 address. */
- uint32_t dseg_6_length; /* Data segment 6 length. */
+ struct dsd32 dsd[7];
} cont_entry_t;
/*
@@ -1815,16 +1881,7 @@ typedef struct {
uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
- uint32_t dseg_0_address[2]; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address[2]; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
- uint32_t dseg_2_address [2]; /* Data segment 2 address. */
- uint32_t dseg_2_length; /* Data segment 2 length. */
- uint32_t dseg_3_address[2]; /* Data segment 3 address. */
- uint32_t dseg_3_length; /* Data segment 3 length. */
- uint32_t dseg_4_address[2]; /* Data segment 4 address. */
- uint32_t dseg_4_length; /* Data segment 4 length. */
+ struct dsd64 dsd[5];
} cont_a64_entry_t;
#define PO_MODE_DIF_INSERT 0
@@ -1868,8 +1925,7 @@ struct crc_context {
uint16_t reserved_2;
uint16_t reserved_3;
uint32_t reserved_4;
- uint32_t data_address[2];
- uint32_t data_length;
+ struct dsd64 data_dsd[1];
uint32_t reserved_5[2];
uint32_t reserved_6;
} nobundling;
@@ -1879,11 +1935,8 @@ struct crc_context {
uint16_t reserved_1;
__le16 dseg_count; /* Data segment count */
uint32_t reserved_2;
- uint32_t data_address[2];
- uint32_t data_length;
- uint32_t dif_address[2];
- uint32_t dif_length; /* Data segment 0
- * length */
+ struct dsd64 data_dsd[1];
+ struct dsd64 dif_dsd;
} bundling;
} u;
@@ -1892,6 +1945,13 @@ struct crc_context {
/* List of DMA context transfers */
struct list_head dsd_list;
+ /* List of DIF Bundling context DMA address */
+ struct list_head ldif_dsd_list;
+ u8 no_ldif_dsd;
+
+ struct list_head ldif_dma_hndl_list;
+ u32 dif_bundl_len;
+ u8 no_dif_bundl;
/* This structure should not exceed 512 bytes */
};
@@ -2075,10 +2135,8 @@ typedef struct {
uint32_t handle2;
uint32_t rsp_bytecount;
uint32_t req_bytecount;
- uint32_t dseg_req_address[2]; /* Data segment 0 address. */
- uint32_t dseg_req_length; /* Data segment 0 length. */
- uint32_t dseg_rsp_address[2]; /* Data segment 1 address. */
- uint32_t dseg_rsp_length; /* Data segment 1 length. */
+ struct dsd64 req_dsd;
+ struct dsd64 rsp_dsd;
} ms_iocb_entry_t;
@@ -2250,7 +2308,10 @@ typedef enum {
FCT_BROADCAST,
FCT_INITIATOR,
FCT_TARGET,
- FCT_NVME
+ FCT_NVME_INITIATOR = 0x10,
+ FCT_NVME_TARGET = 0x20,
+ FCT_NVME_DISCOVERY = 0x40,
+ FCT_NVME = 0xf0,
} fc_port_type_t;
enum qla_sess_deletion {
@@ -2302,22 +2363,6 @@ enum login_state { /* FW control Target side */
DSC_LS_LOGO_PEND,
};
-enum fcport_mgt_event {
- FCME_RELOGIN = 1,
- FCME_RSCN,
- FCME_PLOGI_DONE, /* Initiator side sent LLIOCB */
- FCME_PRLI_DONE,
- FCME_GNL_DONE,
- FCME_GPSC_DONE,
- FCME_GPDB_DONE,
- FCME_GPNID_DONE,
- FCME_GFFID_DONE,
- FCME_ADISC_DONE,
- FCME_GNNID_DONE,
- FCME_GFPNID_DONE,
- FCME_ELS_PLOGI_DONE,
-};
-
enum rscn_addr_format {
RSCN_PORT_ADDR,
RSCN_AREA_ADDR,
@@ -2352,14 +2397,15 @@ typedef struct fc_port {
unsigned int id_changed:1;
unsigned int scan_needed:1;
- struct work_struct nvme_del_work;
struct completion nvme_del_done;
uint32_t nvme_prli_service_param;
#define NVME_PRLI_SP_CONF BIT_7
#define NVME_PRLI_SP_INITIATOR BIT_5
#define NVME_PRLI_SP_TARGET BIT_4
#define NVME_PRLI_SP_DISCOVERY BIT_3
+#define NVME_PRLI_SP_FIRST_BURST BIT_0
uint8_t nvme_flag;
+ uint32_t nvme_first_burst_size;
#define NVME_FLAG_REGISTERED 4
#define NVME_FLAG_DELETING 2
#define NVME_FLAG_RESETTING 1
@@ -2434,7 +2480,6 @@ typedef struct fc_port {
#define QLA_FCPORT_FOUND 2
struct event_arg {
- enum fcport_mgt_event event;
fc_port_t *fcport;
srb_t *sp;
port_id_t id;
@@ -2453,13 +2498,7 @@ struct event_arg {
#define FCS_DEVICE_LOST 3
#define FCS_ONLINE 4
-static const char * const port_state_str[] = {
- "Unknown",
- "UNCONFIGURED",
- "DEAD",
- "LOST",
- "ONLINE"
-};
+extern const char *const port_state_str[5];
/*
* FC port flags.
@@ -2662,6 +2701,7 @@ struct ct_fdmiv2_hba_attributes {
#define FDMI_PORT_SPEED_8GB 0x10
#define FDMI_PORT_SPEED_16GB 0x20
#define FDMI_PORT_SPEED_32GB 0x40
+#define FDMI_PORT_SPEED_64GB 0x80
#define FDMI_PORT_SPEED_UNKNOWN 0x8000
#define FC_CLASS_2 0x04
@@ -2762,7 +2802,7 @@ struct ct_sns_req {
/* GA_NXT, GPN_ID, GNN_ID, GFT_ID, GFPN_ID */
struct {
uint8_t reserved;
- uint8_t port_id[3];
+ be_id_t port_id;
} port_id;
struct {
@@ -2781,13 +2821,13 @@ struct ct_sns_req {
struct {
uint8_t reserved;
- uint8_t port_id[3];
+ be_id_t port_id;
uint8_t fc4_types[32];
} rft_id;
struct {
uint8_t reserved;
- uint8_t port_id[3];
+ be_id_t port_id;
uint16_t reserved2;
uint8_t fc4_feature;
uint8_t fc4_type;
@@ -2795,7 +2835,7 @@ struct ct_sns_req {
struct {
uint8_t reserved;
- uint8_t port_id[3];
+ be_id_t port_id;
uint8_t node_name[8];
} rnn_id;
@@ -2882,7 +2922,7 @@ struct ct_rsp_hdr {
struct ct_sns_gid_pt_data {
uint8_t control_byte;
- uint8_t port_id[3];
+ be_id_t port_id;
};
/* It's the same for both GPN_FT and GNN_FT */
@@ -2912,7 +2952,7 @@ struct ct_sns_rsp {
union {
struct {
uint8_t port_type;
- uint8_t port_id[3];
+ be_id_t port_id;
uint8_t port_name[8];
uint8_t sym_port_name_len;
uint8_t sym_port_name[255];
@@ -3050,7 +3090,7 @@ struct sns_cmd_pkt {
struct {
uint16_t buffer_length;
uint16_t reserved_1;
- uint32_t buffer_address[2];
+ __le64 buffer_address __packed;
uint16_t subcommand_length;
uint16_t reserved_2;
uint16_t subcommand;
@@ -3120,15 +3160,15 @@ struct rsp_que;
struct isp_operations {
int (*pci_config) (struct scsi_qla_host *);
- void (*reset_chip) (struct scsi_qla_host *);
+ int (*reset_chip)(struct scsi_qla_host *);
int (*chip_diag) (struct scsi_qla_host *);
void (*config_rings) (struct scsi_qla_host *);
- void (*reset_adapter) (struct scsi_qla_host *);
+ int (*reset_adapter)(struct scsi_qla_host *);
int (*nvram_config) (struct scsi_qla_host *);
void (*update_fw_options) (struct scsi_qla_host *);
int (*load_risc) (struct scsi_qla_host *, uint32_t *);
- char * (*pci_info_str) (struct scsi_qla_host *, char *);
+ char * (*pci_info_str)(struct scsi_qla_host *, char *, size_t);
char * (*fw_version_str)(struct scsi_qla_host *, char *, size_t);
irq_handler_t intr_handler;
@@ -3149,9 +3189,9 @@ struct isp_operations {
void *(*prep_ms_fdmi_iocb) (struct scsi_qla_host *, uint32_t,
uint32_t);
- uint8_t *(*read_nvram) (struct scsi_qla_host *, uint8_t *,
+ uint8_t *(*read_nvram)(struct scsi_qla_host *, void *,
uint32_t, uint32_t);
- int (*write_nvram) (struct scsi_qla_host *, uint8_t *, uint32_t,
+ int (*write_nvram)(struct scsi_qla_host *, void *, uint32_t,
uint32_t);
void (*fw_dump) (struct scsi_qla_host *, int);
@@ -3160,16 +3200,16 @@ struct isp_operations {
int (*beacon_off) (struct scsi_qla_host *);
void (*beacon_blink) (struct scsi_qla_host *);
- uint8_t * (*read_optrom) (struct scsi_qla_host *, uint8_t *,
+ void *(*read_optrom)(struct scsi_qla_host *, void *,
uint32_t, uint32_t);
- int (*write_optrom) (struct scsi_qla_host *, uint8_t *, uint32_t,
+ int (*write_optrom)(struct scsi_qla_host *, void *, uint32_t,
uint32_t);
int (*get_flash_version) (struct scsi_qla_host *, void *);
int (*start_scsi) (srb_t *);
int (*start_scsi_mq) (srb_t *);
int (*abort_isp) (struct scsi_qla_host *);
- int (*iospace_config)(struct qla_hw_data*);
+ int (*iospace_config)(struct qla_hw_data *);
int (*initialize_adapter)(struct scsi_qla_host *);
};
@@ -3358,7 +3398,8 @@ struct qla_tc_param {
#define QLA_MQ_SIZE 32
#define QLA_MAX_QUEUES 256
#define ISP_QUE_REG(ha, id) \
- ((ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) ? \
+ ((ha->mqenable || IS_QLA83XX(ha) || \
+ IS_QLA27XX(ha) || IS_QLA28XX(ha)) ? \
((void __iomem *)ha->mqiobase + (QLA_QUE_PAGE * id)) :\
((void __iomem *)ha->iobase))
#define QLA_REQ_QUE_ID(tag) \
@@ -3611,6 +3652,8 @@ struct qla_hw_data {
uint32_t rida_fmt2:1;
uint32_t purge_mbox:1;
uint32_t n2n_bigger:1;
+ uint32_t secure_adapter:1;
+ uint32_t secure_fw:1;
} flags;
uint16_t max_exchg;
@@ -3688,12 +3731,15 @@ struct qla_hw_data {
#define PORT_SPEED_UNKNOWN 0xFFFF
#define PORT_SPEED_1GB 0x00
#define PORT_SPEED_2GB 0x01
+#define PORT_SPEED_AUTO 0x02
#define PORT_SPEED_4GB 0x03
#define PORT_SPEED_8GB 0x04
#define PORT_SPEED_16GB 0x05
#define PORT_SPEED_32GB 0x06
+#define PORT_SPEED_64GB 0x07
#define PORT_SPEED_10GB 0x13
uint16_t link_data_rate; /* F/W operating speed */
+ uint16_t set_data_rate; /* Set by user */
uint8_t current_topology;
uint8_t prev_topology;
@@ -3717,6 +3763,11 @@ struct qla_hw_data {
#define PCI_DEVICE_ID_QLOGIC_ISP2071 0x2071
#define PCI_DEVICE_ID_QLOGIC_ISP2271 0x2271
#define PCI_DEVICE_ID_QLOGIC_ISP2261 0x2261
+#define PCI_DEVICE_ID_QLOGIC_ISP2061 0x2061
+#define PCI_DEVICE_ID_QLOGIC_ISP2081 0x2081
+#define PCI_DEVICE_ID_QLOGIC_ISP2089 0x2089
+#define PCI_DEVICE_ID_QLOGIC_ISP2281 0x2281
+#define PCI_DEVICE_ID_QLOGIC_ISP2289 0x2289
uint32_t isp_type;
#define DT_ISP2100 BIT_0
@@ -3741,7 +3792,12 @@ struct qla_hw_data {
#define DT_ISP2071 BIT_19
#define DT_ISP2271 BIT_20
#define DT_ISP2261 BIT_21
-#define DT_ISP_LAST (DT_ISP2261 << 1)
+#define DT_ISP2061 BIT_22
+#define DT_ISP2081 BIT_23
+#define DT_ISP2089 BIT_24
+#define DT_ISP2281 BIT_25
+#define DT_ISP2289 BIT_26
+#define DT_ISP_LAST (DT_ISP2289 << 1)
uint32_t device_type;
#define DT_T10_PI BIT_25
@@ -3776,6 +3832,8 @@ struct qla_hw_data {
#define IS_QLA2071(ha) (DT_MASK(ha) & DT_ISP2071)
#define IS_QLA2271(ha) (DT_MASK(ha) & DT_ISP2271)
#define IS_QLA2261(ha) (DT_MASK(ha) & DT_ISP2261)
+#define IS_QLA2081(ha) (DT_MASK(ha) & DT_ISP2081)
+#define IS_QLA2281(ha) (DT_MASK(ha) & DT_ISP2281)
#define IS_QLA23XX(ha) (IS_QLA2300(ha) || IS_QLA2312(ha) || IS_QLA2322(ha) || \
IS_QLA6312(ha) || IS_QLA6322(ha))
@@ -3785,6 +3843,7 @@ struct qla_hw_data {
#define IS_QLA83XX(ha) (IS_QLA2031(ha) || IS_QLA8031(ha))
#define IS_QLA84XX(ha) (IS_QLA8432(ha))
#define IS_QLA27XX(ha) (IS_QLA2071(ha) || IS_QLA2271(ha) || IS_QLA2261(ha))
+#define IS_QLA28XX(ha) (IS_QLA2081(ha) || IS_QLA2281(ha))
#define IS_QLA24XX_TYPE(ha) (IS_QLA24XX(ha) || IS_QLA54XX(ha) || \
IS_QLA84XX(ha))
#define IS_CNA_CAPABLE(ha) (IS_QLA81XX(ha) || IS_QLA82XX(ha) || \
@@ -3793,14 +3852,15 @@ struct qla_hw_data {
#define IS_QLA2XXX_MIDTYPE(ha) (IS_QLA24XX(ha) || IS_QLA84XX(ha) || \
IS_QLA25XX(ha) || IS_QLA81XX(ha) || \
IS_QLA82XX(ha) || IS_QLA83XX(ha) || \
- IS_QLA8044(ha) || IS_QLA27XX(ha))
+ IS_QLA8044(ha) || IS_QLA27XX(ha) || \
+ IS_QLA28XX(ha))
#define IS_MSIX_NACK_CAPABLE(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha) || \
- IS_QLA27XX(ha))
+ IS_QLA27XX(ha) || IS_QLA28XX(ha))
#define IS_NOPOLLING_TYPE(ha) (IS_QLA81XX(ha) && (ha)->flags.msix_enabled)
#define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha) || \
- IS_QLA27XX(ha))
+ IS_QLA27XX(ha) || IS_QLA28XX(ha))
#define IS_NOCACHE_VPD_TYPE(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha) || \
- IS_QLA27XX(ha))
+ IS_QLA27XX(ha) || IS_QLA28XX(ha))
#define IS_ALOGIO_CAPABLE(ha) (IS_QLA23XX(ha) || IS_FWI2_CAPABLE(ha))
#define IS_T10_PI_CAPABLE(ha) ((ha)->device_type & DT_T10_PI)
@@ -3811,28 +3871,34 @@ struct qla_hw_data {
#define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS)
#define IS_CT6_SUPPORTED(ha) ((ha)->device_type & DT_CT6_SUPPORTED)
#define IS_MQUE_CAPABLE(ha) ((ha)->mqenable || IS_QLA83XX(ha) || \
- IS_QLA27XX(ha))
-#define IS_BIDI_CAPABLE(ha) ((IS_QLA25XX(ha) || IS_QLA2031(ha)))
+ IS_QLA27XX(ha) || IS_QLA28XX(ha))
+#define IS_BIDI_CAPABLE(ha) \
+ (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
/* Bit 21 of fw_attributes decides the MCTP capabilities */
#define IS_MCTP_CAPABLE(ha) (IS_QLA2031(ha) && \
((ha)->fw_attributes_ext[0] & BIT_0))
#define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
#define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
#define IS_PI_DIFB_DIX0_CAPABLE(ha) (0)
-#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
+ IS_QLA28XX(ha))
#define IS_PI_SPLIT_DET_CAPABLE(ha) (IS_PI_SPLIT_DET_CAPABLE_HBA(ha) && \
(((ha)->fw_attributes_h << 16 | (ha)->fw_attributes) & BIT_22))
-#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
+ IS_QLA28XX(ha))
#define IS_TGT_MODE_CAPABLE(ha) (ha->tgt.atio_q_length)
-#define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha))
-#define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
-#define IS_FAWWN_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+#define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha) || IS_QLA28XX(ha))
+#define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
+ IS_QLA28XX(ha))
+#define IS_FAWWN_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
+ IS_QLA28XX(ha))
#define IS_EXCHG_OFFLD_CAPABLE(ha) \
- (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+ (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
#define IS_EXLOGIN_OFFLD_CAPABLE(ha) \
- (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+ (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) || \
+ IS_QLA27XX(ha) || IS_QLA28XX(ha))
#define USE_ASYNC_SCAN(ha) (IS_QLA25XX(ha) || IS_QLA81XX(ha) ||\
- IS_QLA83XX(ha) || IS_QLA27XX(ha))
+ IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
/* HBA serial number */
uint8_t serial0;
@@ -3841,7 +3907,7 @@ struct qla_hw_data {
/* NVRAM configuration data */
#define MAX_NVRAM_SIZE 4096
-#define VPD_OFFSET MAX_NVRAM_SIZE / 2
+#define VPD_OFFSET (MAX_NVRAM_SIZE / 2)
uint16_t nvram_size;
uint16_t nvram_base;
void *nvram;
@@ -3876,6 +3942,9 @@ struct qla_hw_data {
void *sfp_data;
dma_addr_t sfp_data_dma;
+ void *flt;
+ dma_addr_t flt_dma;
+
#define XGMAC_DATA_SIZE 4096
void *xgmac_data;
dma_addr_t xgmac_data_dma;
@@ -3958,6 +4027,7 @@ struct qla_hw_data {
uint16_t fw_subminor_version;
uint16_t fw_attributes;
uint16_t fw_attributes_h;
+#define FW_ATTR_H_NVME_FBURST BIT_1
#define FW_ATTR_H_NVME BIT_10
#define FW_ATTR_H_NVME_UPDATED BIT_14
@@ -3986,18 +4056,23 @@ struct qla_hw_data {
uint8_t fw_seriallink_options[4];
uint16_t fw_seriallink_options24[4];
+ uint8_t serdes_version[3];
uint8_t mpi_version[3];
uint32_t mpi_capabilities;
uint8_t phy_version[3];
uint8_t pep_version[3];
/* Firmware dump template */
- void *fw_dump_template;
- uint32_t fw_dump_template_len;
- /* Firmware dump information. */
+ struct fwdt {
+ void *template;
+ ulong length;
+ ulong dump_size;
+ } fwdt[2];
struct qla2xxx_fw_dump *fw_dump;
uint32_t fw_dump_len;
- int fw_dumped;
+ u32 fw_dump_alloc_len;
+ bool fw_dumped;
+ bool fw_dump_mpi;
unsigned long fw_dump_cap_flags;
#define RISC_PAUSE_CMPL 0
#define DMA_SHUTDOWN_CMPL 1
@@ -4036,7 +4111,6 @@ struct qla_hw_data {
uint16_t product_id[4];
uint8_t model_number[16+1];
-#define BINZERO "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
char model_desc[80];
uint8_t adapter_id[16+1];
@@ -4076,22 +4150,28 @@ struct qla_hw_data {
uint32_t fdt_protect_sec_cmd;
uint32_t fdt_wrt_sts_reg_cmd;
- uint32_t flt_region_flt;
- uint32_t flt_region_fdt;
- uint32_t flt_region_boot;
- uint32_t flt_region_boot_sec;
- uint32_t flt_region_fw;
- uint32_t flt_region_fw_sec;
- uint32_t flt_region_vpd_nvram;
- uint32_t flt_region_vpd;
- uint32_t flt_region_vpd_sec;
- uint32_t flt_region_nvram;
- uint32_t flt_region_npiv_conf;
- uint32_t flt_region_gold_fw;
- uint32_t flt_region_fcp_prio;
- uint32_t flt_region_bootload;
- uint32_t flt_region_img_status_pri;
- uint32_t flt_region_img_status_sec;
+ struct {
+ uint32_t flt_region_flt;
+ uint32_t flt_region_fdt;
+ uint32_t flt_region_boot;
+ uint32_t flt_region_boot_sec;
+ uint32_t flt_region_fw;
+ uint32_t flt_region_fw_sec;
+ uint32_t flt_region_vpd_nvram;
+ uint32_t flt_region_vpd_nvram_sec;
+ uint32_t flt_region_vpd;
+ uint32_t flt_region_vpd_sec;
+ uint32_t flt_region_nvram;
+ uint32_t flt_region_nvram_sec;
+ uint32_t flt_region_npiv_conf;
+ uint32_t flt_region_gold_fw;
+ uint32_t flt_region_fcp_prio;
+ uint32_t flt_region_bootload;
+ uint32_t flt_region_img_status_pri;
+ uint32_t flt_region_img_status_sec;
+ uint32_t flt_region_aux_img_status_pri;
+ uint32_t flt_region_aux_img_status_sec;
+ };
uint8_t active_image;
/* Needed for BEACON */
@@ -4184,15 +4264,46 @@ struct qla_hw_data {
struct qlt_hw_data tgt;
int allow_cna_fw_dump;
uint32_t fw_ability_mask;
- uint16_t min_link_speed;
- uint16_t max_speed_sup;
+ uint16_t min_supported_speed;
+ uint16_t max_supported_speed;
+
+ /* DMA pool for the DIF bundling buffers */
+ struct dma_pool *dif_bundl_pool;
+ #define DIF_BUNDLING_DMA_POOL_SIZE 1024
+ struct {
+ struct {
+ struct list_head head;
+ uint count;
+ } good;
+ struct {
+ struct list_head head;
+ uint count;
+ } unusable;
+ } pool;
+
+ unsigned long long dif_bundle_crossed_pages;
+ unsigned long long dif_bundle_reads;
+ unsigned long long dif_bundle_writes;
+ unsigned long long dif_bundle_kallocs;
+ unsigned long long dif_bundle_dma_allocs;
atomic_t nvme_active_aen_cnt;
uint16_t nvme_last_rptd_aen; /* Last recorded aen count */
atomic_t zio_threshold;
uint16_t last_zio_threshold;
-#define DEFAULT_ZIO_THRESHOLD 64
+
+#define DEFAULT_ZIO_THRESHOLD 5
+};
+
+struct active_regions {
+ uint8_t global;
+ struct {
+ uint8_t board_config;
+ uint8_t vpd_nvram;
+ uint8_t npiv_config_0_1;
+ uint8_t npiv_config_2_3;
+ } aux;
};
#define FW_ABILITY_MAX_SPEED_MASK 0xFUL
@@ -4201,6 +4312,10 @@ struct qla_hw_data {
#define FW_ABILITY_MAX_SPEED(ha) \
(ha->fw_ability_mask & FW_ABILITY_MAX_SPEED_MASK)
+#define QLA_GET_DATA_RATE 0
+#define QLA_SET_DATA_RATE_NOLR 1
+#define QLA_SET_DATA_RATE_LR 2 /* Set speed and initiate LR */
+
/*
* Qlogic scsi host structure
*/
@@ -4232,6 +4347,7 @@ typedef struct scsi_qla_host {
uint32_t qpairs_req_created:1;
uint32_t qpairs_rsp_created:1;
uint32_t nvme_enabled:1;
+ uint32_t nvme_first_burst:1;
} flags;
atomic_t loop_state;
@@ -4277,6 +4393,7 @@ typedef struct scsi_qla_host {
#define N2N_LOGIN_NEEDED 30
#define IOCB_WORK_ACTIVE 31
#define SET_ZIO_THRESHOLD_NEEDED 32
+#define ISP_ABORT_TO_ROM 33
unsigned long pci_flags;
#define PFLG_DISCONNECTED 0 /* PCI device removed */
@@ -4318,7 +4435,6 @@ typedef struct scsi_qla_host {
struct nvme_fc_local_port *nvme_local_port;
struct completion nvme_del_done;
- struct list_head nvme_rport_list;
uint16_t fcoe_vlan_id;
uint16_t fcoe_fcf_idx;
@@ -4391,7 +4507,7 @@ typedef struct scsi_qla_host {
int fcport_count;
wait_queue_head_t fcport_waitQ;
wait_queue_head_t vref_waitq;
- uint8_t min_link_speed_feat;
+ uint8_t min_supported_speed;
uint8_t n2n_node_name[WWN_SIZE];
uint8_t n2n_port_name[WWN_SIZE];
uint16_t n2n_id;
@@ -4401,14 +4517,21 @@ typedef struct scsi_qla_host {
struct qla27xx_image_status {
uint8_t image_status_mask;
- uint16_t generation_number;
- uint8_t reserved[3];
- uint8_t ver_minor;
+ uint16_t generation;
uint8_t ver_major;
+ uint8_t ver_minor;
+ uint8_t bitmap; /* 28xx only */
+ uint8_t reserved[2];
uint32_t checksum;
uint32_t signature;
} __packed;
+/* 28xx aux image status bimap values */
+#define QLA28XX_AUX_IMG_BOARD_CONFIG BIT_0
+#define QLA28XX_AUX_IMG_VPD_NVRAM BIT_1
+#define QLA28XX_AUX_IMG_NPIV_CONFIG_0_1 BIT_2
+#define QLA28XX_AUX_IMG_NPIV_CONFIG_2_3 BIT_3
+
#define SET_VP_IDX 1
#define SET_AL_PA 2
#define RESET_VP_IDX 3
@@ -4455,6 +4578,24 @@ struct qla2_sgx {
} \
}
+
+#define SFUB_CHECKSUM_SIZE 4
+
+struct secure_flash_update_block {
+ uint32_t block_info;
+ uint32_t signature_lo;
+ uint32_t signature_hi;
+ uint32_t signature_upper[0x3e];
+};
+
+struct secure_flash_update_block_pk {
+ uint32_t block_info;
+ uint32_t signature_lo;
+ uint32_t signature_hi;
+ uint32_t signature_upper[0x3e];
+ uint32_t public_key[0x41];
+};
+
/*
* Macros to help code, maintain, etc.
*/
@@ -4542,6 +4683,7 @@ struct qla2_sgx {
#define QLA_SUSPENDED 0x106
#define QLA_BUSY 0x107
#define QLA_ALREADY_REGISTERED 0x109
+#define QLA_OS_TIMER_EXPIRED 0x10a
#define NVRAM_DELAY() udelay(10)
@@ -4555,6 +4697,7 @@ struct qla2_sgx {
#define OPTROM_SIZE_81XX 0x400000
#define OPTROM_SIZE_82XX 0x800000
#define OPTROM_SIZE_83XX 0x1000000
+#define OPTROM_SIZE_28XX 0x2000000
#define OPTROM_BURST_SIZE 0x1000
#define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4)
@@ -4651,10 +4794,13 @@ struct sff_8247_a0 {
#define AUTO_DETECT_SFP_SUPPORT(_vha)\
(ql2xautodetectsfp && !_vha->vp_idx && \
(IS_QLA25XX(_vha->hw) || IS_QLA81XX(_vha->hw) ||\
- IS_QLA83XX(_vha->hw) || IS_QLA27XX(_vha->hw)))
+ IS_QLA83XX(_vha->hw) || IS_QLA27XX(_vha->hw) || \
+ IS_QLA28XX(_vha->hw)))
+
+#define FLASH_SEMAPHORE_REGISTER_ADDR 0x00101016
#define USER_CTRL_IRQ(_ha) (ql2xuctrlirq && QLA_TGT_MODE_ENABLED() && \
- (IS_QLA27XX(_ha) || IS_QLA83XX(_ha)))
+ (IS_QLA27XX(_ha) || IS_QLA28XX(_ha) || IS_QLA83XX(_ha)))
#define SAVE_TOPO(_ha) { \
if (_ha->current_topology) \
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index d647760d4804..0a6fb359f4d5 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -41,6 +41,7 @@ static int
qla2x00_dfs_tgt_sess_open(struct inode *inode, struct file *file)
{
scsi_qla_host_t *vha = inode->i_private;
+
return single_open(file, qla2x00_dfs_tgt_sess_show, vha);
}
@@ -56,10 +57,9 @@ qla2x00_dfs_tgt_port_database_show(struct seq_file *s, void *unused)
{
scsi_qla_host_t *vha = s->private;
struct qla_hw_data *ha = vha->hw;
- struct gid_list_info *gid_list;
+ struct gid_list_info *gid_list, *gid;
dma_addr_t gid_list_dma;
fc_port_t fc_port;
- char *id_iter;
int rc, i;
uint16_t entries, loop_id;
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
@@ -81,13 +81,11 @@ qla2x00_dfs_tgt_port_database_show(struct seq_file *s, void *unused)
if (rc != QLA_SUCCESS)
goto out_free_id_list;
- id_iter = (char *)gid_list;
+ gid = gid_list;
seq_puts(s, "Port Name Port ID Loop ID\n");
for (i = 0; i < entries; i++) {
- struct gid_list_info *gid =
- (struct gid_list_info *)id_iter;
loop_id = le16_to_cpu(gid->loop_id);
memset(&fc_port, 0, sizeof(fc_port_t));
@@ -98,7 +96,7 @@ qla2x00_dfs_tgt_port_database_show(struct seq_file *s, void *unused)
fc_port.port_name, fc_port.d_id.b.domain,
fc_port.d_id.b.area, fc_port.d_id.b.al_pa,
fc_port.loop_id);
- id_iter += ha->gid_list_info_size;
+ gid = (void *)gid + ha->gid_list_info_size;
}
out_free_id_list:
dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha),
@@ -161,6 +159,7 @@ static int
qla_dfs_fw_resource_cnt_open(struct inode *inode, struct file *file)
{
struct scsi_qla_host *vha = inode->i_private;
+
return single_open(file, qla_dfs_fw_resource_cnt_show, vha);
}
@@ -250,6 +249,7 @@ static int
qla_dfs_tgt_counters_open(struct inode *inode, struct file *file)
{
struct scsi_qla_host *vha = inode->i_private;
+
return single_open(file, qla_dfs_tgt_counters_show, vha);
}
@@ -386,7 +386,7 @@ qla_dfs_naqp_write(struct file *file, const char __user *buffer,
int rc = 0;
unsigned long num_act_qp;
- if (!(IS_QLA27XX(ha) || IS_QLA83XX(ha))) {
+ if (!(IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha))) {
pr_err("host%ld: this adapter does not support Multi Q.",
vha->host_no);
return -EINVAL;
@@ -438,7 +438,7 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha)
struct qla_hw_data *ha = vha->hw;
if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
- !IS_QLA27XX(ha))
+ !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
goto out;
if (!ha->fce)
goto out;
@@ -448,11 +448,6 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha)
atomic_set(&qla2x00_dfs_root_count, 0);
qla2x00_dfs_root = debugfs_create_dir(QLA2XXX_DRIVER_NAME, NULL);
- if (!qla2x00_dfs_root) {
- ql_log(ql_log_warn, vha, 0x00f7,
- "Unable to create debugfs root directory.\n");
- goto out;
- }
create_dir:
if (ha->dfs_dir)
@@ -460,64 +455,28 @@ create_dir:
mutex_init(&ha->fce_mutex);
ha->dfs_dir = debugfs_create_dir(vha->host_str, qla2x00_dfs_root);
- if (!ha->dfs_dir) {
- ql_log(ql_log_warn, vha, 0x00f8,
- "Unable to create debugfs ha directory.\n");
- goto out;
- }
atomic_inc(&qla2x00_dfs_root_count);
create_nodes:
ha->dfs_fw_resource_cnt = debugfs_create_file("fw_resource_count",
S_IRUSR, ha->dfs_dir, vha, &dfs_fw_resource_cnt_ops);
- if (!ha->dfs_fw_resource_cnt) {
- ql_log(ql_log_warn, vha, 0x00fd,
- "Unable to create debugFS fw_resource_count node.\n");
- goto out;
- }
ha->dfs_tgt_counters = debugfs_create_file("tgt_counters", S_IRUSR,
ha->dfs_dir, vha, &dfs_tgt_counters_ops);
- if (!ha->dfs_tgt_counters) {
- ql_log(ql_log_warn, vha, 0xd301,
- "Unable to create debugFS tgt_counters node.\n");
- goto out;
- }
ha->tgt.dfs_tgt_port_database = debugfs_create_file("tgt_port_database",
S_IRUSR, ha->dfs_dir, vha, &dfs_tgt_port_database_ops);
- if (!ha->tgt.dfs_tgt_port_database) {
- ql_log(ql_log_warn, vha, 0xd03f,
- "Unable to create debugFS tgt_port_database node.\n");
- goto out;
- }
ha->dfs_fce = debugfs_create_file("fce", S_IRUSR, ha->dfs_dir, vha,
&dfs_fce_ops);
- if (!ha->dfs_fce) {
- ql_log(ql_log_warn, vha, 0x00f9,
- "Unable to create debugfs fce node.\n");
- goto out;
- }
ha->tgt.dfs_tgt_sess = debugfs_create_file("tgt_sess",
S_IRUSR, ha->dfs_dir, vha, &dfs_tgt_sess_ops);
- if (!ha->tgt.dfs_tgt_sess) {
- ql_log(ql_log_warn, vha, 0xd040,
- "Unable to create debugFS tgt_sess node.\n");
- goto out;
- }
- if (IS_QLA27XX(ha) || IS_QLA83XX(ha)) {
+ if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha))
ha->tgt.dfs_naqp = debugfs_create_file("naqp",
0400, ha->dfs_dir, vha, &dfs_naqp_ops);
- if (!ha->tgt.dfs_naqp) {
- ql_log(ql_log_warn, vha, 0xd011,
- "Unable to create debugFS naqp node.\n");
- goto out;
- }
- }
out:
return 0;
}
diff --git a/drivers/scsi/qla2xxx/qla_dsd.h b/drivers/scsi/qla2xxx/qla_dsd.h
new file mode 100644
index 000000000000..20788054b91b
--- /dev/null
+++ b/drivers/scsi/qla2xxx/qla_dsd.h
@@ -0,0 +1,32 @@
+#ifndef _QLA_DSD_H_
+#define _QLA_DSD_H_
+
+#include <asm/unaligned.h>
+
+/* 32-bit data segment descriptor (8 bytes) */
+struct dsd32 {
+ __le32 address;
+ __le32 length;
+};
+
+static inline void append_dsd32(struct dsd32 **dsd, struct scatterlist *sg)
+{
+ put_unaligned_le32(sg_dma_address(sg), &(*dsd)->address);
+ put_unaligned_le32(sg_dma_len(sg), &(*dsd)->length);
+ (*dsd)++;
+}
+
+/* 64-bit data segment descriptor (12 bytes) */
+struct dsd64 {
+ __le64 address;
+ __le32 length;
+} __packed;
+
+static inline void append_dsd64(struct dsd64 **dsd, struct scatterlist *sg)
+{
+ put_unaligned_le64(sg_dma_address(sg), &(*dsd)->address);
+ put_unaligned_le32(sg_dma_len(sg), &(*dsd)->length);
+ (*dsd)++;
+}
+
+#endif
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 50c1e6c62e31..732bb871c433 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -10,6 +10,8 @@
#include <linux/nvme.h>
#include <linux/nvme-fc.h>
+#include "qla_dsd.h"
+
#define MBS_CHECKSUM_ERROR 0x4010
#define MBS_INVALID_PRODUCT_KEY 0x4020
@@ -339,9 +341,9 @@ struct init_cb_24xx {
uint16_t prio_request_q_length;
- uint32_t request_q_address[2];
- uint32_t response_q_address[2];
- uint32_t prio_request_q_address[2];
+ __le64 request_q_address __packed;
+ __le64 response_q_address __packed;
+ __le64 prio_request_q_address __packed;
uint16_t msix;
uint16_t msix_atio;
@@ -349,7 +351,7 @@ struct init_cb_24xx {
uint16_t atio_q_inpointer;
uint16_t atio_q_length;
- uint32_t atio_q_address[2];
+ __le64 atio_q_address __packed;
uint16_t interrupt_delay_timer; /* 100us increments. */
uint16_t login_timeout;
@@ -453,7 +455,7 @@ struct cmd_bidir {
#define BD_WRITE_DATA BIT_0
uint16_t fcp_cmnd_dseg_len; /* Data segment length. */
- uint32_t fcp_cmnd_dseg_address[2]; /* Data segment address. */
+ __le64 fcp_cmnd_dseg_address __packed;/* Data segment address. */
uint16_t reserved[2]; /* Reserved */
@@ -463,8 +465,7 @@ struct cmd_bidir {
uint8_t port_id[3]; /* PortID of destination port.*/
uint8_t vp_index;
- uint32_t fcp_data_dseg_address[2]; /* Data segment address. */
- uint16_t fcp_data_dseg_len; /* Data segment length. */
+ struct dsd64 fcp_dsd;
};
#define COMMAND_TYPE_6 0x48 /* Command Type 6 entry */
@@ -491,18 +492,18 @@ struct cmd_type_6 {
#define CF_READ_DATA BIT_1
#define CF_WRITE_DATA BIT_0
- uint16_t fcp_cmnd_dseg_len; /* Data segment length. */
- uint32_t fcp_cmnd_dseg_address[2]; /* Data segment address. */
-
- uint32_t fcp_rsp_dseg_address[2]; /* Data segment address. */
+ uint16_t fcp_cmnd_dseg_len; /* Data segment length. */
+ /* Data segment address. */
+ __le64 fcp_cmnd_dseg_address __packed;
+ /* Data segment address. */
+ __le64 fcp_rsp_dseg_address __packed;
uint32_t byte_count; /* Total byte count. */
uint8_t port_id[3]; /* PortID of destination port. */
uint8_t vp_index;
- uint32_t fcp_data_dseg_address[2]; /* Data segment address. */
- uint32_t fcp_data_dseg_len; /* Data segment length. */
+ struct dsd64 fcp_dsd;
};
#define COMMAND_TYPE_7 0x18 /* Command Type 7 entry */
@@ -548,8 +549,7 @@ struct cmd_type_7 {
uint8_t port_id[3]; /* PortID of destination port. */
uint8_t vp_index;
- uint32_t dseg_0_address[2]; /* Data segment 0 address. */
- uint32_t dseg_0_len; /* Data segment 0 length. */
+ struct dsd64 dsd;
};
#define COMMAND_TYPE_CRC_2 0x6A /* Command Type CRC_2 (Type 6)
@@ -573,17 +573,17 @@ struct cmd_type_crc_2 {
uint16_t control_flags; /* Control flags. */
- uint16_t fcp_cmnd_dseg_len; /* Data segment length. */
- uint32_t fcp_cmnd_dseg_address[2]; /* Data segment address. */
-
- uint32_t fcp_rsp_dseg_address[2]; /* Data segment address. */
+ uint16_t fcp_cmnd_dseg_len; /* Data segment length. */
+ __le64 fcp_cmnd_dseg_address __packed;
+ /* Data segment address. */
+ __le64 fcp_rsp_dseg_address __packed;
uint32_t byte_count; /* Total byte count. */
uint8_t port_id[3]; /* PortID of destination port. */
uint8_t vp_index;
- uint32_t crc_context_address[2]; /* Data segment address. */
+ __le64 crc_context_address __packed; /* Data segment address. */
uint16_t crc_context_len; /* Data segment length. */
uint16_t reserved_1; /* MUST be set to 0. */
};
@@ -717,10 +717,7 @@ struct ct_entry_24xx {
uint32_t rsp_byte_count;
uint32_t cmd_byte_count;
- uint32_t dseg_0_address[2]; /* Data segment 0 address. */
- uint32_t dseg_0_len; /* Data segment 0 length. */
- uint32_t dseg_1_address[2]; /* Data segment 1 address. */
- uint32_t dseg_1_len; /* Data segment 1 length. */
+ struct dsd64 dsd[2];
};
/*
@@ -764,13 +761,13 @@ struct els_entry_24xx {
#define ECF_CLR_PASSTHRU_PEND BIT_12
#define ECF_INCL_FRAME_HDR BIT_11
- uint32_t rx_byte_count;
- uint32_t tx_byte_count;
+ __le32 rx_byte_count;
+ __le32 tx_byte_count;
- uint32_t tx_address[2]; /* Data segment 0 address. */
- uint32_t tx_len; /* Data segment 0 length. */
- uint32_t rx_address[2]; /* Data segment 1 address. */
- uint32_t rx_len; /* Data segment 1 length. */
+ __le64 tx_address __packed; /* Data segment 0 address. */
+ __le32 tx_len; /* Data segment 0 length. */
+ __le64 rx_address __packed; /* Data segment 1 address. */
+ __le32 rx_len; /* Data segment 1 length. */
};
struct els_sts_entry_24xx {
@@ -1422,9 +1419,9 @@ struct vf_evfp_entry_24xx {
uint16_t control_flags;
uint32_t io_parameter_0;
uint32_t io_parameter_1;
- uint32_t tx_address[2]; /* Data segment 0 address. */
+ __le64 tx_address __packed; /* Data segment 0 address. */
uint32_t tx_len; /* Data segment 0 length. */
- uint32_t rx_address[2]; /* Data segment 1 address. */
+ __le64 rx_address __packed; /* Data segment 1 address. */
uint32_t rx_len; /* Data segment 1 length. */
};
@@ -1515,13 +1512,31 @@ struct qla_flt_header {
#define FLT_REG_VPD_SEC_27XX_2 0xD8
#define FLT_REG_VPD_SEC_27XX_3 0xDA
+/* 28xx */
+#define FLT_REG_AUX_IMG_PRI_28XX 0x125
+#define FLT_REG_AUX_IMG_SEC_28XX 0x126
+#define FLT_REG_VPD_SEC_28XX_0 0x10C
+#define FLT_REG_VPD_SEC_28XX_1 0x10E
+#define FLT_REG_VPD_SEC_28XX_2 0x110
+#define FLT_REG_VPD_SEC_28XX_3 0x112
+#define FLT_REG_NVRAM_SEC_28XX_0 0x10D
+#define FLT_REG_NVRAM_SEC_28XX_1 0x10F
+#define FLT_REG_NVRAM_SEC_28XX_2 0x111
+#define FLT_REG_NVRAM_SEC_28XX_3 0x113
+
struct qla_flt_region {
- uint32_t code;
+ uint16_t code;
+ uint8_t attribute;
+ uint8_t reserved;
uint32_t size;
uint32_t start;
uint32_t end;
};
+#define FLT_REGION_SIZE 16
+#define FLT_MAX_REGIONS 0xFF
+#define FLT_REGIONS_SIZE (FLT_REGION_SIZE * FLT_MAX_REGIONS)
+
/* Flash NPIV Configuration Table ********************************************/
struct qla_npiv_header {
@@ -1588,8 +1603,7 @@ struct verify_chip_entry_84xx {
uint32_t fw_seq_size;
uint32_t relative_offset;
- uint32_t dseg_address[2];
- uint32_t dseg_length;
+ struct dsd64 dsd;
};
struct verify_chip_rsp_84xx {
@@ -1646,8 +1660,7 @@ struct access_chip_84xx {
uint32_t total_byte_cnt;
uint32_t reserved4;
- uint32_t dseg_address[2];
- uint32_t dseg_length;
+ struct dsd64 dsd;
};
struct access_chip_rsp_84xx {
@@ -1711,6 +1724,10 @@ struct access_chip_rsp_84xx {
#define LR_DIST_FW_SHIFT (LR_DIST_FW_POS - LR_DIST_NV_POS)
#define LR_DIST_FW_FIELD(x) ((x) << LR_DIST_FW_SHIFT & 0xf000)
+/* FAC semaphore defines */
+#define FAC_SEMAPHORE_UNLOCK 0
+#define FAC_SEMAPHORE_LOCK 1
+
struct nvram_81xx {
/* NVRAM header. */
uint8_t id[4];
@@ -1757,7 +1774,7 @@ struct nvram_81xx {
uint16_t reserved_6_3[14];
/* Offset 192. */
- uint8_t min_link_speed;
+ uint8_t min_supported_speed;
uint8_t reserved_7_0;
uint16_t reserved_7[31];
@@ -1911,15 +1928,15 @@ struct init_cb_81xx {
uint16_t prio_request_q_length;
- uint32_t request_q_address[2];
- uint32_t response_q_address[2];
- uint32_t prio_request_q_address[2];
+ __le64 request_q_address __packed;
+ __le64 response_q_address __packed;
+ __le64 prio_request_q_address __packed;
uint8_t reserved_4[8];
uint16_t atio_q_inpointer;
uint16_t atio_q_length;
- uint32_t atio_q_address[2];
+ __le64 atio_q_address __packed;
uint16_t interrupt_delay_timer; /* 100us increments. */
uint16_t login_timeout;
@@ -2005,6 +2022,8 @@ struct ex_init_cb_81xx {
#define FARX_ACCESS_FLASH_CONF_81XX 0x7FFD0000
#define FARX_ACCESS_FLASH_DATA_81XX 0x7F800000
+#define FARX_ACCESS_FLASH_CONF_28XX 0x7FFD0000
+#define FARX_ACCESS_FLASH_DATA_28XX 0x7F7D0000
/* FCP priority config defines *************************************/
/* operations */
@@ -2079,6 +2098,7 @@ struct qla_fcp_prio_cfg {
#define FA_NPIV_CONF1_ADDR_81 0xD2000
/* 83XX Flash locations -- occupies second 8MB region. */
-#define FA_FLASH_LAYOUT_ADDR_83 0xFC400
+#define FA_FLASH_LAYOUT_ADDR_83 (0x3F1000/4)
+#define FA_FLASH_LAYOUT_ADDR_28 (0x11000/4)
#endif
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index bf9d22a931d9..156d76f59253 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -18,14 +18,14 @@ extern int qla2100_pci_config(struct scsi_qla_host *);
extern int qla2300_pci_config(struct scsi_qla_host *);
extern int qla24xx_pci_config(scsi_qla_host_t *);
extern int qla25xx_pci_config(scsi_qla_host_t *);
-extern void qla2x00_reset_chip(struct scsi_qla_host *);
-extern void qla24xx_reset_chip(struct scsi_qla_host *);
+extern int qla2x00_reset_chip(struct scsi_qla_host *);
+extern int qla24xx_reset_chip(struct scsi_qla_host *);
extern int qla2x00_chip_diag(struct scsi_qla_host *);
extern int qla24xx_chip_diag(struct scsi_qla_host *);
extern void qla2x00_config_rings(struct scsi_qla_host *);
extern void qla24xx_config_rings(struct scsi_qla_host *);
-extern void qla2x00_reset_adapter(struct scsi_qla_host *);
-extern void qla24xx_reset_adapter(struct scsi_qla_host *);
+extern int qla2x00_reset_adapter(struct scsi_qla_host *);
+extern int qla24xx_reset_adapter(struct scsi_qla_host *);
extern int qla2x00_nvram_config(struct scsi_qla_host *);
extern int qla24xx_nvram_config(struct scsi_qla_host *);
extern int qla81xx_nvram_config(struct scsi_qla_host *);
@@ -38,14 +38,15 @@ extern int qla81xx_load_risc(scsi_qla_host_t *, uint32_t *);
extern int qla2x00_perform_loop_resync(scsi_qla_host_t *);
extern int qla2x00_loop_resync(scsi_qla_host_t *);
-
-extern int qla2x00_find_new_loop_id(scsi_qla_host_t *, fc_port_t *);
+extern void qla2x00_clear_loop_id(fc_port_t *fcport);
extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);
extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *);
extern int qla24xx_els_dcmd_iocb(scsi_qla_host_t *, int, port_id_t);
extern int qla24xx_els_dcmd2_iocb(scsi_qla_host_t *, int, fc_port_t *, bool);
+extern void qla2x00_els_dcmd2_free(scsi_qla_host_t *vha,
+ struct els_plogi *els_plogi);
extern void qla2x00_update_fcports(scsi_qla_host_t *);
@@ -80,6 +81,7 @@ int qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e);
extern void *qla2x00_alloc_iocbs_ready(struct qla_qpair *, srb_t *);
extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *);
+extern void qla2x00_set_fcport_state(fc_port_t *fcport, int state);
extern fc_port_t *
qla2x00_alloc_fcport(scsi_qla_host_t *, gfp_t );
@@ -93,11 +95,14 @@ extern int qla2xxx_mctp_dump(scsi_qla_host_t *);
extern int
qla2x00_alloc_outstanding_cmds(struct qla_hw_data *, struct req_que *);
extern int qla2x00_init_rings(scsi_qla_host_t *);
-extern uint8_t qla27xx_find_valid_image(struct scsi_qla_host *);
extern struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *,
int, int, bool);
extern int qla2xxx_delete_qpair(struct scsi_qla_host *, struct qla_qpair *);
-void qla2x00_fcport_event_handler(scsi_qla_host_t *, struct event_arg *);
+void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea);
+void qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha,
+ struct event_arg *ea);
+void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
+ struct event_arg *ea);
int qla24xx_async_gpdb(struct scsi_qla_host *, fc_port_t *, u8);
int qla24xx_async_prli(struct scsi_qla_host *, fc_port_t *);
int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
@@ -108,6 +113,11 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
int qla24xx_detect_sfp(scsi_qla_host_t *vha);
int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
+extern void qla28xx_get_aux_images(struct scsi_qla_host *,
+ struct active_regions *);
+extern void qla27xx_get_active_image(struct scsi_qla_host *,
+ struct active_regions *);
+
void qla2x00_async_prlo_done(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
extern int qla2x00_post_async_prlo_work(struct scsi_qla_host *, fc_port_t *,
@@ -118,6 +128,7 @@ int qla_post_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport);
void qla_do_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport);
int qla2x00_reserve_mgmt_server_loop_id(scsi_qla_host_t *);
void qla_rscn_replay(fc_port_t *fcport);
+extern bool qla24xx_risc_firmware_invalid(uint32_t *);
/*
* Global Data in qla_os.c source file.
@@ -160,6 +171,7 @@ extern int ql2xautodetectsfp;
extern int ql2xenablemsix;
extern int qla2xuseresexchforels;
extern int ql2xexlogins;
+extern int ql2xdifbundlinginternalbuffers;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@@ -207,14 +219,13 @@ extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32);
extern int qla2x00_post_uevent_work(struct scsi_qla_host *, u32);
extern void qla2x00_disable_board_on_pci_error(struct work_struct *);
-extern void qla2x00_sp_compl(void *, int);
-extern void qla2xxx_qpair_sp_free_dma(void *);
-extern void qla2xxx_qpair_sp_compl(void *, int);
+extern void qla2x00_sp_compl(srb_t *sp, int);
+extern void qla2xxx_qpair_sp_free_dma(srb_t *sp);
+extern void qla2xxx_qpair_sp_compl(srb_t *sp, int);
extern void qla24xx_sched_upd_fcport(fc_port_t *);
void qla2x00_handle_login_done_event(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
int qla24xx_post_gnl_work(struct scsi_qla_host *, fc_port_t *);
-int qla24xx_async_abort_cmd(srb_t *, bool);
int qla24xx_post_relogin_work(struct scsi_qla_host *vha);
void qla2x00_wait_for_sess_deletion(scsi_qla_host_t *);
@@ -237,9 +248,9 @@ extern void qla24xx_report_id_acquisition(scsi_qla_host_t *,
struct vp_rpt_id_entry_24xx *);
extern void qla2x00_do_dpc_all_vps(scsi_qla_host_t *);
extern int qla24xx_vport_create_req_sanity_check(struct fc_vport *);
-extern scsi_qla_host_t * qla24xx_create_vhost(struct fc_vport *);
+extern scsi_qla_host_t *qla24xx_create_vhost(struct fc_vport *);
-extern void qla2x00_sp_free_dma(void *);
+extern void qla2x00_sp_free_dma(srb_t *sp);
extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *);
extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int);
@@ -267,29 +278,29 @@ extern void qla2x00_build_scsi_iocbs_32(srb_t *, cmd_entry_t *, uint16_t);
extern void qla2x00_build_scsi_iocbs_64(srb_t *, cmd_entry_t *, uint16_t);
extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *,
uint16_t, struct req_que *);
+extern uint32_t qla2xxx_get_next_handle(struct req_que *req);
extern int qla2x00_start_scsi(srb_t *sp);
extern int qla24xx_start_scsi(srb_t *sp);
-int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *,
- uint16_t, uint64_t, uint8_t);
+int qla2x00_marker(struct scsi_qla_host *, struct qla_qpair *,
+ uint16_t, uint64_t, uint8_t);
extern int qla2x00_start_sp(srb_t *);
extern int qla24xx_dif_start_scsi(srb_t *);
extern int qla2x00_start_bidir(srb_t *, struct scsi_qla_host *, uint32_t);
extern int qla2xxx_dif_start_scsi_mq(srb_t *);
+extern void qla2x00_init_timer(srb_t *sp, unsigned long tmo);
extern unsigned long qla2x00_get_async_timeout(struct scsi_qla_host *);
extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
extern void *__qla2x00_alloc_iocbs(struct qla_qpair *, srb_t *);
extern int qla2x00_issue_marker(scsi_qla_host_t *, int);
extern int qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *, srb_t *,
- uint32_t *, uint16_t, struct qla_tc_param *);
+ struct dsd64 *, uint16_t, struct qla_tc_param *);
extern int qla24xx_walk_and_build_sglist(struct qla_hw_data *, srb_t *,
- uint32_t *, uint16_t, struct qla_tc_param *);
+ struct dsd64 *, uint16_t, struct qla_tc_param *);
extern int qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *, srb_t *,
- uint32_t *, uint16_t, struct qla_tc_param *);
+ struct dsd64 *, uint16_t, struct qla_tgt_cmd *);
extern int qla24xx_get_one_block_sg(uint32_t, struct qla2_sgx *, uint32_t *);
extern int qla24xx_configure_prot_mode(srb_t *, uint16_t *);
-extern int qla24xx_build_scsi_crc_2_iocbs(srb_t *,
- struct cmd_type_crc_2 *, uint16_t, uint16_t, uint16_t);
/*
* Global Function Prototypes in qla_mbx.c source file.
@@ -465,6 +476,8 @@ qla81xx_fac_do_write_enable(scsi_qla_host_t *, int);
extern int
qla81xx_fac_erase_sector(scsi_qla_host_t *, uint32_t, uint32_t);
+extern int qla81xx_fac_semaphore_access(scsi_qla_host_t *, int);
+
extern int
qla2x00_get_xgmac_stats(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t *);
@@ -510,6 +523,14 @@ extern int qla27xx_get_zio_threshold(scsi_qla_host_t *, uint16_t *);
extern int qla27xx_set_zio_threshold(scsi_qla_host_t *, uint16_t);
int qla24xx_res_count_wait(struct scsi_qla_host *, uint16_t *, int);
+extern int qla28xx_secure_flash_update(scsi_qla_host_t *, uint16_t, uint16_t,
+ uint32_t, dma_addr_t, uint32_t);
+
+extern int qla2xxx_read_remote_register(scsi_qla_host_t *, uint32_t,
+ uint32_t *);
+extern int qla2xxx_write_remote_register(scsi_qla_host_t *, uint32_t,
+ uint32_t);
+
/*
* Global Function Prototypes in qla_isr.c source file.
*/
@@ -540,20 +561,21 @@ fc_port_t *qla2x00_find_fcport_by_nportid(scsi_qla_host_t *, port_id_t *, u8);
* Global Function Prototypes in qla_sup.c source file.
*/
extern void qla2x00_release_nvram_protection(scsi_qla_host_t *);
-extern uint32_t *qla24xx_read_flash_data(scsi_qla_host_t *, uint32_t *,
- uint32_t, uint32_t);
-extern uint8_t *qla2x00_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
- uint32_t);
-extern uint8_t *qla24xx_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
- uint32_t);
-extern int qla2x00_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
- uint32_t);
-extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
- uint32_t);
-extern uint8_t *qla25xx_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
- uint32_t);
-extern int qla25xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
- uint32_t);
+extern int qla24xx_read_flash_data(scsi_qla_host_t *, uint32_t *,
+ uint32_t, uint32_t);
+extern uint8_t *qla2x00_read_nvram_data(scsi_qla_host_t *, void *, uint32_t,
+ uint32_t);
+extern uint8_t *qla24xx_read_nvram_data(scsi_qla_host_t *, void *, uint32_t,
+ uint32_t);
+extern int qla2x00_write_nvram_data(scsi_qla_host_t *, void *, uint32_t,
+ uint32_t);
+extern int qla24xx_write_nvram_data(scsi_qla_host_t *, void *, uint32_t,
+ uint32_t);
+extern uint8_t *qla25xx_read_nvram_data(scsi_qla_host_t *, void *, uint32_t,
+ uint32_t);
+extern int qla25xx_write_nvram_data(scsi_qla_host_t *, void *, uint32_t,
+ uint32_t);
+
extern int qla2x00_is_a_vp_did(scsi_qla_host_t *, uint32_t);
bool qla2x00_check_reg32_for_disconnect(scsi_qla_host_t *, uint32_t);
bool qla2x00_check_reg16_for_disconnect(scsi_qla_host_t *, uint16_t);
@@ -573,18 +595,18 @@ extern int qla83xx_restart_nic_firmware(scsi_qla_host_t *);
extern int qla83xx_access_control(scsi_qla_host_t *, uint16_t, uint32_t,
uint32_t, uint16_t *);
-extern uint8_t *qla2x00_read_optrom_data(struct scsi_qla_host *, uint8_t *,
+extern void *qla2x00_read_optrom_data(struct scsi_qla_host *, void *,
uint32_t, uint32_t);
-extern int qla2x00_write_optrom_data(struct scsi_qla_host *, uint8_t *,
+extern int qla2x00_write_optrom_data(struct scsi_qla_host *, void *,
uint32_t, uint32_t);
-extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
+extern void *qla24xx_read_optrom_data(struct scsi_qla_host *, void *,
uint32_t, uint32_t);
-extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *,
+extern int qla24xx_write_optrom_data(struct scsi_qla_host *, void *,
uint32_t, uint32_t);
-extern uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
+extern void *qla25xx_read_optrom_data(struct scsi_qla_host *, void *,
uint32_t, uint32_t);
-extern uint8_t *qla8044_read_optrom_data(struct scsi_qla_host *,
- uint8_t *, uint32_t, uint32_t);
+extern void *qla8044_read_optrom_data(struct scsi_qla_host *,
+ void *, uint32_t, uint32_t);
extern void qla8044_watchdog(struct scsi_qla_host *vha);
extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *);
@@ -609,20 +631,13 @@ extern void qla82xx_fw_dump(scsi_qla_host_t *, int);
extern void qla8044_fw_dump(scsi_qla_host_t *, int);
extern void qla27xx_fwdump(scsi_qla_host_t *, int);
-extern ulong qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *);
+extern ulong qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *, void *);
extern int qla27xx_fwdt_template_valid(void *);
extern ulong qla27xx_fwdt_template_size(void *);
-extern const void *qla27xx_fwdt_template_default(void);
-extern ulong qla27xx_fwdt_template_default_size(void);
-
-extern void qla2x00_dump_regs(scsi_qla_host_t *);
-extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
-extern void qla2x00_dump_buffer_zipped(uint8_t *, uint32_t);
-extern void ql_dump_regs(uint32_t, scsi_qla_host_t *, int32_t);
-extern void ql_dump_buffer(uint32_t, scsi_qla_host_t *, int32_t,
- uint8_t *, uint32_t);
-extern void qla2xxx_dump_post_process(scsi_qla_host_t *, int);
+extern void qla2xxx_dump_post_process(scsi_qla_host_t *, int);
+extern void ql_dump_regs(uint, scsi_qla_host_t *, uint);
+extern void ql_dump_buffer(uint, scsi_qla_host_t *, uint, const void *, uint);
/*
* Global Function Prototypes in qla_gs.c source file.
*/
@@ -721,10 +736,10 @@ extern void qla24xx_wrt_rsp_reg(struct qla_hw_data *, uint16_t, uint16_t);
/* qlafx00 related functions */
extern int qlafx00_pci_config(struct scsi_qla_host *);
extern int qlafx00_initialize_adapter(struct scsi_qla_host *);
-extern void qlafx00_soft_reset(scsi_qla_host_t *);
+extern int qlafx00_soft_reset(scsi_qla_host_t *);
extern int qlafx00_chip_diag(scsi_qla_host_t *);
extern void qlafx00_config_rings(struct scsi_qla_host *);
-extern char *qlafx00_pci_info_str(struct scsi_qla_host *, char *);
+extern char *qlafx00_pci_info_str(struct scsi_qla_host *, char *, size_t);
extern char *qlafx00_fw_version_str(struct scsi_qla_host *, char *, size_t);
extern irqreturn_t qlafx00_intr_handler(int, void *);
extern void qlafx00_enable_intrs(struct qla_hw_data *);
@@ -764,16 +779,16 @@ extern int qla82xx_pci_region_offset(struct pci_dev *, int);
extern int qla82xx_iospace_config(struct qla_hw_data *);
/* Initialization related functions */
-extern void qla82xx_reset_chip(struct scsi_qla_host *);
+extern int qla82xx_reset_chip(struct scsi_qla_host *);
extern void qla82xx_config_rings(struct scsi_qla_host *);
extern void qla82xx_watchdog(scsi_qla_host_t *);
extern int qla82xx_start_firmware(scsi_qla_host_t *);
/* Firmware and flash related functions */
extern int qla82xx_load_risc(scsi_qla_host_t *, uint32_t *);
-extern uint8_t *qla82xx_read_optrom_data(struct scsi_qla_host *, uint8_t *,
+extern void *qla82xx_read_optrom_data(struct scsi_qla_host *, void *,
uint32_t, uint32_t);
-extern int qla82xx_write_optrom_data(struct scsi_qla_host *, uint8_t *,
+extern int qla82xx_write_optrom_data(struct scsi_qla_host *, void *,
uint32_t, uint32_t);
/* Mailbox related functions */
@@ -782,10 +797,10 @@ extern int qla82xx_restart_isp(scsi_qla_host_t *);
/* IOCB related functions */
extern int qla82xx_start_scsi(srb_t *);
-extern void qla2x00_sp_free(void *);
+extern void qla2x00_sp_free(srb_t *sp);
extern void qla2x00_sp_timeout(unsigned long);
-extern void qla2x00_bsg_job_done(void *, int);
-extern void qla2x00_bsg_sp_free(void *);
+extern void qla2x00_bsg_job_done(srb_t *sp, int);
+extern void qla2x00_bsg_sp_free(srb_t *sp);
extern void qla2x00_start_iocbs(struct scsi_qla_host *, struct req_que *);
/* Interrupt related */
@@ -814,8 +829,8 @@ extern int qla82xx_device_state_handler(scsi_qla_host_t *);
extern void qla8xxx_dev_failed_handler(scsi_qla_host_t *);
extern void qla82xx_clear_qsnt_ready(scsi_qla_host_t *);
-extern void qla2x00_set_model_info(scsi_qla_host_t *, uint8_t *,
- size_t, char *);
+extern void qla2x00_set_model_info(scsi_qla_host_t *, uint8_t *, size_t,
+ const char *);
extern int qla82xx_mbx_intr_enable(scsi_qla_host_t *);
extern int qla82xx_mbx_intr_disable(scsi_qla_host_t *);
extern void qla82xx_start_iocbs(scsi_qla_host_t *);
@@ -869,7 +884,7 @@ extern void qla8044_clear_drv_active(struct qla_hw_data *);
void qla8044_get_minidump(struct scsi_qla_host *vha);
int qla8044_collect_md_data(struct scsi_qla_host *vha);
extern int qla8044_md_get_template(scsi_qla_host_t *);
-extern int qla8044_write_optrom_data(struct scsi_qla_host *, uint8_t *,
+extern int qla8044_write_optrom_data(struct scsi_qla_host *, void *,
uint32_t, uint32_t);
extern irqreturn_t qla8044_intr_handler(int, void *);
extern void qla82xx_mbx_completion(scsi_qla_host_t *, uint16_t);
@@ -898,5 +913,8 @@ void qlt_update_host_map(struct scsi_qla_host *, port_id_t);
void qlt_remove_target_resources(struct qla_hw_data *);
void qlt_clr_qp_table(struct scsi_qla_host *vha);
void qlt_set_mode(struct scsi_qla_host *);
+int qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode);
+/* nvme.c */
+void qla_nvme_unregister_remote_port(struct fc_port *fcport);
#endif /* _QLA_GBL_H */
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 3aae78a78917..1cf5b973e0e3 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -45,13 +45,11 @@ qla2x00_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
ms_pkt->rsp_bytecount = cpu_to_le32(arg->rsp_size);
ms_pkt->req_bytecount = cpu_to_le32(arg->req_size);
- ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(arg->req_dma));
- ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(arg->req_dma));
- ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
+ put_unaligned_le64(arg->req_dma, &ms_pkt->req_dsd.address);
+ ms_pkt->req_dsd.length = ms_pkt->req_bytecount;
- ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(arg->rsp_dma));
- ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(arg->rsp_dma));
- ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
+ put_unaligned_le64(arg->rsp_dma, &ms_pkt->rsp_dsd.address);
+ ms_pkt->rsp_dsd.length = ms_pkt->rsp_bytecount;
vha->qla_stats.control_requests++;
@@ -83,13 +81,11 @@ qla24xx_prep_ms_iocb(scsi_qla_host_t *vha, struct ct_arg *arg)
ct_pkt->rsp_byte_count = cpu_to_le32(arg->rsp_size);
ct_pkt->cmd_byte_count = cpu_to_le32(arg->req_size);
- ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(arg->req_dma));
- ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(arg->req_dma));
- ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
+ put_unaligned_le64(arg->req_dma, &ct_pkt->dsd[0].address);
+ ct_pkt->dsd[0].length = ct_pkt->cmd_byte_count;
- ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(arg->rsp_dma));
- ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(arg->rsp_dma));
- ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
+ put_unaligned_le64(arg->rsp_dma, &ct_pkt->dsd[1].address);
+ ct_pkt->dsd[1].length = ct_pkt->rsp_byte_count;
ct_pkt->vp_index = vha->vp_idx;
vha->qla_stats.control_requests++;
@@ -152,8 +148,8 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
vha->d_id.b.area, vha->d_id.b.al_pa,
comp_status, ct_rsp->header.response);
ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha,
- 0x2078, (uint8_t *)&ct_rsp->header,
- sizeof(struct ct_rsp_hdr));
+ 0x2078, ct_rsp,
+ offsetof(typeof(*ct_rsp), rsp));
rval = QLA_INVALID_COMMAND;
} else
rval = QLA_SUCCESS;
@@ -230,9 +226,7 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
ct_rsp = &ha->ct_sns->p.rsp;
/* Prepare CT arguments -- port_id */
- ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
- ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
- ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
+ ct_req->req.port_id.port_id = port_id_to_be_id(fcport->d_id);
/* Execute MS IOCB */
rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
@@ -246,9 +240,7 @@ qla2x00_ga_nxt(scsi_qla_host_t *vha, fc_port_t *fcport)
rval = QLA_FUNCTION_FAILED;
} else {
/* Populate fc_port_t entry. */
- fcport->d_id.b.domain = ct_rsp->rsp.ga_nxt.port_id[0];
- fcport->d_id.b.area = ct_rsp->rsp.ga_nxt.port_id[1];
- fcport->d_id.b.al_pa = ct_rsp->rsp.ga_nxt.port_id[2];
+ fcport->d_id = be_to_port_id(ct_rsp->rsp.ga_nxt.port_id);
memcpy(fcport->node_name, ct_rsp->rsp.ga_nxt.node_name,
WWN_SIZE);
@@ -341,9 +333,7 @@ qla2x00_gid_pt(scsi_qla_host_t *vha, sw_info_t *list)
/* Set port IDs in switch info list. */
for (i = 0; i < ha->max_fibre_devices; i++) {
gid_data = &ct_rsp->rsp.gid_pt.entries[i];
- list[i].d_id.b.domain = gid_data->port_id[0];
- list[i].d_id.b.area = gid_data->port_id[1];
- list[i].d_id.b.al_pa = gid_data->port_id[2];
+ list[i].d_id = be_to_port_id(gid_data->port_id);
memset(list[i].fabric_port_name, 0, WWN_SIZE);
list[i].fp_speed = PORT_SPEED_UNKNOWN;
@@ -407,9 +397,7 @@ qla2x00_gpn_id(scsi_qla_host_t *vha, sw_info_t *list)
ct_rsp = &ha->ct_sns->p.rsp;
/* Prepare CT arguments -- port_id */
- ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
- ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
- ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
+ ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id);
/* Execute MS IOCB */
rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
@@ -476,9 +464,7 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
ct_rsp = &ha->ct_sns->p.rsp;
/* Prepare CT arguments -- port_id */
- ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
- ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
- ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
+ ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id);
/* Execute MS IOCB */
rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
@@ -513,9 +499,8 @@ qla2x00_gnn_id(scsi_qla_host_t *vha, sw_info_t *list)
return (rval);
}
-static void qla2x00_async_sns_sp_done(void *s, int rc)
+static void qla2x00_async_sns_sp_done(srb_t *sp, int rc)
{
- struct srb *sp = s;
struct scsi_qla_host *vha = sp->vha;
struct ct_sns_pkt *ct_sns;
struct qla_work_evt *e;
@@ -643,9 +628,7 @@ static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
ct_req = qla2x00_prep_ct_req(ct_sns, RFT_ID_CMD, RFT_ID_RSP_SIZE);
/* Prepare CT arguments -- port_id, FC-4 types */
- ct_req->req.rft_id.port_id[0] = vha->d_id.b.domain;
- ct_req->req.rft_id.port_id[1] = vha->d_id.b.area;
- ct_req->req.rft_id.port_id[2] = vha->d_id.b.al_pa;
+ ct_req->req.rft_id.port_id = port_id_to_be_id(vha->d_id);
ct_req->req.rft_id.fc4_types[2] = 0x01; /* FCP-3 */
if (vha->flags.nvme_enabled)
@@ -657,15 +640,16 @@ static int qla_async_rftid(scsi_qla_host_t *vha, port_id_t *d_id)
sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
sp->done = qla2x00_async_sns_sp_done;
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async-%s - hdl=%x portid %06x.\n",
+ sp->name, sp->handle, d_id->b24);
+
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_disc, vha, 0x2043,
"RFT_ID issue IOCB failed (%d).\n", rval);
goto done_free_sp;
}
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async-%s - hdl=%x portid %06x.\n",
- sp->name, sp->handle, d_id->b24);
return rval;
done_free_sp:
sp->free(sp);
@@ -740,9 +724,7 @@ static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
ct_req = qla2x00_prep_ct_req(ct_sns, RFF_ID_CMD, RFF_ID_RSP_SIZE);
/* Prepare CT arguments -- port_id, FC-4 feature, FC-4 type */
- ct_req->req.rff_id.port_id[0] = d_id->b.domain;
- ct_req->req.rff_id.port_id[1] = d_id->b.area;
- ct_req->req.rff_id.port_id[2] = d_id->b.al_pa;
+ ct_req->req.rff_id.port_id = port_id_to_be_id(*d_id);
ct_req->req.rff_id.fc4_feature = fc4feature;
ct_req->req.rff_id.fc4_type = fc4type; /* SCSI - FCP */
@@ -752,6 +734,10 @@ static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
sp->done = qla2x00_async_sns_sp_done;
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async-%s - hdl=%x portid %06x feature %x type %x.\n",
+ sp->name, sp->handle, d_id->b24, fc4feature, fc4type);
+
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_disc, vha, 0x2047,
@@ -759,9 +745,6 @@ static int qla_async_rffid(scsi_qla_host_t *vha, port_id_t *d_id,
goto done_free_sp;
}
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async-%s - hdl=%x portid %06x feature %x type %x.\n",
- sp->name, sp->handle, d_id->b24, fc4feature, fc4type);
return rval;
done_free_sp:
@@ -832,9 +815,7 @@ static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
ct_req = qla2x00_prep_ct_req(ct_sns, RNN_ID_CMD, RNN_ID_RSP_SIZE);
/* Prepare CT arguments -- port_id, node_name */
- ct_req->req.rnn_id.port_id[0] = vha->d_id.b.domain;
- ct_req->req.rnn_id.port_id[1] = vha->d_id.b.area;
- ct_req->req.rnn_id.port_id[2] = vha->d_id.b.al_pa;
+ ct_req->req.rnn_id.port_id = port_id_to_be_id(vha->d_id);
memcpy(ct_req->req.rnn_id.node_name, vha->node_name, WWN_SIZE);
sp->u.iocb_cmd.u.ctarg.req_size = RNN_ID_REQ_SIZE;
@@ -844,15 +825,16 @@ static int qla_async_rnnid(scsi_qla_host_t *vha, port_id_t *d_id,
sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
sp->done = qla2x00_async_sns_sp_done;
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async-%s - hdl=%x portid %06x\n",
+ sp->name, sp->handle, d_id->b24);
+
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_disc, vha, 0x204d,
"RNN_ID issue IOCB failed (%d).\n", rval);
goto done_free_sp;
}
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async-%s - hdl=%x portid %06x\n",
- sp->name, sp->handle, d_id->b24);
return rval;
@@ -957,15 +939,16 @@ static int qla_async_rsnn_nn(scsi_qla_host_t *vha)
sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
sp->done = qla2x00_async_sns_sp_done;
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async-%s - hdl=%x.\n",
+ sp->name, sp->handle);
+
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_disc, vha, 0x2043,
"RFT_ID issue IOCB failed (%d).\n", rval);
goto done_free_sp;
}
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async-%s - hdl=%x.\n",
- sp->name, sp->handle);
return rval;
@@ -996,8 +979,7 @@ qla2x00_prep_sns_cmd(scsi_qla_host_t *vha, uint16_t cmd, uint16_t scmd_len,
memset(sns_cmd, 0, sizeof(struct sns_cmd_pkt));
wc = data_size / 2; /* Size in 16bit words. */
sns_cmd->p.cmd.buffer_length = cpu_to_le16(wc);
- sns_cmd->p.cmd.buffer_address[0] = cpu_to_le32(LSD(ha->sns_cmd_dma));
- sns_cmd->p.cmd.buffer_address[1] = cpu_to_le32(MSD(ha->sns_cmd_dma));
+ put_unaligned_le64(ha->sns_cmd_dma, &sns_cmd->p.cmd.buffer_address);
sns_cmd->p.cmd.subcommand_length = cpu_to_le16(scmd_len);
sns_cmd->p.cmd.subcommand = cpu_to_le16(cmd);
wc = (data_size - 16) / 4; /* Size in 32bit words. */
@@ -1381,6 +1363,7 @@ qla2x00_mgmt_svr_login(scsi_qla_host_t *vha)
int ret, rval;
uint16_t mb[MAILBOX_REGISTER_COUNT];
struct qla_hw_data *ha = vha->hw;
+
ret = QLA_SUCCESS;
if (vha->flags.management_server_logged_in)
return ret;
@@ -1419,6 +1402,7 @@ qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
{
ms_iocb_entry_t *ms_pkt;
struct qla_hw_data *ha = vha->hw;
+
ms_pkt = ha->ms_iocb;
memset(ms_pkt, 0, sizeof(ms_iocb_entry_t));
@@ -1432,13 +1416,11 @@ qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size);
ms_pkt->req_bytecount = cpu_to_le32(req_size);
- ms_pkt->dseg_req_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
- ms_pkt->dseg_req_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
- ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
+ put_unaligned_le64(ha->ct_sns_dma, &ms_pkt->req_dsd.address);
+ ms_pkt->req_dsd.length = ms_pkt->req_bytecount;
- ms_pkt->dseg_rsp_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
- ms_pkt->dseg_rsp_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
- ms_pkt->dseg_rsp_length = ms_pkt->rsp_bytecount;
+ put_unaligned_le64(ha->ct_sns_dma, &ms_pkt->rsp_dsd.address);
+ ms_pkt->rsp_dsd.length = ms_pkt->rsp_bytecount;
return ms_pkt;
}
@@ -1470,19 +1452,17 @@ qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size,
ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size);
ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
- ct_pkt->dseg_0_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
- ct_pkt->dseg_0_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
- ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
+ put_unaligned_le64(ha->ct_sns_dma, &ct_pkt->dsd[0].address);
+ ct_pkt->dsd[0].length = ct_pkt->cmd_byte_count;
- ct_pkt->dseg_1_address[0] = cpu_to_le32(LSD(ha->ct_sns_dma));
- ct_pkt->dseg_1_address[1] = cpu_to_le32(MSD(ha->ct_sns_dma));
- ct_pkt->dseg_1_len = ct_pkt->rsp_byte_count;
+ put_unaligned_le64(ha->ct_sns_dma, &ct_pkt->dsd[1].address);
+ ct_pkt->dsd[1].length = ct_pkt->rsp_byte_count;
ct_pkt->vp_index = vha->vp_idx;
return ct_pkt;
}
-static inline ms_iocb_entry_t *
+static void
qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size)
{
struct qla_hw_data *ha = vha->hw;
@@ -1491,13 +1471,11 @@ qla2x00_update_ms_fdmi_iocb(scsi_qla_host_t *vha, uint32_t req_size)
if (IS_FWI2_CAPABLE(ha)) {
ct_pkt->cmd_byte_count = cpu_to_le32(req_size);
- ct_pkt->dseg_0_len = ct_pkt->cmd_byte_count;
+ ct_pkt->dsd[0].length = ct_pkt->cmd_byte_count;
} else {
ms_pkt->req_bytecount = cpu_to_le32(req_size);
- ms_pkt->dseg_req_length = ms_pkt->req_bytecount;
+ ms_pkt->req_dsd.length = ms_pkt->req_bytecount;
}
-
- return ms_pkt;
}
/**
@@ -1560,7 +1538,7 @@ qla2x00_fdmi_rhba(scsi_qla_host_t *vha)
/* Attributes */
ct_req->req.rhba.attrs.count =
cpu_to_be32(FDMI_HBA_ATTR_COUNT);
- entries = ct_req->req.rhba.hba_identifier;
+ entries = &ct_req->req;
/* Nodename. */
eiter = entries + size;
@@ -1769,7 +1747,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
/* Attributes */
ct_req->req.rpa.attrs.count = cpu_to_be32(FDMI_PORT_ATTR_COUNT);
- entries = ct_req->req.rpa.port_name;
+ entries = &ct_req->req;
/* FC4 types. */
eiter = entries + size;
@@ -1790,7 +1768,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *vha)
if (IS_CNA_CAPABLE(ha))
eiter->a.sup_speed = cpu_to_be32(
FDMI_PORT_SPEED_10GB);
- else if (IS_QLA27XX(ha))
+ else if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
eiter->a.sup_speed = cpu_to_be32(
FDMI_PORT_SPEED_32GB|
FDMI_PORT_SPEED_16GB|
@@ -1982,7 +1960,7 @@ qla2x00_fdmiv2_rhba(scsi_qla_host_t *vha)
/* Attributes */
ct_req->req.rhba2.attrs.count = cpu_to_be32(FDMIV2_HBA_ATTR_COUNT);
- entries = ct_req->req.rhba2.hba_identifier;
+ entries = &ct_req->req;
/* Nodename. */
eiter = entries + size;
@@ -2341,7 +2319,7 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha)
/* Attributes */
ct_req->req.rpa2.attrs.count = cpu_to_be32(FDMIV2_PORT_ATTR_COUNT);
- entries = ct_req->req.rpa2.port_name;
+ entries = &ct_req->req;
/* FC4 types. */
eiter = entries + size;
@@ -2369,7 +2347,7 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha)
if (IS_CNA_CAPABLE(ha))
eiter->a.sup_speed = cpu_to_be32(
FDMI_PORT_SPEED_10GB);
- else if (IS_QLA27XX(ha))
+ else if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
eiter->a.sup_speed = cpu_to_be32(
FDMI_PORT_SPEED_32GB|
FDMI_PORT_SPEED_16GB|
@@ -2442,7 +2420,7 @@ qla2x00_fdmiv2_rpa(scsi_qla_host_t *vha)
eiter->type = cpu_to_be16(FDMI_PORT_MAX_FRAME_SIZE);
eiter->len = cpu_to_be16(4 + 4);
eiter->a.max_frame_size = IS_FWI2_CAPABLE(ha) ?
- le16_to_cpu(icb24->frame_payload_size):
+ le16_to_cpu(icb24->frame_payload_size) :
le16_to_cpu(ha->init_cb->frame_payload_size);
eiter->a.max_frame_size = cpu_to_be32(eiter->a.max_frame_size);
size += 4 + 4;
@@ -2733,9 +2711,7 @@ qla2x00_gfpn_id(scsi_qla_host_t *vha, sw_info_t *list)
ct_rsp = &ha->ct_sns->p.rsp;
/* Prepare CT arguments -- port_id */
- ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
- ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
- ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
+ ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id);
/* Execute MS IOCB */
rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
@@ -2779,6 +2755,31 @@ qla24xx_prep_ct_fm_req(struct ct_sns_pkt *p, uint16_t cmd,
return &p->p.req;
}
+static uint16_t
+qla2x00_port_speed_capability(uint16_t speed)
+{
+ switch (speed) {
+ case BIT_15:
+ return PORT_SPEED_1GB;
+ case BIT_14:
+ return PORT_SPEED_2GB;
+ case BIT_13:
+ return PORT_SPEED_4GB;
+ case BIT_12:
+ return PORT_SPEED_10GB;
+ case BIT_11:
+ return PORT_SPEED_8GB;
+ case BIT_10:
+ return PORT_SPEED_16GB;
+ case BIT_8:
+ return PORT_SPEED_32GB;
+ case BIT_7:
+ return PORT_SPEED_64GB;
+ default:
+ return PORT_SPEED_UNKNOWN;
+ }
+}
+
/**
* qla2x00_gpsc() - FCS Get Port Speed Capabilities (GPSC) query.
* @vha: HA context
@@ -2851,31 +2852,8 @@ qla2x00_gpsc(scsi_qla_host_t *vha, sw_info_t *list)
}
rval = QLA_FUNCTION_FAILED;
} else {
- /* Save port-speed */
- switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
- case BIT_15:
- list[i].fp_speed = PORT_SPEED_1GB;
- break;
- case BIT_14:
- list[i].fp_speed = PORT_SPEED_2GB;
- break;
- case BIT_13:
- list[i].fp_speed = PORT_SPEED_4GB;
- break;
- case BIT_12:
- list[i].fp_speed = PORT_SPEED_10GB;
- break;
- case BIT_11:
- list[i].fp_speed = PORT_SPEED_8GB;
- break;
- case BIT_10:
- list[i].fp_speed = PORT_SPEED_16GB;
- break;
- case BIT_8:
- list[i].fp_speed = PORT_SPEED_32GB;
- break;
- }
-
+ list->fp_speed = qla2x00_port_speed_capability(
+ be16_to_cpu(ct_rsp->rsp.gpsc.speed));
ql_dbg(ql_dbg_disc, vha, 0x205b,
"GPSC ext entry - fpn "
"%8phN speeds=%04x speed=%04x.\n",
@@ -2937,9 +2915,7 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
ct_rsp = &ha->ct_sns->p.rsp;
/* Prepare CT arguments -- port_id */
- ct_req->req.port_id.port_id[0] = list[i].d_id.b.domain;
- ct_req->req.port_id.port_id[1] = list[i].d_id.b.area;
- ct_req->req.port_id.port_id[2] = list[i].d_id.b.al_pa;
+ ct_req->req.port_id.port_id = port_id_to_be_id(list[i].d_id);
/* Execute MS IOCB */
rval = qla2x00_issue_iocb(vha, ha->ms_iocb, ha->ms_iocb_dma,
@@ -3012,9 +2988,8 @@ void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea)
qla_post_iidma_work(vha, fcport);
}
-static void qla24xx_async_gpsc_sp_done(void *s, int res)
+static void qla24xx_async_gpsc_sp_done(srb_t *sp, int res)
{
- struct srb *sp = s;
struct scsi_qla_host *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
fc_port_t *fcport = sp->fcport;
@@ -3027,6 +3002,8 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res)
"Async done-%s res %x, WWPN %8phC \n",
sp->name, res, fcport->port_name);
+ fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
+
if (res == QLA_FUNCTION_TIMEOUT)
return;
@@ -3044,29 +3021,8 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res)
goto done;
}
} else {
- switch (be16_to_cpu(ct_rsp->rsp.gpsc.speed)) {
- case BIT_15:
- fcport->fp_speed = PORT_SPEED_1GB;
- break;
- case BIT_14:
- fcport->fp_speed = PORT_SPEED_2GB;
- break;
- case BIT_13:
- fcport->fp_speed = PORT_SPEED_4GB;
- break;
- case BIT_12:
- fcport->fp_speed = PORT_SPEED_10GB;
- break;
- case BIT_11:
- fcport->fp_speed = PORT_SPEED_8GB;
- break;
- case BIT_10:
- fcport->fp_speed = PORT_SPEED_16GB;
- break;
- case BIT_8:
- fcport->fp_speed = PORT_SPEED_32GB;
- break;
- }
+ fcport->fp_speed = qla2x00_port_speed_capability(
+ be16_to_cpu(ct_rsp->rsp.gpsc.speed));
ql_dbg(ql_dbg_disc, vha, 0x2054,
"Async-%s OUT WWPN %8phC speeds=%04x speed=%04x.\n",
@@ -3075,11 +3031,10 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res)
be16_to_cpu(ct_rsp->rsp.gpsc.speed));
}
memset(&ea, 0, sizeof(ea));
- ea.event = FCME_GPSC_DONE;
ea.rc = res;
ea.fcport = fcport;
ea.sp = sp;
- qla2x00_fcport_event_handler(vha, &ea);
+ qla24xx_handle_gpsc_event(vha, &ea);
done:
sp->free(sp);
@@ -3164,17 +3119,7 @@ void qla24xx_sp_unmap(scsi_qla_host_t *vha, srb_t *sp)
switch (sp->type) {
case SRB_ELS_DCMD:
- if (c->u.els_plogi.els_plogi_pyld)
- dma_free_coherent(&vha->hw->pdev->dev,
- c->u.els_plogi.tx_size,
- c->u.els_plogi.els_plogi_pyld,
- c->u.els_plogi.els_plogi_pyld_dma);
-
- if (c->u.els_plogi.els_resp_pyld)
- dma_free_coherent(&vha->hw->pdev->dev,
- c->u.els_plogi.rx_size,
- c->u.els_plogi.els_resp_pyld,
- c->u.els_plogi.els_resp_pyld_dma);
+ qla2x00_els_dcmd2_free(vha, &c->u.els_plogi);
break;
case SRB_CT_PTHRU_CMD:
default:
@@ -3300,9 +3245,8 @@ void qla24xx_handle_gpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
}
}
-static void qla2x00_async_gpnid_sp_done(void *s, int res)
+static void qla2x00_async_gpnid_sp_done(srb_t *sp, int res)
{
- struct srb *sp = s;
struct scsi_qla_host *vha = sp->vha;
struct ct_sns_req *ct_req =
(struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
@@ -3315,22 +3259,19 @@ static void qla2x00_async_gpnid_sp_done(void *s, int res)
if (res)
ql_dbg(ql_dbg_disc, vha, 0x2066,
"Async done-%s fail res %x rscn gen %d ID %3phC. %8phC\n",
- sp->name, res, sp->gen1, ct_req->req.port_id.port_id,
+ sp->name, res, sp->gen1, &ct_req->req.port_id.port_id,
ct_rsp->rsp.gpn_id.port_name);
else
ql_dbg(ql_dbg_disc, vha, 0x2066,
"Async done-%s good rscn gen %d ID %3phC. %8phC\n",
- sp->name, sp->gen1, ct_req->req.port_id.port_id,
+ sp->name, sp->gen1, &ct_req->req.port_id.port_id,
ct_rsp->rsp.gpn_id.port_name);
memset(&ea, 0, sizeof(ea));
memcpy(ea.port_name, ct_rsp->rsp.gpn_id.port_name, WWN_SIZE);
ea.sp = sp;
- ea.id.b.domain = ct_req->req.port_id.port_id[0];
- ea.id.b.area = ct_req->req.port_id.port_id[1];
- ea.id.b.al_pa = ct_req->req.port_id.port_id[2];
+ ea.id = be_to_port_id(ct_req->req.port_id.port_id);
ea.rc = res;
- ea.event = FCME_GPNID_DONE;
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
list_del(&sp->elem);
@@ -3349,25 +3290,22 @@ static void qla2x00_async_gpnid_sp_done(void *s, int res)
return;
}
- qla2x00_fcport_event_handler(vha, &ea);
+ qla24xx_handle_gpnid_event(vha, &ea);
e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
if (!e) {
/* please ignore kernel warning. otherwise, we have mem leak. */
- if (sp->u.iocb_cmd.u.ctarg.req) {
- dma_free_coherent(&vha->hw->pdev->dev,
- sp->u.iocb_cmd.u.ctarg.req_allocated_size,
- sp->u.iocb_cmd.u.ctarg.req,
- sp->u.iocb_cmd.u.ctarg.req_dma);
- sp->u.iocb_cmd.u.ctarg.req = NULL;
- }
- if (sp->u.iocb_cmd.u.ctarg.rsp) {
- dma_free_coherent(&vha->hw->pdev->dev,
- sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
- sp->u.iocb_cmd.u.ctarg.rsp,
- sp->u.iocb_cmd.u.ctarg.rsp_dma);
- sp->u.iocb_cmd.u.ctarg.rsp = NULL;
- }
+ dma_free_coherent(&vha->hw->pdev->dev,
+ sp->u.iocb_cmd.u.ctarg.req_allocated_size,
+ sp->u.iocb_cmd.u.ctarg.req,
+ sp->u.iocb_cmd.u.ctarg.req_dma);
+ sp->u.iocb_cmd.u.ctarg.req = NULL;
+
+ dma_free_coherent(&vha->hw->pdev->dev,
+ sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
+ sp->u.iocb_cmd.u.ctarg.rsp,
+ sp->u.iocb_cmd.u.ctarg.rsp_dma);
+ sp->u.iocb_cmd.u.ctarg.rsp = NULL;
sp->free(sp);
return;
@@ -3439,9 +3377,7 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
ct_req = qla2x00_prep_ct_req(ct_sns, GPN_ID_CMD, GPN_ID_RSP_SIZE);
/* GPN_ID req */
- ct_req->req.port_id.port_id[0] = id->b.domain;
- ct_req->req.port_id.port_id[1] = id->b.area;
- ct_req->req.port_id.port_id[2] = id->b.al_pa;
+ ct_req->req.port_id.port_id = port_id_to_be_id(*id);
sp->u.iocb_cmd.u.ctarg.req_size = GPN_ID_REQ_SIZE;
sp->u.iocb_cmd.u.ctarg.rsp_size = GPN_ID_RSP_SIZE;
@@ -3452,7 +3388,7 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
ql_dbg(ql_dbg_disc, vha, 0x2067,
"Async-%s hdl=%x ID %3phC.\n", sp->name,
- sp->handle, ct_req->req.port_id.port_id);
+ sp->handle, &ct_req->req.port_id.port_id);
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS)
@@ -3487,54 +3423,52 @@ done:
void qla24xx_handle_gffid_event(scsi_qla_host_t *vha, struct event_arg *ea)
{
- fc_port_t *fcport = ea->fcport;
+ fc_port_t *fcport = ea->fcport;
- qla24xx_post_gnl_work(vha, fcport);
+ qla24xx_post_gnl_work(vha, fcport);
}
-void qla24xx_async_gffid_sp_done(void *s, int res)
+void qla24xx_async_gffid_sp_done(srb_t *sp, int res)
{
- struct srb *sp = s;
- struct scsi_qla_host *vha = sp->vha;
- fc_port_t *fcport = sp->fcport;
- struct ct_sns_rsp *ct_rsp;
- struct event_arg ea;
-
- ql_dbg(ql_dbg_disc, vha, 0x2133,
- "Async done-%s res %x ID %x. %8phC\n",
- sp->name, res, fcport->d_id.b24, fcport->port_name);
-
- fcport->flags &= ~FCF_ASYNC_SENT;
- ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
- /*
- * FC-GS-7, 5.2.3.12 FC-4 Features - format
- * The format of the FC-4 Features object, as defined by the FC-4,
- * Shall be an array of 4-bit values, one for each type code value
- */
- if (!res) {
- if (ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET] & 0xf) {
- /* w1 b00:03 */
- fcport->fc4_type =
- ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
- fcport->fc4_type &= 0xf;
- }
+ struct scsi_qla_host *vha = sp->vha;
+ fc_port_t *fcport = sp->fcport;
+ struct ct_sns_rsp *ct_rsp;
+ struct event_arg ea;
- if (ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET] & 0xf) {
- /* w5 [00:03]/28h */
- fcport->fc4f_nvme =
- ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
- fcport->fc4f_nvme &= 0xf;
+ ql_dbg(ql_dbg_disc, vha, 0x2133,
+ "Async done-%s res %x ID %x. %8phC\n",
+ sp->name, res, fcport->d_id.b24, fcport->port_name);
+
+ fcport->flags &= ~FCF_ASYNC_SENT;
+ ct_rsp = &fcport->ct_desc.ct_sns->p.rsp;
+ /*
+ * FC-GS-7, 5.2.3.12 FC-4 Features - format
+ * The format of the FC-4 Features object, as defined by the FC-4,
+ * Shall be an array of 4-bit values, one for each type code value
+ */
+ if (!res) {
+ if (ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET] & 0xf) {
+ /* w1 b00:03 */
+ fcport->fc4_type =
+ ct_rsp->rsp.gff_id.fc4_features[GFF_FCP_SCSI_OFFSET];
+ fcport->fc4_type &= 0xf;
}
- }
- memset(&ea, 0, sizeof(ea));
- ea.sp = sp;
- ea.fcport = sp->fcport;
- ea.rc = res;
- ea.event = FCME_GFFID_DONE;
+ if (ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET] & 0xf) {
+ /* w5 [00:03]/28h */
+ fcport->fc4f_nvme =
+ ct_rsp->rsp.gff_id.fc4_features[GFF_NVME_OFFSET];
+ fcport->fc4f_nvme &= 0xf;
+ }
+ }
- qla2x00_fcport_event_handler(vha, &ea);
- sp->free(sp);
+ memset(&ea, 0, sizeof(ea));
+ ea.sp = sp;
+ ea.fcport = sp->fcport;
+ ea.rc = res;
+
+ qla24xx_handle_gffid_event(vha, &ea);
+ sp->free(sp);
}
/* Get FC4 Feature with Nport ID. */
@@ -3578,14 +3512,14 @@ int qla24xx_async_gffid(scsi_qla_host_t *vha, fc_port_t *fcport)
sp->done = qla24xx_async_gffid_sp_done;
- rval = qla2x00_start_sp(sp);
- if (rval != QLA_SUCCESS)
- goto done_free_sp;
-
ql_dbg(ql_dbg_disc, vha, 0x2132,
"Async-%s hdl=%x %8phC.\n", sp->name,
sp->handle, fcport->port_name);
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS)
+ goto done_free_sp;
+
return rval;
done_free_sp:
sp->free(sp);
@@ -3694,7 +3628,6 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
list_for_each_entry(fcport, &vha->vp_fcports, list) {
if (memcmp(rp->port_name, fcport->port_name, WWN_SIZE))
continue;
- fcport->scan_needed = 0;
fcport->scan_state = QLA_FCPORT_FOUND;
found = true;
/*
@@ -3703,10 +3636,12 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {
qla2x00_clear_loop_id(fcport);
fcport->flags |= FCF_FABRIC_DEVICE;
- } else if (fcport->d_id.b24 != rp->id.b24) {
+ } else if (fcport->d_id.b24 != rp->id.b24 ||
+ fcport->scan_needed) {
qlt_schedule_sess_for_deletion(fcport);
}
fcport->d_id.b24 = rp->id.b24;
+ fcport->scan_needed = 0;
break;
}
@@ -3918,9 +3853,8 @@ static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha,
}
}
-static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
+static void qla2x00_async_gpnft_gnnft_sp_done(srb_t *sp, int res)
{
- struct srb *sp = s;
struct scsi_qla_host *vha = sp->vha;
struct ct_sns_req *ct_req =
(struct ct_sns_req *)sp->u.iocb_cmd.u.ctarg.req;
@@ -4067,17 +4001,15 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
sp->done = qla2x00_async_gpnft_gnnft_sp_done;
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async-%s hdl=%x FC4Type %x.\n", sp->name,
+ sp->handle, ct_req->req.gpn_ft.port_type);
+
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
- spin_lock_irqsave(&vha->work_lock, flags);
- vha->scan.scan_flags &= ~SF_SCANNING;
- spin_unlock_irqrestore(&vha->work_lock, flags);
goto done_free_sp;
}
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async-%s hdl=%x FC4Type %x.\n", sp->name,
- sp->handle, ct_req->req.gpn_ft.port_type);
return rval;
done_free_sp:
@@ -4098,6 +4030,17 @@ done_free_sp:
sp->free(sp);
+ spin_lock_irqsave(&vha->work_lock, flags);
+ vha->scan.scan_flags &= ~SF_SCANNING;
+ if (vha->scan.scan_flags == 0) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s: schedule\n", __func__);
+ vha->scan.scan_flags |= SF_QUEUED;
+ schedule_delayed_work(&vha->scan.scan_work, 5);
+ }
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+
+
return rval;
} /* GNNFT */
@@ -4157,7 +4100,8 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
spin_lock_irqsave(&vha->work_lock, flags);
vha->scan.scan_flags &= ~SF_SCANNING;
spin_unlock_irqrestore(&vha->work_lock, flags);
- goto done_free_sp;
+ qla2x00_rel_sp(sp);
+ return rval;
}
sp->u.iocb_cmd.u.ctarg.req_size = GPN_FT_REQ_SIZE;
@@ -4168,14 +4112,20 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
sp->u.iocb_cmd.u.ctarg.rsp = dma_zalloc_coherent(
&vha->hw->pdev->dev, rspsz,
&sp->u.iocb_cmd.u.ctarg.rsp_dma, GFP_KERNEL);
- sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt);
+ sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = rspsz;
if (!sp->u.iocb_cmd.u.ctarg.rsp) {
ql_log(ql_log_warn, vha, 0xffff,
"Failed to allocate ct_sns request.\n");
spin_lock_irqsave(&vha->work_lock, flags);
vha->scan.scan_flags &= ~SF_SCANNING;
spin_unlock_irqrestore(&vha->work_lock, flags);
- goto done_free_sp;
+ dma_free_coherent(&vha->hw->pdev->dev,
+ sp->u.iocb_cmd.u.ctarg.req_allocated_size,
+ sp->u.iocb_cmd.u.ctarg.req,
+ sp->u.iocb_cmd.u.ctarg.req_dma);
+ sp->u.iocb_cmd.u.ctarg.req = NULL;
+ qla2x00_rel_sp(sp);
+ return rval;
}
sp->u.iocb_cmd.u.ctarg.rsp_size = rspsz;
@@ -4212,17 +4162,15 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
sp->done = qla2x00_async_gpnft_gnnft_sp_done;
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "Async-%s hdl=%x FC4Type %x.\n", sp->name,
+ sp->handle, ct_req->req.gpn_ft.port_type);
+
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
- spin_lock_irqsave(&vha->work_lock, flags);
- vha->scan.scan_flags &= ~SF_SCANNING;
- spin_unlock_irqrestore(&vha->work_lock, flags);
goto done_free_sp;
}
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "Async-%s hdl=%x FC4Type %x.\n", sp->name,
- sp->handle, ct_req->req.gpn_ft.port_type);
return rval;
done_free_sp:
@@ -4243,6 +4191,17 @@ done_free_sp:
sp->free(sp);
+ spin_lock_irqsave(&vha->work_lock, flags);
+ vha->scan.scan_flags &= ~SF_SCANNING;
+ if (vha->scan.scan_flags == 0) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff,
+ "%s: schedule\n", __func__);
+ vha->scan.scan_flags |= SF_QUEUED;
+ schedule_delayed_work(&vha->scan.scan_work, 5);
+ }
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+
+
return rval;
}
@@ -4270,9 +4229,8 @@ void qla24xx_handle_gnnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
qla24xx_post_gnl_work(vha, ea->fcport);
}
-static void qla2x00_async_gnnid_sp_done(void *s, int res)
+static void qla2x00_async_gnnid_sp_done(srb_t *sp, int res)
{
- struct srb *sp = s;
struct scsi_qla_host *vha = sp->vha;
fc_port_t *fcport = sp->fcport;
u8 *node_name = fcport->ct_desc.ct_sns->p.rsp.rsp.gnn_id.node_name;
@@ -4288,13 +4246,12 @@ static void qla2x00_async_gnnid_sp_done(void *s, int res)
ea.fcport = fcport;
ea.sp = sp;
ea.rc = res;
- ea.event = FCME_GNNID_DONE;
ql_dbg(ql_dbg_disc, vha, 0x204f,
"Async done-%s res %x, WWPN %8phC %8phC\n",
sp->name, res, fcport->port_name, fcport->node_name);
- qla2x00_fcport_event_handler(vha, &ea);
+ qla24xx_handle_gnnid_event(vha, &ea);
sp->free(sp);
}
@@ -4327,9 +4284,7 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
GNN_ID_RSP_SIZE);
/* GNN_ID req */
- ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
- ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
- ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
+ ct_req->req.port_id.port_id = port_id_to_be_id(fcport->d_id);
/* req & rsp use the same buffer */
@@ -4343,17 +4298,19 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
sp->done = qla2x00_async_gnnid_sp_done;
- rval = qla2x00_start_sp(sp);
- if (rval != QLA_SUCCESS)
- goto done_free_sp;
ql_dbg(ql_dbg_disc, vha, 0xffff,
"Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",
sp->name, fcport->port_name,
sp->handle, fcport->loop_id, fcport->d_id.b24);
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS)
+ goto done_free_sp;
return rval;
done_free_sp:
sp->free(sp);
+ fcport->flags &= ~FCF_ASYNC_SENT;
done:
return rval;
}
@@ -4403,9 +4360,8 @@ void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
qla24xx_post_gpsc_work(vha, fcport);
}
-static void qla2x00_async_gfpnid_sp_done(void *s, int res)
+static void qla2x00_async_gfpnid_sp_done(srb_t *sp, int res)
{
- struct srb *sp = s;
struct scsi_qla_host *vha = sp->vha;
fc_port_t *fcport = sp->fcport;
u8 *fpn = fcport->ct_desc.ct_sns->p.rsp.rsp.gfpn_id.port_name;
@@ -4420,13 +4376,12 @@ static void qla2x00_async_gfpnid_sp_done(void *s, int res)
ea.fcport = fcport;
ea.sp = sp;
ea.rc = res;
- ea.event = FCME_GFPNID_DONE;
ql_dbg(ql_dbg_disc, vha, 0x204f,
"Async done-%s res %x, WWPN %8phC %8phC\n",
sp->name, res, fcport->port_name, fcport->fabric_port_name);
- qla2x00_fcport_event_handler(vha, &ea);
+ qla24xx_handle_gfpnid_event(vha, &ea);
sp->free(sp);
}
@@ -4457,9 +4412,7 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
GFPN_ID_RSP_SIZE);
/* GFPN_ID req */
- ct_req->req.port_id.port_id[0] = fcport->d_id.b.domain;
- ct_req->req.port_id.port_id[1] = fcport->d_id.b.area;
- ct_req->req.port_id.port_id[2] = fcport->d_id.b.al_pa;
+ ct_req->req.port_id.port_id = port_id_to_be_id(fcport->d_id);
/* req & rsp use the same buffer */
@@ -4473,14 +4426,15 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
sp->done = qla2x00_async_gfpnid_sp_done;
- rval = qla2x00_start_sp(sp);
- if (rval != QLA_SUCCESS)
- goto done_free_sp;
-
ql_dbg(ql_dbg_disc, vha, 0xffff,
"Async-%s - %8phC hdl=%x loopid=%x portid %06x.\n",
sp->name, fcport->port_name,
sp->handle, fcport->loop_id, fcport->d_id.b24);
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS)
+ goto done_free_sp;
+
return rval;
done_free_sp:
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index cf27603b1959..fb2fecbac623 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -37,8 +37,8 @@ static struct qla_chip_state_84xx *qla84xx_get_chip(struct scsi_qla_host *);
static int qla84xx_init_chip(scsi_qla_host_t *);
static int qla25xx_init_queues(struct qla_hw_data *);
static int qla24xx_post_prli_work(struct scsi_qla_host*, fc_port_t *);
-static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
- struct event_arg *);
+static void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha,
+ struct event_arg *ea);
static void qla24xx_handle_prli_done_event(struct scsi_qla_host *,
struct event_arg *);
static void __qla24xx_handle_gpdb_event(scsi_qla_host_t *, struct event_arg *);
@@ -63,10 +63,8 @@ qla2x00_sp_timeout(unsigned long __data)
iocb->timeout(sp);
}
-void
-qla2x00_sp_free(void *ptr)
+void qla2x00_sp_free(srb_t *sp)
{
- srb_t *sp = ptr;
struct srb_iocb *iocb = &sp->u.iocb_cmd;
del_timer(&iocb->timer);
@@ -95,6 +93,88 @@ qla2x00_get_async_timeout(struct scsi_qla_host *vha)
return tmo;
}
+static void qla24xx_abort_iocb_timeout(void *data)
+{
+ srb_t *sp = data;
+ struct srb_iocb *abt = &sp->u.iocb_cmd;
+ struct qla_qpair *qpair = sp->qpair;
+ u32 handle;
+ unsigned long flags;
+
+ spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+ for (handle = 1; handle < qpair->req->num_outstanding_cmds; handle++) {
+ /* removing the abort */
+ if (qpair->req->outstanding_cmds[handle] == sp) {
+ qpair->req->outstanding_cmds[handle] = NULL;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+
+ abt->u.abt.comp_status = CS_TIMEOUT;
+ sp->done(sp, QLA_OS_TIMER_EXPIRED);
+}
+
+static void qla24xx_abort_sp_done(srb_t *sp, int res)
+{
+ struct srb_iocb *abt = &sp->u.iocb_cmd;
+
+ del_timer(&sp->u.iocb_cmd.timer);
+ if (sp->flags & SRB_WAKEUP_ON_COMP)
+ complete(&abt->u.abt.comp);
+ else
+ sp->free(sp);
+}
+
+static int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
+{
+ scsi_qla_host_t *vha = cmd_sp->vha;
+ struct srb_iocb *abt_iocb;
+ srb_t *sp;
+ int rval = QLA_FUNCTION_FAILED;
+
+ sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport,
+ GFP_ATOMIC);
+ if (!sp)
+ return rval;
+
+ abt_iocb = &sp->u.iocb_cmd;
+ sp->type = SRB_ABT_CMD;
+ sp->name = "abort";
+ sp->qpair = cmd_sp->qpair;
+ if (wait)
+ sp->flags = SRB_WAKEUP_ON_COMP;
+
+ abt_iocb->timeout = qla24xx_abort_iocb_timeout;
+ init_completion(&abt_iocb->u.abt.comp);
+ /* FW can send 2 x ABTS's timeout/20s */
+ qla2x00_init_timer(sp, 42);
+
+ abt_iocb->u.abt.cmd_hndl = cmd_sp->handle;
+ abt_iocb->u.abt.req_que_no = cpu_to_le16(cmd_sp->qpair->req->id);
+
+ sp->done = qla24xx_abort_sp_done;
+
+ ql_dbg(ql_dbg_async, vha, 0x507c,
+ "Abort command issued - hdl=%x, type=%x\n", cmd_sp->handle,
+ cmd_sp->type);
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS) {
+ sp->free(sp);
+ return rval;
+ }
+
+ if (wait) {
+ wait_for_completion(&abt_iocb->u.abt.comp);
+ rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ?
+ QLA_SUCCESS : QLA_FUNCTION_FAILED;
+ sp->free(sp);
+ }
+
+ return rval;
+}
+
void
qla2x00_async_iocb_timeout(void *data)
{
@@ -161,13 +241,15 @@ qla2x00_async_iocb_timeout(void *data)
sp->done(sp, QLA_FUNCTION_TIMEOUT);
}
break;
+ default:
+ WARN_ON_ONCE(true);
+ sp->done(sp, QLA_FUNCTION_TIMEOUT);
+ break;
}
}
-static void
-qla2x00_async_login_sp_done(void *ptr, int res)
+static void qla2x00_async_login_sp_done(srb_t *sp, int res)
{
- srb_t *sp = ptr;
struct scsi_qla_host *vha = sp->vha;
struct srb_iocb *lio = &sp->u.iocb_cmd;
struct event_arg ea;
@@ -179,14 +261,13 @@ qla2x00_async_login_sp_done(void *ptr, int res)
if (!test_bit(UNLOADING, &vha->dpc_flags)) {
memset(&ea, 0, sizeof(ea));
- ea.event = FCME_PLOGI_DONE;
ea.fcport = sp->fcport;
ea.data[0] = lio->u.logio.data[0];
ea.data[1] = lio->u.logio.data[1];
ea.iop[0] = lio->u.logio.iop[0];
ea.iop[1] = lio->u.logio.iop[1];
ea.sp = sp;
- qla2x00_fcport_event_handler(vha, &ea);
+ qla24xx_handle_plogi_done_event(vha, &ea);
}
sp->free(sp);
@@ -216,8 +297,13 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
struct srb_iocb *lio;
int rval = QLA_FUNCTION_FAILED;
- if (!vha->flags.online)
- goto done;
+ if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT) ||
+ fcport->loop_id == FC_NO_LOOP_ID) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "%s: %8phC - not sending command.\n",
+ __func__, fcport->port_name);
+ return rval;
+ }
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
@@ -268,11 +354,8 @@ done:
return rval;
}
-static void
-qla2x00_async_logout_sp_done(void *ptr, int res)
+static void qla2x00_async_logout_sp_done(srb_t *sp, int res)
{
- srb_t *sp = ptr;
-
sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
sp->fcport->login_gen++;
qlt_logo_completion_handler(sp->fcport, res);
@@ -286,9 +369,6 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
struct srb_iocb *lio;
int rval = QLA_FUNCTION_FAILED;
- if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
- return rval;
-
fcport->flags |= FCF_ASYNC_SENT;
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
@@ -332,10 +412,8 @@ qla2x00_async_prlo_done(struct scsi_qla_host *vha, fc_port_t *fcport,
qlt_logo_completion_handler(fcport, data[0]);
}
-static void
-qla2x00_async_prlo_sp_done(void *s, int res)
+static void qla2x00_async_prlo_sp_done(srb_t *sp, int res)
{
- srb_t *sp = (srb_t *)s;
struct srb_iocb *lio = &sp->u.iocb_cmd;
struct scsi_qla_host *vha = sp->vha;
@@ -366,14 +444,16 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t *fcport)
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
sp->done = qla2x00_async_prlo_sp_done;
- rval = qla2x00_start_sp(sp);
- if (rval != QLA_SUCCESS)
- goto done_free_sp;
ql_dbg(ql_dbg_disc, vha, 0x2070,
"Async-prlo - hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
sp->handle, fcport->loop_id, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa);
+
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS)
+ goto done_free_sp;
+
return rval;
done_free_sp:
@@ -394,6 +474,9 @@ void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2,
fcport->rscn_gen, ea->sp->gen1, fcport->loop_id);
+ WARN_ONCE(!qla2xxx_is_valid_mbs(ea->data[0]), "mbs: %#x\n",
+ ea->data[0]);
+
if (ea->data[0] != MBS_COMMAND_COMPLETE) {
ql_dbg(ql_dbg_disc, vha, 0x2066,
"%s %8phC: adisc fail: post delete\n",
@@ -436,10 +519,8 @@ static int qla_post_els_plogi_work(struct scsi_qla_host *vha, fc_port_t *fcport)
return qla2x00_post_work(vha, e);
}
-static void
-qla2x00_async_adisc_sp_done(void *ptr, int res)
+static void qla2x00_async_adisc_sp_done(srb_t *sp, int res)
{
- srb_t *sp = ptr;
struct scsi_qla_host *vha = sp->vha;
struct event_arg ea;
struct srb_iocb *lio = &sp->u.iocb_cmd;
@@ -451,7 +532,6 @@ qla2x00_async_adisc_sp_done(void *ptr, int res)
sp->fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
memset(&ea, 0, sizeof(ea));
- ea.event = FCME_ADISC_DONE;
ea.rc = res;
ea.data[0] = lio->u.logio.data[0];
ea.data[1] = lio->u.logio.data[1];
@@ -460,7 +540,7 @@ qla2x00_async_adisc_sp_done(void *ptr, int res)
ea.fcport = sp->fcport;
ea.sp = sp;
- qla2x00_fcport_event_handler(vha, &ea);
+ qla24xx_handle_adisc_event(vha, &ea);
sp->free(sp);
}
@@ -471,9 +551,11 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
{
srb_t *sp;
struct srb_iocb *lio;
- int rval;
+ int rval = QLA_FUNCTION_FAILED;
+
+ if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
+ return rval;
- rval = QLA_FUNCTION_FAILED;
fcport->flags |= FCF_ASYNC_SENT;
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
@@ -510,6 +592,72 @@ done:
return rval;
}
+static bool qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id)
+{
+ struct qla_hw_data *ha = vha->hw;
+
+ if (IS_FWI2_CAPABLE(ha))
+ return loop_id > NPH_LAST_HANDLE;
+
+ return (loop_id > ha->max_loop_id && loop_id < SNS_FIRST_LOOP_ID) ||
+ loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST;
+}
+
+/**
+ * qla2x00_find_new_loop_id - scan through our port list and find a new usable loop ID
+ * @vha: adapter state pointer.
+ * @dev: port structure pointer.
+ *
+ * Returns:
+ * qla2x00 local function return status code.
+ *
+ * Context:
+ * Kernel context.
+ */
+static int qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
+{
+ int rval;
+ struct qla_hw_data *ha = vha->hw;
+ unsigned long flags = 0;
+
+ rval = QLA_SUCCESS;
+
+ spin_lock_irqsave(&ha->vport_slock, flags);
+
+ dev->loop_id = find_first_zero_bit(ha->loop_id_map, LOOPID_MAP_SIZE);
+ if (dev->loop_id >= LOOPID_MAP_SIZE ||
+ qla2x00_is_reserved_id(vha, dev->loop_id)) {
+ dev->loop_id = FC_NO_LOOP_ID;
+ rval = QLA_FUNCTION_FAILED;
+ } else {
+ set_bit(dev->loop_id, ha->loop_id_map);
+ }
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
+
+ if (rval == QLA_SUCCESS)
+ ql_dbg(ql_dbg_disc, dev->vha, 0x2086,
+ "Assigning new loopid=%x, portid=%x.\n",
+ dev->loop_id, dev->d_id.b24);
+ else
+ ql_log(ql_log_warn, dev->vha, 0x2087,
+ "No loop_id's available, portid=%x.\n",
+ dev->d_id.b24);
+
+ return rval;
+}
+
+void qla2x00_clear_loop_id(fc_port_t *fcport)
+{
+ struct qla_hw_data *ha = fcport->vha->hw;
+
+ if (fcport->loop_id == FC_NO_LOOP_ID ||
+ qla2x00_is_reserved_id(fcport->vha, fcport->loop_id))
+ return;
+
+ clear_bit(fcport->loop_id, ha->loop_id_map);
+ fcport->loop_id = FC_NO_LOOP_ID;
+}
+
static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
struct event_arg *ea)
{
@@ -644,11 +792,14 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
break;
case DSC_LS_PORT_UNAVAIL:
default:
- if (fcport->loop_id != FC_NO_LOOP_ID)
- qla2x00_clear_loop_id(fcport);
-
- fcport->loop_id = loop_id;
- fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
+ if (fcport->loop_id == FC_NO_LOOP_ID) {
+ qla2x00_find_new_loop_id(vha, fcport);
+ fcport->fw_login_state =
+ DSC_LS_PORT_UNAVAIL;
+ }
+ ql_dbg(ql_dbg_disc, vha, 0x20e5,
+ "%s %d %8phC\n", __func__, __LINE__,
+ fcport->port_name);
qla24xx_fcport_handle_login(vha, fcport);
break;
}
@@ -657,6 +808,15 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
fcport->fw_login_state = current_login_state;
fcport->d_id = id;
switch (current_login_state) {
+ case DSC_LS_PRLI_PEND:
+ /*
+ * In the middle of PRLI. Let it finish.
+ * Allow relogin code to recheck state again
+ * with GNL. Push disc_state back to DELETED
+ * so GNL can go out again
+ */
+ fcport->disc_state = DSC_DELETED;
+ break;
case DSC_LS_PRLI_COMP:
if ((e->prli_svc_param_word_3[0] & BIT_4) == 0)
fcport->port_type = FCT_INITIATOR;
@@ -773,10 +933,8 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
}
} /* gnl_event */
-static void
-qla24xx_async_gnl_sp_done(void *s, int res)
+static void qla24xx_async_gnl_sp_done(srb_t *sp, int res)
{
- struct srb *sp = s;
struct scsi_qla_host *vha = sp->vha;
unsigned long flags;
struct fc_port *fcport = NULL, *tf;
@@ -799,7 +957,6 @@ qla24xx_async_gnl_sp_done(void *s, int res)
memset(&ea, 0, sizeof(ea));
ea.sp = sp;
ea.rc = res;
- ea.event = FCME_GNL_DONE;
if (sp->u.iocb_cmd.u.mbx.in_mb[1] >=
sizeof(struct get_name_list_extended)) {
@@ -838,7 +995,7 @@ qla24xx_async_gnl_sp_done(void *s, int res)
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
ea.fcport = fcport;
- qla2x00_fcport_event_handler(vha, &ea);
+ qla24xx_handle_gnl_done_event(vha, &ea);
}
/* create new fcport if fw has knowledge of new sessions */
@@ -933,14 +1090,14 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
sp->done = qla24xx_async_gnl_sp_done;
- rval = qla2x00_start_sp(sp);
- if (rval != QLA_SUCCESS)
- goto done_free_sp;
-
ql_dbg(ql_dbg_disc, vha, 0x20da,
"Async-%s - OUT WWPN %8phC hndl %x\n",
sp->name, fcport->port_name, sp->handle);
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS)
+ goto done_free_sp;
+
return rval;
done_free_sp:
@@ -963,10 +1120,8 @@ int qla24xx_post_gnl_work(struct scsi_qla_host *vha, fc_port_t *fcport)
return qla2x00_post_work(vha, e);
}
-static
-void qla24xx_async_gpdb_sp_done(void *s, int res)
+static void qla24xx_async_gpdb_sp_done(srb_t *sp, int res)
{
- struct srb *sp = s;
struct scsi_qla_host *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
fc_port_t *fcport = sp->fcport;
@@ -985,11 +1140,10 @@ void qla24xx_async_gpdb_sp_done(void *s, int res)
fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
memset(&ea, 0, sizeof(ea));
- ea.event = FCME_GPDB_DONE;
ea.fcport = fcport;
ea.sp = sp;
- qla2x00_fcport_event_handler(vha, &ea);
+ qla24xx_handle_gpdb_event(vha, &ea);
dma_pool_free(ha->s_dma_pool, sp->u.iocb_cmd.u.mbx.in,
sp->u.iocb_cmd.u.mbx.in_dma);
@@ -1010,10 +1164,8 @@ static int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
return qla2x00_post_work(vha, e);
}
-static void
-qla2x00_async_prli_sp_done(void *ptr, int res)
+static void qla2x00_async_prli_sp_done(srb_t *sp, int res)
{
- srb_t *sp = ptr;
struct scsi_qla_host *vha = sp->vha;
struct srb_iocb *lio = &sp->u.iocb_cmd;
struct event_arg ea;
@@ -1026,7 +1178,6 @@ qla2x00_async_prli_sp_done(void *ptr, int res)
if (!test_bit(UNLOADING, &vha->dpc_flags)) {
memset(&ea, 0, sizeof(ea));
- ea.event = FCME_PRLI_DONE;
ea.fcport = sp->fcport;
ea.data[0] = lio->u.logio.data[0];
ea.data[1] = lio->u.logio.data[1];
@@ -1034,7 +1185,7 @@ qla2x00_async_prli_sp_done(void *ptr, int res)
ea.iop[1] = lio->u.logio.iop[1];
ea.sp = sp;
- qla2x00_fcport_event_handler(vha, &ea);
+ qla24xx_handle_prli_done_event(vha, &ea);
}
sp->free(sp);
@@ -1074,6 +1225,11 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)
if (fcport->fc4f_nvme)
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",
+ fcport->port_name, sp->handle, fcport->loop_id, fcport->d_id.b24,
+ fcport->login_retry, fcport->fc4f_nvme ? "nvme" : "fc");
+
rval = qla2x00_start_sp(sp);
if (rval != QLA_SUCCESS) {
fcport->flags |= FCF_LOGIN_NEEDED;
@@ -1081,11 +1237,6 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)
goto done_free_sp;
}
- ql_dbg(ql_dbg_disc, vha, 0x211b,
- "Async-prli - %8phC hdl=%x, loopid=%x portid=%06x retries=%d %s.\n",
- fcport->port_name, sp->handle, fcport->loop_id, fcport->d_id.b24,
- fcport->login_retry, fcport->fc4f_nvme ? "nvme" : "fc");
-
return rval;
done_free_sp:
@@ -1118,8 +1269,13 @@ int qla24xx_async_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport, u8 opt)
struct port_database_24xx *pd;
struct qla_hw_data *ha = vha->hw;
- if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
+ if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT) ||
+ fcport->loop_id == FC_NO_LOOP_ID) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "%s: %8phC - not sending command.\n",
+ __func__, fcport->port_name);
return rval;
+ }
fcport->disc_state = DSC_GPDB;
@@ -1329,7 +1485,7 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
u64 wwn;
u16 sec;
- ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x20d8,
+ ql_dbg(ql_dbg_disc, vha, 0x20d8,
"%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d lid %d scan %d\n",
__func__, fcport->port_name, fcport->disc_state,
fcport->fw_login_state, fcport->login_pause, fcport->flags,
@@ -1340,6 +1496,7 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
return 0;
if ((fcport->loop_id != FC_NO_LOOP_ID) &&
+ qla_dual_mode_enabled(vha) &&
((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
(fcport->fw_login_state == DSC_LS_PRLI_PEND)))
return 0;
@@ -1473,33 +1630,11 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
return 0;
}
-static
-void qla24xx_handle_rscn_event(fc_port_t *fcport, struct event_arg *ea)
-{
- fcport->rscn_gen++;
-
- ql_dbg(ql_dbg_disc, fcport->vha, 0x210c,
- "%s %8phC DS %d LS %d\n",
- __func__, fcport->port_name, fcport->disc_state,
- fcport->fw_login_state);
-
- if (fcport->flags & FCF_ASYNC_SENT)
- return;
-
- switch (fcport->disc_state) {
- case DSC_DELETED:
- case DSC_LOGIN_COMPLETE:
- qla24xx_post_gpnid_work(fcport->vha, &ea->id);
- break;
- default:
- break;
- }
-}
-
int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
u8 *port_name, u8 *node_name, void *pla, u8 fc4_type)
{
struct qla_work_evt *e;
+
e = qla2x00_alloc_work(vha, QLA_EVT_NEW_SESS);
if (!e)
return QLA_FUNCTION_FAILED;
@@ -1514,12 +1649,34 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *vha, port_id_t *id,
return qla2x00_post_work(vha, e);
}
-static
+void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
+{
+ fc_port_t *fcport;
+ unsigned long flags;
+
+ fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
+ if (fcport) {
+ fcport->scan_needed = 1;
+ fcport->rscn_gen++;
+ }
+
+ spin_lock_irqsave(&vha->work_lock, flags);
+ if (vha->scan.scan_flags == 0) {
+ ql_dbg(ql_dbg_disc, vha, 0xffff, "%s: schedule\n", __func__);
+ vha->scan.scan_flags |= SF_QUEUED;
+ schedule_delayed_work(&vha->scan.scan_work, 5);
+ }
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+}
+
void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
struct event_arg *ea)
{
fc_port_t *fcport = ea->fcport;
+ if (test_bit(UNLOADING, &vha->dpc_flags))
+ return;
+
ql_dbg(ql_dbg_disc, vha, 0x2102,
"%s %8phC DS %d LS %d P %d del %d cnfl %p rscn %d|%d login %d|%d fl %x\n",
__func__, fcport->port_name, fcport->disc_state,
@@ -1529,193 +1686,36 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
fcport->last_login_gen, fcport->login_gen,
fcport->flags);
- if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
- (fcport->fw_login_state == DSC_LS_PRLI_PEND))
- return;
-
- if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
- if (time_before_eq(jiffies, fcport->plogi_nack_done_deadline)) {
- set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
- return;
- }
- }
-
if (fcport->last_rscn_gen != fcport->rscn_gen) {
- ql_dbg(ql_dbg_disc, vha, 0x20e9, "%s %d %8phC post gidpn\n",
+ ql_dbg(ql_dbg_disc, vha, 0x20e9, "%s %d %8phC post gnl\n",
__func__, __LINE__, fcport->port_name);
-
+ qla24xx_post_gnl_work(vha, fcport);
return;
}
qla24xx_fcport_handle_login(vha, fcport);
}
-
-static void qla_handle_els_plogi_done(scsi_qla_host_t *vha,
- struct event_arg *ea)
-{
- ql_dbg(ql_dbg_disc, vha, 0x2118,
- "%s %d %8phC post PRLI\n",
- __func__, __LINE__, ea->fcport->port_name);
- qla24xx_post_prli_work(vha, ea->fcport);
-}
-
-void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
-{
- fc_port_t *f, *tf;
- uint32_t id = 0, mask, rid;
- fc_port_t *fcport;
-
- switch (ea->event) {
- case FCME_RELOGIN:
- if (test_bit(UNLOADING, &vha->dpc_flags))
- return;
-
- qla24xx_handle_relogin_event(vha, ea);
- break;
- case FCME_RSCN:
- if (test_bit(UNLOADING, &vha->dpc_flags))
- return;
- switch (ea->id.b.rsvd_1) {
- case RSCN_PORT_ADDR:
-#define BIGSCAN 1
-#if defined BIGSCAN & BIGSCAN > 0
- {
- unsigned long flags;
- fcport = qla2x00_find_fcport_by_nportid
- (vha, &ea->id, 1);
- if (fcport) {
- fcport->scan_needed = 1;
- fcport->rscn_gen++;
- }
-
- spin_lock_irqsave(&vha->work_lock, flags);
- if (vha->scan.scan_flags == 0) {
- ql_dbg(ql_dbg_disc, vha, 0xffff,
- "%s: schedule\n", __func__);
- vha->scan.scan_flags |= SF_QUEUED;
- schedule_delayed_work(&vha->scan.scan_work, 5);
- }
- spin_unlock_irqrestore(&vha->work_lock, flags);
- }
-#else
- {
- int rc;
- fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
- if (!fcport) {
- /* cable moved */
- rc = qla24xx_post_gpnid_work(vha, &ea->id);
- if (rc) {
- ql_log(ql_log_warn, vha, 0xd044,
- "RSCN GPNID work failed %06x\n",
- ea->id.b24);
- }
- } else {
- ea->fcport = fcport;
- fcport->scan_needed = 1;
- qla24xx_handle_rscn_event(fcport, ea);
- }
- }
-#endif
- break;
- case RSCN_AREA_ADDR:
- case RSCN_DOM_ADDR:
- if (ea->id.b.rsvd_1 == RSCN_AREA_ADDR) {
- mask = 0xffff00;
- ql_dbg(ql_dbg_async, vha, 0x5044,
- "RSCN: Area 0x%06x was affected\n",
- ea->id.b24);
- } else {
- mask = 0xff0000;
- ql_dbg(ql_dbg_async, vha, 0x507a,
- "RSCN: Domain 0x%06x was affected\n",
- ea->id.b24);
- }
-
- rid = ea->id.b24 & mask;
- list_for_each_entry_safe(f, tf, &vha->vp_fcports,
- list) {
- id = f->d_id.b24 & mask;
- if (rid == id) {
- ea->fcport = f;
- qla24xx_handle_rscn_event(f, ea);
- }
- }
- break;
- case RSCN_FAB_ADDR:
- default:
- ql_log(ql_log_warn, vha, 0xd045,
- "RSCN: Fabric was affected. Addr format %d\n",
- ea->id.b.rsvd_1);
- qla2x00_mark_all_devices_lost(vha, 1);
- set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
- set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
- }
- break;
- case FCME_GNL_DONE:
- qla24xx_handle_gnl_done_event(vha, ea);
- break;
- case FCME_GPSC_DONE:
- qla24xx_handle_gpsc_event(vha, ea);
- break;
- case FCME_PLOGI_DONE: /* Initiator side sent LLIOCB */
- qla24xx_handle_plogi_done_event(vha, ea);
- break;
- case FCME_PRLI_DONE:
- qla24xx_handle_prli_done_event(vha, ea);
- break;
- case FCME_GPDB_DONE:
- qla24xx_handle_gpdb_event(vha, ea);
- break;
- case FCME_GPNID_DONE:
- qla24xx_handle_gpnid_event(vha, ea);
- break;
- case FCME_GFFID_DONE:
- qla24xx_handle_gffid_event(vha, ea);
- break;
- case FCME_ADISC_DONE:
- qla24xx_handle_adisc_event(vha, ea);
- break;
- case FCME_GNNID_DONE:
- qla24xx_handle_gnnid_event(vha, ea);
- break;
- case FCME_GFPNID_DONE:
- qla24xx_handle_gfpnid_event(vha, ea);
- break;
- case FCME_ELS_PLOGI_DONE:
- qla_handle_els_plogi_done(vha, ea);
- break;
- default:
- BUG_ON(1);
- break;
- }
-}
-
/*
* RSCN(s) came in for this fcport, but the RSCN(s) was not able
* to be consumed by the fcport
*/
void qla_rscn_replay(fc_port_t *fcport)
{
- struct event_arg ea;
-
- switch (fcport->disc_state) {
- case DSC_DELETE_PEND:
- return;
- default:
- break;
- }
-
- if (fcport->scan_needed) {
- memset(&ea, 0, sizeof(ea));
- ea.event = FCME_RSCN;
- ea.id = fcport->d_id;
- ea.id.b.rsvd_1 = RSCN_PORT_ADDR;
-#if defined BIGSCAN & BIGSCAN > 0
- qla2x00_fcport_event_handler(fcport->vha, &ea);
-#else
- qla24xx_post_gpnid_work(fcport->vha, &ea.id);
-#endif
+ struct event_arg ea;
+
+ switch (fcport->disc_state) {
+ case DSC_DELETE_PEND:
+ return;
+ default:
+ break;
+ }
+
+ if (fcport->scan_needed) {
+ memset(&ea, 0, sizeof(ea));
+ ea.id = fcport->d_id;
+ ea.id.b.rsvd_1 = RSCN_PORT_ADDR;
+ qla2x00_handle_rscn(fcport->vha, &ea);
}
}
@@ -1729,10 +1729,8 @@ qla2x00_tmf_iocb_timeout(void *data)
complete(&tmf->u.tmf.comp);
}
-static void
-qla2x00_tmf_sp_done(void *ptr, int res)
+static void qla2x00_tmf_sp_done(srb_t *sp, int res)
{
- srb_t *sp = ptr;
struct srb_iocb *tmf = &sp->u.iocb_cmd;
complete(&tmf->u.tmf.comp);
@@ -1786,90 +1784,14 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
lun = (uint16_t)tm_iocb->u.tmf.lun;
/* Issue Marker IOCB */
- qla2x00_marker(vha, vha->hw->req_q_map[0],
- vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun,
+ qla2x00_marker(vha, vha->hw->base_qpair,
+ fcport->loop_id, lun,
flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
}
done_free_sp:
sp->free(sp);
- sp->fcport->flags &= ~FCF_ASYNC_SENT;
-done:
- return rval;
-}
-
-static void
-qla24xx_abort_iocb_timeout(void *data)
-{
- srb_t *sp = data;
- struct srb_iocb *abt = &sp->u.iocb_cmd;
-
- abt->u.abt.comp_status = CS_TIMEOUT;
- sp->done(sp, QLA_FUNCTION_TIMEOUT);
-}
-
-static void
-qla24xx_abort_sp_done(void *ptr, int res)
-{
- srb_t *sp = ptr;
- struct srb_iocb *abt = &sp->u.iocb_cmd;
-
- if (del_timer(&sp->u.iocb_cmd.timer)) {
- if (sp->flags & SRB_WAKEUP_ON_COMP)
- complete(&abt->u.abt.comp);
- else
- sp->free(sp);
- }
-}
-
-int
-qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait)
-{
- scsi_qla_host_t *vha = cmd_sp->vha;
- struct srb_iocb *abt_iocb;
- srb_t *sp;
- int rval = QLA_FUNCTION_FAILED;
-
- sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport,
- GFP_KERNEL);
- if (!sp)
- goto done;
-
- abt_iocb = &sp->u.iocb_cmd;
- sp->type = SRB_ABT_CMD;
- sp->name = "abort";
- sp->qpair = cmd_sp->qpair;
- if (wait)
- sp->flags = SRB_WAKEUP_ON_COMP;
-
- abt_iocb->timeout = qla24xx_abort_iocb_timeout;
- init_completion(&abt_iocb->u.abt.comp);
- /* FW can send 2 x ABTS's timeout/20s */
- qla2x00_init_timer(sp, 42);
-
- abt_iocb->u.abt.cmd_hndl = cmd_sp->handle;
- abt_iocb->u.abt.req_que_no = cpu_to_le16(cmd_sp->qpair->req->id);
-
- sp->done = qla24xx_abort_sp_done;
-
- ql_dbg(ql_dbg_async, vha, 0x507c,
- "Abort command issued - hdl=%x, type=%x\n",
- cmd_sp->handle, cmd_sp->type);
-
- rval = qla2x00_start_sp(sp);
- if (rval != QLA_SUCCESS)
- goto done_free_sp;
-
- if (wait) {
- wait_for_completion(&abt_iocb->u.abt.comp);
- rval = abt_iocb->u.abt.comp_status == CS_COMPLETE ?
- QLA_SUCCESS : QLA_FUNCTION_FAILED;
- } else {
- goto done;
- }
-
-done_free_sp:
- sp->free(sp);
+ fcport->flags &= ~FCF_ASYNC_SENT;
done:
return rval;
}
@@ -1906,6 +1828,9 @@ qla24xx_async_abort_command(srb_t *sp)
static void
qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
{
+ WARN_ONCE(!qla2xxx_is_valid_mbs(ea->data[0]), "mbs: %#x\n",
+ ea->data[0]);
+
switch (ea->data[0]) {
case MBS_COMMAND_COMPLETE:
ql_dbg(ql_dbg_disc, vha, 0x2118,
@@ -1914,6 +1839,12 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
ea->fcport->chip_reset = vha->hw->base_qpair->chip_reset;
ea->fcport->logout_on_delete = 1;
+ ea->fcport->nvme_prli_service_param = ea->iop[0];
+ if (ea->iop[0] & NVME_PRLI_SP_FIRST_BURST)
+ ea->fcport->nvme_first_burst_size =
+ (ea->iop[1] & 0xffff) * 512;
+ else
+ ea->fcport->nvme_first_burst_size = 0;
qla24xx_post_gpdb_work(vha, ea->fcport, 0);
break;
default:
@@ -1939,7 +1870,7 @@ qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
}
}
-static void
+void
qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
{
port_id_t cid; /* conflict Nport id */
@@ -1963,8 +1894,11 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
return;
}
- if (fcport->disc_state == DSC_DELETE_PEND)
+ if ((fcport->disc_state == DSC_DELETE_PEND) ||
+ (fcport->disc_state == DSC_DELETED)) {
+ set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
return;
+ }
if (ea->sp->gen2 != fcport->login_gen) {
/* target side must have changed it. */
@@ -1982,6 +1916,9 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
return;
}
+ WARN_ONCE(!qla2xxx_is_valid_mbs(ea->data[0]), "mbs: %#x\n",
+ ea->data[0]);
+
switch (ea->data[0]) {
case MBS_COMMAND_COMPLETE:
/*
@@ -2177,6 +2114,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
int rval;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
+ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
memset(&vha->qla_stats, 0, sizeof(vha->qla_stats));
memset(&vha->fc_host_stat, 0, sizeof(vha->fc_host_stat));
@@ -2211,6 +2149,15 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
ha->isp_ops->reset_chip(vha);
+ /* Check for secure flash support */
+ if (IS_QLA28XX(ha)) {
+ if (RD_REG_DWORD(&reg->mailbox12) & BIT_0) {
+ ql_log(ql_log_info, vha, 0xffff, "Adapter is Secure\n");
+ ha->flags.secure_adapter = 1;
+ }
+ }
+
+
rval = qla2xxx_get_flash_info(vha);
if (rval) {
ql_log(ql_log_fatal, vha, 0x004f,
@@ -2266,6 +2213,10 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
if (qla_ini_mode_enabled(vha) || qla_dual_mode_enabled(vha))
rval = qla2x00_init_rings(vha);
+ /* No point in continuing if firmware initialization failed. */
+ if (rval != QLA_SUCCESS)
+ return rval;
+
ha->flags.chip_reset_done = 1;
if (rval == QLA_SUCCESS && IS_QLA84XX(ha)) {
@@ -2527,7 +2478,7 @@ qla2x00_isp_firmware(scsi_qla_host_t *vha)
*
* Returns 0 on success.
*/
-void
+int
qla2x00_reset_chip(scsi_qla_host_t *vha)
{
unsigned long flags = 0;
@@ -2535,9 +2486,10 @@ qla2x00_reset_chip(scsi_qla_host_t *vha)
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
uint32_t cnt;
uint16_t cmd;
+ int rval = QLA_FUNCTION_FAILED;
if (unlikely(pci_channel_offline(ha->pdev)))
- return;
+ return rval;
ha->isp_ops->disable_intrs(ha);
@@ -2663,6 +2615,8 @@ qla2x00_reset_chip(scsi_qla_host_t *vha)
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ return QLA_SUCCESS;
}
/**
@@ -2903,14 +2857,15 @@ acquired:
*
* Returns 0 on success.
*/
-void
+int
qla24xx_reset_chip(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
+ int rval = QLA_FUNCTION_FAILED;
if (pci_channel_offline(ha->pdev) &&
ha->flags.pci_channel_io_perm_failure) {
- return;
+ return rval;
}
ha->isp_ops->disable_intrs(ha);
@@ -2918,7 +2873,9 @@ qla24xx_reset_chip(scsi_qla_host_t *vha)
qla25xx_manipulate_risc_semaphore(vha);
/* Perform RISC reset. */
- qla24xx_reset_risc(vha);
+ rval = qla24xx_reset_risc(vha);
+
+ return rval;
}
/**
@@ -3076,89 +3033,102 @@ qla24xx_chip_diag(scsi_qla_host_t *vha)
}
static void
-qla2x00_alloc_offload_mem(scsi_qla_host_t *vha)
+qla2x00_init_fce_trace(scsi_qla_host_t *vha)
{
int rval;
dma_addr_t tc_dma;
void *tc;
struct qla_hw_data *ha = vha->hw;
- if (ha->eft) {
+ if (!IS_FWI2_CAPABLE(ha))
+ return;
+
+ if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
+ !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+ return;
+
+ if (ha->fce) {
ql_dbg(ql_dbg_init, vha, 0x00bd,
- "%s: Offload Mem is already allocated.\n",
- __func__);
+ "%s: FCE Mem is already allocated.\n",
+ __func__);
return;
}
- if (IS_FWI2_CAPABLE(ha)) {
- /* Allocate memory for Fibre Channel Event Buffer. */
- if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
- !IS_QLA27XX(ha))
- goto try_eft;
+ /* Allocate memory for Fibre Channel Event Buffer. */
+ tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
+ GFP_KERNEL);
+ if (!tc) {
+ ql_log(ql_log_warn, vha, 0x00be,
+ "Unable to allocate (%d KB) for FCE.\n",
+ FCE_SIZE / 1024);
+ return;
+ }
- if (ha->fce)
- dma_free_coherent(&ha->pdev->dev,
- FCE_SIZE, ha->fce, ha->fce_dma);
-
- /* Allocate memory for Fibre Channel Event Buffer. */
- tc = dma_zalloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
- GFP_KERNEL);
- if (!tc) {
- ql_log(ql_log_warn, vha, 0x00be,
- "Unable to allocate (%d KB) for FCE.\n",
- FCE_SIZE / 1024);
- goto try_eft;
- }
-
- rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS,
- ha->fce_mb, &ha->fce_bufs);
- if (rval) {
- ql_log(ql_log_warn, vha, 0x00bf,
- "Unable to initialize FCE (%d).\n", rval);
- dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc,
- tc_dma);
- ha->flags.fce_enabled = 0;
- goto try_eft;
- }
- ql_dbg(ql_dbg_init, vha, 0x00c0,
- "Allocate (%d KB) for FCE...\n", FCE_SIZE / 1024);
-
- ha->flags.fce_enabled = 1;
- ha->fce_dma = tc_dma;
- ha->fce = tc;
-
-try_eft:
- if (ha->eft)
- dma_free_coherent(&ha->pdev->dev,
- EFT_SIZE, ha->eft, ha->eft_dma);
+ rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS,
+ ha->fce_mb, &ha->fce_bufs);
+ if (rval) {
+ ql_log(ql_log_warn, vha, 0x00bf,
+ "Unable to initialize FCE (%d).\n", rval);
+ dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc, tc_dma);
+ return;
+ }
- /* Allocate memory for Extended Trace Buffer. */
- tc = dma_zalloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
- GFP_KERNEL);
- if (!tc) {
- ql_log(ql_log_warn, vha, 0x00c1,
- "Unable to allocate (%d KB) for EFT.\n",
- EFT_SIZE / 1024);
- goto eft_err;
- }
+ ql_dbg(ql_dbg_init, vha, 0x00c0,
+ "Allocated (%d KB) for FCE...\n", FCE_SIZE / 1024);
- rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
- if (rval) {
- ql_log(ql_log_warn, vha, 0x00c2,
- "Unable to initialize EFT (%d).\n", rval);
- dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc,
- tc_dma);
- goto eft_err;
- }
- ql_dbg(ql_dbg_init, vha, 0x00c3,
- "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
+ ha->flags.fce_enabled = 1;
+ ha->fce_dma = tc_dma;
+ ha->fce = tc;
+}
+
+static void
+qla2x00_init_eft_trace(scsi_qla_host_t *vha)
+{
+ int rval;
+ dma_addr_t tc_dma;
+ void *tc;
+ struct qla_hw_data *ha = vha->hw;
- ha->eft_dma = tc_dma;
- ha->eft = tc;
+ if (!IS_FWI2_CAPABLE(ha))
+ return;
+
+ if (ha->eft) {
+ ql_dbg(ql_dbg_init, vha, 0x00bd,
+ "%s: EFT Mem is already allocated.\n",
+ __func__);
+ return;
}
-eft_err:
- return;
+ /* Allocate memory for Extended Trace Buffer. */
+ tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
+ GFP_KERNEL);
+ if (!tc) {
+ ql_log(ql_log_warn, vha, 0x00c1,
+ "Unable to allocate (%d KB) for EFT.\n",
+ EFT_SIZE / 1024);
+ return;
+ }
+
+ rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
+ if (rval) {
+ ql_log(ql_log_warn, vha, 0x00c2,
+ "Unable to initialize EFT (%d).\n", rval);
+ dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc, tc_dma);
+ return;
+ }
+
+ ql_dbg(ql_dbg_init, vha, 0x00c3,
+ "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
+
+ ha->eft_dma = tc_dma;
+ ha->eft = tc;
+}
+
+static void
+qla2x00_alloc_offload_mem(scsi_qla_host_t *vha)
+{
+ qla2x00_init_fce_trace(vha);
+ qla2x00_init_eft_trace(vha);
}
void
@@ -3181,7 +3151,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
mem_size = (ha->fw_memory_size - 0x11000 + 1) *
sizeof(uint16_t);
} else if (IS_FWI2_CAPABLE(ha)) {
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem);
else if (IS_QLA81XX(ha))
fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem);
@@ -3193,94 +3163,124 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
mem_size = (ha->fw_memory_size - 0x100000 + 1) *
sizeof(uint32_t);
if (ha->mqenable) {
- if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+ if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) &&
+ !IS_QLA28XX(ha))
mq_size = sizeof(struct qla2xxx_mq_chain);
/*
- * Allocate maximum buffer size for all queues.
+ * Allocate maximum buffer size for all queues - Q0.
* Resizing must be done at end-of-dump processing.
*/
- mq_size += ha->max_req_queues *
+ mq_size += (ha->max_req_queues - 1) *
(req->length * sizeof(request_t));
- mq_size += ha->max_rsp_queues *
+ mq_size += (ha->max_rsp_queues - 1) *
(rsp->length * sizeof(response_t));
}
if (ha->tgt.atio_ring)
mq_size += ha->tgt.atio_q_length * sizeof(request_t);
- /* Allocate memory for Fibre Channel Event Buffer. */
- if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
- !IS_QLA27XX(ha))
- goto try_eft;
-
- fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
-try_eft:
- ql_dbg(ql_dbg_init, vha, 0x00c3,
- "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
- eft_size = EFT_SIZE;
- }
-
- if (IS_QLA27XX(ha)) {
- if (!ha->fw_dump_template) {
- ql_log(ql_log_warn, vha, 0x00ba,
- "Failed missing fwdump template\n");
- return;
- }
- dump_size = qla27xx_fwdt_calculate_dump_size(vha);
- ql_dbg(ql_dbg_init, vha, 0x00fa,
- "-> allocating fwdump (%x bytes)...\n", dump_size);
- goto allocate;
- }
-
- req_q_size = req->length * sizeof(request_t);
- rsp_q_size = rsp->length * sizeof(response_t);
- dump_size = offsetof(struct qla2xxx_fw_dump, isp);
- dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + eft_size;
- ha->chain_offset = dump_size;
- dump_size += mq_size + fce_size;
-
- if (ha->exchoffld_buf)
- dump_size += sizeof(struct qla2xxx_offld_chain) +
- ha->exchoffld_size;
- if (ha->exlogin_buf)
- dump_size += sizeof(struct qla2xxx_offld_chain) +
- ha->exlogin_size;
-
-allocate:
- if (!ha->fw_dump_len || dump_size != ha->fw_dump_len) {
+
+ qla2x00_init_fce_trace(vha);
+ if (ha->fce)
+ fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
+ qla2x00_init_eft_trace(vha);
+ if (ha->eft)
+ eft_size = EFT_SIZE;
+ }
+
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ struct fwdt *fwdt = ha->fwdt;
+ uint j;
+
+ for (j = 0; j < 2; j++, fwdt++) {
+ if (!fwdt->template) {
+ ql_log(ql_log_warn, vha, 0x00ba,
+ "-> fwdt%u no template\n", j);
+ continue;
+ }
+ ql_dbg(ql_dbg_init, vha, 0x00fa,
+ "-> fwdt%u calculating fwdump size...\n", j);
+ fwdt->dump_size = qla27xx_fwdt_calculate_dump_size(
+ vha, fwdt->template);
+ ql_dbg(ql_dbg_init, vha, 0x00fa,
+ "-> fwdt%u calculated fwdump size = %#lx bytes\n",
+ j, fwdt->dump_size);
+ dump_size += fwdt->dump_size;
+ }
+ } else {
+ req_q_size = req->length * sizeof(request_t);
+ rsp_q_size = rsp->length * sizeof(response_t);
+ dump_size = offsetof(struct qla2xxx_fw_dump, isp);
+ dump_size += fixed_size + mem_size + req_q_size + rsp_q_size
+ + eft_size;
+ ha->chain_offset = dump_size;
+ dump_size += mq_size + fce_size;
+ if (ha->exchoffld_buf)
+ dump_size += sizeof(struct qla2xxx_offld_chain) +
+ ha->exchoffld_size;
+ if (ha->exlogin_buf)
+ dump_size += sizeof(struct qla2xxx_offld_chain) +
+ ha->exlogin_size;
+ }
+
+ if (!ha->fw_dump_len || dump_size > ha->fw_dump_alloc_len) {
+
+ ql_dbg(ql_dbg_init, vha, 0x00c5,
+ "%s dump_size %d fw_dump_len %d fw_dump_alloc_len %d\n",
+ __func__, dump_size, ha->fw_dump_len,
+ ha->fw_dump_alloc_len);
+
fw_dump = vmalloc(dump_size);
if (!fw_dump) {
ql_log(ql_log_warn, vha, 0x00c4,
"Unable to allocate (%d KB) for firmware dump.\n",
dump_size / 1024);
} else {
- if (ha->fw_dump)
+ mutex_lock(&ha->optrom_mutex);
+ if (ha->fw_dumped) {
+ memcpy(fw_dump, ha->fw_dump, ha->fw_dump_len);
vfree(ha->fw_dump);
- ha->fw_dump = fw_dump;
-
- ha->fw_dump_len = dump_size;
- ql_dbg(ql_dbg_init, vha, 0x00c5,
- "Allocated (%d KB) for firmware dump.\n",
- dump_size / 1024);
-
- if (IS_QLA27XX(ha))
- return;
-
- ha->fw_dump->signature[0] = 'Q';
- ha->fw_dump->signature[1] = 'L';
- ha->fw_dump->signature[2] = 'G';
- ha->fw_dump->signature[3] = 'C';
- ha->fw_dump->version = htonl(1);
-
- ha->fw_dump->fixed_size = htonl(fixed_size);
- ha->fw_dump->mem_size = htonl(mem_size);
- ha->fw_dump->req_q_size = htonl(req_q_size);
- ha->fw_dump->rsp_q_size = htonl(rsp_q_size);
-
- ha->fw_dump->eft_size = htonl(eft_size);
- ha->fw_dump->eft_addr_l = htonl(LSD(ha->eft_dma));
- ha->fw_dump->eft_addr_h = htonl(MSD(ha->eft_dma));
+ ha->fw_dump = fw_dump;
+ ha->fw_dump_alloc_len = dump_size;
+ ql_dbg(ql_dbg_init, vha, 0x00c5,
+ "Re-Allocated (%d KB) and save firmware dump.\n",
+ dump_size / 1024);
+ } else {
+ if (ha->fw_dump)
+ vfree(ha->fw_dump);
+ ha->fw_dump = fw_dump;
+
+ ha->fw_dump_len = ha->fw_dump_alloc_len =
+ dump_size;
+ ql_dbg(ql_dbg_init, vha, 0x00c5,
+ "Allocated (%d KB) for firmware dump.\n",
+ dump_size / 1024);
+
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ mutex_unlock(&ha->optrom_mutex);
+ return;
+ }
- ha->fw_dump->header_size =
- htonl(offsetof(struct qla2xxx_fw_dump, isp));
+ ha->fw_dump->signature[0] = 'Q';
+ ha->fw_dump->signature[1] = 'L';
+ ha->fw_dump->signature[2] = 'G';
+ ha->fw_dump->signature[3] = 'C';
+ ha->fw_dump->version = htonl(1);
+
+ ha->fw_dump->fixed_size = htonl(fixed_size);
+ ha->fw_dump->mem_size = htonl(mem_size);
+ ha->fw_dump->req_q_size = htonl(req_q_size);
+ ha->fw_dump->rsp_q_size = htonl(rsp_q_size);
+
+ ha->fw_dump->eft_size = htonl(eft_size);
+ ha->fw_dump->eft_addr_l =
+ htonl(LSD(ha->eft_dma));
+ ha->fw_dump->eft_addr_h =
+ htonl(MSD(ha->eft_dma));
+
+ ha->fw_dump->header_size =
+ htonl(offsetof
+ (struct qla2xxx_fw_dump, isp));
+ }
+ mutex_unlock(&ha->optrom_mutex);
}
}
}
@@ -3571,7 +3571,8 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
if (rval == QLA_SUCCESS) {
qla24xx_detect_sfp(vha);
- if ((IS_QLA83XX(ha) || IS_QLA27XX(ha)) &&
+ if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha)) &&
(ha->zio_mode == QLA_ZIO_MODE_6))
qla27xx_set_zio_threshold(vha,
ha->last_zio_threshold);
@@ -3643,7 +3644,7 @@ enable_82xx_npiv:
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
- if (IS_QLA27XX(ha))
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
ha->flags.fac_supported = 1;
else if (rval == QLA_SUCCESS && IS_FAC_REQUIRED(ha)) {
uint32_t size;
@@ -3658,7 +3659,8 @@ enable_82xx_npiv:
ha->fw_major_version, ha->fw_minor_version,
ha->fw_subminor_version);
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha)) {
ha->flags.fac_supported = 0;
rval = QLA_SUCCESS;
}
@@ -3720,8 +3722,7 @@ qla2x00_update_fw_options(scsi_qla_host_t *vha)
ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0115,
"Serial link options.\n");
ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0109,
- (uint8_t *)&ha->fw_seriallink_options,
- sizeof(ha->fw_seriallink_options));
+ ha->fw_seriallink_options, sizeof(ha->fw_seriallink_options));
ha->fw_options[1] &= ~FO1_SET_EMPHASIS_SWING;
if (ha->fw_seriallink_options[3] & BIT_2) {
@@ -3811,7 +3812,7 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
/* Move PUREX, ABTS RX & RIDA to ATIOQ */
if (ql2xmvasynctoatio &&
- (IS_QLA83XX(ha) || IS_QLA27XX(ha))) {
+ (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))) {
if (qla_tgt_mode_enabled(vha) ||
qla_dual_mode_enabled(vha))
ha->fw_options[2] |= BIT_11;
@@ -3819,7 +3820,8 @@ qla24xx_update_fw_options(scsi_qla_host_t *vha)
ha->fw_options[2] &= ~BIT_11;
}
- if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ if (IS_QLA25XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha)) {
/*
* Tell FW to track each exchange to prevent
* driver from using stale exchange.
@@ -3872,10 +3874,8 @@ qla2x00_config_rings(struct scsi_qla_host *vha)
ha->init_cb->response_q_inpointer = cpu_to_le16(0);
ha->init_cb->request_q_length = cpu_to_le16(req->length);
ha->init_cb->response_q_length = cpu_to_le16(rsp->length);
- ha->init_cb->request_q_address[0] = cpu_to_le32(LSD(req->dma));
- ha->init_cb->request_q_address[1] = cpu_to_le32(MSD(req->dma));
- ha->init_cb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma));
- ha->init_cb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma));
+ put_unaligned_le64(req->dma, &ha->init_cb->request_q_address);
+ put_unaligned_le64(rsp->dma, &ha->init_cb->response_q_address);
WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), 0);
WRT_REG_WORD(ISP_REQ_Q_OUT(ha, reg), 0);
@@ -3902,21 +3902,19 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
icb->response_q_inpointer = cpu_to_le16(0);
icb->request_q_length = cpu_to_le16(req->length);
icb->response_q_length = cpu_to_le16(rsp->length);
- icb->request_q_address[0] = cpu_to_le32(LSD(req->dma));
- icb->request_q_address[1] = cpu_to_le32(MSD(req->dma));
- icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma));
- icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma));
+ put_unaligned_le64(req->dma, &icb->request_q_address);
+ put_unaligned_le64(rsp->dma, &icb->response_q_address);
/* Setup ATIO queue dma pointers for target mode */
icb->atio_q_inpointer = cpu_to_le16(0);
icb->atio_q_length = cpu_to_le16(ha->tgt.atio_q_length);
- icb->atio_q_address[0] = cpu_to_le32(LSD(ha->tgt.atio_dma));
- icb->atio_q_address[1] = cpu_to_le32(MSD(ha->tgt.atio_dma));
+ put_unaligned_le64(ha->tgt.atio_dma, &icb->atio_q_address);
if (IS_SHADOW_REG_CAPABLE(ha))
icb->firmware_options_2 |= cpu_to_le32(BIT_30|BIT_29);
- if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha)) {
icb->qos = cpu_to_le16(QLA_DEFAULT_QUE_QOS);
icb->rid = cpu_to_le16(rid);
if (ha->flags.msix_enabled) {
@@ -3955,8 +3953,17 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
WRT_REG_DWORD(&reg->isp24.rsp_q_in, 0);
WRT_REG_DWORD(&reg->isp24.rsp_q_out, 0);
}
+
qlt_24xx_config_rings(vha);
+ /* If the user has configured the speed, set it here */
+ if (ha->set_data_rate) {
+ ql_dbg(ql_dbg_init, vha, 0x00fd,
+ "Speed set by user : %s Gbps \n",
+ qla2x00_get_link_speed_str(ha, ha->set_data_rate));
+ icb->firmware_options_3 = (ha->set_data_rate << 13);
+ }
+
/* PCI posting */
RD_REG_DWORD(&ioreg->hccr);
}
@@ -4326,16 +4333,19 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
inline void
qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
- char *def)
+ const char *def)
{
char *st, *en;
uint16_t index;
+ uint64_t zero[2] = { 0 };
struct qla_hw_data *ha = vha->hw;
int use_tbl = !IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) &&
!IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha);
- if (memcmp(model, BINZERO, len) != 0) {
- strncpy(ha->model_number, model, len);
+ if (len > sizeof(zero))
+ len = sizeof(zero);
+ if (memcmp(model, &zero, len) != 0) {
+ memcpy(ha->model_number, model, len);
st = en = ha->model_number;
en += len - 1;
while (en > st) {
@@ -4348,21 +4358,23 @@ qla2x00_set_model_info(scsi_qla_host_t *vha, uint8_t *model, size_t len,
if (use_tbl &&
ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
index < QLA_MODEL_NAMES)
- strncpy(ha->model_desc,
+ strlcpy(ha->model_desc,
qla2x00_model_name[index * 2 + 1],
- sizeof(ha->model_desc) - 1);
+ sizeof(ha->model_desc));
} else {
index = (ha->pdev->subsystem_device & 0xff);
if (use_tbl &&
ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
index < QLA_MODEL_NAMES) {
- strcpy(ha->model_number,
- qla2x00_model_name[index * 2]);
- strncpy(ha->model_desc,
+ strlcpy(ha->model_number,
+ qla2x00_model_name[index * 2],
+ sizeof(ha->model_number));
+ strlcpy(ha->model_desc,
qla2x00_model_name[index * 2 + 1],
- sizeof(ha->model_desc) - 1);
+ sizeof(ha->model_desc));
} else {
- strcpy(ha->model_number, def);
+ strlcpy(ha->model_number, def,
+ sizeof(ha->model_number));
}
}
if (IS_FWI2_CAPABLE(ha))
@@ -4421,7 +4433,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
rval = QLA_SUCCESS;
/* Determine NVRAM starting address. */
- ha->nvram_size = sizeof(nvram_t);
+ ha->nvram_size = sizeof(*nv);
ha->nvram_base = 0;
if (!IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA2300(ha))
if ((RD_REG_WORD(&reg->ctrl_status) >> 14) == 1)
@@ -4435,16 +4447,15 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x010f,
"Contents of NVRAM.\n");
ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0110,
- (uint8_t *)nv, ha->nvram_size);
+ nv, ha->nvram_size);
/* Bad NVRAM data, set defaults parameters. */
- if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
- nv->id[2] != 'P' || nv->id[3] != ' ' || nv->nvram_version < 1) {
+ if (chksum || memcmp("ISP ", nv->id, sizeof(nv->id)) ||
+ nv->nvram_version < 1) {
/* Reset NVRAM data. */
ql_log(ql_log_warn, vha, 0x0064,
- "Inconsistent NVRAM "
- "detected: checksum=0x%x id=%c version=0x%x.\n",
- chksum, nv->id[0], nv->nvram_version);
+ "Inconsistent NVRAM detected: checksum=%#x id=%.4s version=%#x.\n",
+ chksum, nv->id, nv->nvram_version);
ql_log(ql_log_warn, vha, 0x0065,
"Falling back to "
"functioning (yet invalid -- WWPN) defaults.\n");
@@ -4499,20 +4510,6 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
rval = 1;
}
-#if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2)
- /*
- * The SN2 does not provide BIOS emulation which means you can't change
- * potentially bogus BIOS settings. Force the use of default settings
- * for link rate and frame size. Hope that the rest of the settings
- * are valid.
- */
- if (ia64_platform_is("sn2")) {
- nv->frame_payload_size = 2048;
- if (IS_QLA23XX(ha))
- nv->special_options[1] = BIT_7;
- }
-#endif
-
/* Reset Initialization control block */
memset(icb, 0, ha->init_cb_size);
@@ -4693,7 +4690,7 @@ qla2x00_nvram_config(scsi_qla_host_t *vha)
ha->zio_mode = icb->add_firmware_options[0] &
(BIT_3 | BIT_2 | BIT_1 | BIT_0);
ha->zio_timer = icb->interrupt_delay_timer ?
- icb->interrupt_delay_timer: 2;
+ icb->interrupt_delay_timer : 2;
}
icb->add_firmware_options[0] &=
~(BIT_3 | BIT_2 | BIT_1 | BIT_0);
@@ -4726,7 +4723,7 @@ qla2x00_rport_del(void *data)
unsigned long flags;
spin_lock_irqsave(fcport->vha->host->host_lock, flags);
- rport = fcport->drport ? fcport->drport: fcport->rport;
+ rport = fcport->drport ? fcport->drport : fcport->rport;
fcport->drport = NULL;
spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
if (rport) {
@@ -4739,6 +4736,23 @@ qla2x00_rport_del(void *data)
}
}
+void qla2x00_set_fcport_state(fc_port_t *fcport, int state)
+{
+ int old_state;
+
+ old_state = atomic_read(&fcport->state);
+ atomic_set(&fcport->state, state);
+
+ /* Don't print state transitions during initial allocation of fcport */
+ if (old_state && old_state != state) {
+ ql_dbg(ql_dbg_disc, fcport->vha, 0x207d,
+ "FCPort %8phC state transitioned from %s to %s - portid=%02x%02x%02x.\n",
+ fcport->port_name, port_state_str[old_state],
+ port_state_str[state], fcport->d_id.b.domain,
+ fcport->d_id.b.area, fcport->d_id.b.al_pa);
+ }
+}
+
/**
* qla2x00_alloc_fcport() - Allocate a generic fcport.
* @vha: HA context
@@ -4755,6 +4769,16 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
if (!fcport)
return NULL;
+ fcport->ct_desc.ct_sns = dma_alloc_coherent(&vha->hw->pdev->dev,
+ sizeof(struct ct_sns_pkt), &fcport->ct_desc.ct_sns_dma,
+ flags);
+ if (!fcport->ct_desc.ct_sns) {
+ ql_log(ql_log_warn, vha, 0xd049,
+ "Failed to allocate ct_sns request.\n");
+ kfree(fcport);
+ return NULL;
+ }
+
/* Setup fcport template structure. */
fcport->vha = vha;
fcport->port_type = FCT_UNKNOWN;
@@ -4763,21 +4787,20 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
fcport->supported_classes = FC_COS_UNSPECIFIED;
fcport->fp_speed = PORT_SPEED_UNKNOWN;
- fcport->ct_desc.ct_sns = dma_alloc_coherent(&vha->hw->pdev->dev,
- sizeof(struct ct_sns_pkt), &fcport->ct_desc.ct_sns_dma,
- flags);
fcport->disc_state = DSC_DELETED;
fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
fcport->deleted = QLA_SESS_DELETED;
fcport->login_retry = vha->hw->login_retry_count;
+ fcport->chip_reset = vha->hw->base_qpair->chip_reset;
fcport->logout_on_delete = 1;
if (!fcport->ct_desc.ct_sns) {
ql_log(ql_log_warn, vha, 0xd049,
"Failed to allocate ct_sns request.\n");
kfree(fcport);
- fcport = NULL;
+ return NULL;
}
+
INIT_WORK(&fcport->del_work, qla24xx_delete_sess_fn);
INIT_WORK(&fcport->reg_work, qla_register_fcport_fn);
INIT_LIST_HEAD(&fcport->gnl_entry);
@@ -4796,6 +4819,8 @@ qla2x00_free_fcport(fc_port_t *fcport)
fcport->ct_desc.ct_sns = NULL;
}
+ list_del(&fcport->list);
+ qla2x00_clear_loop_id(fcport);
kfree(fcport);
}
@@ -4817,6 +4842,7 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
int rval;
unsigned long flags, save_flags;
struct qla_hw_data *ha = vha->hw;
+
rval = QLA_SUCCESS;
/* Get Initiator ID */
@@ -4953,7 +4979,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
uint16_t index;
uint16_t entries;
- char *id_iter;
+ struct gid_list_info *gid;
uint16_t loop_id;
uint8_t domain, area, al_pa;
struct qla_hw_data *ha = vha->hw;
@@ -4998,8 +5024,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
ql_dbg(ql_dbg_disc, vha, 0x2011,
"Entries in ID list (%d).\n", entries);
ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x2075,
- (uint8_t *)ha->gid_list,
- entries * sizeof(struct gid_list_info));
+ ha->gid_list, entries * sizeof(*ha->gid_list));
if (entries == 0) {
spin_lock_irqsave(&vha->work_lock, flags);
@@ -5029,18 +5054,16 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
new_fcport->flags &= ~FCF_FABRIC_DEVICE;
/* Add devices to port list. */
- id_iter = (char *)ha->gid_list;
+ gid = ha->gid_list;
for (index = 0; index < entries; index++) {
- domain = ((struct gid_list_info *)id_iter)->domain;
- area = ((struct gid_list_info *)id_iter)->area;
- al_pa = ((struct gid_list_info *)id_iter)->al_pa;
+ domain = gid->domain;
+ area = gid->area;
+ al_pa = gid->al_pa;
if (IS_QLA2100(ha) || IS_QLA2200(ha))
- loop_id = (uint16_t)
- ((struct gid_list_info *)id_iter)->loop_id_2100;
+ loop_id = gid->loop_id_2100;
else
- loop_id = le16_to_cpu(
- ((struct gid_list_info *)id_iter)->loop_id);
- id_iter += ha->gid_list_info_size;
+ loop_id = le16_to_cpu(gid->loop_id);
+ gid = (void *)gid + ha->gid_list_info_size;
/* Bypass reserved domain fields. */
if ((domain & 0xf0) == 0xf0)
@@ -5249,16 +5272,23 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
rport->supported_classes = fcport->supported_classes;
- rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
+ rport_ids.roles = FC_PORT_ROLE_UNKNOWN;
if (fcport->port_type == FCT_INITIATOR)
- rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+ rport_ids.roles |= FC_PORT_ROLE_FCP_INITIATOR;
if (fcport->port_type == FCT_TARGET)
- rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
+ rport_ids.roles |= FC_PORT_ROLE_FCP_TARGET;
+ if (fcport->port_type & FCT_NVME_INITIATOR)
+ rport_ids.roles |= FC_PORT_ROLE_NVME_INITIATOR;
+ if (fcport->port_type & FCT_NVME_TARGET)
+ rport_ids.roles |= FC_PORT_ROLE_NVME_TARGET;
+ if (fcport->port_type & FCT_NVME_DISCOVERY)
+ rport_ids.roles |= FC_PORT_ROLE_NVME_DISCOVERY;
ql_dbg(ql_dbg_disc, vha, 0x20ee,
"%s %8phN. rport %p is %s mode\n",
__func__, fcport->port_name, rport,
- (fcport->port_type == FCT_TARGET) ? "tgt" : "ini");
+ (fcport->port_type == FCT_TARGET) ? "tgt" :
+ ((fcport->port_type & FCT_NVME) ? "nvme" : "ini"));
fc_remote_port_rolechg(rport, rport_ids.roles);
}
@@ -5292,7 +5322,6 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
fcport->deleted = 0;
fcport->logout_on_delete = 1;
- fcport->login_retry = vha->hw->login_retry_count;
fcport->n2n_chip_reset = fcport->n2n_link_reset_cnt = 0;
switch (vha->hw->current_topology) {
@@ -5833,55 +5862,6 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
return (rval);
}
-/*
- * qla2x00_find_new_loop_id
- * Scan through our port list and find a new usable loop ID.
- *
- * Input:
- * ha: adapter state pointer.
- * dev: port structure pointer.
- *
- * Returns:
- * qla2x00 local function return status code.
- *
- * Context:
- * Kernel context.
- */
-int
-qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
-{
- int rval;
- struct qla_hw_data *ha = vha->hw;
- unsigned long flags = 0;
-
- rval = QLA_SUCCESS;
-
- spin_lock_irqsave(&ha->vport_slock, flags);
-
- dev->loop_id = find_first_zero_bit(ha->loop_id_map,
- LOOPID_MAP_SIZE);
- if (dev->loop_id >= LOOPID_MAP_SIZE ||
- qla2x00_is_reserved_id(vha, dev->loop_id)) {
- dev->loop_id = FC_NO_LOOP_ID;
- rval = QLA_FUNCTION_FAILED;
- } else
- set_bit(dev->loop_id, ha->loop_id_map);
-
- spin_unlock_irqrestore(&ha->vport_slock, flags);
-
- if (rval == QLA_SUCCESS)
- ql_dbg(ql_dbg_disc, dev->vha, 0x2086,
- "Assigning new loopid=%x, portid=%x.\n",
- dev->loop_id, dev->d_id.b24);
- else
- ql_log(ql_log_warn, dev->vha, 0x2087,
- "No loop_id's available, portid=%x.\n",
- dev->d_id.b24);
-
- return (rval);
-}
-
-
/* FW does not set aside Loop id for MGMT Server/FFFFFAh */
int
qla2x00_reserve_mgmt_server_loop_id(scsi_qla_host_t *vha)
@@ -6103,11 +6083,6 @@ qla2x00_loop_resync(scsi_qla_host_t *vha)
{
int rval = QLA_SUCCESS;
uint32_t wait_time;
- struct req_que *req;
- struct rsp_que *rsp;
-
- req = vha->req;
- rsp = req->rsp;
clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
if (vha->flags.online) {
@@ -6120,8 +6095,8 @@ qla2x00_loop_resync(scsi_qla_host_t *vha)
* Issue a marker after FW becomes
* ready.
*/
- qla2x00_marker(vha, req, rsp, 0, 0,
- MK_SYNC_ALL);
+ qla2x00_marker(vha, vha->hw->base_qpair,
+ 0, 0, MK_SYNC_ALL);
vha->marker_needed = 0;
}
@@ -6378,6 +6353,7 @@ qla83xx_initiating_reset(scsi_qla_host_t *vha)
qla83xx_idc_audit(vha, IDC_AUDIT_TIMESTAMP);
} else {
const char *state = qla83xx_dev_state_to_string(dev_state);
+
ql_log(ql_log_info, vha, 0xb057, "HW State: %s.\n", state);
/* SV: XXX: Is timeout required here? */
@@ -6553,7 +6529,8 @@ qla2x00_quiesce_io(scsi_qla_host_t *vha)
LOOP_DOWN_TIME);
}
/* Wait for pending cmds to complete */
- qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST);
+ WARN_ON_ONCE(qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST)
+ != QLA_SUCCESS);
}
void
@@ -6641,8 +6618,10 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
}
/* Clear all async request states across all VPs. */
- list_for_each_entry(fcport, &vha->vp_fcports, list)
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
+ fcport->scan_state = 0;
+ }
spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry(vp, &ha->vp_list, list) {
atomic_inc(&vp->vref_count);
@@ -6699,6 +6678,14 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
if (vha->flags.online) {
qla2x00_abort_isp_cleanup(vha);
+ if (test_and_clear_bit(ISP_ABORT_TO_ROM, &vha->dpc_flags)) {
+ ha->flags.chip_reset_done = 1;
+ vha->flags.online = 1;
+ status = 0;
+ clear_bit(ISP_ABORT_RETRY, &vha->dpc_flags);
+ return status;
+ }
+
if (IS_QLA8031(ha)) {
ql_dbg(ql_dbg_p3p, vha, 0xb05c,
"Clearing fcoe driver presence.\n");
@@ -6859,8 +6846,6 @@ qla2x00_restart_isp(scsi_qla_host_t *vha)
{
int status = 0;
struct qla_hw_data *ha = vha->hw;
- struct req_que *req = ha->req_q_map[0];
- struct rsp_que *rsp = ha->rsp_q_map[0];
/* If firmware needs to be loaded */
if (qla2x00_isp_firmware(vha)) {
@@ -6880,7 +6865,7 @@ qla2x00_restart_isp(scsi_qla_host_t *vha)
status = qla2x00_fw_ready(vha);
if (!status) {
/* Issue a marker after FW becomes ready. */
- qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
+ qla2x00_marker(vha, ha->base_qpair, 0, 0, MK_SYNC_ALL);
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
}
@@ -6941,7 +6926,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)
* Input:
* ha = adapter block pointer.
*/
-void
+int
qla2x00_reset_adapter(scsi_qla_host_t *vha)
{
unsigned long flags = 0;
@@ -6957,17 +6942,20 @@ qla2x00_reset_adapter(scsi_qla_host_t *vha)
WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
RD_REG_WORD(&reg->hccr); /* PCI Posting. */
spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+ return QLA_SUCCESS;
}
-void
+int
qla24xx_reset_adapter(scsi_qla_host_t *vha)
{
unsigned long flags = 0;
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+ int rval = QLA_SUCCESS;
if (IS_P3P_TYPE(ha))
- return;
+ return rval;
vha->flags.online = 0;
ha->isp_ops->disable_intrs(ha);
@@ -6981,6 +6969,8 @@ qla24xx_reset_adapter(scsi_qla_host_t *vha)
if (IS_NOPOLLING_TYPE(ha))
ha->isp_ops->enable_intrs(ha);
+
+ return rval;
}
/* On sparc systems, obtain port and node WWN from firmware
@@ -7031,34 +7021,33 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
ha->vpd_base = FA_NVRAM_VPD1_ADDR;
}
- ha->nvram_size = sizeof(struct nvram_24xx);
+ ha->nvram_size = sizeof(*nv);
ha->vpd_size = FA_NVRAM_VPD_SIZE;
/* Get VPD data into cache */
ha->vpd = ha->nvram + VPD_OFFSET;
- ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd,
+ ha->isp_ops->read_nvram(vha, ha->vpd,
ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4);
/* Get NVRAM data into cache and calculate checksum. */
dptr = (uint32_t *)nv;
- ha->isp_ops->read_nvram(vha, (uint8_t *)dptr, ha->nvram_base,
- ha->nvram_size);
+ ha->isp_ops->read_nvram(vha, dptr, ha->nvram_base, ha->nvram_size);
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++)
chksum += le32_to_cpu(*dptr);
ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x006a,
"Contents of NVRAM\n");
ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010d,
- (uint8_t *)nv, ha->nvram_size);
+ nv, ha->nvram_size);
/* Bad NVRAM data, set defaults parameters. */
- if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P'
- || nv->id[3] != ' ' ||
- nv->nvram_version < cpu_to_le16(ICB_VERSION)) {
+ if (chksum || memcmp("ISP ", nv->id, sizeof(nv->id)) ||
+ le16_to_cpu(nv->nvram_version) < ICB_VERSION) {
/* Reset NVRAM data. */
ql_log(ql_log_warn, vha, 0x006b,
- "Inconsistent NVRAM detected: checksum=0x%x id=%c "
- "version=0x%x.\n", chksum, nv->id[0], nv->nvram_version);
+ "Inconsistent NVRAM checksum=%#x id=%.4s version=%#x.\n",
+ chksum, nv->id, nv->nvram_version);
+ ql_dump_buffer(ql_dbg_init, vha, 0x006b, nv, sizeof(*nv));
ql_log(ql_log_warn, vha, 0x006c,
"Falling back to functioning (yet invalid -- WWPN) "
"defaults.\n");
@@ -7166,11 +7155,11 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
ha->flags.disable_risc_code_load = 0;
ha->flags.enable_lip_reset = 0;
ha->flags.enable_lip_full_login =
- le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0;
+ le32_to_cpu(nv->host_p) & BIT_10 ? 1 : 0;
ha->flags.enable_target_reset =
- le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0;
+ le32_to_cpu(nv->host_p) & BIT_11 ? 1 : 0;
ha->flags.enable_led_scheme = 0;
- ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0;
+ ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1 : 0;
ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) &
(BIT_6 | BIT_5 | BIT_4)) >> 4;
@@ -7244,7 +7233,7 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
ha->zio_mode = le32_to_cpu(icb->firmware_options_2) &
(BIT_3 | BIT_2 | BIT_1 | BIT_0);
ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ?
- le16_to_cpu(icb->interrupt_delay_timer): 2;
+ le16_to_cpu(icb->interrupt_delay_timer) : 2;
}
icb->firmware_options_2 &= cpu_to_le32(
~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
@@ -7267,128 +7256,315 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
return (rval);
}
-uint8_t qla27xx_find_valid_image(struct scsi_qla_host *vha)
+static void
+qla27xx_print_image(struct scsi_qla_host *vha, char *name,
+ struct qla27xx_image_status *image_status)
+{
+ ql_dbg(ql_dbg_init, vha, 0x018b,
+ "%s %s: mask=%#02x gen=%#04x ver=%u.%u map=%#01x sum=%#08x sig=%#08x\n",
+ name, "status",
+ image_status->image_status_mask,
+ le16_to_cpu(image_status->generation),
+ image_status->ver_major,
+ image_status->ver_minor,
+ image_status->bitmap,
+ le32_to_cpu(image_status->checksum),
+ le32_to_cpu(image_status->signature));
+}
+
+static bool
+qla28xx_check_aux_image_status_signature(
+ struct qla27xx_image_status *image_status)
+{
+ ulong signature = le32_to_cpu(image_status->signature);
+
+ return signature != QLA28XX_AUX_IMG_STATUS_SIGN;
+}
+
+static bool
+qla27xx_check_image_status_signature(struct qla27xx_image_status *image_status)
+{
+ ulong signature = le32_to_cpu(image_status->signature);
+
+ return
+ signature != QLA27XX_IMG_STATUS_SIGN &&
+ signature != QLA28XX_IMG_STATUS_SIGN;
+}
+
+static ulong
+qla27xx_image_status_checksum(struct qla27xx_image_status *image_status)
+{
+ uint32_t *p = (void *)image_status;
+ uint n = sizeof(*image_status) / sizeof(*p);
+ uint32_t sum = 0;
+
+ for ( ; n--; p++)
+ sum += le32_to_cpup(p);
+
+ return sum;
+}
+
+static inline uint
+qla28xx_component_bitmask(struct qla27xx_image_status *aux, uint bitmask)
+{
+ return aux->bitmap & bitmask ?
+ QLA27XX_SECONDARY_IMAGE : QLA27XX_PRIMARY_IMAGE;
+}
+
+static void
+qla28xx_component_status(
+ struct active_regions *active_regions, struct qla27xx_image_status *aux)
+{
+ active_regions->aux.board_config =
+ qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_BOARD_CONFIG);
+
+ active_regions->aux.vpd_nvram =
+ qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_VPD_NVRAM);
+
+ active_regions->aux.npiv_config_0_1 =
+ qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_NPIV_CONFIG_0_1);
+
+ active_regions->aux.npiv_config_2_3 =
+ qla28xx_component_bitmask(aux, QLA28XX_AUX_IMG_NPIV_CONFIG_2_3);
+}
+
+static int
+qla27xx_compare_image_generation(
+ struct qla27xx_image_status *pri_image_status,
+ struct qla27xx_image_status *sec_image_status)
+{
+ /* calculate generation delta as uint16 (this accounts for wrap) */
+ int16_t delta =
+ le16_to_cpu(pri_image_status->generation) -
+ le16_to_cpu(sec_image_status->generation);
+
+ ql_dbg(ql_dbg_init, NULL, 0x0180, "generation delta = %d\n", delta);
+
+ return delta;
+}
+
+void
+qla28xx_get_aux_images(
+ struct scsi_qla_host *vha, struct active_regions *active_regions)
{
- struct qla27xx_image_status pri_image_status, sec_image_status;
- uint8_t valid_pri_image, valid_sec_image;
- uint32_t *wptr;
- uint32_t cnt, chksum, size;
struct qla_hw_data *ha = vha->hw;
+ struct qla27xx_image_status pri_aux_image_status, sec_aux_image_status;
+ bool valid_pri_image = false, valid_sec_image = false;
+ bool active_pri_image = false, active_sec_image = false;
+
+ if (!ha->flt_region_aux_img_status_pri) {
+ ql_dbg(ql_dbg_init, vha, 0x018a, "Primary aux image not addressed\n");
+ goto check_sec_image;
+ }
- valid_pri_image = valid_sec_image = 1;
- ha->active_image = 0;
- size = sizeof(struct qla27xx_image_status) / sizeof(uint32_t);
+ qla24xx_read_flash_data(vha, (void *)&pri_aux_image_status,
+ ha->flt_region_aux_img_status_pri,
+ sizeof(pri_aux_image_status) >> 2);
+ qla27xx_print_image(vha, "Primary aux image", &pri_aux_image_status);
- if (!ha->flt_region_img_status_pri) {
- valid_pri_image = 0;
+ if (qla28xx_check_aux_image_status_signature(&pri_aux_image_status)) {
+ ql_dbg(ql_dbg_init, vha, 0x018b,
+ "Primary aux image signature (%#x) not valid\n",
+ le32_to_cpu(pri_aux_image_status.signature));
+ goto check_sec_image;
+ }
+
+ if (qla27xx_image_status_checksum(&pri_aux_image_status)) {
+ ql_dbg(ql_dbg_init, vha, 0x018c,
+ "Primary aux image checksum failed\n");
goto check_sec_image;
}
- qla24xx_read_flash_data(vha, (uint32_t *)(&pri_image_status),
- ha->flt_region_img_status_pri, size);
+ valid_pri_image = true;
+
+ if (pri_aux_image_status.image_status_mask & 1) {
+ ql_dbg(ql_dbg_init, vha, 0x018d,
+ "Primary aux image is active\n");
+ active_pri_image = true;
+ }
+
+check_sec_image:
+ if (!ha->flt_region_aux_img_status_sec) {
+ ql_dbg(ql_dbg_init, vha, 0x018a,
+ "Secondary aux image not addressed\n");
+ goto check_valid_image;
+ }
+
+ qla24xx_read_flash_data(vha, (void *)&sec_aux_image_status,
+ ha->flt_region_aux_img_status_sec,
+ sizeof(sec_aux_image_status) >> 2);
+ qla27xx_print_image(vha, "Secondary aux image", &sec_aux_image_status);
- if (pri_image_status.signature != QLA27XX_IMG_STATUS_SIGN) {
+ if (qla28xx_check_aux_image_status_signature(&sec_aux_image_status)) {
ql_dbg(ql_dbg_init, vha, 0x018b,
- "Primary image signature (0x%x) not valid\n",
- pri_image_status.signature);
- valid_pri_image = 0;
+ "Secondary aux image signature (%#x) not valid\n",
+ le32_to_cpu(sec_aux_image_status.signature));
+ goto check_valid_image;
+ }
+
+ if (qla27xx_image_status_checksum(&sec_aux_image_status)) {
+ ql_dbg(ql_dbg_init, vha, 0x018c,
+ "Secondary aux image checksum failed\n");
+ goto check_valid_image;
+ }
+
+ valid_sec_image = true;
+
+ if (sec_aux_image_status.image_status_mask & 1) {
+ ql_dbg(ql_dbg_init, vha, 0x018d,
+ "Secondary aux image is active\n");
+ active_sec_image = true;
+ }
+
+check_valid_image:
+ if (valid_pri_image && active_pri_image &&
+ valid_sec_image && active_sec_image) {
+ if (qla27xx_compare_image_generation(&pri_aux_image_status,
+ &sec_aux_image_status) >= 0) {
+ qla28xx_component_status(active_regions,
+ &pri_aux_image_status);
+ } else {
+ qla28xx_component_status(active_regions,
+ &sec_aux_image_status);
+ }
+ } else if (valid_pri_image && active_pri_image) {
+ qla28xx_component_status(active_regions, &pri_aux_image_status);
+ } else if (valid_sec_image && active_sec_image) {
+ qla28xx_component_status(active_regions, &sec_aux_image_status);
+ }
+
+ ql_dbg(ql_dbg_init, vha, 0x018f,
+ "aux images active: BCFG=%u VPD/NVR=%u NPIV0/1=%u NPIV2/3=%u\n",
+ active_regions->aux.board_config,
+ active_regions->aux.vpd_nvram,
+ active_regions->aux.npiv_config_0_1,
+ active_regions->aux.npiv_config_2_3);
+}
+
+void
+qla27xx_get_active_image(struct scsi_qla_host *vha,
+ struct active_regions *active_regions)
+{
+ struct qla_hw_data *ha = vha->hw;
+ struct qla27xx_image_status pri_image_status, sec_image_status;
+ bool valid_pri_image = false, valid_sec_image = false;
+ bool active_pri_image = false, active_sec_image = false;
+
+ if (!ha->flt_region_img_status_pri) {
+ ql_dbg(ql_dbg_init, vha, 0x018a, "Primary image not addressed\n");
goto check_sec_image;
}
- wptr = (uint32_t *)(&pri_image_status);
- cnt = size;
+ if (qla24xx_read_flash_data(vha, (void *)(&pri_image_status),
+ ha->flt_region_img_status_pri, sizeof(pri_image_status) >> 2) !=
+ QLA_SUCCESS) {
+ WARN_ON_ONCE(true);
+ goto check_sec_image;
+ }
+ qla27xx_print_image(vha, "Primary image", &pri_image_status);
- for (chksum = 0; cnt--; wptr++)
- chksum += le32_to_cpu(*wptr);
+ if (qla27xx_check_image_status_signature(&pri_image_status)) {
+ ql_dbg(ql_dbg_init, vha, 0x018b,
+ "Primary image signature (%#x) not valid\n",
+ le32_to_cpu(pri_image_status.signature));
+ goto check_sec_image;
+ }
- if (chksum) {
+ if (qla27xx_image_status_checksum(&pri_image_status)) {
ql_dbg(ql_dbg_init, vha, 0x018c,
- "Checksum validation failed for primary image (0x%x)\n",
- chksum);
- valid_pri_image = 0;
+ "Primary image checksum failed\n");
+ goto check_sec_image;
+ }
+
+ valid_pri_image = true;
+
+ if (pri_image_status.image_status_mask & 1) {
+ ql_dbg(ql_dbg_init, vha, 0x018d,
+ "Primary image is active\n");
+ active_pri_image = true;
}
check_sec_image:
if (!ha->flt_region_img_status_sec) {
- valid_sec_image = 0;
+ ql_dbg(ql_dbg_init, vha, 0x018a, "Secondary image not addressed\n");
goto check_valid_image;
}
qla24xx_read_flash_data(vha, (uint32_t *)(&sec_image_status),
- ha->flt_region_img_status_sec, size);
+ ha->flt_region_img_status_sec, sizeof(sec_image_status) >> 2);
+ qla27xx_print_image(vha, "Secondary image", &sec_image_status);
- if (sec_image_status.signature != QLA27XX_IMG_STATUS_SIGN) {
- ql_dbg(ql_dbg_init, vha, 0x018d,
- "Secondary image signature(0x%x) not valid\n",
- sec_image_status.signature);
- valid_sec_image = 0;
+ if (qla27xx_check_image_status_signature(&sec_image_status)) {
+ ql_dbg(ql_dbg_init, vha, 0x018b,
+ "Secondary image signature (%#x) not valid\n",
+ le32_to_cpu(sec_image_status.signature));
+ goto check_valid_image;
+ }
+
+ if (qla27xx_image_status_checksum(&sec_image_status)) {
+ ql_dbg(ql_dbg_init, vha, 0x018c,
+ "Secondary image checksum failed\n");
goto check_valid_image;
}
- wptr = (uint32_t *)(&sec_image_status);
- cnt = size;
- for (chksum = 0; cnt--; wptr++)
- chksum += le32_to_cpu(*wptr);
- if (chksum) {
- ql_dbg(ql_dbg_init, vha, 0x018e,
- "Checksum validation failed for secondary image (0x%x)\n",
- chksum);
- valid_sec_image = 0;
+ valid_sec_image = true;
+
+ if (sec_image_status.image_status_mask & 1) {
+ ql_dbg(ql_dbg_init, vha, 0x018d,
+ "Secondary image is active\n");
+ active_sec_image = true;
}
check_valid_image:
- if (valid_pri_image && (pri_image_status.image_status_mask & 0x1))
- ha->active_image = QLA27XX_PRIMARY_IMAGE;
- if (valid_sec_image && (sec_image_status.image_status_mask & 0x1)) {
- if (!ha->active_image ||
- pri_image_status.generation_number <
- sec_image_status.generation_number)
- ha->active_image = QLA27XX_SECONDARY_IMAGE;
+ if (valid_pri_image && active_pri_image)
+ active_regions->global = QLA27XX_PRIMARY_IMAGE;
+
+ if (valid_sec_image && active_sec_image) {
+ if (!active_regions->global ||
+ qla27xx_compare_image_generation(
+ &pri_image_status, &sec_image_status) < 0) {
+ active_regions->global = QLA27XX_SECONDARY_IMAGE;
+ }
}
- ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x018f, "%s image\n",
- ha->active_image == 0 ? "default bootld and fw" :
- ha->active_image == 1 ? "primary" :
- ha->active_image == 2 ? "secondary" :
- "Invalid");
+ ql_dbg(ql_dbg_init, vha, 0x018f, "active image %s (%u)\n",
+ active_regions->global == QLA27XX_DEFAULT_IMAGE ?
+ "default (boot/fw)" :
+ active_regions->global == QLA27XX_PRIMARY_IMAGE ?
+ "primary" :
+ active_regions->global == QLA27XX_SECONDARY_IMAGE ?
+ "secondary" : "invalid",
+ active_regions->global);
+}
- return ha->active_image;
+bool qla24xx_risc_firmware_invalid(uint32_t *dword)
+{
+ return
+ !(dword[4] | dword[5] | dword[6] | dword[7]) ||
+ !(~dword[4] | ~dword[5] | ~dword[6] | ~dword[7]);
}
static int
qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
uint32_t faddr)
{
- int rval = QLA_SUCCESS;
- int segments, fragment;
- uint32_t *dcode, dlen;
- uint32_t risc_addr;
- uint32_t risc_size;
- uint32_t i;
+ int rval;
+ uint templates, segments, fragment;
+ ulong i;
+ uint j;
+ ulong dlen;
+ uint32_t *dcode;
+ uint32_t risc_addr, risc_size, risc_attr = 0;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
+ struct fwdt *fwdt = ha->fwdt;
ql_dbg(ql_dbg_init, vha, 0x008b,
"FW: Loading firmware from flash (%x).\n", faddr);
- rval = QLA_SUCCESS;
-
- segments = FA_RISC_CODE_SEGMENTS;
- dcode = (uint32_t *)req->ring;
- *srisc_addr = 0;
-
- if (IS_QLA27XX(ha) &&
- qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
- faddr = ha->flt_region_fw_sec;
-
- /* Validate firmware image by checking version. */
- qla24xx_read_flash_data(vha, dcode, faddr + 4, 4);
- for (i = 0; i < 4; i++)
- dcode[i] = be32_to_cpu(dcode[i]);
- if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff &&
- dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
- (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
- dcode[3] == 0)) {
+ dcode = (void *)req->ring;
+ qla24xx_read_flash_data(vha, dcode, faddr, 8);
+ if (qla24xx_risc_firmware_invalid(dcode)) {
ql_log(ql_log_fatal, vha, 0x008c,
"Unable to verify the integrity of flash firmware "
"image.\n");
@@ -7399,34 +7575,36 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
return QLA_FUNCTION_FAILED;
}
- while (segments && rval == QLA_SUCCESS) {
- /* Read segment's load information. */
- qla24xx_read_flash_data(vha, dcode, faddr, 4);
-
+ dcode = (void *)req->ring;
+ *srisc_addr = 0;
+ segments = FA_RISC_CODE_SEGMENTS;
+ for (j = 0; j < segments; j++) {
+ ql_dbg(ql_dbg_init, vha, 0x008d,
+ "-> Loading segment %u...\n", j);
+ qla24xx_read_flash_data(vha, dcode, faddr, 10);
risc_addr = be32_to_cpu(dcode[2]);
- *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr;
risc_size = be32_to_cpu(dcode[3]);
+ if (!*srisc_addr) {
+ *srisc_addr = risc_addr;
+ risc_attr = be32_to_cpu(dcode[9]);
+ }
- fragment = 0;
- while (risc_size > 0 && rval == QLA_SUCCESS) {
- dlen = (uint32_t)(ha->fw_transfer_size >> 2);
+ dlen = ha->fw_transfer_size >> 2;
+ for (fragment = 0; risc_size; fragment++) {
if (dlen > risc_size)
dlen = risc_size;
ql_dbg(ql_dbg_init, vha, 0x008e,
- "Loading risc segment@ risc addr %x "
- "number of dwords 0x%x offset 0x%x.\n",
- risc_addr, dlen, faddr);
-
+ "-> Loading fragment %u: %#x <- %#x (%#lx dwords)...\n",
+ fragment, risc_addr, faddr, dlen);
qla24xx_read_flash_data(vha, dcode, faddr, dlen);
for (i = 0; i < dlen; i++)
dcode[i] = swab32(dcode[i]);
- rval = qla2x00_load_ram(vha, req->dma, risc_addr,
- dlen);
+ rval = qla2x00_load_ram(vha, req->dma, risc_addr, dlen);
if (rval) {
ql_log(ql_log_fatal, vha, 0x008f,
- "Failed to load segment %d of firmware.\n",
+ "-> Failed load firmware fragment %u.\n",
fragment);
return QLA_FUNCTION_FAILED;
}
@@ -7434,107 +7612,82 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
faddr += dlen;
risc_addr += dlen;
risc_size -= dlen;
- fragment++;
}
-
- /* Next segment. */
- segments--;
}
- if (!IS_QLA27XX(ha))
- return rval;
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+ return QLA_SUCCESS;
- if (ha->fw_dump_template)
- vfree(ha->fw_dump_template);
- ha->fw_dump_template = NULL;
- ha->fw_dump_template_len = 0;
-
- ql_dbg(ql_dbg_init, vha, 0x0161,
- "Loading fwdump template from %x\n", faddr);
- qla24xx_read_flash_data(vha, dcode, faddr, 7);
- risc_size = be32_to_cpu(dcode[2]);
- ql_dbg(ql_dbg_init, vha, 0x0162,
- "-> array size %x dwords\n", risc_size);
- if (risc_size == 0 || risc_size == ~0)
- goto default_template;
-
- dlen = (risc_size - 8) * sizeof(*dcode);
- ql_dbg(ql_dbg_init, vha, 0x0163,
- "-> template allocating %x bytes...\n", dlen);
- ha->fw_dump_template = vmalloc(dlen);
- if (!ha->fw_dump_template) {
- ql_log(ql_log_warn, vha, 0x0164,
- "Failed fwdump template allocate %x bytes.\n", risc_size);
- goto default_template;
- }
-
- faddr += 7;
- risc_size -= 8;
- dcode = ha->fw_dump_template;
- qla24xx_read_flash_data(vha, dcode, faddr, risc_size);
- for (i = 0; i < risc_size; i++)
- dcode[i] = le32_to_cpu(dcode[i]);
-
- if (!qla27xx_fwdt_template_valid(dcode)) {
- ql_log(ql_log_warn, vha, 0x0165,
- "Failed fwdump template validate\n");
- goto default_template;
- }
-
- dlen = qla27xx_fwdt_template_size(dcode);
- ql_dbg(ql_dbg_init, vha, 0x0166,
- "-> template size %x bytes\n", dlen);
- if (dlen > risc_size * sizeof(*dcode)) {
- ql_log(ql_log_warn, vha, 0x0167,
- "Failed fwdump template exceeds array by %zx bytes\n",
- (size_t)(dlen - risc_size * sizeof(*dcode)));
- goto default_template;
- }
- ha->fw_dump_template_len = dlen;
- return rval;
+ templates = (risc_attr & BIT_9) ? 2 : 1;
+ ql_dbg(ql_dbg_init, vha, 0x0160, "-> templates = %u\n", templates);
+ for (j = 0; j < templates; j++, fwdt++) {
+ if (fwdt->template)
+ vfree(fwdt->template);
+ fwdt->template = NULL;
+ fwdt->length = 0;
+
+ dcode = (void *)req->ring;
+ qla24xx_read_flash_data(vha, dcode, faddr, 7);
+ risc_size = be32_to_cpu(dcode[2]);
+ ql_dbg(ql_dbg_init, vha, 0x0161,
+ "-> fwdt%u template array at %#x (%#x dwords)\n",
+ j, faddr, risc_size);
+ if (!risc_size || !~risc_size) {
+ ql_dbg(ql_dbg_init, vha, 0x0162,
+ "-> fwdt%u failed to read array\n", j);
+ goto failed;
+ }
-default_template:
- ql_log(ql_log_warn, vha, 0x0168, "Using default fwdump template\n");
- if (ha->fw_dump_template)
- vfree(ha->fw_dump_template);
- ha->fw_dump_template = NULL;
- ha->fw_dump_template_len = 0;
-
- dlen = qla27xx_fwdt_template_default_size();
- ql_dbg(ql_dbg_init, vha, 0x0169,
- "-> template allocating %x bytes...\n", dlen);
- ha->fw_dump_template = vmalloc(dlen);
- if (!ha->fw_dump_template) {
- ql_log(ql_log_warn, vha, 0x016a,
- "Failed fwdump template allocate %x bytes.\n", risc_size);
- goto failed_template;
- }
-
- dcode = ha->fw_dump_template;
- risc_size = dlen / sizeof(*dcode);
- memcpy(dcode, qla27xx_fwdt_template_default(), dlen);
- for (i = 0; i < risc_size; i++)
- dcode[i] = be32_to_cpu(dcode[i]);
-
- if (!qla27xx_fwdt_template_valid(ha->fw_dump_template)) {
- ql_log(ql_log_warn, vha, 0x016b,
- "Failed fwdump template validate\n");
- goto failed_template;
- }
-
- dlen = qla27xx_fwdt_template_size(ha->fw_dump_template);
- ql_dbg(ql_dbg_init, vha, 0x016c,
- "-> template size %x bytes\n", dlen);
- ha->fw_dump_template_len = dlen;
- return rval;
+ /* skip header and ignore checksum */
+ faddr += 7;
+ risc_size -= 8;
+
+ ql_dbg(ql_dbg_init, vha, 0x0163,
+ "-> fwdt%u template allocate template %#x words...\n",
+ j, risc_size);
+ fwdt->template = vmalloc(risc_size * sizeof(*dcode));
+ if (!fwdt->template) {
+ ql_log(ql_log_warn, vha, 0x0164,
+ "-> fwdt%u failed allocate template.\n", j);
+ goto failed;
+ }
-failed_template:
- ql_log(ql_log_warn, vha, 0x016d, "Failed default fwdump template\n");
- if (ha->fw_dump_template)
- vfree(ha->fw_dump_template);
- ha->fw_dump_template = NULL;
- ha->fw_dump_template_len = 0;
- return rval;
+ dcode = fwdt->template;
+ qla24xx_read_flash_data(vha, dcode, faddr, risc_size);
+
+ if (!qla27xx_fwdt_template_valid(dcode)) {
+ ql_log(ql_log_warn, vha, 0x0165,
+ "-> fwdt%u failed template validate\n", j);
+ goto failed;
+ }
+
+ dlen = qla27xx_fwdt_template_size(dcode);
+ ql_dbg(ql_dbg_init, vha, 0x0166,
+ "-> fwdt%u template size %#lx bytes (%#lx words)\n",
+ j, dlen, dlen / sizeof(*dcode));
+ if (dlen > risc_size * sizeof(*dcode)) {
+ ql_log(ql_log_warn, vha, 0x0167,
+ "-> fwdt%u template exceeds array (%-lu bytes)\n",
+ j, dlen - risc_size * sizeof(*dcode));
+ goto failed;
+ }
+
+ fwdt->length = dlen;
+ ql_dbg(ql_dbg_init, vha, 0x0168,
+ "-> fwdt%u loaded template ok\n", j);
+
+ faddr += risc_size + 1;
+ }
+
+ return QLA_SUCCESS;
+
+failed:
+ if (fwdt->template)
+ vfree(fwdt->template);
+ fwdt->template = NULL;
+ fwdt->length = 0;
+
+ return QLA_SUCCESS;
}
#define QLA_FW_URL "http://ldriver.qlogic.com/firmware/"
@@ -7642,94 +7795,73 @@ static int
qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
{
int rval;
- int segments, fragment;
- uint32_t *dcode, dlen;
- uint32_t risc_addr;
- uint32_t risc_size;
- uint32_t i;
+ uint templates, segments, fragment;
+ uint32_t *dcode;
+ ulong dlen;
+ uint32_t risc_addr, risc_size, risc_attr = 0;
+ ulong i;
+ uint j;
struct fw_blob *blob;
- const uint32_t *fwcode;
- uint32_t fwclen;
+ uint32_t *fwcode;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
+ struct fwdt *fwdt = ha->fwdt;
+
+ ql_dbg(ql_dbg_init, vha, 0x0090,
+ "-> FW: Loading via request-firmware.\n");
- /* Load firmware blob. */
blob = qla2x00_request_firmware(vha);
if (!blob) {
- ql_log(ql_log_warn, vha, 0x0090,
- "Firmware image unavailable.\n");
- ql_log(ql_log_warn, vha, 0x0091,
- "Firmware images can be retrieved from: "
- QLA_FW_URL ".\n");
+ ql_log(ql_log_warn, vha, 0x0092,
+ "-> Firmware file not found.\n");
return QLA_FUNCTION_FAILED;
}
- ql_dbg(ql_dbg_init, vha, 0x0092,
- "FW: Loading via request-firmware.\n");
-
- rval = QLA_SUCCESS;
-
- segments = FA_RISC_CODE_SEGMENTS;
- dcode = (uint32_t *)req->ring;
- *srisc_addr = 0;
- fwcode = (uint32_t *)blob->fw->data;
- fwclen = 0;
-
- /* Validate firmware image by checking version. */
- if (blob->fw->size < 8 * sizeof(uint32_t)) {
+ fwcode = (void *)blob->fw->data;
+ dcode = fwcode;
+ if (qla24xx_risc_firmware_invalid(dcode)) {
ql_log(ql_log_fatal, vha, 0x0093,
"Unable to verify integrity of firmware image (%zd).\n",
blob->fw->size);
- return QLA_FUNCTION_FAILED;
- }
- for (i = 0; i < 4; i++)
- dcode[i] = be32_to_cpu(fwcode[i + 4]);
- if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff &&
- dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
- (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
- dcode[3] == 0)) {
- ql_log(ql_log_fatal, vha, 0x0094,
- "Unable to verify integrity of firmware image (%zd).\n",
- blob->fw->size);
ql_log(ql_log_fatal, vha, 0x0095,
"Firmware data: %08x %08x %08x %08x.\n",
dcode[0], dcode[1], dcode[2], dcode[3]);
return QLA_FUNCTION_FAILED;
}
- while (segments && rval == QLA_SUCCESS) {
+ dcode = (void *)req->ring;
+ *srisc_addr = 0;
+ segments = FA_RISC_CODE_SEGMENTS;
+ for (j = 0; j < segments; j++) {
+ ql_dbg(ql_dbg_init, vha, 0x0096,
+ "-> Loading segment %u...\n", j);
risc_addr = be32_to_cpu(fwcode[2]);
- *srisc_addr = *srisc_addr == 0 ? risc_addr : *srisc_addr;
risc_size = be32_to_cpu(fwcode[3]);
- /* Validate firmware image size. */
- fwclen += risc_size * sizeof(uint32_t);
- if (blob->fw->size < fwclen) {
- ql_log(ql_log_fatal, vha, 0x0096,
- "Unable to verify integrity of firmware image "
- "(%zd).\n", blob->fw->size);
- return QLA_FUNCTION_FAILED;
+ if (!*srisc_addr) {
+ *srisc_addr = risc_addr;
+ risc_attr = be32_to_cpu(fwcode[9]);
}
- fragment = 0;
- while (risc_size > 0 && rval == QLA_SUCCESS) {
- dlen = (uint32_t)(ha->fw_transfer_size >> 2);
+ dlen = ha->fw_transfer_size >> 2;
+ for (fragment = 0; risc_size; fragment++) {
if (dlen > risc_size)
dlen = risc_size;
ql_dbg(ql_dbg_init, vha, 0x0097,
- "Loading risc segment@ risc addr %x "
- "number of dwords 0x%x.\n", risc_addr, dlen);
+ "-> Loading fragment %u: %#x <- %#x (%#lx words)...\n",
+ fragment, risc_addr,
+ (uint32_t)(fwcode - (typeof(fwcode))blob->fw->data),
+ dlen);
for (i = 0; i < dlen; i++)
dcode[i] = swab32(fwcode[i]);
- rval = qla2x00_load_ram(vha, req->dma, risc_addr,
- dlen);
+ rval = qla2x00_load_ram(vha, req->dma, risc_addr, dlen);
if (rval) {
ql_log(ql_log_fatal, vha, 0x0098,
- "Failed to load segment %d of firmware.\n",
+ "-> Failed load firmware fragment %u.\n",
fragment);
return QLA_FUNCTION_FAILED;
}
@@ -7737,106 +7869,82 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
fwcode += dlen;
risc_addr += dlen;
risc_size -= dlen;
- fragment++;
}
-
- /* Next segment. */
- segments--;
}
- if (!IS_QLA27XX(ha))
- return rval;
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+ return QLA_SUCCESS;
- if (ha->fw_dump_template)
- vfree(ha->fw_dump_template);
- ha->fw_dump_template = NULL;
- ha->fw_dump_template_len = 0;
-
- ql_dbg(ql_dbg_init, vha, 0x171,
- "Loading fwdump template from %x\n",
- (uint32_t)((void *)fwcode - (void *)blob->fw->data));
- risc_size = be32_to_cpu(fwcode[2]);
- ql_dbg(ql_dbg_init, vha, 0x172,
- "-> array size %x dwords\n", risc_size);
- if (risc_size == 0 || risc_size == ~0)
- goto default_template;
-
- dlen = (risc_size - 8) * sizeof(*fwcode);
- ql_dbg(ql_dbg_init, vha, 0x0173,
- "-> template allocating %x bytes...\n", dlen);
- ha->fw_dump_template = vmalloc(dlen);
- if (!ha->fw_dump_template) {
- ql_log(ql_log_warn, vha, 0x0174,
- "Failed fwdump template allocate %x bytes.\n", risc_size);
- goto default_template;
- }
-
- fwcode += 7;
- risc_size -= 8;
- dcode = ha->fw_dump_template;
- for (i = 0; i < risc_size; i++)
- dcode[i] = le32_to_cpu(fwcode[i]);
-
- if (!qla27xx_fwdt_template_valid(dcode)) {
- ql_log(ql_log_warn, vha, 0x0175,
- "Failed fwdump template validate\n");
- goto default_template;
- }
-
- dlen = qla27xx_fwdt_template_size(dcode);
- ql_dbg(ql_dbg_init, vha, 0x0176,
- "-> template size %x bytes\n", dlen);
- if (dlen > risc_size * sizeof(*fwcode)) {
- ql_log(ql_log_warn, vha, 0x0177,
- "Failed fwdump template exceeds array by %zx bytes\n",
- (size_t)(dlen - risc_size * sizeof(*fwcode)));
- goto default_template;
- }
- ha->fw_dump_template_len = dlen;
- return rval;
+ templates = (risc_attr & BIT_9) ? 2 : 1;
+ ql_dbg(ql_dbg_init, vha, 0x0170, "-> templates = %u\n", templates);
+ for (j = 0; j < templates; j++, fwdt++) {
+ if (fwdt->template)
+ vfree(fwdt->template);
+ fwdt->template = NULL;
+ fwdt->length = 0;
+
+ risc_size = be32_to_cpu(fwcode[2]);
+ ql_dbg(ql_dbg_init, vha, 0x0171,
+ "-> fwdt%u template array at %#x (%#x dwords)\n",
+ j, (uint32_t)((void *)fwcode - (void *)blob->fw->data),
+ risc_size);
+ if (!risc_size || !~risc_size) {
+ ql_dbg(ql_dbg_init, vha, 0x0172,
+ "-> fwdt%u failed to read array\n", j);
+ goto failed;
+ }
-default_template:
- ql_log(ql_log_warn, vha, 0x0178, "Using default fwdump template\n");
- if (ha->fw_dump_template)
- vfree(ha->fw_dump_template);
- ha->fw_dump_template = NULL;
- ha->fw_dump_template_len = 0;
-
- dlen = qla27xx_fwdt_template_default_size();
- ql_dbg(ql_dbg_init, vha, 0x0179,
- "-> template allocating %x bytes...\n", dlen);
- ha->fw_dump_template = vmalloc(dlen);
- if (!ha->fw_dump_template) {
- ql_log(ql_log_warn, vha, 0x017a,
- "Failed fwdump template allocate %x bytes.\n", risc_size);
- goto failed_template;
- }
-
- dcode = ha->fw_dump_template;
- risc_size = dlen / sizeof(*fwcode);
- fwcode = qla27xx_fwdt_template_default();
- for (i = 0; i < risc_size; i++)
- dcode[i] = be32_to_cpu(fwcode[i]);
-
- if (!qla27xx_fwdt_template_valid(ha->fw_dump_template)) {
- ql_log(ql_log_warn, vha, 0x017b,
- "Failed fwdump template validate\n");
- goto failed_template;
- }
-
- dlen = qla27xx_fwdt_template_size(ha->fw_dump_template);
- ql_dbg(ql_dbg_init, vha, 0x017c,
- "-> template size %x bytes\n", dlen);
- ha->fw_dump_template_len = dlen;
- return rval;
+ /* skip header and ignore checksum */
+ fwcode += 7;
+ risc_size -= 8;
+
+ ql_dbg(ql_dbg_init, vha, 0x0173,
+ "-> fwdt%u template allocate template %#x words...\n",
+ j, risc_size);
+ fwdt->template = vmalloc(risc_size * sizeof(*dcode));
+ if (!fwdt->template) {
+ ql_log(ql_log_warn, vha, 0x0174,
+ "-> fwdt%u failed allocate template.\n", j);
+ goto failed;
+ }
-failed_template:
- ql_log(ql_log_warn, vha, 0x017d, "Failed default fwdump template\n");
- if (ha->fw_dump_template)
- vfree(ha->fw_dump_template);
- ha->fw_dump_template = NULL;
- ha->fw_dump_template_len = 0;
- return rval;
+ dcode = fwdt->template;
+ for (i = 0; i < risc_size; i++)
+ dcode[i] = fwcode[i];
+
+ if (!qla27xx_fwdt_template_valid(dcode)) {
+ ql_log(ql_log_warn, vha, 0x0175,
+ "-> fwdt%u failed template validate\n", j);
+ goto failed;
+ }
+
+ dlen = qla27xx_fwdt_template_size(dcode);
+ ql_dbg(ql_dbg_init, vha, 0x0176,
+ "-> fwdt%u template size %#lx bytes (%#lx words)\n",
+ j, dlen, dlen / sizeof(*dcode));
+ if (dlen > risc_size * sizeof(*dcode)) {
+ ql_log(ql_log_warn, vha, 0x0177,
+ "-> fwdt%u template exceeds array (%-lu bytes)\n",
+ j, dlen - risc_size * sizeof(*dcode));
+ goto failed;
+ }
+
+ fwdt->length = dlen;
+ ql_dbg(ql_dbg_init, vha, 0x0178,
+ "-> fwdt%u loaded template ok\n", j);
+
+ fwcode += risc_size + 1;
+ }
+
+ return QLA_SUCCESS;
+
+failed:
+ if (fwdt->template)
+ vfree(fwdt->template);
+ fwdt->template = NULL;
+ fwdt->length = 0;
+
+ return QLA_SUCCESS;
}
int
@@ -7865,32 +7973,50 @@ qla81xx_load_risc(scsi_qla_host_t *vha, uint32_t *srisc_addr)
{
int rval;
struct qla_hw_data *ha = vha->hw;
+ struct active_regions active_regions = { };
if (ql2xfwloadbin == 2)
goto try_blob_fw;
- /*
- * FW Load priority:
+ /* FW Load priority:
* 1) Firmware residing in flash.
* 2) Firmware via request-firmware interface (.bin file).
- * 3) Golden-Firmware residing in flash -- limited operation.
+ * 3) Golden-Firmware residing in flash -- (limited operation).
*/
+
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+ goto try_primary_fw;
+
+ qla27xx_get_active_image(vha, &active_regions);
+
+ if (active_regions.global != QLA27XX_SECONDARY_IMAGE)
+ goto try_primary_fw;
+
+ ql_dbg(ql_dbg_init, vha, 0x008b,
+ "Loading secondary firmware image.\n");
+ rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_fw_sec);
+ if (!rval)
+ return rval;
+
+try_primary_fw:
+ ql_dbg(ql_dbg_init, vha, 0x008b,
+ "Loading primary firmware image.\n");
rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_fw);
- if (rval == QLA_SUCCESS)
+ if (!rval)
return rval;
try_blob_fw:
rval = qla24xx_load_risc_blob(vha, srisc_addr);
- if (rval == QLA_SUCCESS || !ha->flt_region_gold_fw)
+ if (!rval || !ha->flt_region_gold_fw)
return rval;
ql_log(ql_log_info, vha, 0x0099,
"Attempting to fallback to golden firmware.\n");
rval = qla24xx_load_risc_flash(vha, srisc_addr, ha->flt_region_gold_fw);
- if (rval != QLA_SUCCESS)
+ if (rval)
return rval;
- ql_log(ql_log_info, vha, 0x009a, "Update operational firmware.\n");
+ ql_log(ql_log_info, vha, 0x009a, "Need firmware flash update.\n");
ha->flags.running_gold_fw = 1;
return rval;
}
@@ -7935,22 +8061,15 @@ qla24xx_configure_vhba(scsi_qla_host_t *vha)
uint16_t mb[MAILBOX_REGISTER_COUNT];
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
- struct req_que *req;
- struct rsp_que *rsp;
if (!vha->vp_idx)
return -EINVAL;
rval = qla2x00_fw_ready(base_vha);
- if (vha->qpair)
- req = vha->qpair->req;
- else
- req = ha->req_q_map[0];
- rsp = req->rsp;
if (rval == QLA_SUCCESS) {
clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
- qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
+ qla2x00_marker(vha, ha->base_qpair, 0, 0, MK_SYNC_ALL);
}
vha->flags.management_server_logged_in = 0;
@@ -8032,6 +8151,7 @@ void
qla84xx_put_chip(struct scsi_qla_host *vha)
{
struct qla_hw_data *ha = vha->hw;
+
if (ha->cs84xx)
kref_put(&ha->cs84xx->kref, __qla84xx_chip_release);
}
@@ -8049,7 +8169,7 @@ qla84xx_init_chip(scsi_qla_host_t *vha)
mutex_unlock(&ha->cs84xx->fw_update_mutex);
- return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED:
+ return rval != QLA_SUCCESS || status[0] ? QLA_FUNCTION_FAILED :
QLA_SUCCESS;
}
@@ -8066,25 +8186,48 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
uint32_t chksum;
uint16_t cnt;
struct qla_hw_data *ha = vha->hw;
+ uint32_t faddr;
+ struct active_regions active_regions = { };
rval = QLA_SUCCESS;
icb = (struct init_cb_81xx *)ha->init_cb;
nv = ha->nvram;
/* Determine NVRAM starting address. */
- ha->nvram_size = sizeof(struct nvram_81xx);
+ ha->nvram_size = sizeof(*nv);
ha->vpd_size = FA_NVRAM_VPD_SIZE;
if (IS_P3P_TYPE(ha) || IS_QLA8031(ha))
ha->vpd_size = FA_VPD_SIZE_82XX;
+ if (IS_QLA28XX(ha) || IS_QLA27XX(ha))
+ qla28xx_get_aux_images(vha, &active_regions);
+
/* Get VPD data into cache */
ha->vpd = ha->nvram + VPD_OFFSET;
- ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2,
- ha->vpd_size);
+
+ faddr = ha->flt_region_vpd;
+ if (IS_QLA28XX(ha)) {
+ if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE)
+ faddr = ha->flt_region_vpd_sec;
+ ql_dbg(ql_dbg_init, vha, 0x0110,
+ "Loading %s nvram image.\n",
+ active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ?
+ "primary" : "secondary");
+ }
+ ha->isp_ops->read_optrom(vha, ha->vpd, faddr << 2, ha->vpd_size);
/* Get NVRAM data into cache and calculate checksum. */
- ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2,
- ha->nvram_size);
+ faddr = ha->flt_region_nvram;
+ if (IS_QLA28XX(ha)) {
+ if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE)
+ faddr = ha->flt_region_nvram_sec;
+ }
+ ql_dbg(ql_dbg_init, vha, 0x0110,
+ "Loading %s nvram image.\n",
+ active_regions.aux.vpd_nvram == QLA27XX_PRIMARY_IMAGE ?
+ "primary" : "secondary");
+ ha->isp_ops->read_optrom(vha, ha->nvram, faddr << 2, ha->nvram_size);
+
dptr = (uint32_t *)nv;
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++, dptr++)
chksum += le32_to_cpu(*dptr);
@@ -8092,17 +8235,16 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
ql_dbg(ql_dbg_init + ql_dbg_buffer, vha, 0x0111,
"Contents of NVRAM:\n");
ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0112,
- (uint8_t *)nv, ha->nvram_size);
+ nv, ha->nvram_size);
/* Bad NVRAM data, set defaults parameters. */
- if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' || nv->id[2] != 'P'
- || nv->id[3] != ' ' ||
- nv->nvram_version < cpu_to_le16(ICB_VERSION)) {
+ if (chksum || memcmp("ISP ", nv->id, sizeof(nv->id)) ||
+ le16_to_cpu(nv->nvram_version) < ICB_VERSION) {
/* Reset NVRAM data. */
ql_log(ql_log_info, vha, 0x0073,
- "Inconsistent NVRAM detected: checksum=0x%x id=%c "
- "version=0x%x.\n", chksum, nv->id[0],
- le16_to_cpu(nv->nvram_version));
+ "Inconsistent NVRAM checksum=%#x id=%.4s version=%#x.\n",
+ chksum, nv->id, le16_to_cpu(nv->nvram_version));
+ ql_dump_buffer(ql_dbg_init, vha, 0x0073, nv, sizeof(*nv));
ql_log(ql_log_info, vha, 0x0074,
"Falling back to functioning (yet invalid -- WWPN) "
"defaults.\n");
@@ -8223,11 +8365,11 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
ha->flags.disable_risc_code_load = 0;
ha->flags.enable_lip_reset = 0;
ha->flags.enable_lip_full_login =
- le32_to_cpu(nv->host_p) & BIT_10 ? 1: 0;
+ le32_to_cpu(nv->host_p) & BIT_10 ? 1 : 0;
ha->flags.enable_target_reset =
- le32_to_cpu(nv->host_p) & BIT_11 ? 1: 0;
+ le32_to_cpu(nv->host_p) & BIT_11 ? 1 : 0;
ha->flags.enable_led_scheme = 0;
- ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1: 0;
+ ha->flags.disable_serdes = le32_to_cpu(nv->host_p) & BIT_5 ? 1 : 0;
ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) &
(BIT_6 | BIT_5 | BIT_4)) >> 4;
@@ -8291,7 +8433,8 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
ha->login_retry_count = ql2xloginretrycount;
/* if not running MSI-X we need handshaking on interrupts */
- if (!vha->hw->flags.msix_enabled && (IS_QLA83XX(ha) || IS_QLA27XX(ha)))
+ if (!vha->hw->flags.msix_enabled &&
+ (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)))
icb->firmware_options_2 |= cpu_to_le32(BIT_22);
/* Enable ZIO. */
@@ -8299,7 +8442,7 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
ha->zio_mode = le32_to_cpu(icb->firmware_options_2) &
(BIT_3 | BIT_2 | BIT_1 | BIT_0);
ha->zio_timer = le16_to_cpu(icb->interrupt_delay_timer) ?
- le16_to_cpu(icb->interrupt_delay_timer): 2;
+ le16_to_cpu(icb->interrupt_delay_timer) : 2;
}
icb->firmware_options_2 &= cpu_to_le32(
~(BIT_3 | BIT_2 | BIT_1 | BIT_0));
@@ -8324,12 +8467,6 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
/* N2N: driver will initiate Login instead of FW */
icb->firmware_options_3 |= BIT_8;
- if (IS_QLA27XX(ha)) {
- icb->firmware_options_3 |= BIT_8;
- ql_dbg(ql_log_info, vha, 0x0075,
- "Enabling direct connection.\n");
- }
-
if (rval) {
ql_log(ql_log_warn, vha, 0x0076,
"NVRAM configuration failed.\n");
@@ -8342,8 +8479,6 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
{
int status, rval;
struct qla_hw_data *ha = vha->hw;
- struct req_que *req = ha->req_q_map[0];
- struct rsp_que *rsp = ha->rsp_q_map[0];
struct scsi_qla_host *vp;
unsigned long flags;
@@ -8355,7 +8490,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
status = qla2x00_fw_ready(vha);
if (!status) {
/* Issue a marker after FW becomes ready. */
- qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL);
+ qla2x00_marker(vha, ha->base_qpair, 0, 0, MK_SYNC_ALL);
vha->flags.online = 1;
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
}
@@ -8692,7 +8827,6 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos,
"Failed to allocate memory for queue pair.\n");
return NULL;
}
- memset(qpair, 0, sizeof(struct qla_qpair));
qpair->hw = vha->hw;
qpair->vha = vha;
@@ -8739,7 +8873,7 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos,
qpair->msix->in_use = 1;
list_add_tail(&qpair->qp_list_elem, &vha->qp_list);
qpair->pdev = ha->pdev;
- if (IS_QLA27XX(ha) || IS_QLA83XX(ha))
+ if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha))
qpair->reqq_start_iocbs = qla_83xx_start_iocbs;
mutex_unlock(&ha->mq_lock);
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index e396dd14ab5f..0c3d907af769 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -91,43 +91,6 @@ host_to_adap(uint8_t *src, uint8_t *dst, uint32_t bsize)
}
static inline void
-qla2x00_set_reserved_loop_ids(struct qla_hw_data *ha)
-{
- int i;
-
- if (IS_FWI2_CAPABLE(ha))
- return;
-
- for (i = 0; i < SNS_FIRST_LOOP_ID; i++)
- set_bit(i, ha->loop_id_map);
- set_bit(MANAGEMENT_SERVER, ha->loop_id_map);
- set_bit(BROADCAST, ha->loop_id_map);
-}
-
-static inline int
-qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id)
-{
- struct qla_hw_data *ha = vha->hw;
- if (IS_FWI2_CAPABLE(ha))
- return (loop_id > NPH_LAST_HANDLE);
-
- return ((loop_id > ha->max_loop_id && loop_id < SNS_FIRST_LOOP_ID) ||
- loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST);
-}
-
-static inline void
-qla2x00_clear_loop_id(fc_port_t *fcport) {
- struct qla_hw_data *ha = fcport->vha->hw;
-
- if (fcport->loop_id == FC_NO_LOOP_ID ||
- qla2x00_is_reserved_id(fcport->vha, fcport->loop_id))
- return;
-
- clear_bit(fcport->loop_id, ha->loop_id_map);
- fcport->loop_id = FC_NO_LOOP_ID;
-}
-
-static inline void
qla2x00_clean_dsd_pool(struct qla_hw_data *ha, struct crc_context *ctx)
{
struct dsd_dma *dsd, *tdsd;
@@ -142,25 +105,6 @@ qla2x00_clean_dsd_pool(struct qla_hw_data *ha, struct crc_context *ctx)
INIT_LIST_HEAD(&ctx->dsd_list);
}
-static inline void
-qla2x00_set_fcport_state(fc_port_t *fcport, int state)
-{
- int old_state;
-
- old_state = atomic_read(&fcport->state);
- atomic_set(&fcport->state, state);
-
- /* Don't print state transitions during initial allocation of fcport */
- if (old_state && old_state != state) {
- ql_dbg(ql_dbg_disc, fcport->vha, 0x207d,
- "FCPort %8phC state transitioned from %s to %s - "
- "portid=%02x%02x%02x.\n", fcport->port_name,
- port_state_str[old_state], port_state_str[state],
- fcport->d_id.b.domain, fcport->d_id.b.area,
- fcport->d_id.b.al_pa);
- }
-}
-
static inline int
qla2x00_hba_err_chk_enabled(srb_t *sp)
{
@@ -208,6 +152,18 @@ qla2x00_chip_is_down(scsi_qla_host_t *vha)
return (qla2x00_reset_active(vha) || !vha->hw->flags.fw_started);
}
+static void qla2xxx_init_sp(srb_t *sp, scsi_qla_host_t *vha,
+ struct qla_qpair *qpair, fc_port_t *fcport)
+{
+ memset(sp, 0, sizeof(*sp));
+ sp->fcport = fcport;
+ sp->iocbs = 1;
+ sp->vha = vha;
+ sp->qpair = qpair;
+ sp->cmd_type = TYPE_SRB;
+ INIT_LIST_HEAD(&sp->elem);
+}
+
static inline srb_t *
qla2xxx_get_qpair_sp(scsi_qla_host_t *vha, struct qla_qpair *qpair,
fc_port_t *fcport, gfp_t flag)
@@ -220,19 +176,9 @@ qla2xxx_get_qpair_sp(scsi_qla_host_t *vha, struct qla_qpair *qpair,
return NULL;
sp = mempool_alloc(qpair->srb_mempool, flag);
- if (!sp)
- goto done;
-
- memset(sp, 0, sizeof(*sp));
- sp->fcport = fcport;
- sp->iocbs = 1;
- sp->vha = vha;
- sp->qpair = qpair;
- sp->cmd_type = TYPE_SRB;
- INIT_LIST_HEAD(&sp->elem);
-
-done:
- if (!sp)
+ if (sp)
+ qla2xxx_init_sp(sp, vha, qpair, fcport);
+ else
QLA_QPAIR_MARK_NOT_BUSY(qpair);
return sp;
}
@@ -240,6 +186,7 @@ done:
static inline void
qla2xxx_rel_qpair_sp(struct qla_qpair *qpair, srb_t *sp)
{
+ sp->qpair = NULL;
mempool_free(sp, qpair->srb_mempool);
QLA_QPAIR_MARK_NOT_BUSY(qpair);
}
@@ -274,20 +221,6 @@ qla2x00_rel_sp(srb_t *sp)
qla2xxx_rel_qpair_sp(sp->qpair, sp);
}
-static inline void
-qla2x00_init_timer(srb_t *sp, unsigned long tmo)
-{
- init_timer(&sp->u.iocb_cmd.timer);
- sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ;
- sp->u.iocb_cmd.timer.data = (unsigned long)sp;
- sp->u.iocb_cmd.timer.function = qla2x00_sp_timeout;
- sp->free = qla2x00_sp_free;
- init_completion(&sp->comp);
- if (IS_QLAFX00(sp->vha->hw) && (sp->type == SRB_FXIOCB_DCMD))
- init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp);
- add_timer(&sp->u.iocb_cmd.timer);
-}
-
static inline int
qla2x00_gid_list_size(struct qla_hw_data *ha)
{
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index a8eb42f993c4..bdd45cb2c9c3 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -107,7 +107,7 @@ qla2x00_prep_cont_type0_iocb(struct scsi_qla_host *vha)
cont_pkt = (cont_entry_t *)req->ring_ptr;
/* Load packet defaults. */
- *((uint32_t *)(&cont_pkt->entry_type)) = cpu_to_le32(CONTINUE_TYPE);
+ put_unaligned_le32(CONTINUE_TYPE, &cont_pkt->entry_type);
return (cont_pkt);
}
@@ -136,9 +136,8 @@ qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha, struct req_que *req)
cont_pkt = (cont_a64_entry_t *)req->ring_ptr;
/* Load packet defaults. */
- *((uint32_t *)(&cont_pkt->entry_type)) = IS_QLAFX00(vha->hw) ?
- cpu_to_le32(CONTINUE_A64_TYPE_FX00) :
- cpu_to_le32(CONTINUE_A64_TYPE);
+ put_unaligned_le32(IS_QLAFX00(vha->hw) ? CONTINUE_A64_TYPE_FX00 :
+ CONTINUE_A64_TYPE, &cont_pkt->entry_type);
return (cont_pkt);
}
@@ -193,7 +192,7 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt,
uint16_t tot_dsds)
{
uint16_t avail_dsds;
- uint32_t *cur_dsd;
+ struct dsd32 *cur_dsd;
scsi_qla_host_t *vha;
struct scsi_cmnd *cmd;
struct scatterlist *sg;
@@ -202,8 +201,7 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt,
cmd = GET_CMD_SP(sp);
/* Update entry type to indicate Command Type 2 IOCB */
- *((uint32_t *)(&cmd_pkt->entry_type)) =
- cpu_to_le32(COMMAND_TYPE);
+ put_unaligned_le32(COMMAND_TYPE, &cmd_pkt->entry_type);
/* No data transfer */
if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
@@ -215,8 +213,8 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt,
cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp));
/* Three DSDs are available in the Command Type 2 IOCB */
- avail_dsds = 3;
- cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;
+ avail_dsds = ARRAY_SIZE(cmd_pkt->dsd32);
+ cur_dsd = cmd_pkt->dsd32;
/* Load data segments */
scsi_for_each_sg(cmd, sg, tot_dsds, i) {
@@ -229,12 +227,11 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt,
* Type 0 IOCB.
*/
cont_pkt = qla2x00_prep_cont_type0_iocb(vha);
- cur_dsd = (uint32_t *)&cont_pkt->dseg_0_address;
- avail_dsds = 7;
+ cur_dsd = cont_pkt->dsd;
+ avail_dsds = ARRAY_SIZE(cont_pkt->dsd);
}
- *cur_dsd++ = cpu_to_le32(sg_dma_address(sg));
- *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ append_dsd32(&cur_dsd, sg);
avail_dsds--;
}
}
@@ -251,7 +248,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt,
uint16_t tot_dsds)
{
uint16_t avail_dsds;
- uint32_t *cur_dsd;
+ struct dsd64 *cur_dsd;
scsi_qla_host_t *vha;
struct scsi_cmnd *cmd;
struct scatterlist *sg;
@@ -260,7 +257,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt,
cmd = GET_CMD_SP(sp);
/* Update entry type to indicate Command Type 3 IOCB */
- *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_A64_TYPE);
+ put_unaligned_le32(COMMAND_A64_TYPE, &cmd_pkt->entry_type);
/* No data transfer */
if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
@@ -272,12 +269,11 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt,
cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp));
/* Two DSDs are available in the Command Type 3 IOCB */
- avail_dsds = 2;
- cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;
+ avail_dsds = ARRAY_SIZE(cmd_pkt->dsd64);
+ cur_dsd = cmd_pkt->dsd64;
/* Load data segments */
scsi_for_each_sg(cmd, sg, tot_dsds, i) {
- dma_addr_t sle_dma;
cont_a64_entry_t *cont_pkt;
/* Allocate additional continuation packets? */
@@ -287,18 +283,35 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt,
* Type 1 IOCB.
*/
cont_pkt = qla2x00_prep_cont_type1_iocb(vha, vha->req);
- cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
- avail_dsds = 5;
+ cur_dsd = cont_pkt->dsd;
+ avail_dsds = ARRAY_SIZE(cont_pkt->dsd);
}
- sle_dma = sg_dma_address(sg);
- *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ append_dsd64(&cur_dsd, sg);
avail_dsds--;
}
}
+/*
+ * Find the first handle that is not in use, starting from
+ * req->current_outstanding_cmd + 1. The caller must hold the lock that is
+ * associated with @req.
+ */
+uint32_t qla2xxx_get_next_handle(struct req_que *req)
+{
+ uint32_t index, handle = req->current_outstanding_cmd;
+
+ for (index = 1; index < req->num_outstanding_cmds; index++) {
+ handle++;
+ if (handle == req->num_outstanding_cmds)
+ handle = 1;
+ if (!req->outstanding_cmds[handle])
+ return handle;
+ }
+
+ return 0;
+}
+
/**
* qla2x00_start_scsi() - Send a SCSI command to the ISP
* @sp: command to send to the ISP
@@ -313,7 +326,6 @@ qla2x00_start_scsi(srb_t *sp)
scsi_qla_host_t *vha;
struct scsi_cmnd *cmd;
uint32_t *clr_ptr;
- uint32_t index;
uint32_t handle;
cmd_entry_t *cmd_pkt;
uint16_t cnt;
@@ -336,7 +348,7 @@ qla2x00_start_scsi(srb_t *sp)
/* Send marker if required */
if (vha->marker_needed != 0) {
- if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
+ if (qla2x00_marker(vha, ha->base_qpair, 0, 0, MK_SYNC_ALL) !=
QLA_SUCCESS) {
return (QLA_FUNCTION_FAILED);
}
@@ -346,16 +358,8 @@ qla2x00_start_scsi(srb_t *sp)
/* Acquire ring specific lock */
spin_lock_irqsave(&ha->hardware_lock, flags);
- /* Check for room in outstanding command list. */
- handle = req->current_outstanding_cmd;
- for (index = 1; index < req->num_outstanding_cmds; index++) {
- handle++;
- if (handle == req->num_outstanding_cmds)
- handle = 1;
- if (!req->outstanding_cmds[handle])
- break;
- }
- if (index == req->num_outstanding_cmds)
+ handle = qla2xxx_get_next_handle(req);
+ if (handle == 0)
goto queuing_error;
/* Map the sg table so we have an accurate count of sg entries needed */
@@ -467,7 +471,7 @@ qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req)
req->ring_ptr++;
/* Set chip new ring index. */
- if (ha->mqenable || IS_QLA27XX(ha)) {
+ if (ha->mqenable || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
WRT_REG_DWORD(req->req_q_in, req->ring_index);
} else if (IS_QLA83XX(ha)) {
WRT_REG_DWORD(req->req_q_in, req->ring_index);
@@ -490,8 +494,7 @@ qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req)
/**
* qla2x00_marker() - Send a marker IOCB to the firmware.
* @vha: HA context
- * @req: request queue
- * @rsp: response queue
+ * @qpair: queue pair pointer
* @loop_id: loop ID
* @lun: LUN
* @type: marker modifier
@@ -501,18 +504,16 @@ qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req)
* Returns non-zero if a failure occurred, else zero.
*/
static int
-__qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req,
- struct rsp_que *rsp, uint16_t loop_id,
- uint64_t lun, uint8_t type)
+__qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair,
+ uint16_t loop_id, uint64_t lun, uint8_t type)
{
mrk_entry_t *mrk;
struct mrk_entry_24xx *mrk24 = NULL;
-
+ struct req_que *req = qpair->req;
struct qla_hw_data *ha = vha->hw;
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
- req = ha->req_q_map[0];
- mrk = (mrk_entry_t *)qla2x00_alloc_iocbs(vha, NULL);
+ mrk = (mrk_entry_t *)__qla2x00_alloc_iocbs(qpair, NULL);
if (mrk == NULL) {
ql_log(ql_log_warn, base_vha, 0x3026,
"Failed to allocate Marker IOCB.\n");
@@ -543,16 +544,15 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req,
}
int
-qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req,
- struct rsp_que *rsp, uint16_t loop_id, uint64_t lun,
- uint8_t type)
+qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair,
+ uint16_t loop_id, uint64_t lun, uint8_t type)
{
int ret;
unsigned long flags = 0;
- spin_lock_irqsave(&vha->hw->hardware_lock, flags);
- ret = __qla2x00_marker(vha, req, rsp, loop_id, lun, type);
- spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
+ spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+ ret = __qla2x00_marker(vha, qpair, loop_id, lun, type);
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
return (ret);
}
@@ -567,11 +567,11 @@ qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req,
int qla2x00_issue_marker(scsi_qla_host_t *vha, int ha_locked)
{
if (ha_locked) {
- if (__qla2x00_marker(vha, vha->req, vha->req->rsp, 0, 0,
+ if (__qla2x00_marker(vha, vha->hw->base_qpair, 0, 0,
MK_SYNC_ALL) != QLA_SUCCESS)
return QLA_FUNCTION_FAILED;
} else {
- if (qla2x00_marker(vha, vha->req, vha->req->rsp, 0, 0,
+ if (qla2x00_marker(vha, vha->hw->base_qpair, 0, 0,
MK_SYNC_ALL) != QLA_SUCCESS)
return QLA_FUNCTION_FAILED;
}
@@ -584,13 +584,11 @@ static inline int
qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt,
uint16_t tot_dsds)
{
- uint32_t *cur_dsd = NULL;
+ struct dsd64 *cur_dsd = NULL, *next_dsd;
scsi_qla_host_t *vha;
struct qla_hw_data *ha;
struct scsi_cmnd *cmd;
struct scatterlist *cur_seg;
- uint32_t *dsd_seg;
- void *next_dsd;
uint8_t avail_dsds;
uint8_t first_iocb = 1;
uint32_t dsd_list_len;
@@ -600,7 +598,7 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt,
cmd = GET_CMD_SP(sp);
/* Update entry type to indicate Command Type 3 IOCB */
- *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_TYPE_6);
+ put_unaligned_le32(COMMAND_TYPE_6, &cmd_pkt->entry_type);
/* No data transfer */
if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
@@ -623,7 +621,7 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt,
}
cur_seg = scsi_sglist(cmd);
- ctx = GET_CMD_CTX_SP(sp);
+ ctx = sp->u.scmd.ct6_ctx;
while (tot_dsds) {
avail_dsds = (tot_dsds > QLA_DSDS_PER_IOCB) ?
@@ -642,32 +640,27 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt,
if (first_iocb) {
first_iocb = 0;
- dsd_seg = (uint32_t *)&cmd_pkt->fcp_data_dseg_address;
- *dsd_seg++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
- *dsd_seg++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
- cmd_pkt->fcp_data_dseg_len = cpu_to_le32(dsd_list_len);
+ put_unaligned_le64(dsd_ptr->dsd_list_dma,
+ &cmd_pkt->fcp_dsd.address);
+ cmd_pkt->fcp_dsd.length = cpu_to_le32(dsd_list_len);
} else {
- *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
- *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
- *cur_dsd++ = cpu_to_le32(dsd_list_len);
+ put_unaligned_le64(dsd_ptr->dsd_list_dma,
+ &cur_dsd->address);
+ cur_dsd->length = cpu_to_le32(dsd_list_len);
+ cur_dsd++;
}
- cur_dsd = (uint32_t *)next_dsd;
+ cur_dsd = next_dsd;
while (avail_dsds) {
- dma_addr_t sle_dma;
-
- sle_dma = sg_dma_address(cur_seg);
- *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(sg_dma_len(cur_seg));
+ append_dsd64(&cur_dsd, cur_seg);
cur_seg = sg_next(cur_seg);
avail_dsds--;
}
}
/* Null termination */
- *cur_dsd++ = 0;
- *cur_dsd++ = 0;
- *cur_dsd++ = 0;
+ cur_dsd->address = 0;
+ cur_dsd->length = 0;
+ cur_dsd++;
cmd_pkt->control_flags |= CF_DATA_SEG_DESCR_ENABLE;
return 0;
}
@@ -706,7 +699,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt,
uint16_t tot_dsds, struct req_que *req)
{
uint16_t avail_dsds;
- uint32_t *cur_dsd;
+ struct dsd64 *cur_dsd;
scsi_qla_host_t *vha;
struct scsi_cmnd *cmd;
struct scatterlist *sg;
@@ -715,7 +708,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt,
cmd = GET_CMD_SP(sp);
/* Update entry type to indicate Command Type 3 IOCB */
- *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_TYPE_7);
+ put_unaligned_le32(COMMAND_TYPE_7, &cmd_pkt->entry_type);
/* No data transfer */
if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) {
@@ -738,12 +731,11 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt,
/* One DSD is available in the Command Type 3 IOCB */
avail_dsds = 1;
- cur_dsd = (uint32_t *)&cmd_pkt->dseg_0_address;
+ cur_dsd = &cmd_pkt->dsd;
/* Load data segments */
scsi_for_each_sg(cmd, sg, tot_dsds, i) {
- dma_addr_t sle_dma;
cont_a64_entry_t *cont_pkt;
/* Allocate additional continuation packets? */
@@ -753,14 +745,11 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt,
* Type 1 IOCB.
*/
cont_pkt = qla2x00_prep_cont_type1_iocb(vha, req);
- cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
- avail_dsds = 5;
+ cur_dsd = cont_pkt->dsd;
+ avail_dsds = ARRAY_SIZE(cont_pkt->dsd);
}
- sle_dma = sg_dma_address(sg);
- *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ append_dsd64(&cur_dsd, sg);
avail_dsds--;
}
}
@@ -896,14 +885,14 @@ qla24xx_get_one_block_sg(uint32_t blk_sz, struct qla2_sgx *sgx,
int
qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp,
- uint32_t *dsd, uint16_t tot_dsds, struct qla_tc_param *tc)
+ struct dsd64 *dsd, uint16_t tot_dsds, struct qla_tc_param *tc)
{
void *next_dsd;
uint8_t avail_dsds = 0;
uint32_t dsd_list_len;
struct dsd_dma *dsd_ptr;
struct scatterlist *sg_prot;
- uint32_t *cur_dsd = dsd;
+ struct dsd64 *cur_dsd = dsd;
uint16_t used_dsds = tot_dsds;
uint32_t prot_int; /* protection interval */
uint32_t partial;
@@ -965,8 +954,7 @@ alloc_and_fill:
if (sp) {
list_add_tail(&dsd_ptr->list,
- &((struct crc_context *)
- sp->u.scmd.ctx)->dsd_list);
+ &sp->u.scmd.crc_ctx->dsd_list);
sp->flags |= SRB_CRC_CTX_DSD_VALID;
} else {
@@ -977,14 +965,14 @@ alloc_and_fill:
/* add new list to cmd iocb or last list */
- *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
- *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
- *cur_dsd++ = dsd_list_len;
- cur_dsd = (uint32_t *)next_dsd;
+ put_unaligned_le64(dsd_ptr->dsd_list_dma,
+ &cur_dsd->address);
+ cur_dsd->length = cpu_to_le32(dsd_list_len);
+ cur_dsd = next_dsd;
}
- *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(sle_dma_len);
+ put_unaligned_le64(sle_dma, &cur_dsd->address);
+ cur_dsd->length = cpu_to_le32(sle_dma_len);
+ cur_dsd++;
avail_dsds--;
if (partial == 0) {
@@ -1003,22 +991,22 @@ alloc_and_fill:
}
}
/* Null termination */
- *cur_dsd++ = 0;
- *cur_dsd++ = 0;
- *cur_dsd++ = 0;
+ cur_dsd->address = 0;
+ cur_dsd->length = 0;
+ cur_dsd++;
return 0;
}
int
-qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
- uint16_t tot_dsds, struct qla_tc_param *tc)
+qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp,
+ struct dsd64 *dsd, uint16_t tot_dsds, struct qla_tc_param *tc)
{
void *next_dsd;
uint8_t avail_dsds = 0;
uint32_t dsd_list_len;
struct dsd_dma *dsd_ptr;
struct scatterlist *sg, *sgl;
- uint32_t *cur_dsd = dsd;
+ struct dsd64 *cur_dsd = dsd;
int i;
uint16_t used_dsds = tot_dsds;
struct scsi_cmnd *cmd;
@@ -1035,8 +1023,6 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
for_each_sg(sgl, sg, tot_dsds, i) {
- dma_addr_t sle_dma;
-
/* Allocate additional continuation packets? */
if (avail_dsds == 0) {
avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ?
@@ -1065,8 +1051,7 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
if (sp) {
list_add_tail(&dsd_ptr->list,
- &((struct crc_context *)
- sp->u.scmd.ctx)->dsd_list);
+ &sp->u.scmd.crc_ctx->dsd_list);
sp->flags |= SRB_CRC_CTX_DSD_VALID;
} else {
@@ -1076,115 +1061,316 @@ qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd,
}
/* add new list to cmd iocb or last list */
- *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
- *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
- *cur_dsd++ = dsd_list_len;
- cur_dsd = (uint32_t *)next_dsd;
+ put_unaligned_le64(dsd_ptr->dsd_list_dma,
+ &cur_dsd->address);
+ cur_dsd->length = cpu_to_le32(dsd_list_len);
+ cur_dsd = next_dsd;
}
- sle_dma = sg_dma_address(sg);
-
- *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ append_dsd64(&cur_dsd, sg);
avail_dsds--;
}
/* Null termination */
- *cur_dsd++ = 0;
- *cur_dsd++ = 0;
- *cur_dsd++ = 0;
+ cur_dsd->address = 0;
+ cur_dsd->length = 0;
+ cur_dsd++;
return 0;
}
int
qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
- uint32_t *dsd, uint16_t tot_dsds, struct qla_tc_param *tc)
+ struct dsd64 *cur_dsd, uint16_t tot_dsds, struct qla_tgt_cmd *tc)
{
- void *next_dsd;
- uint8_t avail_dsds = 0;
- uint32_t dsd_list_len;
- struct dsd_dma *dsd_ptr;
+ struct dsd_dma *dsd_ptr = NULL, *dif_dsd, *nxt_dsd;
struct scatterlist *sg, *sgl;
- int i;
- struct scsi_cmnd *cmd;
- uint32_t *cur_dsd = dsd;
- uint16_t used_dsds = tot_dsds;
+ struct crc_context *difctx = NULL;
struct scsi_qla_host *vha;
+ uint dsd_list_len;
+ uint avail_dsds = 0;
+ uint used_dsds = tot_dsds;
+ bool dif_local_dma_alloc = false;
+ bool direction_to_device = false;
+ int i;
if (sp) {
- cmd = GET_CMD_SP(sp);
+ struct scsi_cmnd *cmd = GET_CMD_SP(sp);
+
sgl = scsi_prot_sglist(cmd);
vha = sp->vha;
+ difctx = sp->u.scmd.crc_ctx;
+ direction_to_device = cmd->sc_data_direction == DMA_TO_DEVICE;
+ ql_dbg(ql_dbg_tgt + ql_dbg_verbose, vha, 0xe021,
+ "%s: scsi_cmnd: %p, crc_ctx: %p, sp: %p\n",
+ __func__, cmd, difctx, sp);
} else if (tc) {
vha = tc->vha;
sgl = tc->prot_sg;
+ difctx = tc->ctx;
+ direction_to_device = tc->dma_data_direction == DMA_TO_DEVICE;
} else {
BUG();
return 1;
}
- ql_dbg(ql_dbg_tgt, vha, 0xe021,
- "%s: enter\n", __func__);
-
- for_each_sg(sgl, sg, tot_dsds, i) {
- dma_addr_t sle_dma;
-
- /* Allocate additional continuation packets? */
- if (avail_dsds == 0) {
- avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ?
- QLA_DSDS_PER_IOCB : used_dsds;
- dsd_list_len = (avail_dsds + 1) * 12;
- used_dsds -= avail_dsds;
-
- /* allocate tracking DS */
- dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC);
- if (!dsd_ptr)
- return 1;
-
- /* allocate new list */
- dsd_ptr->dsd_addr = next_dsd =
- dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC,
- &dsd_ptr->dsd_list_dma);
-
- if (!next_dsd) {
- /*
- * Need to cleanup only this dsd_ptr, rest
- * will be done by sp_free_dma()
- */
- kfree(dsd_ptr);
- return 1;
+ ql_dbg(ql_dbg_tgt + ql_dbg_verbose, vha, 0xe021,
+ "%s: enter (write=%u)\n", __func__, direction_to_device);
+
+ /* if initiator doing write or target doing read */
+ if (direction_to_device) {
+ for_each_sg(sgl, sg, tot_dsds, i) {
+ u64 sle_phys = sg_phys(sg);
+
+ /* If SGE addr + len flips bits in upper 32-bits */
+ if (MSD(sle_phys + sg->length) ^ MSD(sle_phys)) {
+ ql_dbg(ql_dbg_tgt + ql_dbg_verbose, vha, 0xe022,
+ "%s: page boundary crossing (phys=%llx len=%x)\n",
+ __func__, sle_phys, sg->length);
+
+ if (difctx) {
+ ha->dif_bundle_crossed_pages++;
+ dif_local_dma_alloc = true;
+ } else {
+ ql_dbg(ql_dbg_tgt + ql_dbg_verbose,
+ vha, 0xe022,
+ "%s: difctx pointer is NULL\n",
+ __func__);
+ }
+ break;
}
+ }
+ ha->dif_bundle_writes++;
+ } else {
+ ha->dif_bundle_reads++;
+ }
+
+ if (ql2xdifbundlinginternalbuffers)
+ dif_local_dma_alloc = direction_to_device;
+
+ if (dif_local_dma_alloc) {
+ u32 track_difbundl_buf = 0;
+ u32 ldma_sg_len = 0;
+ u8 ldma_needed = 1;
+
+ difctx->no_dif_bundl = 0;
+ difctx->dif_bundl_len = 0;
+
+ /* Track DSD buffers */
+ INIT_LIST_HEAD(&difctx->ldif_dsd_list);
+ /* Track local DMA buffers */
+ INIT_LIST_HEAD(&difctx->ldif_dma_hndl_list);
+
+ for_each_sg(sgl, sg, tot_dsds, i) {
+ u32 sglen = sg_dma_len(sg);
+
+ ql_dbg(ql_dbg_tgt + ql_dbg_verbose, vha, 0xe023,
+ "%s: sg[%x] (phys=%llx sglen=%x) ldma_sg_len: %x dif_bundl_len: %x ldma_needed: %x\n",
+ __func__, i, (u64)sg_phys(sg), sglen, ldma_sg_len,
+ difctx->dif_bundl_len, ldma_needed);
+
+ while (sglen) {
+ u32 xfrlen = 0;
+
+ if (ldma_needed) {
+ /*
+ * Allocate list item to store
+ * the DMA buffers
+ */
+ dsd_ptr = kzalloc(sizeof(*dsd_ptr),
+ GFP_ATOMIC);
+ if (!dsd_ptr) {
+ ql_dbg(ql_dbg_tgt, vha, 0xe024,
+ "%s: failed alloc dsd_ptr\n",
+ __func__);
+ return 1;
+ }
+ ha->dif_bundle_kallocs++;
+
+ /* allocate dma buffer */
+ dsd_ptr->dsd_addr = dma_pool_alloc
+ (ha->dif_bundl_pool, GFP_ATOMIC,
+ &dsd_ptr->dsd_list_dma);
+ if (!dsd_ptr->dsd_addr) {
+ ql_dbg(ql_dbg_tgt, vha, 0xe024,
+ "%s: failed alloc ->dsd_ptr\n",
+ __func__);
+ /*
+ * need to cleanup only this
+ * dsd_ptr rest will be done
+ * by sp_free_dma()
+ */
+ kfree(dsd_ptr);
+ ha->dif_bundle_kallocs--;
+ return 1;
+ }
+ ha->dif_bundle_dma_allocs++;
+ ldma_needed = 0;
+ difctx->no_dif_bundl++;
+ list_add_tail(&dsd_ptr->list,
+ &difctx->ldif_dma_hndl_list);
+ }
+
+ /* xfrlen is min of dma pool size and sglen */
+ xfrlen = (sglen >
+ (DIF_BUNDLING_DMA_POOL_SIZE - ldma_sg_len)) ?
+ DIF_BUNDLING_DMA_POOL_SIZE - ldma_sg_len :
+ sglen;
+
+ /* replace with local allocated dma buffer */
+ sg_pcopy_to_buffer(sgl, sg_nents(sgl),
+ dsd_ptr->dsd_addr + ldma_sg_len, xfrlen,
+ difctx->dif_bundl_len);
+ difctx->dif_bundl_len += xfrlen;
+ sglen -= xfrlen;
+ ldma_sg_len += xfrlen;
+ if (ldma_sg_len == DIF_BUNDLING_DMA_POOL_SIZE ||
+ sg_is_last(sg)) {
+ ldma_needed = 1;
+ ldma_sg_len = 0;
+ }
+ }
+ }
- if (sp) {
- list_add_tail(&dsd_ptr->list,
- &((struct crc_context *)
- sp->u.scmd.ctx)->dsd_list);
+ track_difbundl_buf = used_dsds = difctx->no_dif_bundl;
+ ql_dbg(ql_dbg_tgt + ql_dbg_verbose, vha, 0xe025,
+ "dif_bundl_len=%x, no_dif_bundl=%x track_difbundl_buf: %x\n",
+ difctx->dif_bundl_len, difctx->no_dif_bundl,
+ track_difbundl_buf);
- sp->flags |= SRB_CRC_CTX_DSD_VALID;
- } else {
- list_add_tail(&dsd_ptr->list,
- &(tc->ctx->dsd_list));
- *tc->ctx_dsd_alloced = 1;
+ if (sp)
+ sp->flags |= SRB_DIF_BUNDL_DMA_VALID;
+ else
+ tc->prot_flags = DIF_BUNDL_DMA_VALID;
+
+ list_for_each_entry_safe(dif_dsd, nxt_dsd,
+ &difctx->ldif_dma_hndl_list, list) {
+ u32 sglen = (difctx->dif_bundl_len >
+ DIF_BUNDLING_DMA_POOL_SIZE) ?
+ DIF_BUNDLING_DMA_POOL_SIZE : difctx->dif_bundl_len;
+
+ BUG_ON(track_difbundl_buf == 0);
+
+ /* Allocate additional continuation packets? */
+ if (avail_dsds == 0) {
+ ql_dbg(ql_dbg_tgt + ql_dbg_verbose, vha,
+ 0xe024,
+ "%s: adding continuation iocb's\n",
+ __func__);
+ avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ?
+ QLA_DSDS_PER_IOCB : used_dsds;
+ dsd_list_len = (avail_dsds + 1) * 12;
+ used_dsds -= avail_dsds;
+
+ /* allocate tracking DS */
+ dsd_ptr = kzalloc(sizeof(*dsd_ptr), GFP_ATOMIC);
+ if (!dsd_ptr) {
+ ql_dbg(ql_dbg_tgt, vha, 0xe026,
+ "%s: failed alloc dsd_ptr\n",
+ __func__);
+ return 1;
+ }
+ ha->dif_bundle_kallocs++;
+
+ difctx->no_ldif_dsd++;
+ /* allocate new list */
+ dsd_ptr->dsd_addr =
+ dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC,
+ &dsd_ptr->dsd_list_dma);
+ if (!dsd_ptr->dsd_addr) {
+ ql_dbg(ql_dbg_tgt, vha, 0xe026,
+ "%s: failed alloc ->dsd_addr\n",
+ __func__);
+ /*
+ * need to cleanup only this dsd_ptr
+ * rest will be done by sp_free_dma()
+ */
+ kfree(dsd_ptr);
+ ha->dif_bundle_kallocs--;
+ return 1;
+ }
+ ha->dif_bundle_dma_allocs++;
+
+ if (sp) {
+ list_add_tail(&dsd_ptr->list,
+ &difctx->ldif_dsd_list);
+ sp->flags |= SRB_CRC_CTX_DSD_VALID;
+ } else {
+ list_add_tail(&dsd_ptr->list,
+ &difctx->ldif_dsd_list);
+ tc->ctx_dsd_alloced = 1;
+ }
+
+ /* add new list to cmd iocb or last list */
+ put_unaligned_le64(dsd_ptr->dsd_list_dma,
+ &cur_dsd->address);
+ cur_dsd->length = cpu_to_le32(dsd_list_len);
+ cur_dsd = dsd_ptr->dsd_addr;
}
-
- /* add new list to cmd iocb or last list */
- *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
- *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
- *cur_dsd++ = dsd_list_len;
- cur_dsd = (uint32_t *)next_dsd;
+ put_unaligned_le64(dif_dsd->dsd_list_dma,
+ &cur_dsd->address);
+ cur_dsd->length = cpu_to_le32(sglen);
+ cur_dsd++;
+ avail_dsds--;
+ difctx->dif_bundl_len -= sglen;
+ track_difbundl_buf--;
}
- sle_dma = sg_dma_address(sg);
- *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
-
- avail_dsds--;
+ ql_dbg(ql_dbg_tgt + ql_dbg_verbose, vha, 0xe026,
+ "%s: no_ldif_dsd:%x, no_dif_bundl:%x\n", __func__,
+ difctx->no_ldif_dsd, difctx->no_dif_bundl);
+ } else {
+ for_each_sg(sgl, sg, tot_dsds, i) {
+ /* Allocate additional continuation packets? */
+ if (avail_dsds == 0) {
+ avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ?
+ QLA_DSDS_PER_IOCB : used_dsds;
+ dsd_list_len = (avail_dsds + 1) * 12;
+ used_dsds -= avail_dsds;
+
+ /* allocate tracking DS */
+ dsd_ptr = kzalloc(sizeof(*dsd_ptr), GFP_ATOMIC);
+ if (!dsd_ptr) {
+ ql_dbg(ql_dbg_tgt + ql_dbg_verbose,
+ vha, 0xe027,
+ "%s: failed alloc dsd_dma...\n",
+ __func__);
+ return 1;
+ }
+
+ /* allocate new list */
+ dsd_ptr->dsd_addr =
+ dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC,
+ &dsd_ptr->dsd_list_dma);
+ if (!dsd_ptr->dsd_addr) {
+ /* need to cleanup only this dsd_ptr */
+ /* rest will be done by sp_free_dma() */
+ kfree(dsd_ptr);
+ return 1;
+ }
+
+ if (sp) {
+ list_add_tail(&dsd_ptr->list,
+ &difctx->dsd_list);
+ sp->flags |= SRB_CRC_CTX_DSD_VALID;
+ } else {
+ list_add_tail(&dsd_ptr->list,
+ &difctx->dsd_list);
+ tc->ctx_dsd_alloced = 1;
+ }
+
+ /* add new list to cmd iocb or last list */
+ put_unaligned_le64(dsd_ptr->dsd_list_dma,
+ &cur_dsd->address);
+ cur_dsd->length = cpu_to_le32(dsd_list_len);
+ cur_dsd = dsd_ptr->dsd_addr;
+ }
+ append_dsd64(&cur_dsd, sg);
+ avail_dsds--;
+ }
}
/* Null termination */
- *cur_dsd++ = 0;
- *cur_dsd++ = 0;
- *cur_dsd++ = 0;
+ cur_dsd->address = 0;
+ cur_dsd->length = 0;
+ cur_dsd++;
return 0;
}
@@ -1198,11 +1384,12 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp,
* @tot_prot_dsds: Total number of segments with protection information
* @fw_prot_opts: Protection options to be passed to firmware
*/
-inline int
+static inline int
qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
uint16_t tot_dsds, uint16_t tot_prot_dsds, uint16_t fw_prot_opts)
{
- uint32_t *cur_dsd, *fcp_dl;
+ struct dsd64 *cur_dsd;
+ uint32_t *fcp_dl;
scsi_qla_host_t *vha;
struct scsi_cmnd *cmd;
uint32_t total_bytes = 0;
@@ -1210,7 +1397,6 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
uint32_t dif_bytes;
uint8_t bundling = 1;
uint16_t blk_size;
- uint8_t *clr_ptr;
struct crc_context *crc_ctx_pkt = NULL;
struct qla_hw_data *ha;
uint8_t additional_fcpcdb_len;
@@ -1221,7 +1407,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
cmd = GET_CMD_SP(sp);
/* Update entry type to indicate Command Type CRC_2 IOCB */
- *((uint32_t *)(&cmd_pkt->entry_type)) = cpu_to_le32(COMMAND_TYPE_CRC_2);
+ put_unaligned_le32(COMMAND_TYPE_CRC_2, &cmd_pkt->entry_type);
vha = sp->vha;
ha = vha->hw;
@@ -1251,16 +1437,12 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
bundling = 0;
/* Allocate CRC context from global pool */
- crc_ctx_pkt = sp->u.scmd.ctx =
- dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC, &crc_ctx_dma);
+ crc_ctx_pkt = sp->u.scmd.crc_ctx =
+ dma_pool_zalloc(ha->dl_dma_pool, GFP_ATOMIC, &crc_ctx_dma);
if (!crc_ctx_pkt)
goto crc_queuing_error;
- /* Zero out CTX area. */
- clr_ptr = (uint8_t *)crc_ctx_pkt;
- memset(clr_ptr, 0, sizeof(*crc_ctx_pkt));
-
crc_ctx_pkt->crc_ctx_dma = crc_ctx_dma;
sp->flags |= SRB_CRC_CTX_DMA_VALID;
@@ -1273,8 +1455,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
qla24xx_set_t10dif_tags(sp, (struct fw_dif_context *)
&crc_ctx_pkt->ref_tag, tot_prot_dsds);
- cmd_pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma));
- cmd_pkt->crc_context_address[1] = cpu_to_le32(MSD(crc_ctx_dma));
+ put_unaligned_le64(crc_ctx_dma, &cmd_pkt->crc_context_address);
cmd_pkt->crc_context_len = CRC_CONTEXT_LEN_FW;
/* Determine SCSI command length -- align to 4 byte boundary */
@@ -1301,10 +1482,8 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
int_to_scsilun(cmd->device->lun, &fcp_cmnd->lun);
memcpy(fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len);
cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(fcp_cmnd_len);
- cmd_pkt->fcp_cmnd_dseg_address[0] = cpu_to_le32(
- LSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF));
- cmd_pkt->fcp_cmnd_dseg_address[1] = cpu_to_le32(
- MSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF));
+ put_unaligned_le64(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF,
+ &cmd_pkt->fcp_cmnd_dseg_address);
fcp_cmnd->task_management = 0;
fcp_cmnd->task_attribute = TSK_SIMPLE;
@@ -1318,18 +1497,18 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
switch (scsi_get_prot_op(GET_CMD_SP(sp))) {
case SCSI_PROT_READ_INSERT:
case SCSI_PROT_WRITE_STRIP:
- total_bytes = data_bytes;
- data_bytes += dif_bytes;
- break;
+ total_bytes = data_bytes;
+ data_bytes += dif_bytes;
+ break;
case SCSI_PROT_READ_STRIP:
case SCSI_PROT_WRITE_INSERT:
case SCSI_PROT_READ_PASS:
case SCSI_PROT_WRITE_PASS:
- total_bytes = data_bytes + dif_bytes;
- break;
+ total_bytes = data_bytes + dif_bytes;
+ break;
default:
- BUG();
+ BUG();
}
if (!qla2x00_hba_err_chk_enabled(sp))
@@ -1346,7 +1525,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
}
if (!bundling) {
- cur_dsd = (uint32_t *) &crc_ctx_pkt->u.nobundling.data_address;
+ cur_dsd = &crc_ctx_pkt->u.nobundling.data_dsd[0];
} else {
/*
* Configure Bundling if we need to fetch interlaving
@@ -1356,7 +1535,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
crc_ctx_pkt->u.bundling.dif_byte_count = cpu_to_le32(dif_bytes);
crc_ctx_pkt->u.bundling.dseg_count = cpu_to_le16(tot_dsds -
tot_prot_dsds);
- cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.data_address;
+ cur_dsd = &crc_ctx_pkt->u.bundling.data_dsd[0];
}
/* Finish the common fields of CRC pkt */
@@ -1389,7 +1568,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
if (bundling && tot_prot_dsds) {
/* Walks dif segments */
cmd_pkt->control_flags |= cpu_to_le16(CF_DIF_SEG_DESCR_ENABLE);
- cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address;
+ cur_dsd = &crc_ctx_pkt->u.bundling.dif_dsd;
if (qla24xx_walk_and_build_prot_sglist(ha, sp, cur_dsd,
tot_prot_dsds, NULL))
goto crc_queuing_error;
@@ -1414,28 +1593,25 @@ qla24xx_start_scsi(srb_t *sp)
int nseg;
unsigned long flags;
uint32_t *clr_ptr;
- uint32_t index;
uint32_t handle;
struct cmd_type_7 *cmd_pkt;
uint16_t cnt;
uint16_t req_cnt;
uint16_t tot_dsds;
struct req_que *req = NULL;
- struct rsp_que *rsp = NULL;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
struct scsi_qla_host *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
/* Setup device pointers. */
req = vha->req;
- rsp = req->rsp;
/* So we know we haven't pci_map'ed anything yet */
tot_dsds = 0;
/* Send marker if required */
if (vha->marker_needed != 0) {
- if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
+ if (qla2x00_marker(vha, ha->base_qpair, 0, 0, MK_SYNC_ALL) !=
QLA_SUCCESS)
return QLA_FUNCTION_FAILED;
vha->marker_needed = 0;
@@ -1444,16 +1620,8 @@ qla24xx_start_scsi(srb_t *sp)
/* Acquire ring specific lock */
spin_lock_irqsave(&ha->hardware_lock, flags);
- /* Check for room in outstanding command list. */
- handle = req->current_outstanding_cmd;
- for (index = 1; index < req->num_outstanding_cmds; index++) {
- handle++;
- if (handle == req->num_outstanding_cmds)
- handle = 1;
- if (!req->outstanding_cmds[handle])
- break;
- }
- if (index == req->num_outstanding_cmds)
+ handle = qla2xxx_get_next_handle(req);
+ if (handle == 0)
goto queuing_error;
/* Map the sg table so we have an accurate count of sg entries needed */
@@ -1556,7 +1724,6 @@ qla24xx_dif_start_scsi(srb_t *sp)
int nseg;
unsigned long flags;
uint32_t *clr_ptr;
- uint32_t index;
uint32_t handle;
uint16_t cnt;
uint16_t req_cnt = 0;
@@ -1588,7 +1755,7 @@ qla24xx_dif_start_scsi(srb_t *sp)
/* Send marker if required */
if (vha->marker_needed != 0) {
- if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
+ if (qla2x00_marker(vha, ha->base_qpair, 0, 0, MK_SYNC_ALL) !=
QLA_SUCCESS)
return QLA_FUNCTION_FAILED;
vha->marker_needed = 0;
@@ -1597,17 +1764,8 @@ qla24xx_dif_start_scsi(srb_t *sp)
/* Acquire ring specific lock */
spin_lock_irqsave(&ha->hardware_lock, flags);
- /* Check for room in outstanding command list. */
- handle = req->current_outstanding_cmd;
- for (index = 1; index < req->num_outstanding_cmds; index++) {
- handle++;
- if (handle == req->num_outstanding_cmds)
- handle = 1;
- if (!req->outstanding_cmds[handle])
- break;
- }
-
- if (index == req->num_outstanding_cmds)
+ handle = qla2xxx_get_next_handle(req);
+ if (handle == 0)
goto queuing_error;
/* Compute number of required data segments */
@@ -1752,14 +1910,12 @@ qla2xxx_start_scsi_mq(srb_t *sp)
int nseg;
unsigned long flags;
uint32_t *clr_ptr;
- uint32_t index;
uint32_t handle;
struct cmd_type_7 *cmd_pkt;
uint16_t cnt;
uint16_t req_cnt;
uint16_t tot_dsds;
struct req_que *req = NULL;
- struct rsp_que *rsp = NULL;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
struct scsi_qla_host *vha = sp->fcport->vha;
struct qla_hw_data *ha = vha->hw;
@@ -1769,7 +1925,6 @@ qla2xxx_start_scsi_mq(srb_t *sp)
spin_lock_irqsave(&qpair->qp_lock, flags);
/* Setup qpair pointers */
- rsp = qpair->rsp;
req = qpair->req;
/* So we know we haven't pci_map'ed anything yet */
@@ -1777,7 +1932,7 @@ qla2xxx_start_scsi_mq(srb_t *sp)
/* Send marker if required */
if (vha->marker_needed != 0) {
- if (__qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
+ if (__qla2x00_marker(vha, qpair, 0, 0, MK_SYNC_ALL) !=
QLA_SUCCESS) {
spin_unlock_irqrestore(&qpair->qp_lock, flags);
return QLA_FUNCTION_FAILED;
@@ -1785,16 +1940,8 @@ qla2xxx_start_scsi_mq(srb_t *sp)
vha->marker_needed = 0;
}
- /* Check for room in outstanding command list. */
- handle = req->current_outstanding_cmd;
- for (index = 1; index < req->num_outstanding_cmds; index++) {
- handle++;
- if (handle == req->num_outstanding_cmds)
- handle = 1;
- if (!req->outstanding_cmds[handle])
- break;
- }
- if (index == req->num_outstanding_cmds)
+ handle = qla2xxx_get_next_handle(req);
+ if (handle == 0)
goto queuing_error;
/* Map the sg table so we have an accurate count of sg entries needed */
@@ -1898,7 +2045,6 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp)
int nseg;
unsigned long flags;
uint32_t *clr_ptr;
- uint32_t index;
uint32_t handle;
uint16_t cnt;
uint16_t req_cnt = 0;
@@ -1945,7 +2091,7 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp)
/* Send marker if required */
if (vha->marker_needed != 0) {
- if (__qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) !=
+ if (__qla2x00_marker(vha, qpair, 0, 0, MK_SYNC_ALL) !=
QLA_SUCCESS) {
spin_unlock_irqrestore(&qpair->qp_lock, flags);
return QLA_FUNCTION_FAILED;
@@ -1953,17 +2099,8 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp)
vha->marker_needed = 0;
}
- /* Check for room in outstanding command list. */
- handle = req->current_outstanding_cmd;
- for (index = 1; index < req->num_outstanding_cmds; index++) {
- handle++;
- if (handle == req->num_outstanding_cmds)
- handle = 1;
- if (!req->outstanding_cmds[handle])
- break;
- }
-
- if (index == req->num_outstanding_cmds)
+ handle = qla2xxx_get_next_handle(req);
+ if (handle == 0)
goto queuing_error;
/* Compute number of required data segments */
@@ -2110,7 +2247,7 @@ __qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp)
struct qla_hw_data *ha = vha->hw;
struct req_que *req = qpair->req;
device_reg_t *reg = ISP_QUE_REG(ha, req->id);
- uint32_t index, handle;
+ uint32_t handle;
request_t *pkt;
uint16_t cnt, req_cnt;
@@ -2127,7 +2264,8 @@ __qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp)
if (req->cnt < req_cnt + 2) {
if (qpair->use_shadow_reg)
cnt = *req->out_ptr;
- else if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+ else if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha))
cnt = RD_REG_DWORD(&reg->isp25mq.req_q_out);
else if (IS_P3P_TYPE(ha))
cnt = RD_REG_DWORD(&reg->isp82.req_q_out);
@@ -2149,16 +2287,8 @@ __qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp)
goto queuing_error;
if (sp) {
- /* Check for room in outstanding command list. */
- handle = req->current_outstanding_cmd;
- for (index = 1; index < req->num_outstanding_cmds; index++) {
- handle++;
- if (handle == req->num_outstanding_cmds)
- handle = 1;
- if (!req->outstanding_cmds[handle])
- break;
- }
- if (index == req->num_outstanding_cmds) {
+ handle = qla2xxx_get_next_handle(req);
+ if (handle == 0) {
ql_log(ql_log_warn, vha, 0x700b,
"No room on outstanding cmd array.\n");
goto queuing_error;
@@ -2213,8 +2343,11 @@ qla24xx_prli_iocb(srb_t *sp, struct logio_entry_24xx *logio)
logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
logio->control_flags = cpu_to_le16(LCF_COMMAND_PRLI);
- if (lio->u.logio.flags & SRB_LOGIN_NVME_PRLI)
+ if (lio->u.logio.flags & SRB_LOGIN_NVME_PRLI) {
logio->control_flags |= LCF_NVME_PRLI;
+ if (sp->vha->flags.nvme_first_burst)
+ logio->io_parameter[0] = NVME_PRLI_SP_FIRST_BURST;
+ }
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
logio->port_id[0] = sp->fcport->d_id.b.al_pa;
@@ -2293,7 +2426,7 @@ qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx)
SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id);
mbx->mb0 = cpu_to_le16(MBC_LOGOUT_FABRIC_PORT);
mbx->mb1 = HAS_EXTENDED_IDS(ha) ?
- cpu_to_le16(sp->fcport->loop_id):
+ cpu_to_le16(sp->fcport->loop_id) :
cpu_to_le16(sp->fcport->loop_id << 8);
mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain);
mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 |
@@ -2364,10 +2497,20 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
}
}
-static void
-qla2x00_els_dcmd_sp_free(void *data)
+void qla2x00_init_timer(srb_t *sp, unsigned long tmo)
+{
+ init_timer(&sp->u.iocb_cmd.timer);
+ sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ;
+ sp->u.iocb_cmd.timer.data = (unsigned long)sp;
+ sp->u.iocb_cmd.timer.function = qla2x00_sp_timeout;
+ sp->free = qla2x00_sp_free;
+ if (IS_QLAFX00(sp->vha->hw) && (sp->type == SRB_FXIOCB_DCMD))
+ init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp);
+ sp->start_timer = 1;
+}
+
+static void qla2x00_els_dcmd_sp_free(srb_t *sp)
{
- srb_t *sp = data;
struct srb_iocb *elsio = &sp->u.iocb_cmd;
kfree(sp->fcport);
@@ -2397,10 +2540,8 @@ qla2x00_els_dcmd_iocb_timeout(void *data)
complete(&lio->u.els_logo.comp);
}
-static void
-qla2x00_els_dcmd_sp_done(void *ptr, int res)
+static void qla2x00_els_dcmd_sp_done(srb_t *sp, int res)
{
- srb_t *sp = ptr;
fc_port_t *fcport = sp->fcport;
struct srb_iocb *lio = &sp->u.iocb_cmd;
struct scsi_qla_host *vha = sp->vha;
@@ -2517,42 +2658,37 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa;
els_iocb->port_id[1] = sp->fcport->d_id.b.area;
els_iocb->port_id[2] = sp->fcport->d_id.b.domain;
- els_iocb->s_id[0] = vha->d_id.b.al_pa;
- els_iocb->s_id[1] = vha->d_id.b.area;
- els_iocb->s_id[2] = vha->d_id.b.domain;
- els_iocb->control_flags = 0;
+ /* For SID the byte order is different than DID */
+ els_iocb->s_id[1] = vha->d_id.b.al_pa;
+ els_iocb->s_id[2] = vha->d_id.b.area;
+ els_iocb->s_id[0] = vha->d_id.b.domain;
if (elsio->u.els_logo.els_cmd == ELS_DCMD_PLOGI) {
+ els_iocb->control_flags = 0;
els_iocb->tx_byte_count = els_iocb->tx_len =
- sizeof(struct els_plogi_payload);
- els_iocb->tx_address[0] =
- cpu_to_le32(LSD(elsio->u.els_plogi.els_plogi_pyld_dma));
- els_iocb->tx_address[1] =
- cpu_to_le32(MSD(elsio->u.els_plogi.els_plogi_pyld_dma));
-
+ cpu_to_le32(sizeof(struct els_plogi_payload));
+ put_unaligned_le64(elsio->u.els_plogi.els_plogi_pyld_dma,
+ &els_iocb->tx_address);
els_iocb->rx_dsd_count = 1;
els_iocb->rx_byte_count = els_iocb->rx_len =
- sizeof(struct els_plogi_payload);
- els_iocb->rx_address[0] =
- cpu_to_le32(LSD(elsio->u.els_plogi.els_resp_pyld_dma));
- els_iocb->rx_address[1] =
- cpu_to_le32(MSD(elsio->u.els_plogi.els_resp_pyld_dma));
+ cpu_to_le32(sizeof(struct els_plogi_payload));
+ put_unaligned_le64(elsio->u.els_plogi.els_resp_pyld_dma,
+ &els_iocb->rx_address);
ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073,
"PLOGI ELS IOCB:\n");
ql_dump_buffer(ql_log_info, vha, 0x0109,
(uint8_t *)els_iocb, 0x70);
} else {
- els_iocb->tx_byte_count = sizeof(struct els_logo_payload);
- els_iocb->tx_address[0] =
- cpu_to_le32(LSD(elsio->u.els_logo.els_logo_pyld_dma));
- els_iocb->tx_address[1] =
- cpu_to_le32(MSD(elsio->u.els_logo.els_logo_pyld_dma));
+ els_iocb->control_flags = 1 << 13;
+ els_iocb->tx_byte_count =
+ cpu_to_le32(sizeof(struct els_logo_payload));
+ put_unaligned_le64(elsio->u.els_logo.els_logo_pyld_dma,
+ &els_iocb->tx_address);
els_iocb->tx_len = cpu_to_le32(sizeof(struct els_logo_payload));
els_iocb->rx_byte_count = 0;
- els_iocb->rx_address[0] = 0;
- els_iocb->rx_address[1] = 0;
+ els_iocb->rx_address = 0;
els_iocb->rx_len = 0;
}
@@ -2584,10 +2720,23 @@ qla2x00_els_dcmd2_iocb_timeout(void *data)
sp->done(sp, QLA_FUNCTION_TIMEOUT);
}
-static void
-qla2x00_els_dcmd2_sp_done(void *ptr, int res)
+void qla2x00_els_dcmd2_free(scsi_qla_host_t *vha, struct els_plogi *els_plogi)
+{
+ if (els_plogi->els_plogi_pyld)
+ dma_free_coherent(&vha->hw->pdev->dev,
+ els_plogi->tx_size,
+ els_plogi->els_plogi_pyld,
+ els_plogi->els_plogi_pyld_dma);
+
+ if (els_plogi->els_resp_pyld)
+ dma_free_coherent(&vha->hw->pdev->dev,
+ els_plogi->rx_size,
+ els_plogi->els_resp_pyld,
+ els_plogi->els_resp_pyld_dma);
+}
+
+static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res)
{
- srb_t *sp = ptr;
fc_port_t *fcport = sp->fcport;
struct srb_iocb *lio = &sp->u.iocb_cmd;
struct scsi_qla_host *vha = sp->vha;
@@ -2609,26 +2758,16 @@ qla2x00_els_dcmd2_sp_done(void *ptr, int res)
} else {
memset(&ea, 0, sizeof(ea));
ea.fcport = fcport;
- ea.rc = res;
- ea.event = FCME_ELS_PLOGI_DONE;
- qla2x00_fcport_event_handler(vha, &ea);
+ ea.data[0] = MBS_COMMAND_COMPLETE;
+ ea.sp = sp;
+ qla24xx_handle_plogi_done_event(vha, &ea);
}
e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
if (!e) {
struct srb_iocb *elsio = &sp->u.iocb_cmd;
- if (elsio->u.els_plogi.els_plogi_pyld)
- dma_free_coherent(&sp->vha->hw->pdev->dev,
- elsio->u.els_plogi.tx_size,
- elsio->u.els_plogi.els_plogi_pyld,
- elsio->u.els_plogi.els_plogi_pyld_dma);
-
- if (elsio->u.els_plogi.els_resp_pyld)
- dma_free_coherent(&sp->vha->hw->pdev->dev,
- elsio->u.els_plogi.rx_size,
- elsio->u.els_plogi.els_resp_pyld,
- elsio->u.els_plogi.els_resp_pyld_dma);
+ qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
sp->free(sp);
return;
}
@@ -2646,7 +2785,6 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
struct qla_hw_data *ha = vha->hw;
int rval = QLA_SUCCESS;
void *ptr, *resp_ptr;
- dma_addr_t ptr_dma;
/* Alloc SRB structure */
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
@@ -2678,7 +2816,6 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
ptr = elsio->u.els_plogi.els_plogi_pyld =
dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE,
&elsio->u.els_plogi.els_plogi_pyld_dma, GFP_KERNEL);
- ptr_dma = elsio->u.els_plogi.els_plogi_pyld_dma;
if (!elsio->u.els_plogi.els_plogi_pyld) {
rval = QLA_FUNCTION_FAILED;
@@ -2730,18 +2867,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
out:
fcport->flags &= ~(FCF_ASYNC_SENT);
- if (elsio->u.els_plogi.els_plogi_pyld)
- dma_free_coherent(&sp->vha->hw->pdev->dev,
- elsio->u.els_plogi.tx_size,
- elsio->u.els_plogi.els_plogi_pyld,
- elsio->u.els_plogi.els_plogi_pyld_dma);
-
- if (elsio->u.els_plogi.els_resp_pyld)
- dma_free_coherent(&sp->vha->hw->pdev->dev,
- elsio->u.els_plogi.rx_size,
- elsio->u.els_plogi.els_resp_pyld,
- elsio->u.els_plogi.els_resp_pyld_dma);
-
+ qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
sp->free(sp);
done:
return rval;
@@ -2777,17 +2903,13 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
els_iocb->tx_byte_count =
cpu_to_le32(bsg_job->request_payload.payload_len);
- els_iocb->tx_address[0] = cpu_to_le32(LSD(sg_dma_address
- (bsg_job->request_payload.sg_list)));
- els_iocb->tx_address[1] = cpu_to_le32(MSD(sg_dma_address
- (bsg_job->request_payload.sg_list)));
+ put_unaligned_le64(sg_dma_address(bsg_job->request_payload.sg_list),
+ &els_iocb->tx_address);
els_iocb->tx_len = cpu_to_le32(sg_dma_len
(bsg_job->request_payload.sg_list));
- els_iocb->rx_address[0] = cpu_to_le32(LSD(sg_dma_address
- (bsg_job->reply_payload.sg_list)));
- els_iocb->rx_address[1] = cpu_to_le32(MSD(sg_dma_address
- (bsg_job->reply_payload.sg_list)));
+ put_unaligned_le64(sg_dma_address(bsg_job->reply_payload.sg_list),
+ &els_iocb->rx_address);
els_iocb->rx_len = cpu_to_le32(sg_dma_len
(bsg_job->reply_payload.sg_list));
@@ -2798,14 +2920,13 @@ static void
qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb)
{
uint16_t avail_dsds;
- uint32_t *cur_dsd;
+ struct dsd64 *cur_dsd;
struct scatterlist *sg;
int index;
uint16_t tot_dsds;
scsi_qla_host_t *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
struct bsg_job *bsg_job = sp->u.bsg_job;
- int loop_iterartion = 0;
int entry_count = 1;
memset(ct_iocb, 0, sizeof(ms_iocb_entry_t));
@@ -2825,25 +2946,20 @@ qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb)
ct_iocb->rsp_bytecount =
cpu_to_le32(bsg_job->reply_payload.payload_len);
- ct_iocb->dseg_req_address[0] = cpu_to_le32(LSD(sg_dma_address
- (bsg_job->request_payload.sg_list)));
- ct_iocb->dseg_req_address[1] = cpu_to_le32(MSD(sg_dma_address
- (bsg_job->request_payload.sg_list)));
- ct_iocb->dseg_req_length = ct_iocb->req_bytecount;
+ put_unaligned_le64(sg_dma_address(bsg_job->request_payload.sg_list),
+ &ct_iocb->req_dsd.address);
+ ct_iocb->req_dsd.length = ct_iocb->req_bytecount;
- ct_iocb->dseg_rsp_address[0] = cpu_to_le32(LSD(sg_dma_address
- (bsg_job->reply_payload.sg_list)));
- ct_iocb->dseg_rsp_address[1] = cpu_to_le32(MSD(sg_dma_address
- (bsg_job->reply_payload.sg_list)));
- ct_iocb->dseg_rsp_length = ct_iocb->rsp_bytecount;
+ put_unaligned_le64(sg_dma_address(bsg_job->reply_payload.sg_list),
+ &ct_iocb->rsp_dsd.address);
+ ct_iocb->rsp_dsd.length = ct_iocb->rsp_bytecount;
avail_dsds = 1;
- cur_dsd = (uint32_t *)ct_iocb->dseg_rsp_address;
+ cur_dsd = &ct_iocb->rsp_dsd;
index = 0;
tot_dsds = bsg_job->reply_payload.sg_cnt;
for_each_sg(bsg_job->reply_payload.sg_list, sg, tot_dsds, index) {
- dma_addr_t sle_dma;
cont_a64_entry_t *cont_pkt;
/* Allocate additional continuation packets? */
@@ -2854,16 +2970,12 @@ qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb)
*/
cont_pkt = qla2x00_prep_cont_type1_iocb(vha,
vha->hw->req_q_map[0]);
- cur_dsd = (uint32_t *) cont_pkt->dseg_0_address;
+ cur_dsd = cont_pkt->dsd;
avail_dsds = 5;
entry_count++;
}
- sle_dma = sg_dma_address(sg);
- *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
- loop_iterartion++;
+ append_dsd64(&cur_dsd, sg);
avail_dsds--;
}
ct_iocb->entry_count = entry_count;
@@ -2875,7 +2987,7 @@ static void
qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb)
{
uint16_t avail_dsds;
- uint32_t *cur_dsd;
+ struct dsd64 *cur_dsd;
struct scatterlist *sg;
int index;
uint16_t cmd_dsds, rsp_dsds;
@@ -2904,12 +3016,10 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb)
cpu_to_le32(bsg_job->request_payload.payload_len);
avail_dsds = 2;
- cur_dsd = (uint32_t *)ct_iocb->dseg_0_address;
+ cur_dsd = ct_iocb->dsd;
index = 0;
for_each_sg(bsg_job->request_payload.sg_list, sg, cmd_dsds, index) {
- dma_addr_t sle_dma;
-
/* Allocate additional continuation packets? */
if (avail_dsds == 0) {
/*
@@ -2918,23 +3028,18 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb)
*/
cont_pkt = qla2x00_prep_cont_type1_iocb(
vha, ha->req_q_map[0]);
- cur_dsd = (uint32_t *) cont_pkt->dseg_0_address;
+ cur_dsd = cont_pkt->dsd;
avail_dsds = 5;
entry_count++;
}
- sle_dma = sg_dma_address(sg);
- *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ append_dsd64(&cur_dsd, sg);
avail_dsds--;
}
index = 0;
for_each_sg(bsg_job->reply_payload.sg_list, sg, rsp_dsds, index) {
- dma_addr_t sle_dma;
-
/* Allocate additional continuation packets? */
if (avail_dsds == 0) {
/*
@@ -2943,15 +3048,12 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb)
*/
cont_pkt = qla2x00_prep_cont_type1_iocb(vha,
ha->req_q_map[0]);
- cur_dsd = (uint32_t *) cont_pkt->dseg_0_address;
+ cur_dsd = cont_pkt->dsd;
avail_dsds = 5;
entry_count++;
}
- sle_dma = sg_dma_address(sg);
- *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ append_dsd64(&cur_dsd, sg);
avail_dsds--;
}
ct_iocb->entry_count = entry_count;
@@ -2970,7 +3072,6 @@ qla82xx_start_scsi(srb_t *sp)
unsigned long flags;
struct scsi_cmnd *cmd;
uint32_t *clr_ptr;
- uint32_t index;
uint32_t handle;
uint16_t cnt;
uint16_t req_cnt;
@@ -2998,8 +3099,8 @@ qla82xx_start_scsi(srb_t *sp)
/* Send marker if required */
if (vha->marker_needed != 0) {
- if (qla2x00_marker(vha, req,
- rsp, 0, 0, MK_SYNC_ALL) != QLA_SUCCESS) {
+ if (qla2x00_marker(vha, ha->base_qpair,
+ 0, 0, MK_SYNC_ALL) != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x300c,
"qla2x00_marker failed for cmd=%p.\n", cmd);
return QLA_FUNCTION_FAILED;
@@ -3010,16 +3111,8 @@ qla82xx_start_scsi(srb_t *sp)
/* Acquire ring specific lock */
spin_lock_irqsave(&ha->hardware_lock, flags);
- /* Check for room in outstanding command list. */
- handle = req->current_outstanding_cmd;
- for (index = 1; index < req->num_outstanding_cmds; index++) {
- handle++;
- if (handle == req->num_outstanding_cmds)
- handle = 1;
- if (!req->outstanding_cmds[handle])
- break;
- }
- if (index == req->num_outstanding_cmds)
+ handle = qla2xxx_get_next_handle(req);
+ if (handle == 0)
goto queuing_error;
/* Map the sg table so we have an accurate count of sg entries needed */
@@ -3090,7 +3183,7 @@ sufficient_dsds:
goto queuing_error;
}
- ctx = sp->u.scmd.ctx =
+ ctx = sp->u.scmd.ct6_ctx =
mempool_alloc(ha->ctx_mempool, GFP_ATOMIC);
if (!ctx) {
ql_log(ql_log_fatal, vha, 0x3010,
@@ -3099,7 +3192,7 @@ sufficient_dsds:
}
memset(ctx, 0, sizeof(struct ct6_dsd));
- ctx->fcp_cmnd = dma_pool_alloc(ha->fcp_cmnd_dma_pool,
+ ctx->fcp_cmnd = dma_pool_zalloc(ha->fcp_cmnd_dma_pool,
GFP_ATOMIC, &ctx->fcp_cmnd_dma);
if (!ctx->fcp_cmnd) {
ql_log(ql_log_fatal, vha, 0x3011,
@@ -3152,7 +3245,6 @@ sufficient_dsds:
host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
/* build FCP_CMND IU */
- memset(ctx->fcp_cmnd, 0, sizeof(struct fcp_cmnd));
int_to_scsilun(cmd->device->lun, &ctx->fcp_cmnd->lun);
ctx->fcp_cmnd->additional_cdb_len = additional_cdb_len;
@@ -3173,10 +3265,8 @@ sufficient_dsds:
*fcp_dl = htonl((uint32_t)scsi_bufflen(cmd));
cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(ctx->fcp_cmnd_len);
- cmd_pkt->fcp_cmnd_dseg_address[0] =
- cpu_to_le32(LSD(ctx->fcp_cmnd_dma));
- cmd_pkt->fcp_cmnd_dseg_address[1] =
- cpu_to_le32(MSD(ctx->fcp_cmnd_dma));
+ put_unaligned_le64(ctx->fcp_cmnd_dma,
+ &cmd_pkt->fcp_cmnd_dseg_address);
sp->flags |= SRB_FCP_CMND_DMA_VALID;
cmd_pkt->byte_count = cpu_to_le32((uint32_t)scsi_bufflen(cmd));
@@ -3188,6 +3278,7 @@ sufficient_dsds:
cmd_pkt->entry_status = (uint8_t) rsp->id;
} else {
struct cmd_type_7 *cmd_pkt;
+
req_cnt = qla24xx_calc_iocbs(vha, tot_dsds);
if (req->cnt < (req_cnt + 2)) {
cnt = (uint16_t)RD_REG_DWORD_RELAXED(
@@ -3288,9 +3379,9 @@ queuing_error:
if (tot_dsds)
scsi_dma_unmap(cmd);
- if (sp->u.scmd.ctx) {
- mempool_free(sp->u.scmd.ctx, ha->ctx_mempool);
- sp->u.scmd.ctx = NULL;
+ if (sp->u.scmd.crc_ctx) {
+ mempool_free(sp->u.scmd.crc_ctx, ha->ctx_mempool);
+ sp->u.scmd.crc_ctx = NULL;
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -3392,15 +3483,13 @@ qla_nvme_ls(srb_t *sp, struct pt_ls4_request *cmd_pkt)
cmd_pkt->tx_dseg_count = 1;
cmd_pkt->tx_byte_count = nvme->u.nvme.cmd_len;
- cmd_pkt->dseg0_len = nvme->u.nvme.cmd_len;
- cmd_pkt->dseg0_address[0] = cpu_to_le32(LSD(nvme->u.nvme.cmd_dma));
- cmd_pkt->dseg0_address[1] = cpu_to_le32(MSD(nvme->u.nvme.cmd_dma));
+ cmd_pkt->dsd[0].length = nvme->u.nvme.cmd_len;
+ put_unaligned_le64(nvme->u.nvme.cmd_dma, &cmd_pkt->dsd[0].address);
cmd_pkt->rx_dseg_count = 1;
cmd_pkt->rx_byte_count = nvme->u.nvme.rsp_len;
- cmd_pkt->dseg1_len = nvme->u.nvme.rsp_len;
- cmd_pkt->dseg1_address[0] = cpu_to_le32(LSD(nvme->u.nvme.rsp_dma));
- cmd_pkt->dseg1_address[1] = cpu_to_le32(MSD(nvme->u.nvme.rsp_dma));
+ cmd_pkt->dsd[1].length = nvme->u.nvme.rsp_len;
+ put_unaligned_le64(nvme->u.nvme.rsp_dma, &cmd_pkt->dsd[1].address);
return rval;
}
@@ -3442,23 +3531,22 @@ qla24xx_prlo_iocb(srb_t *sp, struct logio_entry_24xx *logio)
int
qla2x00_start_sp(srb_t *sp)
{
- int rval;
+ int rval = QLA_SUCCESS;
scsi_qla_host_t *vha = sp->vha;
struct qla_hw_data *ha = vha->hw;
struct qla_qpair *qp = sp->qpair;
void *pkt;
unsigned long flags;
- rval = QLA_FUNCTION_FAILED;
spin_lock_irqsave(qp->qp_lock_ptr, flags);
pkt = __qla2x00_alloc_iocbs(sp->qpair, sp);
if (!pkt) {
+ rval = EAGAIN;
ql_log(ql_log_warn, vha, 0x700c,
"qla2x00_alloc_iocbs failed.\n");
goto done;
}
- rval = QLA_SUCCESS;
switch (sp->type) {
case SRB_LOGIN_CMD:
IS_FWI2_CAPABLE(ha) ?
@@ -3528,6 +3616,9 @@ qla2x00_start_sp(srb_t *sp)
break;
}
+ if (sp->start_timer)
+ add_timer(&sp->u.iocb_cmd.timer);
+
wmb();
qla2x00_start_iocbs(vha, qp->req);
done:
@@ -3540,7 +3631,7 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha,
struct cmd_bidir *cmd_pkt, uint32_t tot_dsds)
{
uint16_t avail_dsds;
- uint32_t *cur_dsd;
+ struct dsd64 *cur_dsd;
uint32_t req_data_len = 0;
uint32_t rsp_data_len = 0;
struct scatterlist *sg;
@@ -3549,8 +3640,7 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha,
struct bsg_job *bsg_job = sp->u.bsg_job;
/*Update entry type to indicate bidir command */
- *((uint32_t *)(&cmd_pkt->entry_type)) =
- cpu_to_le32(COMMAND_BIDIRECTIONAL);
+ put_unaligned_le32(COMMAND_BIDIRECTIONAL, &cmd_pkt->entry_type);
/* Set the transfer direction, in this set both flags
* Also set the BD_WRAP_BACK flag, firmware will take care
@@ -3576,13 +3666,12 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha,
* are bundled in continuation iocb
*/
avail_dsds = 1;
- cur_dsd = (uint32_t *)&cmd_pkt->fcp_data_dseg_address;
+ cur_dsd = &cmd_pkt->fcp_dsd;
index = 0;
for_each_sg(bsg_job->request_payload.sg_list, sg,
bsg_job->request_payload.sg_cnt, index) {
- dma_addr_t sle_dma;
cont_a64_entry_t *cont_pkt;
/* Allocate additional continuation packets */
@@ -3591,14 +3680,11 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha,
* 5 DSDS
*/
cont_pkt = qla2x00_prep_cont_type1_iocb(vha, vha->req);
- cur_dsd = (uint32_t *) cont_pkt->dseg_0_address;
+ cur_dsd = cont_pkt->dsd;
avail_dsds = 5;
entry_count++;
}
- sle_dma = sg_dma_address(sg);
- *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ append_dsd64(&cur_dsd, sg);
avail_dsds--;
}
/* For read request DSD will always goes to continuation IOCB
@@ -3608,7 +3694,6 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha,
*/
for_each_sg(bsg_job->reply_payload.sg_list, sg,
bsg_job->reply_payload.sg_cnt, index) {
- dma_addr_t sle_dma;
cont_a64_entry_t *cont_pkt;
/* Allocate additional continuation packets */
@@ -3617,14 +3702,11 @@ qla25xx_build_bidir_iocb(srb_t *sp, struct scsi_qla_host *vha,
* 5 DSDS
*/
cont_pkt = qla2x00_prep_cont_type1_iocb(vha, vha->req);
- cur_dsd = (uint32_t *) cont_pkt->dseg_0_address;
+ cur_dsd = cont_pkt->dsd;
avail_dsds = 5;
entry_count++;
}
- sle_dma = sg_dma_address(sg);
- *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ append_dsd64(&cur_dsd, sg);
avail_dsds--;
}
/* This value should be same as number of IOCB required for this cmd */
@@ -3638,7 +3720,6 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds)
struct qla_hw_data *ha = vha->hw;
unsigned long flags;
uint32_t handle;
- uint32_t index;
uint16_t req_cnt;
uint16_t cnt;
uint32_t *clr_ptr;
@@ -3654,8 +3735,8 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds)
/* Send marker if required */
if (vha->marker_needed != 0) {
- if (qla2x00_marker(vha, req,
- rsp, 0, 0, MK_SYNC_ALL) != QLA_SUCCESS)
+ if (qla2x00_marker(vha, ha->base_qpair,
+ 0, 0, MK_SYNC_ALL) != QLA_SUCCESS)
return EXT_STATUS_MAILBOX;
vha->marker_needed = 0;
}
@@ -3663,17 +3744,8 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds)
/* Acquire ring specific lock */
spin_lock_irqsave(&ha->hardware_lock, flags);
- /* Check for room in outstanding command list. */
- handle = req->current_outstanding_cmd;
- for (index = 1; index < req->num_outstanding_cmds; index++) {
- handle++;
- if (handle == req->num_outstanding_cmds)
- handle = 1;
- if (!req->outstanding_cmds[handle])
- break;
- }
-
- if (index == req->num_outstanding_cmds) {
+ handle = qla2xxx_get_next_handle(req);
+ if (handle == 0) {
rval = EXT_STATUS_BUSY;
goto queuing_error;
}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 7902ed2a4864..49991573735a 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -23,6 +23,14 @@ static void qla2x00_status_cont_entry(struct rsp_que *, sts_cont_entry_t *);
static int qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *,
sts_entry_t *);
+const char *const port_state_str[] = {
+ "Unknown",
+ "UNCONFIGURED",
+ "DEAD",
+ "LOST",
+ "ONLINE"
+};
+
/**
* qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
* @irq: interrupt number
@@ -41,7 +49,7 @@ qla2100_intr_handler(int irq, void *dev_id)
int status;
unsigned long iter;
uint16_t hccr;
- uint16_t mb[4];
+ uint16_t mb[8];
struct rsp_que *rsp;
unsigned long flags;
@@ -160,7 +168,7 @@ qla2300_intr_handler(int irq, void *dev_id)
unsigned long iter;
uint32_t stat;
uint16_t hccr;
- uint16_t mb[4];
+ uint16_t mb[8];
struct rsp_que *rsp;
struct qla_hw_data *ha;
unsigned long flags;
@@ -366,7 +374,7 @@ qla2x00_get_link_speed_str(struct qla_hw_data *ha, uint16_t speed)
static const char *const link_speeds[] = {
"1", "2", "?", "4", "8", "16", "32", "10"
};
-#define QLA_LAST_SPEED 7
+#define QLA_LAST_SPEED (ARRAY_SIZE(link_speeds) - 1)
if (IS_QLA2100(ha) || IS_QLA2200(ha))
return link_speeds[0];
@@ -708,12 +716,15 @@ skip_rio:
break;
case MBA_SYSTEM_ERR: /* System Error */
- mbx = (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) ?
+ mbx = (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha)) ?
RD_REG_WORD(&reg24->mailbox7) : 0;
ql_log(ql_log_warn, vha, 0x5003,
"ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh "
"mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx);
-
+ ha->fw_dump_mpi =
+ (IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
+ RD_REG_WORD(&reg24->mailbox7) & BIT_8;
ha->isp_ops->fw_dump(vha, 1);
ha->flags.fw_init_done = 0;
QLA_FW_STOPPED(ha);
@@ -765,7 +776,6 @@ skip_rio:
case MBA_LOOP_INIT_ERR:
ql_log(ql_log_warn, vha, 0x5090,
"LOOP INIT ERROR (%x).\n", mb[1]);
- ha->isp_ops->fw_dump(vha, 1);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
break;
@@ -834,8 +844,10 @@ skip_rio:
* Restore for Physical Port only
*/
if (!vha->vp_idx) {
- if (ha->flags.fawwpn_enabled) {
+ if (ha->flags.fawwpn_enabled &&
+ (ha->current_topology == ISP_CFG_F)) {
void *wwpn = ha->init_cb->port_name;
+
memcpy(vha->port_name, wwpn, WWN_SIZE);
fc_host_port_name(vha->host) =
wwn_to_u64(vha->port_name);
@@ -1106,10 +1118,9 @@ global_port_update:
struct event_arg ea;
memset(&ea, 0, sizeof(ea));
- ea.event = FCME_RSCN;
ea.id.b24 = rscn_entry;
ea.id.b.rsvd_1 = rscn_entry >> 24;
- qla2x00_fcport_event_handler(vha, &ea);
+ qla2x00_handle_rscn(vha, &ea);
qla2x00_post_aen_work(vha, FCH_EVT_RSCN, rscn_entry);
}
break;
@@ -1371,7 +1382,7 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
le16_to_cpu(mbx->status_flags));
ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5029,
- (uint8_t *)mbx, sizeof(*mbx));
+ mbx, sizeof(*mbx));
goto logio_done;
}
@@ -1501,7 +1512,7 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
if (comp_status == CS_DATA_UNDERRUN) {
res = DID_OK << 16;
bsg_reply->reply_payload_rcv_len =
- le16_to_cpu(((sts_entry_t *)pkt)->rsp_info_len);
+ le16_to_cpu(pkt->rsp_info_len);
ql_log(ql_log_warn, vha, 0x5048,
"CT pass-through-%s error comp_status=0x%x total_byte=0x%x.\n",
@@ -1515,7 +1526,7 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
bsg_reply->reply_payload_rcv_len = 0;
}
ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035,
- (uint8_t *)pkt, sizeof(*pkt));
+ pkt, sizeof(*pkt));
} else {
res = DID_OK << 16;
bsg_reply->reply_payload_rcv_len =
@@ -1590,8 +1601,8 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
}
comp_status = fw_status[0] = le16_to_cpu(pkt->comp_status);
- fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1);
- fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2);
+ fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx *)pkt)->error_subcode_1);
+ fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx *)pkt)->error_subcode_2);
if (iocb_type == ELS_IOCB_TYPE) {
els = &sp->u.iocb_cmd;
@@ -1612,7 +1623,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
res = DID_ERROR << 16;
}
}
- ql_log(ql_log_info, vha, 0x503f,
+ ql_dbg(ql_dbg_user, vha, 0x503f,
"ELS IOCB Done -%s error hdl=%x comp_status=0x%x error subcode 1=0x%x error subcode 2=0x%x total_byte=0x%x\n",
type, sp->handle, comp_status, fw_status[1], fw_status[2],
le16_to_cpu(((struct els_sts_entry_24xx *)
@@ -1655,7 +1666,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
memcpy(bsg_job->reply + sizeof(struct fc_bsg_reply),
fw_status, sizeof(fw_status));
ql_dump_buffer(ql_dbg_user + ql_dbg_buffer, vha, 0x5056,
- (uint8_t *)pkt, sizeof(*pkt));
+ pkt, sizeof(*pkt));
}
else {
res = DID_OK << 16;
@@ -1699,7 +1710,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
fcport->d_id.b.area, fcport->d_id.b.al_pa,
logio->entry_status);
ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x504d,
- (uint8_t *)logio, sizeof(*logio));
+ logio, sizeof(*logio));
goto logio_done;
}
@@ -1714,6 +1725,15 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
vha->hw->exch_starvation = 0;
data[0] = MBS_COMMAND_COMPLETE;
+
+ if (sp->type == SRB_PRLI_CMD) {
+ lio->u.logio.iop[0] =
+ le32_to_cpu(logio->io_parameter[0]);
+ lio->u.logio.iop[1] =
+ le32_to_cpu(logio->io_parameter[1]);
+ goto logio_done;
+ }
+
if (sp->type != SRB_LOGIN_CMD)
goto logio_done;
@@ -1836,8 +1856,8 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk)
}
if (iocb->u.tmf.data != QLA_SUCCESS)
- ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5055,
- (uint8_t *)sts, sizeof(*sts));
+ ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, sp->vha, 0x5055,
+ sts, sizeof(*sts));
sp->done(sp, 0);
}
@@ -1959,6 +1979,52 @@ static void qla_ctrlvp_completed(scsi_qla_host_t *vha, struct req_que *req,
sp->done(sp, rval);
}
+/* Process a single response queue entry. */
+static void qla2x00_process_response_entry(struct scsi_qla_host *vha,
+ struct rsp_que *rsp,
+ sts_entry_t *pkt)
+{
+ sts21_entry_t *sts21_entry;
+ sts22_entry_t *sts22_entry;
+ uint16_t handle_cnt;
+ uint16_t cnt;
+
+ switch (pkt->entry_type) {
+ case STATUS_TYPE:
+ qla2x00_status_entry(vha, rsp, pkt);
+ break;
+ case STATUS_TYPE_21:
+ sts21_entry = (sts21_entry_t *)pkt;
+ handle_cnt = sts21_entry->handle_count;
+ for (cnt = 0; cnt < handle_cnt; cnt++)
+ qla2x00_process_completed_request(vha, rsp->req,
+ sts21_entry->handle[cnt]);
+ break;
+ case STATUS_TYPE_22:
+ sts22_entry = (sts22_entry_t *)pkt;
+ handle_cnt = sts22_entry->handle_count;
+ for (cnt = 0; cnt < handle_cnt; cnt++)
+ qla2x00_process_completed_request(vha, rsp->req,
+ sts22_entry->handle[cnt]);
+ break;
+ case STATUS_CONT_TYPE:
+ qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt);
+ break;
+ case MBX_IOCB_TYPE:
+ qla2x00_mbx_iocb_entry(vha, rsp->req, (struct mbx_entry *)pkt);
+ break;
+ case CT_IOCB_TYPE:
+ qla2x00_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE);
+ break;
+ default:
+ /* Type Not Supported. */
+ ql_log(ql_log_warn, vha, 0x504a,
+ "Received unknown response pkt type %x entry status=%x.\n",
+ pkt->entry_type, pkt->entry_status);
+ break;
+ }
+}
+
/**
* qla2x00_process_response_queue() - Process response queue entries.
* @rsp: response queue
@@ -1970,8 +2036,6 @@ qla2x00_process_response_queue(struct rsp_que *rsp)
struct qla_hw_data *ha = rsp->hw;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
sts_entry_t *pkt;
- uint16_t handle_cnt;
- uint16_t cnt;
vha = pci_get_drvdata(ha->pdev);
@@ -1996,42 +2060,7 @@ qla2x00_process_response_queue(struct rsp_que *rsp)
continue;
}
- switch (pkt->entry_type) {
- case STATUS_TYPE:
- qla2x00_status_entry(vha, rsp, pkt);
- break;
- case STATUS_TYPE_21:
- handle_cnt = ((sts21_entry_t *)pkt)->handle_count;
- for (cnt = 0; cnt < handle_cnt; cnt++) {
- qla2x00_process_completed_request(vha, rsp->req,
- ((sts21_entry_t *)pkt)->handle[cnt]);
- }
- break;
- case STATUS_TYPE_22:
- handle_cnt = ((sts22_entry_t *)pkt)->handle_count;
- for (cnt = 0; cnt < handle_cnt; cnt++) {
- qla2x00_process_completed_request(vha, rsp->req,
- ((sts22_entry_t *)pkt)->handle[cnt]);
- }
- break;
- case STATUS_CONT_TYPE:
- qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt);
- break;
- case MBX_IOCB_TYPE:
- qla2x00_mbx_iocb_entry(vha, rsp->req,
- (struct mbx_entry *)pkt);
- break;
- case CT_IOCB_TYPE:
- qla2x00_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE);
- break;
- default:
- /* Type Not Supported. */
- ql_log(ql_log_warn, vha, 0x504a,
- "Received unknown response pkt type %x "
- "entry status=%x.\n",
- pkt->entry_type, pkt->entry_status);
- break;
- }
+ qla2x00_process_response_entry(vha, rsp, pkt);
((response_t *)pkt)->signature = RESPONSE_PROCESSED;
wmb();
}
@@ -2226,10 +2255,8 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt,
struct bsg_job *bsg_job = NULL;
struct fc_bsg_request *bsg_request;
struct fc_bsg_reply *bsg_reply;
- sts_entry_t *sts;
- struct sts_entry_24xx *sts24;
- sts = (sts_entry_t *) pkt;
- sts24 = (struct sts_entry_24xx *) pkt;
+ sts_entry_t *sts = pkt;
+ struct sts_entry_24xx *sts24 = pkt;
/* Validate handle. */
if (index >= req->num_outstanding_cmds) {
@@ -2375,8 +2402,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
srb_t *sp;
fc_port_t *fcport;
struct scsi_cmnd *cp;
- sts_entry_t *sts;
- struct sts_entry_24xx *sts24;
+ sts_entry_t *sts = pkt;
+ struct sts_entry_24xx *sts24 = pkt;
uint16_t comp_status;
uint16_t scsi_status;
uint16_t ox_id;
@@ -2394,8 +2421,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
uint16_t state_flags = 0;
uint16_t retry_delay = 0;
- sts = (sts_entry_t *) pkt;
- sts24 = (struct sts_entry_24xx *) pkt;
if (IS_FWI2_CAPABLE(ha)) {
comp_status = le16_to_cpu(sts24->comp_status);
scsi_status = le16_to_cpu(sts24->scsi_status) & SS_MASK;
@@ -2508,7 +2533,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
/* Valid values of the retry delay timer are 0x1-0xffef */
if (sts24->retry_delay > 0 && sts24->retry_delay < 0xfff1) {
retry_delay = sts24->retry_delay & 0x3fff;
- ql_dbg(ql_dbg_io, vha, 0x3033,
+ ql_dbg(ql_dbg_io, sp->vha, 0x3033,
"%s: scope=%#x retry_delay=%#x\n", __func__,
sts24->retry_delay >> 14, retry_delay);
}
@@ -2695,7 +2720,7 @@ check_scsi_status:
"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[atomic_read(&fcport->state)],
+ port_state_str[FCS_ONLINE],
comp_status);
qla2x00_mark_device_lost(fcport->vha, fcport, 1, 1);
@@ -2725,6 +2750,17 @@ check_scsi_status:
cp->device->vendor);
break;
+ case CS_DMA:
+ ql_log(ql_log_info, fcport->vha, 0x3022,
+ "CS_DMA error: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu portid=%06x oxid=0x%x cdb=%10phN len=0x%x rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
+ comp_status, scsi_status, res, vha->host_no,
+ cp->device->id, cp->device->lun, fcport->d_id.b24,
+ ox_id, cp->cmnd, scsi_bufflen(cp), rsp_info_len,
+ resid_len, fw_resid_len, sp, cp);
+ ql_dump_buffer(ql_dbg_tgt + ql_dbg_verbose, vha, 0xe0ee,
+ pkt, sizeof(*sts24));
+ res = DID_ERROR << 16;
+ break;
default:
res = DID_ERROR << 16;
break;
@@ -2993,7 +3029,8 @@ process_err:
qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE);
break;
case ABTS_RECV_24XX:
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha)) {
/* ensure that the ATIO queue is empty */
qlt_handle_abts_recv(vha, rsp,
(response_t *)pkt);
@@ -3051,6 +3088,7 @@ process_err:
/* Adjust ring index */
if (IS_P3P_TYPE(ha)) {
struct device_reg_82xx __iomem *reg = &ha->iobase->isp82;
+
WRT_REG_DWORD(&reg->rsp_q_out[0], rsp->ring_index);
} else {
WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index);
@@ -3066,7 +3104,7 @@ qla2xxx_check_risc_status(scsi_qla_host_t *vha)
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
- !IS_QLA27XX(ha))
+ !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return;
rval = QLA_SUCCESS;
@@ -3410,7 +3448,8 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
min_vecs++;
}
- if (USER_CTRL_IRQ(ha) || !shost_use_blk_mq(vha->host)) {
+ if (USER_CTRL_IRQ(ha) || !ha->mqiobase ||
+ !shost_use_blk_mq(vha->host)) {
/* user wants to control IRQ setting for target mode */
ret = pci_alloc_irq_vectors(ha->pdev, min_vecs,
ha->msix_count, PCI_IRQ_MSIX);
@@ -3426,10 +3465,8 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
ha->msix_count, ret);
goto msix_out;
} else if (ret < ha->msix_count) {
- ql_log(ql_log_warn, vha, 0x00c6,
- "MSI-X: Failed to enable support "
- "with %d vectors, using %d vectors.\n",
- ha->msix_count, ret);
+ ql_log(ql_log_info, vha, 0x00c6,
+ "MSI-X: Using %d vectors\n", ret);
ha->msix_count = ret;
/* Recalculate queue values */
if (ha->mqiobase && (ql2xmqsupport || ql2xnvmeenable)) {
@@ -3452,7 +3489,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
ql_log(ql_log_fatal, vha, 0x00c8,
"Failed to allocate memory for ha->msix_entries.\n");
ret = -ENOMEM;
- goto msix_out;
+ goto free_irqs;
}
ha->flags.msix_enabled = 1;
@@ -3516,7 +3553,7 @@ msix_register_fail:
}
/* Enable MSI-X vector for response queue update for queue 0 */
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
if (ha->msixbase && ha->mqiobase &&
(ha->max_rsp_queues > 1 || ha->max_req_queues > 1 ||
ql2xmqsupport))
@@ -3535,6 +3572,10 @@ msix_register_fail:
msix_out:
return ret;
+
+free_irqs:
+ pci_free_irq_vectors(ha->pdev);
+ goto msix_out;
}
int
@@ -3547,7 +3588,7 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp)
/* If possible, enable MSI-X. */
if (ql2xenablemsix == 0 || (!IS_QLA2432(ha) && !IS_QLA2532(ha) &&
!IS_QLA8432(ha) && !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) &&
- !IS_QLAFX00(ha) && !IS_QLA27XX(ha)))
+ !IS_QLAFX00(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha)))
goto skip_msi;
if (ql2xenablemsix == 2)
@@ -3586,7 +3627,7 @@ skip_msix:
if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) &&
!IS_QLA8001(ha) && !IS_P3P_TYPE(ha) && !IS_QLAFX00(ha) &&
- !IS_QLA27XX(ha))
+ !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
goto skip_msi;
ret = pci_alloc_irq_vectors(ha->pdev, 1, 1, PCI_IRQ_MSI);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index f753aa495753..4c858e2d0ea8 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -253,21 +253,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
if ((!abort_active && io_lock_on) || IS_NOPOLLING_TYPE(ha)) {
set_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
- if (IS_P3P_TYPE(ha)) {
- if (RD_REG_DWORD(&reg->isp82.hint) &
- HINT_MBX_INT_PENDING) {
- ha->flags.mbox_busy = 0;
- spin_unlock_irqrestore(&ha->hardware_lock,
- flags);
-
- atomic_dec(&ha->num_pend_mbx_stage2);
- ql_dbg(ql_dbg_mbx, vha, 0x1010,
- "Pending mailbox timeout, exiting.\n");
- rval = QLA_FUNCTION_TIMEOUT;
- goto premature_exit;
- }
+ if (IS_P3P_TYPE(ha))
WRT_REG_DWORD(&reg->isp82.hint, HINT_MBX_INT_PENDING);
- } else if (IS_FWI2_CAPABLE(ha))
+ else if (IS_FWI2_CAPABLE(ha))
WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_SET_HOST_INT);
else
WRT_REG_WORD(&reg->isp.hccr, HCCR_SET_HOST_INT);
@@ -394,8 +382,12 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
goto premature_exit;
}
- if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE)
+ if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE) {
+ ql_dbg(ql_dbg_mbx, vha, 0x11ff,
+ "mb_out[0] = %#x <> %#x\n", ha->mailbox_out[0],
+ MBS_COMMAND_COMPLETE);
rval = QLA_FUNCTION_FAILED;
+ }
/* Load return mailbox registers. */
iptr2 = mcp->mb;
@@ -567,9 +559,9 @@ mbx_done:
mcp->mb[0]);
} else if (rval) {
if (ql2xextended_error_logging & (ql_dbg_disc|ql_dbg_mbx)) {
- pr_warn("%s [%s]-%04x:%ld: **** Failed", QL_MSGHDR,
+ pr_warn("%s [%s]-%04x:%ld: **** Failed=%x", QL_MSGHDR,
dev_name(&ha->pdev->dev), 0x1020+0x800,
- vha->host_no);
+ vha->host_no, rval);
mboxes = mcp->in_mb;
cnt = 4;
for (i = 0; i < ha->mbx_count && cnt; i++, mboxes >>= 1)
@@ -634,14 +626,15 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr,
mcp->out_mb |= MBX_4;
}
- mcp->in_mb = MBX_0;
+ mcp->in_mb = MBX_1|MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_mbx, vha, 0x1023,
- "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+ "Failed=%x mb[0]=%x mb[1]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1]);
} else {
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1024,
"Done %s.\n", __func__);
@@ -656,7 +649,7 @@ static inline uint16_t qla25xx_set_sfp_lr_dist(struct qla_hw_data *ha)
{
uint16_t mb4 = BIT_0;
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
mb4 |= ha->long_range_distance << LR_DIST_FW_POS;
return mb4;
@@ -666,7 +659,7 @@ static inline uint16_t qla25xx_set_nvr_lr_dist(struct qla_hw_data *ha)
{
uint16_t mb4 = BIT_0;
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
struct nvram_81xx *nv = ha->nvram;
mb4 |= LR_DIST_FW_FIELD(nv->enhanced_features);
@@ -711,7 +704,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
mcp->mb[4] = 0;
ha->flags.using_lr_setting = 0;
if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
- IS_QLA27XX(ha)) {
+ IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
if (ql2xautodetectsfp) {
if (ha->flags.detected_lr_sfp) {
mcp->mb[4] |=
@@ -730,19 +723,20 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
}
}
- if (ql2xnvmeenable && IS_QLA27XX(ha))
+ if (ql2xnvmeenable && (IS_QLA27XX(ha) || IS_QLA28XX(ha)))
mcp->mb[4] |= NVME_ENABLE_FLAG;
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
struct nvram_81xx *nv = ha->nvram;
/* set minimum speed if specified in nvram */
- if (nv->min_link_speed >= 2 &&
- nv->min_link_speed <= 5) {
+ if (nv->min_supported_speed >= 2 &&
+ nv->min_supported_speed <= 5) {
mcp->mb[4] |= BIT_4;
- mcp->mb[11] = nv->min_link_speed;
+ mcp->mb[11] |= nv->min_supported_speed & 0xF;
mcp->out_mb |= MBX_11;
mcp->in_mb |= BIT_5;
- vha->min_link_speed_feat = nv->min_link_speed;
+ vha->min_supported_speed =
+ nv->min_supported_speed;
}
}
@@ -770,34 +764,39 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_mbx, vha, 0x1026,
"Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
- } else {
- if (IS_FWI2_CAPABLE(ha)) {
- ha->fw_ability_mask = mcp->mb[3] << 16 | mcp->mb[2];
- ql_dbg(ql_dbg_mbx, vha, 0x119a,
- "fw_ability_mask=%x.\n", ha->fw_ability_mask);
- ql_dbg(ql_dbg_mbx, vha, 0x1027,
- "exchanges=%x.\n", mcp->mb[1]);
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
- ha->max_speed_sup = mcp->mb[2] & BIT_0;
- ql_dbg(ql_dbg_mbx, vha, 0x119b,
- "Maximum speed supported=%s.\n",
- ha->max_speed_sup ? "32Gps" : "16Gps");
- if (vha->min_link_speed_feat) {
- ha->min_link_speed = mcp->mb[5];
- ql_dbg(ql_dbg_mbx, vha, 0x119c,
- "Minimum speed set=%s.\n",
- mcp->mb[5] == 5 ? "32Gps" :
- mcp->mb[5] == 4 ? "16Gps" :
- mcp->mb[5] == 3 ? "8Gps" :
- mcp->mb[5] == 2 ? "4Gps" :
- "unknown");
- }
- }
+ return rval;
+ }
+
+ if (!IS_FWI2_CAPABLE(ha))
+ goto done;
+
+ ha->fw_ability_mask = mcp->mb[3] << 16 | mcp->mb[2];
+ ql_dbg(ql_dbg_mbx, vha, 0x119a,
+ "fw_ability_mask=%x.\n", ha->fw_ability_mask);
+ ql_dbg(ql_dbg_mbx, vha, 0x1027, "exchanges=%x.\n", mcp->mb[1]);
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ ha->max_supported_speed = mcp->mb[2] & (BIT_0|BIT_1);
+ ql_dbg(ql_dbg_mbx, vha, 0x119b, "max_supported_speed=%s.\n",
+ ha->max_supported_speed == 0 ? "16Gps" :
+ ha->max_supported_speed == 1 ? "32Gps" :
+ ha->max_supported_speed == 2 ? "64Gps" : "unknown");
+ if (vha->min_supported_speed) {
+ ha->min_supported_speed = mcp->mb[5] &
+ (BIT_0 | BIT_1 | BIT_2);
+ ql_dbg(ql_dbg_mbx, vha, 0x119c,
+ "min_supported_speed=%s.\n",
+ ha->min_supported_speed == 6 ? "64Gps" :
+ ha->min_supported_speed == 5 ? "32Gps" :
+ ha->min_supported_speed == 4 ? "16Gps" :
+ ha->min_supported_speed == 3 ? "8Gps" :
+ ha->min_supported_speed == 2 ? "4Gps" : "unknown");
}
- ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028,
- "Done.\n");
}
+done:
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1028,
+ "Done %s.\n", __func__);
+
return rval;
}
@@ -1053,10 +1052,10 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha)
mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8;
if (IS_FWI2_CAPABLE(ha))
mcp->in_mb |= MBX_17|MBX_16|MBX_15;
- if (IS_QLA27XX(ha))
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
mcp->in_mb |=
MBX_25|MBX_24|MBX_23|MBX_22|MBX_21|MBX_20|MBX_19|MBX_18|
- MBX_14|MBX_13|MBX_11|MBX_10|MBX_9|MBX_8;
+ MBX_14|MBX_13|MBX_11|MBX_10|MBX_9|MBX_8|MBX_7;
mcp->flags = 0;
mcp->tov = MBX_TOV_SECONDS;
@@ -1112,6 +1111,9 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha)
if ((ha->fw_attributes_h &
(FW_ATTR_H_NVME | FW_ATTR_H_NVME_UPDATED)) &&
ql2xnvmeenable) {
+ if (ha->fw_attributes_h & FW_ATTR_H_NVME_FBURST)
+ vha->flags.nvme_first_burst = 1;
+
vha->flags.nvme_enabled = 1;
ql_log(ql_log_info, vha, 0xd302,
"%s: FC-NVMe is Enabled (0x%x)\n",
@@ -1119,7 +1121,10 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha)
}
}
- if (IS_QLA27XX(ha)) {
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ ha->serdes_version[0] = mcp->mb[7] & 0xff;
+ ha->serdes_version[1] = mcp->mb[8] >> 8;
+ ha->serdes_version[2] = mcp->mb[8] & 0xff;
ha->mpi_version[0] = mcp->mb[10] & 0xff;
ha->mpi_version[1] = mcp->mb[11] >> 8;
ha->mpi_version[2] = mcp->mb[11] & 0xff;
@@ -1130,6 +1135,13 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha)
ha->fw_shared_ram_end = (mcp->mb[21] << 16) | mcp->mb[20];
ha->fw_ddr_ram_start = (mcp->mb[23] << 16) | mcp->mb[22];
ha->fw_ddr_ram_end = (mcp->mb[25] << 16) | mcp->mb[24];
+ if (IS_QLA28XX(ha)) {
+ if (mcp->mb[16] & BIT_10) {
+ ql_log(ql_log_info, vha, 0xffff,
+ "FW support secure flash updates\n");
+ ha->flags.secure_fw = 1;
+ }
+ }
}
failed:
@@ -1510,16 +1522,12 @@ qla2x00_abort_target(struct fc_port *fcport, uint64_t l, int tag)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
scsi_qla_host_t *vha;
- struct req_que *req;
- struct rsp_que *rsp;
vha = fcport->vha;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x103e,
"Entered %s.\n", __func__);
- req = vha->hw->req_q_map[0];
- rsp = req->rsp;
mcp->mb[0] = MBC_ABORT_TARGET;
mcp->out_mb = MBX_9|MBX_2|MBX_1|MBX_0;
if (HAS_EXTENDED_IDS(vha->hw)) {
@@ -1542,7 +1550,7 @@ qla2x00_abort_target(struct fc_port *fcport, uint64_t l, int tag)
}
/* Issue marker IOCB. */
- rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, 0,
+ rval2 = qla2x00_marker(vha, vha->hw->base_qpair, fcport->loop_id, 0,
MK_SYNC_ID);
if (rval2 != QLA_SUCCESS) {
ql_dbg(ql_dbg_mbx, vha, 0x1040,
@@ -1562,16 +1570,12 @@ qla2x00_lun_reset(struct fc_port *fcport, uint64_t l, int tag)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
scsi_qla_host_t *vha;
- struct req_que *req;
- struct rsp_que *rsp;
vha = fcport->vha;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1042,
"Entered %s.\n", __func__);
- req = vha->hw->req_q_map[0];
- rsp = req->rsp;
mcp->mb[0] = MBC_LUN_RESET;
mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0;
if (HAS_EXTENDED_IDS(vha->hw))
@@ -1591,7 +1595,7 @@ qla2x00_lun_reset(struct fc_port *fcport, uint64_t l, int tag)
}
/* Issue marker IOCB. */
- rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, l,
+ rval2 = qla2x00_marker(vha, vha->hw->base_qpair, fcport->loop_id, l,
MK_SYNC_ID_LUN);
if (rval2 != QLA_SUCCESS) {
ql_dbg(ql_dbg_mbx, vha, 0x1044,
@@ -1643,7 +1647,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
if (IS_FWI2_CAPABLE(vha->hw))
mcp->in_mb |= MBX_19|MBX_18|MBX_17|MBX_16;
- if (IS_QLA27XX(vha->hw))
+ if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw))
mcp->in_mb |= MBX_15;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
@@ -1697,7 +1701,7 @@ qla2x00_get_adapter_id(scsi_qla_host_t *vha, uint16_t *id, uint8_t *al_pa,
}
}
- if (IS_QLA27XX(vha->hw))
+ if (IS_QLA27XX(vha->hw) || IS_QLA28XX(vha->hw))
vha->bbcr = mcp->mb[15];
}
@@ -1813,7 +1817,7 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
}
/* 1 and 2 should normally be captured. */
mcp->in_mb = MBX_2|MBX_1|MBX_0;
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
/* mb3 is additional info about the installed SFP. */
mcp->in_mb |= MBX_3;
mcp->buf_size = size;
@@ -1824,10 +1828,20 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
if (rval != QLA_SUCCESS) {
/*EMPTY*/
ql_dbg(ql_dbg_mbx, vha, 0x104d,
- "Failed=%x mb[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x,.\n",
+ "Failed=%x mb[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x.\n",
rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3]);
+ if (ha->init_cb) {
+ ql_dbg(ql_dbg_mbx, vha, 0x104d, "init_cb:\n");
+ ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha,
+ 0x0104d, ha->init_cb, sizeof(*ha->init_cb));
+ }
+ if (ha->ex_init_cb && ha->ex_init_cb->ex_version) {
+ ql_dbg(ql_dbg_mbx, vha, 0x104d, "ex_init_cb:\n");
+ ql_dump_buffer(ql_dbg_init + ql_dbg_verbose, vha,
+ 0x0104d, ha->ex_init_cb, sizeof(*ha->ex_init_cb));
+ }
} else {
- if (IS_QLA27XX(ha)) {
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
if (mcp->mb[2] == 6 || mcp->mb[3] == 2)
ql_dbg(ql_dbg_mbx, vha, 0x119d,
"Invalid SFP/Validation Failed\n");
@@ -2011,7 +2025,7 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
/* Passback COS information. */
fcport->supported_classes = (pd->options & BIT_4) ?
- FC_COS_CLASS2: FC_COS_CLASS3;
+ FC_COS_CLASS2 : FC_COS_CLASS3;
}
gpd_error_out:
@@ -2081,7 +2095,7 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states)
/*EMPTY*/
ql_dbg(ql_dbg_mbx, vha, 0x1055, "Failed=%x.\n", rval);
} else {
- if (IS_QLA27XX(ha)) {
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
if (mcp->mb[2] == 6 || mcp->mb[3] == 2)
ql_dbg(ql_dbg_mbx, vha, 0x119e,
"Invalid SFP/Validation Failed\n");
@@ -2246,10 +2260,7 @@ qla2x00_lip_reset(scsi_qla_host_t *vha)
mcp->out_mb = MBX_2|MBX_1|MBX_0;
} else if (IS_FWI2_CAPABLE(vha->hw)) {
mcp->mb[0] = MBC_LIP_FULL_LOGIN;
- if (N2N_TOPO(vha->hw))
- mcp->mb[1] = BIT_4; /* re-init */
- else
- mcp->mb[1] = BIT_6; /* LIP */
+ mcp->mb[1] = BIT_4;
mcp->mb[2] = 0;
mcp->mb[3] = vha->hw->loop_reset_delay;
mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
@@ -2759,7 +2770,7 @@ qla2x00_full_login_lip(scsi_qla_host_t *vha)
"Entered %s.\n", __func__);
mcp->mb[0] = MBC_LIP_FULL_LOGIN;
- mcp->mb[1] = IS_FWI2_CAPABLE(vha->hw) ? BIT_3 : 0;
+ mcp->mb[1] = IS_FWI2_CAPABLE(vha->hw) ? BIT_4 : 0;
mcp->mb[2] = 0;
mcp->mb[3] = 0;
mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0;
@@ -2867,7 +2878,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha)
mcp->mb[0] = MBC_GET_RESOURCE_COUNTS;
mcp->out_mb = MBX_0;
mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
- if (IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw) || IS_QLA27XX(vha->hw))
+ if (IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
+ IS_QLA27XX(ha) || IS_QLA28XX(ha))
mcp->in_mb |= MBX_12;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
@@ -2892,7 +2904,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha)
ha->orig_fw_iocb_count = mcp->mb[10];
if (ha->flags.npiv_supported)
ha->max_npiv_vports = mcp->mb[11];
- if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+ if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha))
ha->fw_max_fcf_count = mcp->mb[12];
}
@@ -3186,7 +3199,6 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
scsi_qla_host_t *vha;
struct qla_hw_data *ha;
struct req_que *req;
- struct rsp_que *rsp;
struct qla_qpair *qpair;
vha = fcport->vha;
@@ -3199,10 +3211,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
if (vha->vp_idx && vha->qpair) {
/* NPIV port */
qpair = vha->qpair;
- rsp = qpair->rsp;
req = qpair->req;
- } else {
- rsp = req->rsp;
}
tsk = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &tsk_dma);
@@ -3259,8 +3268,8 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
}
/* Issue marker IOCB. */
- rval2 = qla2x00_marker(vha, req, rsp, fcport->loop_id, l,
- type == TCF_LUN_RESET ? MK_SYNC_ID_LUN: MK_SYNC_ID);
+ rval2 = qla2x00_marker(vha, ha->base_qpair, fcport->loop_id, l,
+ type == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
if (rval2 != QLA_SUCCESS) {
ql_dbg(ql_dbg_mbx, vha, 0x1099,
"Failed to issue marker IOCB (%x).\n", rval2);
@@ -3335,7 +3344,7 @@ qla2x00_write_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t data)
mbx_cmd_t *mcp = &mc;
if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) &&
- !IS_QLA27XX(vha->hw))
+ !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw))
return QLA_FUNCTION_FAILED;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1182,
@@ -3374,7 +3383,7 @@ qla2x00_read_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t *data)
mbx_cmd_t *mcp = &mc;
if (!IS_QLA25XX(vha->hw) && !IS_QLA2031(vha->hw) &&
- !IS_QLA27XX(vha->hw))
+ !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw))
return QLA_FUNCTION_FAILED;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1185,
@@ -3643,7 +3652,8 @@ qla2x00_enable_fce_trace(scsi_qla_host_t *vha, dma_addr_t fce_dma,
"Entered %s.\n", __func__);
if (!IS_QLA25XX(vha->hw) && !IS_QLA81XX(vha->hw) &&
- !IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw))
+ !IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) &&
+ !IS_QLA28XX(vha->hw))
return QLA_FUNCTION_FAILED;
if (unlikely(pci_channel_offline(vha->hw->pdev)))
@@ -3756,7 +3766,7 @@ qla2x00_get_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
rval = qla2x00_mailbox_command(vha, mcp);
/* Return mailbox statuses. */
- if (mb != NULL) {
+ if (mb) {
mb[0] = mcp->mb[0];
mb[1] = mcp->mb[1];
mb[3] = mcp->mb[3];
@@ -3791,7 +3801,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
mcp->mb[0] = MBC_PORT_PARAMS;
mcp->mb[1] = loop_id;
mcp->mb[2] = BIT_0;
- mcp->mb[3] = port_speed & (BIT_5|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0);
+ mcp->mb[3] = port_speed & 0x3F;
mcp->mb[9] = vha->vp_idx;
mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_3|MBX_1|MBX_0;
@@ -3800,7 +3810,7 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id,
rval = qla2x00_mailbox_command(vha, mcp);
/* Return mailbox statuses. */
- if (mb != NULL) {
+ if (mb) {
mb[0] = mcp->mb[0];
mb[1] = mcp->mb[1];
mb[3] = mcp->mb[3];
@@ -4242,7 +4252,7 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status)
ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111c,
"Dump of Verify Request.\n");
ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x111e,
- (uint8_t *)mn, sizeof(*mn));
+ mn, sizeof(*mn));
rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120);
if (rval != QLA_SUCCESS) {
@@ -4254,7 +4264,7 @@ qla84xx_verify_chip(struct scsi_qla_host *vha, uint16_t *status)
ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1110,
"Dump of Verify Response.\n");
ql_dump_buffer(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1118,
- (uint8_t *)mn, sizeof(*mn));
+ mn, sizeof(*mn));
status[0] = le16_to_cpu(mn->p.rsp.comp_status);
status[1] = status[0] == CS_VCS_CHIP_FAILURE ?
@@ -4330,7 +4340,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req)
mcp->mb[12] = req->qos;
mcp->mb[11] = req->vp_idx;
mcp->mb[13] = req->rid;
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
mcp->mb[15] = 0;
mcp->mb[4] = req->id;
@@ -4344,9 +4354,10 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req)
mcp->flags = MBX_DMA_OUT;
mcp->tov = MBX_TOV_SECONDS * 2;
- if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha))
+ if (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha))
mcp->in_mb |= MBX_1;
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
mcp->out_mb |= MBX_15;
/* debug q create issue in SR-IOV */
mcp->in_mb |= MBX_9 | MBX_8 | MBX_7;
@@ -4355,7 +4366,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req)
spin_lock_irqsave(&ha->hardware_lock, flags);
if (!(req->options & BIT_0)) {
WRT_REG_DWORD(req->req_q_in, 0);
- if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+ if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
WRT_REG_DWORD(req->req_q_out, 0);
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -4399,7 +4410,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
mcp->mb[5] = rsp->length;
mcp->mb[14] = rsp->msix->entry;
mcp->mb[13] = rsp->rid;
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
mcp->mb[15] = 0;
mcp->mb[4] = rsp->id;
@@ -4416,7 +4427,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
if (IS_QLA81XX(ha)) {
mcp->out_mb |= MBX_12|MBX_11|MBX_10;
mcp->in_mb |= MBX_1;
- } else if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ } else if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
mcp->out_mb |= MBX_15|MBX_12|MBX_11|MBX_10;
mcp->in_mb |= MBX_1;
/* debug q create issue in SR-IOV */
@@ -4426,7 +4437,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
spin_lock_irqsave(&ha->hardware_lock, flags);
if (!(rsp->options & BIT_0)) {
WRT_REG_DWORD(rsp->rsp_q_out, 0);
- if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+ if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
WRT_REG_DWORD(rsp->rsp_q_in, 0);
}
@@ -4484,7 +4495,7 @@ qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size)
"Entered %s.\n", __func__);
if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) &&
- !IS_QLA27XX(vha->hw))
+ !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw))
return QLA_FUNCTION_FAILED;
mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
@@ -4516,7 +4527,7 @@ qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable)
mbx_cmd_t *mcp = &mc;
if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) &&
- !IS_QLA27XX(vha->hw))
+ !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw))
return QLA_FUNCTION_FAILED;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10df,
@@ -4551,7 +4562,7 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish)
mbx_cmd_t *mcp = &mc;
if (!IS_QLA81XX(vha->hw) && !IS_QLA83XX(vha->hw) &&
- !IS_QLA27XX(vha->hw))
+ !IS_QLA27XX(vha->hw) && !IS_QLA28XX(vha->hw))
return QLA_FUNCTION_FAILED;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e2,
@@ -4582,6 +4593,42 @@ qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish)
}
int
+qla81xx_fac_semaphore_access(scsi_qla_host_t *vha, int lock)
+{
+ int rval = QLA_SUCCESS;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+ struct qla_hw_data *ha = vha->hw;
+
+ if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
+ !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+ return rval;
+
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e2,
+ "Entered %s.\n", __func__);
+
+ mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
+ mcp->mb[1] = (lock ? FAC_OPT_CMD_LOCK_SEMAPHORE :
+ FAC_OPT_CMD_UNLOCK_SEMAPHORE);
+ mcp->out_mb = MBX_1|MBX_0;
+ mcp->in_mb = MBX_1|MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x10e3,
+ "Failed=%x mb[0]=%x mb[1]=%x mb[2]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1], mcp->mb[2]);
+ } else {
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e4,
+ "Done %s.\n", __func__);
+ }
+
+ return rval;
+}
+
+int
qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha)
{
int rval = 0;
@@ -4830,10 +4877,10 @@ qla2x00_read_sfp(scsi_qla_host_t *vha, dma_addr_t sfp_dma, uint8_t *sfp,
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_mbx, vha, 0x10e9,
"Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
- if (mcp->mb[0] == MBS_COMMAND_ERROR &&
- mcp->mb[1] == 0x22)
+ if (mcp->mb[0] == MBS_COMMAND_ERROR && mcp->mb[1] == 0x22) {
/* sfp is not there */
rval = QLA_INTERFACE_ERROR;
+ }
} else {
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea,
"Done %s.\n", __func__);
@@ -5173,13 +5220,14 @@ qla2x00_write_ram_word(scsi_qla_host_t *vha, uint32_t risc_addr, uint32_t data)
mcp->mb[3] = MSW(data);
mcp->mb[8] = MSW(risc_addr);
mcp->out_mb = MBX_8|MBX_3|MBX_2|MBX_1|MBX_0;
- mcp->in_mb = MBX_0;
+ mcp->in_mb = MBX_1|MBX_0;
mcp->tov = 30;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);
if (rval != QLA_SUCCESS) {
ql_dbg(ql_dbg_mbx, vha, 0x1101,
- "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+ "Failed=%x mb[0]=%x mb[1]=%x.\n",
+ rval, mcp->mb[0], mcp->mb[1]);
} else {
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1102,
"Done %s.\n", __func__);
@@ -5250,6 +5298,66 @@ qla81xx_write_mpi_register(scsi_qla_host_t *vha, uint16_t *mb)
return rval;
}
+/* Set the specified data rate */
+int
+qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+ struct qla_hw_data *ha = vha->hw;
+ uint16_t val;
+
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1106,
+ "Entered %s speed:0x%x mode:0x%x.\n", __func__, ha->set_data_rate,
+ mode);
+
+ if (!IS_FWI2_CAPABLE(ha))
+ return QLA_FUNCTION_FAILED;
+
+ memset(mcp, 0, sizeof(*mcp));
+ switch (ha->set_data_rate) {
+ case PORT_SPEED_AUTO:
+ case PORT_SPEED_4GB:
+ case PORT_SPEED_8GB:
+ case PORT_SPEED_16GB:
+ case PORT_SPEED_32GB:
+ val = ha->set_data_rate;
+ break;
+ default:
+ ql_log(ql_log_warn, vha, 0x1199,
+ "Unrecognized speed setting:%d. Setting Autoneg\n",
+ ha->set_data_rate);
+ val = ha->set_data_rate = PORT_SPEED_AUTO;
+ break;
+ }
+
+ mcp->mb[0] = MBC_DATA_RATE;
+ mcp->mb[1] = mode;
+ mcp->mb[2] = val;
+
+ mcp->out_mb = MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_2|MBX_1|MBX_0;
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
+ mcp->in_mb |= MBX_4|MBX_3;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x1107,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+ } else {
+ if (mcp->mb[1] != 0x7)
+ ql_dbg(ql_dbg_mbx, vha, 0x1179,
+ "Speed set:0x%x\n", mcp->mb[1]);
+
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1108,
+ "Done %s.\n", __func__);
+ }
+
+ return rval;
+}
+
int
qla2x00_get_data_rate(scsi_qla_host_t *vha)
{
@@ -5265,10 +5373,10 @@ qla2x00_get_data_rate(scsi_qla_host_t *vha)
return QLA_FUNCTION_FAILED;
mcp->mb[0] = MBC_DATA_RATE;
- mcp->mb[1] = 0;
+ mcp->mb[1] = QLA_GET_DATA_RATE;
mcp->out_mb = MBX_1|MBX_0;
mcp->in_mb = MBX_2|MBX_1|MBX_0;
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
mcp->in_mb |= MBX_3;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
@@ -5298,7 +5406,7 @@ qla81xx_get_port_config(scsi_qla_host_t *vha, uint16_t *mb)
"Entered %s.\n", __func__);
if (!IS_QLA81XX(ha) && !IS_QLA83XX(ha) && !IS_QLA8044(ha) &&
- !IS_QLA27XX(ha))
+ !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return QLA_FUNCTION_FAILED;
mcp->mb[0] = MBC_GET_PORT_CONFIG;
mcp->out_mb = MBX_0;
@@ -5614,6 +5722,7 @@ qla8044_md_get_template(scsi_qla_host_t *vha)
mbx_cmd_t *mcp = &mc;
int rval = QLA_FUNCTION_FAILED;
int offset = 0, size = MINIDUMP_SIZE_36K;
+
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0xb11f,
"Entered %s.\n", __func__);
@@ -5794,7 +5903,7 @@ qla83xx_wr_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t data)
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;
- if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+ if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return QLA_FUNCTION_FAILED;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1130,
@@ -5869,7 +5978,7 @@ qla83xx_rd_reg(scsi_qla_host_t *vha, uint32_t reg, uint32_t *data)
struct qla_hw_data *ha = vha->hw;
unsigned long retry_max_time = jiffies + (2 * HZ);
- if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+ if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return QLA_FUNCTION_FAILED;
ql_dbg(ql_dbg_mbx, vha, 0x114b, "Entered %s.\n", __func__);
@@ -5919,7 +6028,7 @@ qla83xx_restart_nic_firmware(scsi_qla_host_t *vha)
mbx_cmd_t *mcp = &mc;
struct qla_hw_data *ha = vha->hw;
- if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+ if (!IS_QLA83XX(ha))
return QLA_FUNCTION_FAILED;
ql_dbg(ql_dbg_mbx, vha, 0x1143, "Entered %s.\n", __func__);
@@ -6053,7 +6162,8 @@ qla26xx_dport_diagnostics(scsi_qla_host_t *vha,
mbx_cmd_t *mcp = &mc;
dma_addr_t dd_dma;
- if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw))
+ if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) &&
+ !IS_QLA28XX(vha->hw))
return QLA_FUNCTION_FAILED;
ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x119f,
@@ -6095,10 +6205,8 @@ qla26xx_dport_diagnostics(scsi_qla_host_t *vha,
return rval;
}
-static void qla2x00_async_mb_sp_done(void *s, int res)
+static void qla2x00_async_mb_sp_done(srb_t *sp, int res)
{
- struct srb *sp = s;
-
sp->u.iocb_cmd.u.mbx.rc = res;
complete(&sp->u.iocb_cmd.u.mbx.comp);
@@ -6270,9 +6378,13 @@ int __qla24xx_parse_gpdb(struct scsi_qla_host *vha, fc_port_t *fcport,
fcport->d_id.b.rsvd_1 = 0;
if (fcport->fc4f_nvme) {
- fcport->nvme_prli_service_param =
- pd->prli_nvme_svc_param_word_3;
- fcport->port_type = FCT_NVME;
+ fcport->port_type = 0;
+ if ((pd->prli_svc_param_word_3[0] & BIT_5) == 0)
+ fcport->port_type |= FCT_NVME_INITIATOR;
+ if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
+ fcport->port_type |= FCT_NVME_TARGET;
+ if ((pd->prli_svc_param_word_3[0] & BIT_3) == 0)
+ fcport->port_type |= FCT_NVME_DISCOVERY;
} else {
/* If not target must be initiator or unknown type. */
if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
@@ -6461,3 +6573,101 @@ int qla24xx_res_count_wait(struct scsi_qla_host *vha,
done:
return rval;
}
+
+int qla28xx_secure_flash_update(scsi_qla_host_t *vha, uint16_t opts,
+ uint16_t region, uint32_t len, dma_addr_t sfub_dma_addr,
+ uint32_t sfub_len)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ mcp->mb[0] = MBC_SECURE_FLASH_UPDATE;
+ mcp->mb[1] = opts;
+ mcp->mb[2] = region;
+ mcp->mb[3] = MSW(len);
+ mcp->mb[4] = LSW(len);
+ mcp->mb[5] = MSW(sfub_dma_addr);
+ mcp->mb[6] = LSW(sfub_dma_addr);
+ mcp->mb[7] = MSW(MSD(sfub_dma_addr));
+ mcp->mb[8] = LSW(MSD(sfub_dma_addr));
+ mcp->mb[9] = sfub_len;
+ mcp->out_mb =
+ MBX_9|MBX_8|MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_2|MBX_1|MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0xffff, "%s(%ld): failed rval 0x%x, %x %x %x",
+ __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1],
+ mcp->mb[2]);
+ }
+
+ return rval;
+}
+
+int qla2xxx_write_remote_register(scsi_qla_host_t *vha, uint32_t addr,
+ uint32_t data)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e8,
+ "Entered %s.\n", __func__);
+
+ mcp->mb[0] = MBC_WRITE_REMOTE_REG;
+ mcp->mb[1] = LSW(addr);
+ mcp->mb[2] = MSW(addr);
+ mcp->mb[3] = LSW(data);
+ mcp->mb[4] = MSW(data);
+ mcp->out_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_1|MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x10e9,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+ } else {
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea,
+ "Done %s.\n", __func__);
+ }
+
+ return rval;
+}
+
+int qla2xxx_read_remote_register(scsi_qla_host_t *vha, uint32_t addr,
+ uint32_t *data)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10e8,
+ "Entered %s.\n", __func__);
+
+ mcp->mb[0] = MBC_READ_REMOTE_REG;
+ mcp->mb[1] = LSW(addr);
+ mcp->mb[2] = MSW(addr);
+ mcp->out_mb = MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ *data = (uint32_t)((((uint32_t)mcp->mb[4]) << 16) | mcp->mb[3]);
+
+ if (rval != QLA_SUCCESS) {
+ ql_dbg(ql_dbg_mbx, vha, 0x10e9,
+ "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+ } else {
+ ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x10ea,
+ "Done %s.\n", __func__);
+ }
+
+ return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index d102d9ddf026..a3c4bb7b6fd1 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -901,11 +901,10 @@ failed:
return 0;
}
-static void qla_ctrlvp_sp_done(void *s, int res)
+static void qla_ctrlvp_sp_done(srb_t *sp, int res)
{
- struct srb *sp = s;
-
- complete(&sp->comp);
+ if (sp->comp)
+ complete(sp->comp);
/* don't free sp here. Let the caller do the free */
}
@@ -922,6 +921,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
struct qla_hw_data *ha = vha->hw;
int vp_index = vha->vp_idx;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
+ DECLARE_COMPLETION_ONSTACK(comp);
srb_t *sp;
ql_dbg(ql_dbg_vport, vha, 0x10c1,
@@ -936,6 +936,7 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
sp->type = SRB_CTRL_VP;
sp->name = "ctrl_vp";
+ sp->comp = &comp;
sp->done = qla_ctrlvp_sp_done;
sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout;
qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
@@ -953,7 +954,9 @@ int qla24xx_control_vp(scsi_qla_host_t *vha, int cmd)
ql_dbg(ql_dbg_vport, vha, 0x113f, "%s hndl %x submitted\n",
sp->name, sp->handle);
- wait_for_completion(&sp->comp);
+ wait_for_completion(&comp);
+ sp->comp = NULL;
+
rval = sp->rc;
switch (rval) {
case QLA_FUNCTION_TIMEOUT:
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
index 60f964c53c01..605b59c76c90 100644
--- a/drivers/scsi/qla2xxx/qla_mr.c
+++ b/drivers/scsi/qla2xxx/qla_mr.c
@@ -10,7 +10,6 @@
#include <linux/pci.h>
#include <linux/ratelimit.h>
#include <linux/vmalloc.h>
-#include <linux/bsg-lib.h>
#include <scsi/scsi_tcq.h>
#include <linux/utsname.h>
@@ -149,7 +148,8 @@ qlafx00_mailbox_command(scsi_qla_host_t *vha, struct mbx_cmd_32 *mcp)
QLAFX00_SET_HST_INTR(ha, ha->mbx_intr_code);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- wait_for_completion_timeout(&ha->mbx_intr_comp, mcp->tov * HZ);
+ WARN_ON_ONCE(wait_for_completion_timeout(&ha->mbx_intr_comp,
+ mcp->tov * HZ) != 0);
} else {
ql_dbg(ql_dbg_mbx, vha, 0x112c,
"Cmd=%x Polling Mode.\n", command);
@@ -273,9 +273,9 @@ premature_exit:
if (rval) {
ql_log(ql_log_warn, base_vha, 0x1163,
- "**** Failed mbx[0]=%x, mb[1]=%x, mb[2]=%x, "
- "mb[3]=%x, cmd=%x ****.\n",
- mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], command);
+ "**** Failed=%x mbx[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x, cmd=%x ****.\n",
+ rval, mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3],
+ command);
} else {
ql_dbg(ql_dbg_mbx, base_vha, 0x1164, "Done %s.\n", __func__);
}
@@ -629,17 +629,20 @@ qlafx00_soc_cpu_reset(scsi_qla_host_t *vha)
*
* Returns 0 on success.
*/
-void
+int
qlafx00_soft_reset(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
+ int rval = QLA_FUNCTION_FAILED;
if (unlikely(pci_channel_offline(ha->pdev) &&
ha->flags.pci_channel_io_perm_failure))
- return;
+ return rval;
ha->isp_ops->disable_intrs(ha);
qlafx00_soc_cpu_reset(vha);
+
+ return QLA_SUCCESS;
}
/**
@@ -685,14 +688,12 @@ qlafx00_config_rings(struct scsi_qla_host *vha)
}
char *
-qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str)
+qlafx00_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len)
{
struct qla_hw_data *ha = vha->hw;
- if (pci_is_pcie(ha->pdev)) {
- strcpy(str, "PCIe iSA");
- return str;
- }
+ if (pci_is_pcie(ha->pdev))
+ strlcpy(str, "PCIe iSA", str_len);
return str;
}
@@ -1138,8 +1139,8 @@ qlafx00_find_all_targets(scsi_qla_host_t *vha,
ql_dbg(ql_dbg_disc + ql_dbg_init, vha, 0x2088,
"Listing Target bit map...\n");
- ql_dump_buffer(ql_dbg_disc + ql_dbg_init, vha,
- 0x2089, (uint8_t *)ha->gid_list, 32);
+ ql_dump_buffer(ql_dbg_disc + ql_dbg_init, vha, 0x2089,
+ ha->gid_list, 32);
/* Allocate temporary rmtport for any new rmtports discovered. */
new_fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
@@ -1320,6 +1321,7 @@ qlafx00_configure_devices(scsi_qla_host_t *vha)
{
int rval;
unsigned long flags;
+
rval = QLA_SUCCESS;
flags = vha->dpc_flags;
@@ -1795,10 +1797,8 @@ qla2x00_fxdisc_iocb_timeout(void *data)
complete(&lio->u.fxiocb.fxiocb_comp);
}
-static void
-qla2x00_fxdisc_sp_done(void *ptr, int res)
+static void qla2x00_fxdisc_sp_done(srb_t *sp, int res)
{
- srb_t *sp = ptr;
struct srb_iocb *lio = &sp->u.iocb_cmd;
complete(&lio->u.fxiocb.fxiocb_comp);
@@ -1877,22 +1877,22 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
phost_info = &preg_hsi->hsi;
memset(preg_hsi, 0, sizeof(struct register_host_info));
phost_info->os_type = OS_TYPE_LINUX;
- strncpy(phost_info->sysname,
- p_sysid->sysname, SYSNAME_LENGTH);
- strncpy(phost_info->nodename,
- p_sysid->nodename, NODENAME_LENGTH);
+ strlcpy(phost_info->sysname, p_sysid->sysname,
+ sizeof(phost_info->sysname));
+ strlcpy(phost_info->nodename, p_sysid->nodename,
+ sizeof(phost_info->nodename));
if (!strcmp(phost_info->nodename, "(none)"))
ha->mr.host_info_resend = true;
- strncpy(phost_info->release,
- p_sysid->release, RELEASE_LENGTH);
- strncpy(phost_info->version,
- p_sysid->version, VERSION_LENGTH);
- strncpy(phost_info->machine,
- p_sysid->machine, MACHINE_LENGTH);
- strncpy(phost_info->domainname,
- p_sysid->domainname, DOMNAME_LENGTH);
- strncpy(phost_info->hostdriver,
- QLA2XXX_VERSION, VERSION_LENGTH);
+ strlcpy(phost_info->release, p_sysid->release,
+ sizeof(phost_info->release));
+ strlcpy(phost_info->version, p_sysid->version,
+ sizeof(phost_info->version));
+ strlcpy(phost_info->machine, p_sysid->machine,
+ sizeof(phost_info->machine));
+ strlcpy(phost_info->domainname, p_sysid->domainname,
+ sizeof(phost_info->domainname));
+ strlcpy(phost_info->hostdriver, QLA2XXX_VERSION,
+ sizeof(phost_info->hostdriver));
preg_hsi->utc = (uint64_t)ktime_get_real_seconds();
ql_dbg(ql_dbg_init, vha, 0x0149,
"ISP%04X: Host registration with firmware\n",
@@ -1913,8 +1913,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
phost_info->domainname,
phost_info->hostdriver);
ql_dump_buffer(ql_dbg_init + ql_dbg_disc, vha, 0x014d,
- (uint8_t *)phost_info,
- sizeof(struct host_system_info));
+ phost_info, sizeof(*phost_info));
}
}
@@ -1938,8 +1937,10 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
if (fx_type == FXDISC_GET_CONFIG_INFO) {
struct config_info_data *pinfo =
(struct config_info_data *) fdisc->u.fxiocb.rsp_addr;
- strcpy(vha->hw->model_number, pinfo->model_num);
- strcpy(vha->hw->model_desc, pinfo->model_description);
+ strlcpy(vha->hw->model_number, pinfo->model_num,
+ ARRAY_SIZE(vha->hw->model_number));
+ strlcpy(vha->hw->model_desc, pinfo->model_description,
+ ARRAY_SIZE(vha->hw->model_desc));
memcpy(&vha->hw->mr.symbolic_name, pinfo->symbolic_name,
sizeof(vha->hw->mr.symbolic_name));
memcpy(&vha->hw->mr.serial_num, pinfo->serial_num,
@@ -1968,7 +1969,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
vha->d_id.b.al_pa = pinfo->port_id[2];
qlafx00_update_host_attr(vha, pinfo);
ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0141,
- (uint8_t *)pinfo, 16);
+ pinfo, 16);
} else if (fx_type == FXDISC_GET_TGT_NODE_INFO) {
struct qlafx00_tgt_node_info *pinfo =
(struct qlafx00_tgt_node_info *) fdisc->u.fxiocb.rsp_addr;
@@ -1976,12 +1977,12 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, uint16_t fx_type)
memcpy(fcport->port_name, pinfo->tgt_node_wwpn, WWN_SIZE);
fcport->port_type = FCT_TARGET;
ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0144,
- (uint8_t *)pinfo, 16);
+ pinfo, 16);
} else if (fx_type == FXDISC_GET_TGT_NODE_LIST) {
struct qlafx00_tgt_node_info *pinfo =
(struct qlafx00_tgt_node_info *) fdisc->u.fxiocb.rsp_addr;
ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0146,
- (uint8_t *)pinfo, 16);
+ pinfo, 16);
memcpy(vha->hw->gid_list, pinfo, QLAFX00_TGT_NODE_LIST_SIZE);
} else if (fx_type == FXDISC_ABORT_IOCTL)
fdisc->u.fxiocb.result =
@@ -2248,18 +2249,16 @@ qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req,
fw_sts_ptr = bsg_job->reply + sizeof(struct fc_bsg_reply);
- memcpy(fw_sts_ptr, (uint8_t *)&fstatus,
- sizeof(struct qla_mt_iocb_rsp_fx00));
+ memcpy(fw_sts_ptr, &fstatus, sizeof(fstatus));
bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
sizeof(struct qla_mt_iocb_rsp_fx00) + sizeof(uint8_t);
ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
- sp->fcport->vha, 0x5080,
- (uint8_t *)pkt, sizeof(struct ioctl_iocb_entry_fx00));
+ sp->vha, 0x5080, pkt, sizeof(*pkt));
ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
- sp->fcport->vha, 0x5074,
- (uint8_t *)fw_sts_ptr, sizeof(struct qla_mt_iocb_rsp_fx00));
+ sp->vha, 0x5074,
+ fw_sts_ptr, sizeof(fstatus));
res = bsg_reply->result = DID_OK << 16;
bsg_reply->reply_payload_rcv_len =
@@ -2540,6 +2539,8 @@ check_scsi_status:
if (rsp->status_srb == NULL)
sp->done(sp, res);
+ else
+ WARN_ON_ONCE(true);
}
/**
@@ -2597,7 +2598,7 @@ qlafx00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt)
/* Move sense data. */
ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x304e,
- (uint8_t *)pkt, sizeof(sts_cont_entry_t));
+ pkt, sizeof(*pkt));
memcpy(sense_ptr, pkt->data, sense_sz);
ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x304a,
sense_ptr, sense_sz);
@@ -2617,6 +2618,8 @@ qlafx00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt)
if (sense_len == 0) {
rsp->status_srb = NULL;
sp->done(sp, cp->result);
+ } else {
+ WARN_ON_ONCE(true);
}
}
@@ -2992,7 +2995,7 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt,
uint16_t tot_dsds, struct cmd_type_7_fx00 *lcmd_pkt)
{
uint16_t avail_dsds;
- __le32 *cur_dsd;
+ struct dsd64 *cur_dsd;
scsi_qla_host_t *vha;
struct scsi_cmnd *cmd;
struct scatterlist *sg;
@@ -3028,12 +3031,10 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt,
/* One DSD is available in the Command Type 3 IOCB */
avail_dsds = 1;
- cur_dsd = (__le32 *)&lcmd_pkt->dseg_0_address;
+ cur_dsd = &lcmd_pkt->dsd;
/* Load data segments */
scsi_for_each_sg(cmd, sg, tot_dsds, i) {
- dma_addr_t sle_dma;
-
/* Allocate additional continuation packets? */
if (avail_dsds == 0) {
/*
@@ -3043,26 +3044,23 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt,
memset(&lcont_pkt, 0, REQUEST_ENTRY_SIZE);
cont_pkt =
qlafx00_prep_cont_type1_iocb(req, &lcont_pkt);
- cur_dsd = (__le32 *)lcont_pkt.dseg_0_address;
+ cur_dsd = lcont_pkt.dsd;
avail_dsds = 5;
cont = 1;
}
- sle_dma = sg_dma_address(sg);
- *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ append_dsd64(&cur_dsd, sg);
avail_dsds--;
if (avail_dsds == 0 && cont == 1) {
cont = 0;
memcpy_toio((void __iomem *)cont_pkt, &lcont_pkt,
- REQUEST_ENTRY_SIZE);
+ sizeof(lcont_pkt));
}
}
if (avail_dsds != 0 && cont == 1) {
memcpy_toio((void __iomem *)cont_pkt, &lcont_pkt,
- REQUEST_ENTRY_SIZE);
+ sizeof(lcont_pkt));
}
}
@@ -3077,7 +3075,6 @@ qlafx00_start_scsi(srb_t *sp)
{
int nseg;
unsigned long flags;
- uint32_t index;
uint32_t handle;
uint16_t cnt;
uint16_t req_cnt;
@@ -3101,16 +3098,8 @@ qlafx00_start_scsi(srb_t *sp)
/* Acquire ring specific lock */
spin_lock_irqsave(&ha->hardware_lock, flags);
- /* Check for room in outstanding command list. */
- handle = req->current_outstanding_cmd;
- for (index = 1; index < req->num_outstanding_cmds; index++) {
- handle++;
- if (handle == req->num_outstanding_cmds)
- handle = 1;
- if (!req->outstanding_cmds[handle])
- break;
- }
- if (index == req->num_outstanding_cmds)
+ handle = qla2xxx_get_next_handle(req);
+ if (handle == 0)
goto queuing_error;
/* Map the sg table so we have an accurate count of sg entries needed */
@@ -3172,9 +3161,9 @@ qlafx00_start_scsi(srb_t *sp)
lcmd_pkt.entry_status = (uint8_t) rsp->id;
ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302e,
- (uint8_t *)cmd->cmnd, cmd->cmd_len);
+ cmd->cmnd, cmd->cmd_len);
ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x3032,
- (uint8_t *)&lcmd_pkt, REQUEST_ENTRY_SIZE);
+ &lcmd_pkt, sizeof(lcmd_pkt));
memcpy_toio((void __iomem *)cmd_pkt, &lcmd_pkt, REQUEST_ENTRY_SIZE);
wmb();
@@ -3282,11 +3271,9 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
fx_iocb.req_dsdcnt = cpu_to_le16(1);
fx_iocb.req_xfrcnt =
cpu_to_le16(fxio->u.fxiocb.req_len);
- fx_iocb.dseg_rq_address[0] =
- cpu_to_le32(LSD(fxio->u.fxiocb.req_dma_handle));
- fx_iocb.dseg_rq_address[1] =
- cpu_to_le32(MSD(fxio->u.fxiocb.req_dma_handle));
- fx_iocb.dseg_rq_len =
+ put_unaligned_le64(fxio->u.fxiocb.req_dma_handle,
+ &fx_iocb.dseg_rq.address);
+ fx_iocb.dseg_rq.length =
cpu_to_le32(fxio->u.fxiocb.req_len);
}
@@ -3294,11 +3281,9 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
fx_iocb.rsp_dsdcnt = cpu_to_le16(1);
fx_iocb.rsp_xfrcnt =
cpu_to_le16(fxio->u.fxiocb.rsp_len);
- fx_iocb.dseg_rsp_address[0] =
- cpu_to_le32(LSD(fxio->u.fxiocb.rsp_dma_handle));
- fx_iocb.dseg_rsp_address[1] =
- cpu_to_le32(MSD(fxio->u.fxiocb.rsp_dma_handle));
- fx_iocb.dseg_rsp_len =
+ put_unaligned_le64(fxio->u.fxiocb.rsp_dma_handle,
+ &fx_iocb.dseg_rsp.address);
+ fx_iocb.dseg_rsp.length =
cpu_to_le32(fxio->u.fxiocb.rsp_len);
}
@@ -3308,6 +3293,7 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
fx_iocb.flags = fxio->u.fxiocb.flags;
} else {
struct scatterlist *sg;
+
bsg_job = sp->u.bsg_job;
bsg_request = bsg_job->request;
piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *)
@@ -3327,19 +3313,17 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
int avail_dsds, tot_dsds;
cont_a64_entry_t lcont_pkt;
cont_a64_entry_t *cont_pkt = NULL;
- __le32 *cur_dsd;
+ struct dsd64 *cur_dsd;
int index = 0, cont = 0;
fx_iocb.req_dsdcnt =
cpu_to_le16(bsg_job->request_payload.sg_cnt);
tot_dsds =
bsg_job->request_payload.sg_cnt;
- cur_dsd = (__le32 *)&fx_iocb.dseg_rq_address[0];
+ cur_dsd = &fx_iocb.dseg_rq;
avail_dsds = 1;
for_each_sg(bsg_job->request_payload.sg_list, sg,
tot_dsds, index) {
- dma_addr_t sle_dma;
-
/* Allocate additional continuation packets? */
if (avail_dsds == 0) {
/*
@@ -3351,17 +3335,13 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
cont_pkt =
qlafx00_prep_cont_type1_iocb(
sp->vha->req, &lcont_pkt);
- cur_dsd = (__le32 *)
- lcont_pkt.dseg_0_address;
+ cur_dsd = lcont_pkt.dsd;
avail_dsds = 5;
cont = 1;
entry_cnt++;
}
- sle_dma = sg_dma_address(sg);
- *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ append_dsd64(&cur_dsd, sg);
avail_dsds--;
if (avail_dsds == 0 && cont == 1) {
@@ -3389,19 +3369,17 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
int avail_dsds, tot_dsds;
cont_a64_entry_t lcont_pkt;
cont_a64_entry_t *cont_pkt = NULL;
- __le32 *cur_dsd;
+ struct dsd64 *cur_dsd;
int index = 0, cont = 0;
fx_iocb.rsp_dsdcnt =
cpu_to_le16(bsg_job->reply_payload.sg_cnt);
tot_dsds = bsg_job->reply_payload.sg_cnt;
- cur_dsd = (__le32 *)&fx_iocb.dseg_rsp_address[0];
+ cur_dsd = &fx_iocb.dseg_rsp;
avail_dsds = 1;
for_each_sg(bsg_job->reply_payload.sg_list, sg,
tot_dsds, index) {
- dma_addr_t sle_dma;
-
/* Allocate additional continuation packets? */
if (avail_dsds == 0) {
/*
@@ -3413,17 +3391,13 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
cont_pkt =
qlafx00_prep_cont_type1_iocb(
sp->vha->req, &lcont_pkt);
- cur_dsd = (__le32 *)
- lcont_pkt.dseg_0_address;
+ cur_dsd = lcont_pkt.dsd;
avail_dsds = 5;
cont = 1;
entry_cnt++;
}
- sle_dma = sg_dma_address(sg);
- *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ append_dsd64(&cur_dsd, sg);
avail_dsds--;
if (avail_dsds == 0 && cont == 1) {
@@ -3454,10 +3428,8 @@ qlafx00_fxdisc_iocb(srb_t *sp, struct fxdisc_entry_fx00 *pfxiocb)
}
ql_dump_buffer(ql_dbg_user + ql_dbg_verbose,
- sp->vha, 0x3047,
- (uint8_t *)&fx_iocb, sizeof(struct fxdisc_entry_fx00));
+ sp->vha, 0x3047, &fx_iocb, sizeof(fx_iocb));
- memcpy_toio((void __iomem *)pfxiocb, &fx_iocb,
- sizeof(struct fxdisc_entry_fx00));
+ memcpy_toio((void __iomem *)pfxiocb, &fx_iocb, sizeof(fx_iocb));
wmb();
}
diff --git a/drivers/scsi/qla2xxx/qla_mr.h b/drivers/scsi/qla2xxx/qla_mr.h
index aeaa1b40b1fc..4567f0c42486 100644
--- a/drivers/scsi/qla2xxx/qla_mr.h
+++ b/drivers/scsi/qla2xxx/qla_mr.h
@@ -7,6 +7,8 @@
#ifndef __QLA_MR_H
#define __QLA_MR_H
+#include "qla_dsd.h"
+
/*
* The PCI VendorID and DeviceID for our board.
*/
@@ -46,8 +48,7 @@ struct cmd_type_7_fx00 {
uint8_t fcp_cdb[MAX_CMDSZ]; /* SCSI command words. */
__le32 byte_count; /* Total byte count. */
- uint32_t dseg_0_address[2]; /* Data segment 0 address. */
- uint32_t dseg_0_len; /* Data segment 0 length. */
+ struct dsd64 dsd;
};
#define STATUS_TYPE_FX00 0x01 /* Status entry. */
@@ -176,10 +177,8 @@ struct fxdisc_entry_fx00 {
uint8_t flags;
uint8_t reserved_1;
- __le32 dseg_rq_address[2]; /* Data segment 0 address. */
- __le32 dseg_rq_len; /* Data segment 0 length. */
- __le32 dseg_rsp_address[2]; /* Data segment 1 address. */
- __le32 dseg_rsp_len; /* Data segment 1 length. */
+ struct dsd64 dseg_rq;
+ struct dsd64 dseg_rsp;
__le32 dataword;
__le32 adapid;
diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
index 34996fcfd4fc..826fdcf54529 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.c
+++ b/drivers/scsi/qla2xxx/qla_nvme.c
@@ -12,8 +12,6 @@
static struct nvme_fc_port_template qla_nvme_fc_transport;
-static void qla_nvme_unregister_remote_port(struct work_struct *);
-
int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport)
{
struct qla_nvme_rport *rport;
@@ -38,7 +36,6 @@ int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport)
(fcport->nvme_flag & NVME_FLAG_REGISTERED))
return 0;
- INIT_WORK(&fcport->nvme_del_work, qla_nvme_unregister_remote_port);
fcport->nvme_flag &= ~NVME_FLAG_RESETTING;
memset(&req, 0, sizeof(struct nvme_fc_port_info));
@@ -74,7 +71,6 @@ int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport)
rport = fcport->nvme_remote_port->private;
rport->fcport = fcport;
- list_add_tail(&rport->list, &vha->nvme_rport_list);
fcport->nvme_flag |= NVME_FLAG_REGISTERED;
return 0;
@@ -124,54 +120,88 @@ static int qla_nvme_alloc_queue(struct nvme_fc_local_port *lport,
return 0;
}
-static void qla_nvme_sp_ls_done(void *ptr, int res)
+static void qla_nvme_release_fcp_cmd_kref(struct kref *kref)
{
- srb_t *sp = ptr;
+ struct srb *sp = container_of(kref, struct srb, cmd_kref);
+ struct nvme_private *priv = (struct nvme_private *)sp->priv;
+ struct nvmefc_fcp_req *fd;
struct srb_iocb *nvme;
- struct nvmefc_ls_req *fd;
- struct nvme_private *priv;
+ unsigned long flags;
- if (atomic_read(&sp->ref_count) == 0) {
- ql_log(ql_log_warn, sp->fcport->vha, 0x2123,
- "SP reference-count to ZERO on LS_done -- sp=%p.\n", sp);
- return;
+ if (!priv)
+ goto out;
+
+ nvme = &sp->u.iocb_cmd;
+ fd = nvme->u.nvme.desc;
+
+ spin_lock_irqsave(&priv->cmd_lock, flags);
+ priv->sp = NULL;
+ sp->priv = NULL;
+ if (priv->comp_status == QLA_SUCCESS) {
+ fd->rcv_rsplen = nvme->u.nvme.rsp_pyld_len;
+ } else {
+ fd->rcv_rsplen = 0;
+ fd->transferred_length = 0;
}
+ fd->status = 0;
+ spin_unlock_irqrestore(&priv->cmd_lock, flags);
- if (!atomic_dec_and_test(&sp->ref_count))
- return;
+ fd->done(fd);
+out:
+ qla2xxx_rel_qpair_sp(sp->qpair, sp);
+}
- if (res)
- res = -EINVAL;
+static void qla_nvme_release_ls_cmd_kref(struct kref *kref)
+{
+ struct srb *sp = container_of(kref, struct srb, cmd_kref);
+ struct nvme_private *priv = (struct nvme_private *)sp->priv;
+ struct nvmefc_ls_req *fd;
+ unsigned long flags;
- nvme = &sp->u.iocb_cmd;
- fd = nvme->u.nvme.desc;
- priv = fd->private;
- priv->comp_status = res;
- schedule_work(&priv->ls_work);
- /* work schedule doesn't need the sp */
+ if (!priv)
+ goto out;
+
+ spin_lock_irqsave(&priv->cmd_lock, flags);
+ priv->sp = NULL;
+ sp->priv = NULL;
+ spin_unlock_irqrestore(&priv->cmd_lock, flags);
+
+ fd = priv->fd;
+ fd->done(fd, priv->comp_status);
+out:
qla2x00_rel_sp(sp);
}
-static void qla_nvme_sp_done(void *ptr, int res)
+static void qla_nvme_ls_complete(struct work_struct *work)
{
- srb_t *sp = ptr;
- struct srb_iocb *nvme;
- struct nvmefc_fcp_req *fd;
+ struct nvme_private *priv =
+ container_of(work, struct nvme_private, ls_work);
- nvme = &sp->u.iocb_cmd;
- fd = nvme->u.nvme.desc;
+ kref_put(&priv->sp->cmd_kref, qla_nvme_release_ls_cmd_kref);
+}
- if (!atomic_dec_and_test(&sp->ref_count))
+static void qla_nvme_sp_ls_done(srb_t *sp, int res)
+{
+ struct nvme_private *priv = sp->priv;
+
+ if (WARN_ON_ONCE(kref_read(&sp->cmd_kref) == 0))
return;
- if (res == QLA_SUCCESS)
- fd->status = 0;
- else
- fd->status = NVME_SC_INTERNAL;
+ if (res)
+ res = -EINVAL;
- fd->rcv_rsplen = nvme->u.nvme.rsp_pyld_len;
- fd->done(fd);
- qla2xxx_rel_qpair_sp(sp->qpair, sp);
+ priv->comp_status = res;
+ INIT_WORK(&priv->ls_work, qla_nvme_ls_complete);
+ schedule_work(&priv->ls_work);
+}
+
+/* it assumed that QPair lock is held. */
+static void qla_nvme_sp_done(srb_t *sp, int res)
+{
+ struct nvme_private *priv = sp->priv;
+
+ priv->comp_status = res;
+ kref_put(&sp->cmd_kref, qla_nvme_release_fcp_cmd_kref);
return;
}
@@ -185,30 +215,53 @@ static void qla_nvme_abort_work(struct work_struct *work)
struct qla_hw_data *ha = fcport->vha->hw;
int rval;
+ ql_dbg(ql_dbg_io, fcport->vha, 0xffff,
+ "%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)
+ goto out;
+
+ if (ha->flags.host_shutting_down) {
+ ql_log(ql_log_info, sp->fcport->vha, 0xffff,
+ "%s Calling done on sp: %p, type: 0x%x, sp->ref_count: 0x%x\n",
+ __func__, sp, sp->type, atomic_read(&sp->ref_count));
+ sp->done(sp, 0);
+ goto out;
+ }
+
rval = ha->isp_ops->abort_command(sp);
ql_dbg(ql_dbg_io, fcport->vha, 0x212b,
"%s: %s command for sp=%p, handle=%x on fcport=%p rval=%x\n",
__func__, (rval != QLA_SUCCESS) ? "Failed to abort" : "Aborted",
sp, sp->handle, fcport, rval);
+
+out:
+ /* kref_get was done before work was schedule. */
+ kref_put(&sp->cmd_kref, sp->put_fn);
}
static void qla_nvme_ls_abort(struct nvme_fc_local_port *lport,
struct nvme_fc_remote_port *rport, struct nvmefc_ls_req *fd)
{
struct nvme_private *priv = fd->private;
+ unsigned long flags;
- INIT_WORK(&priv->abort_work, qla_nvme_abort_work);
- schedule_work(&priv->abort_work);
-}
+ spin_lock_irqsave(&priv->cmd_lock, flags);
+ if (!priv->sp) {
+ spin_unlock_irqrestore(&priv->cmd_lock, flags);
+ return;
+ }
-static void qla_nvme_ls_complete(struct work_struct *work)
-{
- struct nvme_private *priv =
- container_of(work, struct nvme_private, ls_work);
- struct nvmefc_ls_req *fd = priv->fd;
+ if (!kref_get_unless_zero(&priv->sp->cmd_kref)) {
+ spin_unlock_irqrestore(&priv->cmd_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&priv->cmd_lock, flags);
- fd->done(fd, priv->comp_status);
+ INIT_WORK(&priv->abort_work, qla_nvme_abort_work);
+ schedule_work(&priv->abort_work);
}
static int qla_nvme_ls_req(struct nvme_fc_local_port *lport,
@@ -223,8 +276,16 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport,
struct qla_hw_data *ha;
srb_t *sp;
+
+ if (!fcport || (fcport && fcport->deleted))
+ return rval;
+
vha = fcport->vha;
ha = vha->hw;
+
+ if (!ha->flags.fw_started)
+ return rval;
+
/* Alloc SRB structure */
sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
if (!sp)
@@ -233,11 +294,13 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport,
sp->type = SRB_NVME_LS;
sp->name = "nvme_ls";
sp->done = qla_nvme_sp_ls_done;
- atomic_set(&sp->ref_count, 1);
- nvme = &sp->u.iocb_cmd;
+ sp->put_fn = qla_nvme_release_ls_cmd_kref;
+ sp->priv = (void *)priv;
priv->sp = sp;
+ kref_init(&sp->cmd_kref);
+ spin_lock_init(&priv->cmd_lock);
+ nvme = &sp->u.iocb_cmd;
priv->fd = fd;
- INIT_WORK(&priv->ls_work, qla_nvme_ls_complete);
nvme->u.nvme.desc = fd;
nvme->u.nvme.dir = 0;
nvme->u.nvme.dl = 0;
@@ -254,8 +317,10 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport,
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x700e,
"qla2x00_start_sp failed = %d\n", rval);
- atomic_dec(&sp->ref_count);
wake_up(&sp->nvme_ls_waitq);
+ sp->priv = NULL;
+ priv->sp = NULL;
+ qla2x00_rel_sp(sp);
return rval;
}
@@ -267,6 +332,18 @@ static void qla_nvme_fcp_abort(struct nvme_fc_local_port *lport,
struct nvmefc_fcp_req *fd)
{
struct nvme_private *priv = fd->private;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->cmd_lock, flags);
+ if (!priv->sp) {
+ spin_unlock_irqrestore(&priv->cmd_lock, flags);
+ return;
+ }
+ if (!kref_get_unless_zero(&priv->sp->cmd_kref)) {
+ spin_unlock_irqrestore(&priv->cmd_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&priv->cmd_lock, flags);
INIT_WORK(&priv->abort_work, qla_nvme_abort_work);
schedule_work(&priv->abort_work);
@@ -287,14 +364,13 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp)
{
unsigned long flags;
uint32_t *clr_ptr;
- uint32_t index;
uint32_t handle;
struct cmd_nvme *cmd_pkt;
uint16_t cnt, i;
uint16_t req_cnt;
uint16_t tot_dsds;
uint16_t avail_dsds;
- uint32_t *cur_dsd;
+ struct dsd64 *cur_dsd;
struct req_que *req = NULL;
struct scsi_qla_host *vha = sp->fcport->vha;
struct qla_hw_data *ha = vha->hw;
@@ -311,17 +387,8 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp)
/* Acquire qpair specific lock */
spin_lock_irqsave(&qpair->qp_lock, flags);
- /* Check for room in outstanding command list. */
- handle = req->current_outstanding_cmd;
- for (index = 1; index < req->num_outstanding_cmds; index++) {
- handle++;
- if (handle == req->num_outstanding_cmds)
- handle = 1;
- if (!req->outstanding_cmds[handle])
- break;
- }
-
- if (index == req->num_outstanding_cmds) {
+ handle = qla2xxx_get_next_handle(req);
+ if (handle == 0) {
rval = -EBUSY;
goto queuing_error;
}
@@ -343,6 +410,7 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp)
if (unlikely(!fd->sqid)) {
struct nvme_fc_cmd_iu *cmd = fd->cmdaddr;
+
if (cmd->sqe.common.opcode == nvme_admin_async_event) {
nvme->u.nvme.aen_op = 1;
atomic_inc(&ha->nvme_active_aen_cnt);
@@ -369,17 +437,24 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp)
/* No data transfer how do we check buffer len == 0?? */
if (fd->io_dir == NVMEFC_FCP_READ) {
- cmd_pkt->control_flags =
- cpu_to_le16(CF_READ_DATA | CF_NVME_ENABLE);
+ cmd_pkt->control_flags = CF_READ_DATA;
vha->qla_stats.input_bytes += fd->payload_length;
vha->qla_stats.input_requests++;
} else if (fd->io_dir == NVMEFC_FCP_WRITE) {
- cmd_pkt->control_flags =
- cpu_to_le16(CF_WRITE_DATA | CF_NVME_ENABLE);
+ cmd_pkt->control_flags = CF_WRITE_DATA;
+ if ((vha->flags.nvme_first_burst) &&
+ (sp->fcport->nvme_prli_service_param &
+ NVME_PRLI_SP_FIRST_BURST)) {
+ if ((fd->payload_length <=
+ sp->fcport->nvme_first_burst_size) ||
+ (sp->fcport->nvme_first_burst_size == 0))
+ cmd_pkt->control_flags |=
+ CF_NVME_FIRST_BURST_ENABLE;
+ }
vha->qla_stats.output_bytes += fd->payload_length;
vha->qla_stats.output_requests++;
} else if (fd->io_dir == 0) {
- cmd_pkt->control_flags = cpu_to_le16(CF_NVME_ENABLE);
+ cmd_pkt->control_flags = 0;
}
/* Set NPORT-ID */
@@ -391,25 +466,22 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp)
/* NVME RSP IU */
cmd_pkt->nvme_rsp_dsd_len = cpu_to_le16(fd->rsplen);
- cmd_pkt->nvme_rsp_dseg_address[0] = cpu_to_le32(LSD(fd->rspdma));
- cmd_pkt->nvme_rsp_dseg_address[1] = cpu_to_le32(MSD(fd->rspdma));
+ put_unaligned_le64(fd->rspdma, &cmd_pkt->nvme_rsp_dseg_address);
/* NVME CNMD IU */
cmd_pkt->nvme_cmnd_dseg_len = cpu_to_le16(fd->cmdlen);
- cmd_pkt->nvme_cmnd_dseg_address[0] = cpu_to_le32(LSD(fd->cmddma));
- cmd_pkt->nvme_cmnd_dseg_address[1] = cpu_to_le32(MSD(fd->cmddma));
+ cmd_pkt->nvme_cmnd_dseg_address = cpu_to_le64(fd->cmddma);
cmd_pkt->dseg_count = cpu_to_le16(tot_dsds);
cmd_pkt->byte_count = cpu_to_le32(fd->payload_length);
/* One DSD is available in the Command Type NVME IOCB */
avail_dsds = 1;
- cur_dsd = (uint32_t *)&cmd_pkt->nvme_data_dseg_address[0];
+ cur_dsd = &cmd_pkt->nvme_dsd;
sgl = fd->first_sgl;
/* Load data segments */
for_each_sg(sgl, sg, tot_dsds, i) {
- dma_addr_t sle_dma;
cont_a64_entry_t *cont_pkt;
/* Allocate additional continuation packets? */
@@ -428,17 +500,14 @@ static inline int qla2x00_start_nvme_mq(srb_t *sp)
req->ring_ptr++;
}
cont_pkt = (cont_a64_entry_t *)req->ring_ptr;
- *((uint32_t *)(&cont_pkt->entry_type)) =
- cpu_to_le32(CONTINUE_A64_TYPE);
+ put_unaligned_le32(CONTINUE_A64_TYPE,
+ &cont_pkt->entry_type);
- cur_dsd = (uint32_t *)cont_pkt->dseg_0_address;
- avail_dsds = 5;
+ cur_dsd = cont_pkt->dsd;
+ avail_dsds = ARRAY_SIZE(cont_pkt->dsd);
}
- sle_dma = sg_dma_address(sg);
- *cur_dsd++ = cpu_to_le32(LSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(MSD(sle_dma));
- *cur_dsd++ = cpu_to_le32(sg_dma_len(sg));
+ append_dsd64(&cur_dsd, sg);
avail_dsds--;
}
@@ -479,11 +548,11 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport,
fcport = qla_rport->fcport;
- vha = fcport->vha;
-
- if (test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
+ if (!qpair || !fcport || (qpair && !qpair->fw_started) ||
+ (fcport && fcport->deleted))
return rval;
+ vha = fcport->vha;
/*
* If we know the dev is going away while the transport is still sending
* IO's return busy back to stall the IO Q. This happens when the
@@ -499,12 +568,15 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport,
if (!sp)
return -EBUSY;
- atomic_set(&sp->ref_count, 1);
init_waitqueue_head(&sp->nvme_ls_waitq);
+ kref_init(&sp->cmd_kref);
+ spin_lock_init(&priv->cmd_lock);
+ sp->priv = (void *)priv;
priv->sp = sp;
sp->type = SRB_NVME_CMD;
sp->name = "nvme_cmd";
sp->done = qla_nvme_sp_done;
+ sp->put_fn = qla_nvme_release_fcp_cmd_kref;
sp->qpair = qpair;
sp->vha = vha;
nvme = &sp->u.iocb_cmd;
@@ -514,8 +586,10 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport,
if (rval != QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x212d,
"qla2x00_start_nvme_mq failed = %d\n", rval);
- atomic_dec(&sp->ref_count);
wake_up(&sp->nvme_ls_waitq);
+ sp->priv = NULL;
+ priv->sp = NULL;
+ qla2xxx_rel_qpair_sp(sp->qpair, sp);
}
return rval;
@@ -534,29 +608,16 @@ static void qla_nvme_localport_delete(struct nvme_fc_local_port *lport)
static void qla_nvme_remoteport_delete(struct nvme_fc_remote_port *rport)
{
fc_port_t *fcport;
- struct qla_nvme_rport *qla_rport = rport->private, *trport;
+ struct qla_nvme_rport *qla_rport = rport->private;
fcport = qla_rport->fcport;
fcport->nvme_remote_port = NULL;
fcport->nvme_flag &= ~NVME_FLAG_REGISTERED;
-
- list_for_each_entry_safe(qla_rport, trport,
- &fcport->vha->nvme_rport_list, list) {
- if (qla_rport->fcport == fcport) {
- list_del(&qla_rport->list);
- break;
- }
- }
- complete(&fcport->nvme_del_done);
-
- if (!test_bit(UNLOADING, &fcport->vha->dpc_flags)) {
- INIT_WORK(&fcport->free_work, qlt_free_session_done);
- schedule_work(&fcport->free_work);
- }
-
fcport->nvme_flag &= ~NVME_FLAG_DELETING;
ql_log(ql_log_info, fcport->vha, 0x2110,
- "remoteport_delete of %p completed.\n", fcport);
+ "remoteport_delete of %p %8phN completed.\n",
+ fcport, fcport->port_name);
+ complete(&fcport->nvme_del_done);
}
static struct nvme_fc_port_template qla_nvme_fc_transport = {
@@ -570,7 +631,7 @@ static struct nvme_fc_port_template qla_nvme_fc_transport = {
.fcp_abort = qla_nvme_fcp_abort,
.poll_queue = qla_nvme_poll,
.max_hw_queues = 8,
- .max_sgl_segments = 128,
+ .max_sgl_segments = 1024,
.max_dif_sgl_segments = 64,
.dma_boundary = 0xFFFFFFFF,
.local_priv_sz = 8,
@@ -579,79 +640,36 @@ static struct nvme_fc_port_template qla_nvme_fc_transport = {
.fcprqst_priv_sz = sizeof(struct nvme_private),
};
-#define NVME_ABORT_POLLING_PERIOD 2
-static int qla_nvme_wait_on_command(srb_t *sp)
-{
- int ret = QLA_SUCCESS;
-
- wait_event_timeout(sp->nvme_ls_waitq, (atomic_read(&sp->ref_count) > 1),
- NVME_ABORT_POLLING_PERIOD*HZ);
-
- if (atomic_read(&sp->ref_count) > 1)
- ret = QLA_FUNCTION_FAILED;
-
- return ret;
-}
-
-void qla_nvme_abort(struct qla_hw_data *ha, struct srb *sp, int res)
-{
- int rval;
-
- if (ha->flags.fw_started) {
- rval = ha->isp_ops->abort_command(sp);
- if (!rval && !qla_nvme_wait_on_command(sp))
- ql_log(ql_log_warn, NULL, 0x2112,
- "timed out waiting on sp=%p\n", sp);
- } else {
- sp->done(sp, res);
- }
-}
-
-static void qla_nvme_unregister_remote_port(struct work_struct *work)
+void qla_nvme_unregister_remote_port(struct fc_port *fcport)
{
- struct fc_port *fcport = container_of(work, struct fc_port,
- nvme_del_work);
- struct qla_nvme_rport *qla_rport, *trport;
+ int ret;
if (!IS_ENABLED(CONFIG_NVME_FC))
return;
ql_log(ql_log_warn, NULL, 0x2112,
- "%s: unregister remoteport on %p\n",__func__, fcport);
-
- list_for_each_entry_safe(qla_rport, trport,
- &fcport->vha->nvme_rport_list, list) {
- if (qla_rport->fcport == fcport) {
- ql_log(ql_log_info, fcport->vha, 0x2113,
- "%s: fcport=%p\n", __func__, fcport);
- init_completion(&fcport->nvme_del_done);
- nvme_fc_unregister_remoteport(
- fcport->nvme_remote_port);
- wait_for_completion(&fcport->nvme_del_done);
- break;
- }
- }
+ "%s: unregister remoteport on %p %8phN\n",
+ __func__, fcport, fcport->port_name);
+
+ if (test_bit(PFLG_DRIVER_REMOVING, &fcport->vha->pci_flags))
+ nvme_fc_set_remoteport_devloss(fcport->nvme_remote_port, 0);
+
+ init_completion(&fcport->nvme_del_done);
+ ret = nvme_fc_unregister_remoteport(fcport->nvme_remote_port);
+ if (ret)
+ ql_log(ql_log_info, fcport->vha, 0x2114,
+ "%s: Failed to unregister nvme_remote_port (%d)\n",
+ __func__, ret);
+ wait_for_completion(&fcport->nvme_del_done);
}
void qla_nvme_delete(struct scsi_qla_host *vha)
{
- struct qla_nvme_rport *qla_rport, *trport;
- fc_port_t *fcport;
int nv_ret;
if (!IS_ENABLED(CONFIG_NVME_FC))
return;
- list_for_each_entry_safe(qla_rport, trport,
- &vha->nvme_rport_list, list) {
- fcport = qla_rport->fcport;
-
- ql_log(ql_log_info, fcport->vha, 0x2114, "%s: fcport=%p\n",
- __func__, fcport);
-
- nvme_fc_set_remoteport_devloss(fcport->nvme_remote_port, 0);
- }
-
if (vha->nvme_local_port) {
init_completion(&vha->nvme_del_done);
ql_log(ql_log_info, vha, 0x2116,
diff --git a/drivers/scsi/qla2xxx/qla_nvme.h b/drivers/scsi/qla2xxx/qla_nvme.h
index 4941d107fb1c..ef912902d4e5 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.h
+++ b/drivers/scsi/qla2xxx/qla_nvme.h
@@ -7,12 +7,12 @@
#ifndef __QLA_NVME_H
#define __QLA_NVME_H
-#include <linux/blk-mq.h>
#include <uapi/scsi/fc/fc_fs.h>
#include <uapi/scsi/fc/fc_els.h>
#include <linux/nvme-fc-driver.h>
#include "qla_def.h"
+#include "qla_dsd.h"
/* default dev loss time (seconds) before transport tears down ctrl */
#define NVME_FC_DEV_LOSS_TMO 30
@@ -33,10 +33,10 @@ struct nvme_private {
struct work_struct ls_work;
struct work_struct abort_work;
int comp_status;
+ spinlock_t cmd_lock;
};
struct qla_nvme_rport {
- struct list_head list;
struct fc_port *fcport;
};
@@ -57,23 +57,22 @@ struct cmd_nvme {
uint64_t rsvd;
uint16_t control_flags; /* Control Flags */
-#define CF_NVME_ENABLE BIT_9
+#define CF_NVME_FIRST_BURST_ENABLE BIT_11
#define CF_DIF_SEG_DESCR_ENABLE BIT_3
#define CF_DATA_SEG_DESCR_ENABLE BIT_2
#define CF_READ_DATA BIT_1
#define CF_WRITE_DATA BIT_0
uint16_t nvme_cmnd_dseg_len; /* Data segment length. */
- uint32_t nvme_cmnd_dseg_address[2]; /* Data segment address. */
- uint32_t nvme_rsp_dseg_address[2]; /* Data segment address. */
+ __le64 nvme_cmnd_dseg_address __packed;/* Data segment address. */
+ __le64 nvme_rsp_dseg_address __packed; /* Data segment address. */
uint32_t byte_count; /* Total byte count. */
uint8_t port_id[3]; /* PortID of destination port. */
uint8_t vp_index;
- uint32_t nvme_data_dseg_address[2]; /* Data segment address. */
- uint32_t nvme_data_dseg_len; /* Data segment length. */
+ struct dsd64 nvme_dsd;
};
#define PT_LS4_REQUEST 0x89 /* Link Service pass-through IOCB (request) */
@@ -101,10 +100,7 @@ struct pt_ls4_request {
uint32_t rsvd3;
uint32_t rx_byte_count;
uint32_t tx_byte_count;
- uint32_t dseg0_address[2];
- uint32_t dseg0_len;
- uint32_t dseg1_address[2];
- uint32_t dseg1_len;
+ struct dsd64 dsd[2];
};
#define PT_LS4_UNSOL 0x56 /* pass-up unsolicited rec FC-NVMe request */
@@ -122,7 +118,7 @@ struct pt_ls4_rx_unsol {
uint32_t exchange_address;
uint8_t d_id[3];
uint8_t r_ctl;
- uint8_t s_id[3];
+ be_id_t s_id;
uint8_t cs_ctl;
uint8_t f_ctl[3];
uint8_t type;
@@ -145,8 +141,7 @@ struct pt_ls4_rx_unsol {
int qla_nvme_register_hba(struct scsi_qla_host *);
int qla_nvme_register_remote(struct scsi_qla_host *, struct fc_port *);
void qla_nvme_delete(struct scsi_qla_host *);
-void qla_nvme_abort(struct qla_hw_data *, struct srb *sp, int res);
void qla24xx_nvme_ls4_iocb(struct scsi_qla_host *, struct pt_ls4_request *,
struct req_que *);
-void qla24xx_async_gffid_sp_done(void *, int);
+void qla24xx_async_gffid_sp_done(struct srb *sp, int);
#endif
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index 4d0aaae12253..a8182e2a4143 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -6,6 +6,7 @@
*/
#include "qla_def.h"
#include <linux/delay.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/pci.h>
#include <linux/ratelimit.h>
#include <linux/vmalloc.h>
@@ -608,6 +609,7 @@ qla82xx_pci_set_window(struct qla_hw_data *ha, unsigned long long addr)
} else if (addr_in_range(addr, QLA82XX_ADDR_OCM0,
QLA82XX_ADDR_OCM0_MAX)) {
unsigned int temp1;
+
if ((addr & 0x00ff800) == 0xff800) {
ql_log(ql_log_warn, vha, 0xb004,
"%s: QM access not handled.\n", __func__);
@@ -990,6 +992,7 @@ static int
qla82xx_read_status_reg(struct qla_hw_data *ha, uint32_t *val)
{
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
+
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_RDSR);
qla82xx_wait_rom_busy(ha);
if (qla82xx_wait_rom_done(ha)) {
@@ -1030,6 +1033,7 @@ static int
qla82xx_flash_set_write_enable(struct qla_hw_data *ha)
{
uint32_t val;
+
qla82xx_wait_rom_busy(ha);
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_ABYTE_CNT, 0);
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_WREN);
@@ -1047,6 +1051,7 @@ static int
qla82xx_write_status_reg(struct qla_hw_data *ha, uint32_t val)
{
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
+
if (qla82xx_flash_set_write_enable(ha))
return -1;
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_WDATA, val);
@@ -1063,6 +1068,7 @@ static int
qla82xx_write_disable_flash(struct qla_hw_data *ha)
{
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
+
qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_INSTR_OPCODE, M25P_INSTR_WRDI);
if (qla82xx_wait_rom_done(ha)) {
ql_log(ql_log_warn, vha, 0xb00f,
@@ -1435,6 +1441,7 @@ qla82xx_fw_load_from_flash(struct qla_hw_data *ha)
long memaddr = BOOTLD_START;
u64 data;
u32 high, low;
+
size = (IMAGE_START - BOOTLD_START) / 8;
for (i = 0; i < size; i++) {
@@ -1757,11 +1764,14 @@ qla82xx_pci_config(scsi_qla_host_t *vha)
*
* Returns 0 on success.
*/
-void
+int
qla82xx_reset_chip(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
+
ha->isp_ops->disable_intrs(ha);
+
+ return QLA_SUCCESS;
}
void qla82xx_config_rings(struct scsi_qla_host *vha)
@@ -1778,10 +1788,8 @@ void qla82xx_config_rings(struct scsi_qla_host *vha)
icb->response_q_inpointer = cpu_to_le16(0);
icb->request_q_length = cpu_to_le16(req->length);
icb->response_q_length = cpu_to_le16(rsp->length);
- icb->request_q_address[0] = cpu_to_le32(LSD(req->dma));
- icb->request_q_address[1] = cpu_to_le32(MSD(req->dma));
- icb->response_q_address[0] = cpu_to_le32(LSD(rsp->dma));
- icb->response_q_address[1] = cpu_to_le32(MSD(rsp->dma));
+ put_unaligned_le64(req->dma, &icb->request_q_address);
+ put_unaligned_le64(rsp->dma, &icb->response_q_address);
WRT_REG_DWORD(&reg->req_q_out[0], 0);
WRT_REG_DWORD(&reg->rsp_q_in[0], 0);
@@ -1969,7 +1977,7 @@ qla82xx_check_rcvpeg_state(struct qla_hw_data *ha)
} while (--retries);
ql_log(ql_log_fatal, vha, 0x00ac,
- "Rcv Peg initializatin failed: 0x%x.\n", val);
+ "Rcv Peg initialization failed: 0x%x.\n", val);
read_lock(&ha->hw_lock);
qla82xx_wr_32(ha, CRB_RCVPEG_STATE, PHAN_INITIALIZE_FAILED);
read_unlock(&ha->hw_lock);
@@ -1977,7 +1985,7 @@ qla82xx_check_rcvpeg_state(struct qla_hw_data *ha)
}
/* ISR related functions */
-static struct qla82xx_legacy_intr_set legacy_intr[] = \
+static struct qla82xx_legacy_intr_set legacy_intr[] =
QLA82XX_LEGACY_INTR_CONFIG;
/*
@@ -1992,6 +2000,7 @@ qla82xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
uint16_t __iomem *wptr;
struct qla_hw_data *ha = vha->hw;
struct device_reg_82xx __iomem *reg = &ha->iobase->isp82;
+
wptr = (uint16_t __iomem *)&reg->mailbox_out[1];
/* Load return mailbox registers. */
@@ -2028,7 +2037,7 @@ qla82xx_intr_handler(int irq, void *dev_id)
unsigned long flags;
unsigned long iter;
uint32_t stat = 0;
- uint16_t mb[4];
+ uint16_t mb[8];
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
@@ -2112,7 +2121,7 @@ qla82xx_msix_default(int irq, void *dev_id)
unsigned long flags;
uint32_t stat = 0;
uint32_t host_int = 0;
- uint16_t mb[4];
+ uint16_t mb[8];
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
@@ -2208,7 +2217,7 @@ qla82xx_poll(int irq, void *dev_id)
int status = 0;
uint32_t stat;
uint32_t host_int = 0;
- uint16_t mb[4];
+ uint16_t mb[8];
unsigned long flags;
rsp = (struct rsp_que *) dev_id;
@@ -2262,6 +2271,7 @@ void
qla82xx_enable_intrs(struct qla_hw_data *ha)
{
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
+
qla82xx_mbx_intr_enable(vha);
spin_lock_irq(&ha->hardware_lock);
if (IS_QLA8044(ha))
@@ -2276,7 +2286,10 @@ void
qla82xx_disable_intrs(struct qla_hw_data *ha)
{
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
- qla82xx_mbx_intr_disable(vha);
+
+ if (ha->interrupts_on)
+ qla82xx_mbx_intr_disable(vha);
+
spin_lock_irq(&ha->hardware_lock);
if (IS_QLA8044(ha))
qla8044_wr_reg(ha, LEG_INTR_MASK_OFFSET, 1);
@@ -2658,8 +2671,8 @@ done:
/*
* Address and length are byte address
*/
-uint8_t *
-qla82xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
+void *
+qla82xx_read_optrom_data(struct scsi_qla_host *vha, void *buf,
uint32_t offset, uint32_t length)
{
scsi_block_requests(vha->host);
@@ -2767,15 +2780,14 @@ write_done:
}
int
-qla82xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
+qla82xx_write_optrom_data(struct scsi_qla_host *vha, void *buf,
uint32_t offset, uint32_t length)
{
int rval;
/* Suspend HBA. */
scsi_block_requests(vha->host);
- rval = qla82xx_write_flash_data(vha, (uint32_t *)buf, offset,
- length >> 2);
+ rval = qla82xx_write_flash_data(vha, buf, offset, length >> 2);
scsi_unblock_requests(vha->host);
/* Convert return ISP82xx to generic */
@@ -3276,7 +3288,7 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
case QLA8XXX_DEV_NEED_QUIESCENT:
qla82xx_need_qsnt_handler(vha);
/* Reset timeout value after quiescence handler */
- dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout\
+ dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout
* HZ);
break;
case QLA8XXX_DEV_QUIESCENT:
@@ -3291,7 +3303,7 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
qla82xx_idc_lock(ha);
/* Reset timeout value after quiescence handler */
- dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout\
+ dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout
* HZ);
break;
case QLA8XXX_DEV_FAILED:
@@ -3676,7 +3688,7 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha)
for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
sp = req->outstanding_cmds[cnt];
if (sp) {
- if ((!sp->u.scmd.ctx ||
+ if ((!sp->u.scmd.crc_ctx ||
(sp->flags &
SRB_FCP_CMND_DMA_VALID)) &&
!ha->flags.isp82xx_fw_hung) {
@@ -3700,10 +3712,12 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha)
/* Wait for pending cmds (physical and virtual) to complete */
if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0,
- WAIT_HOST)) {
+ WAIT_HOST) == QLA_SUCCESS) {
ql_dbg(ql_dbg_init, vha, 0x00b3,
"Done wait for "
"pending commands.\n");
+ } else {
+ WARN_ON_ONCE(true);
}
}
}
@@ -4222,7 +4236,7 @@ qla82xx_md_collect(scsi_qla_host_t *vha)
goto md_failed;
}
- entry_hdr = (qla82xx_md_entry_hdr_t *) \
+ entry_hdr = (qla82xx_md_entry_hdr_t *)
(((uint8_t *)ha->md_tmplt_hdr) + tmplt_hdr->first_entry_offset);
/* Walk through the entry headers */
@@ -4329,7 +4343,7 @@ qla82xx_md_collect(scsi_qla_host_t *vha)
data_collected = (uint8_t *)data_ptr -
(uint8_t *)ha->md_dump;
skip_nxt_entry:
- entry_hdr = (qla82xx_md_entry_hdr_t *) \
+ entry_hdr = (qla82xx_md_entry_hdr_t *)
(((uint8_t *)entry_hdr) + entry_hdr->entry_size);
}
@@ -4464,6 +4478,7 @@ qla82xx_beacon_on(struct scsi_qla_host *vha)
int rval;
struct qla_hw_data *ha = vha->hw;
+
qla82xx_idc_lock(ha);
rval = qla82xx_mbx_beacon_ctl(vha, 1);
@@ -4484,6 +4499,7 @@ qla82xx_beacon_off(struct scsi_qla_host *vha)
int rval;
struct qla_hw_data *ha = vha->hw;
+
qla82xx_idc_lock(ha);
rval = qla82xx_mbx_beacon_ctl(vha, 0);
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h
index 71a41093530e..230abee10598 100644
--- a/drivers/scsi/qla2xxx/qla_nx.h
+++ b/drivers/scsi/qla2xxx/qla_nx.h
@@ -7,7 +7,7 @@
#ifndef __QLA_NX_H
#define __QLA_NX_H
-#include <linux/io-64-nonatomic-lo-hi.h>
+#include <scsi/scsi.h>
/*
* Following are the states of the Phantom. Phantom will set them and
@@ -486,13 +486,13 @@
#define QLA82XX_ADDR_QDR_NET (0x0000000300000000ULL)
#define QLA82XX_P3_ADDR_QDR_NET_MAX (0x0000000303ffffffULL)
-#define QLA82XX_PCI_CRBSPACE (unsigned long)0x06000000
-#define QLA82XX_PCI_DIRECT_CRB (unsigned long)0x04400000
-#define QLA82XX_PCI_CAMQM (unsigned long)0x04800000
-#define QLA82XX_PCI_CAMQM_MAX (unsigned long)0x04ffffff
-#define QLA82XX_PCI_DDR_NET (unsigned long)0x00000000
-#define QLA82XX_PCI_QDR_NET (unsigned long)0x04000000
-#define QLA82XX_PCI_QDR_NET_MAX (unsigned long)0x043fffff
+#define QLA82XX_PCI_CRBSPACE 0x06000000UL
+#define QLA82XX_PCI_DIRECT_CRB 0x04400000UL
+#define QLA82XX_PCI_CAMQM 0x04800000UL
+#define QLA82XX_PCI_CAMQM_MAX 0x04ffffffUL
+#define QLA82XX_PCI_DDR_NET 0x00000000UL
+#define QLA82XX_PCI_QDR_NET 0x04000000UL
+#define QLA82XX_PCI_QDR_NET_MAX 0x043fffffUL
/*
* Register offsets for MN
diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c
index fe856b602e03..c056f466f1f4 100644
--- a/drivers/scsi/qla2xxx/qla_nx2.c
+++ b/drivers/scsi/qla2xxx/qla_nx2.c
@@ -559,12 +559,12 @@ exit_lock_error:
/*
* Address and length are byte address
*/
-uint8_t *
-qla8044_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
+void *
+qla8044_read_optrom_data(struct scsi_qla_host *vha, void *buf,
uint32_t offset, uint32_t length)
{
scsi_block_requests(vha->host);
- if (qla8044_read_flash_data(vha, (uint8_t *)buf, offset, length / 4)
+ if (qla8044_read_flash_data(vha, buf, offset, length / 4)
!= QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0xb08d,
"%s: Failed to read from flash\n",
@@ -2810,7 +2810,7 @@ error:
#define ISP8044_PEX_DMA_ENGINE_INDEX 8
#define ISP8044_PEX_DMA_BASE_ADDRESS 0x77320000
-#define ISP8044_PEX_DMA_NUM_OFFSET 0x10000
+#define ISP8044_PEX_DMA_NUM_OFFSET 0x10000UL
#define ISP8044_PEX_DMA_CMD_ADDR_LOW 0x0
#define ISP8044_PEX_DMA_CMD_ADDR_HIGH 0x04
#define ISP8044_PEX_DMA_CMD_STS_AND_CNTRL 0x08
@@ -3007,10 +3007,9 @@ qla8044_minidump_process_rddfe(struct scsi_qla_host *vha,
uint16_t count;
uint32_t poll, mask, modify_mask;
uint32_t wait_count = 0;
-
uint32_t *data_ptr = *d_ptr;
-
struct qla8044_minidump_entry_rddfe *rddfe;
+
rddfe = (struct qla8044_minidump_entry_rddfe *) entry_hdr;
addr1 = rddfe->addr_1;
@@ -3797,7 +3796,7 @@ qla8044_write_flash_dword_mode(scsi_qla_host_t *vha, uint32_t *dwptr,
}
int
-qla8044_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
+qla8044_write_optrom_data(struct scsi_qla_host *vha, void *buf,
uint32_t offset, uint32_t length)
{
int rval = QLA_FUNCTION_FAILED, i, burst_iter_count;
@@ -3896,7 +3895,7 @@ qla8044_intr_handler(int irq, void *dev_id)
unsigned long flags;
unsigned long iter;
uint32_t stat;
- uint16_t mb[4];
+ uint16_t mb[8];
uint32_t leg_int_ptr = 0, pf_bit;
rsp = (struct rsp_que *) dev_id;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 4827a29648f8..03eb636572f0 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -42,7 +42,7 @@ static struct kmem_cache *ctx_cachep;
/*
* error level for logging
*/
-int ql_errlev = ql_log_all;
+uint ql_errlev = 0x8001;
static int ql2xenableclass2;
module_param(ql2xenableclass2, int, S_IRUGO|S_IRUSR);
@@ -69,7 +69,7 @@ MODULE_PARM_DESC(ql2xplogiabsentdevice,
"a Fabric scan. This is needed for several broken switches. "
"Default is 0 - no PLOGI. 1 - perform PLOGI.");
-int ql2xloginretrycount = 0;
+int ql2xloginretrycount;
module_param(ql2xloginretrycount, int, S_IRUGO);
MODULE_PARM_DESC(ql2xloginretrycount,
"Specify an alternate value for the NVRAM login retry count.");
@@ -108,7 +108,7 @@ MODULE_PARM_DESC(ql2xshiftctondsd,
"Set to control shifting of command type processing "
"based on total number of SG elements.");
-int ql2xfdmienable=1;
+int ql2xfdmienable = 1;
module_param(ql2xfdmienable, int, S_IRUGO|S_IWUSR);
module_param_named(fdmi, ql2xfdmienable, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xfdmienable,
@@ -150,7 +150,7 @@ MODULE_PARM_DESC(ql2xenablehba_err_chk,
" 1 -- Error isolation enabled only for DIX Type 0\n"
" 2 -- Error isolation enabled for all Types\n");
-int ql2xiidmaenable=1;
+int ql2xiidmaenable = 1;
module_param(ql2xiidmaenable, int, S_IRUGO);
MODULE_PARM_DESC(ql2xiidmaenable,
"Enables iIDMA settings "
@@ -202,7 +202,7 @@ int ql2xasynctmfenable = 1;
module_param(ql2xasynctmfenable, int, S_IRUGO);
MODULE_PARM_DESC(ql2xasynctmfenable,
"Enables issue of TM IOCBs asynchronously via IOCB mechanism"
- "Default is 0 - Issue TM IOCBs via mailbox mechanism.");
+ "Default is 1 - Issue TM IOCBs via mailbox mechanism.");
int ql2xdontresethba;
module_param(ql2xdontresethba, int, S_IRUGO|S_IWUSR);
@@ -230,7 +230,7 @@ MODULE_PARM_DESC(ql2xmdenable,
"0 - MiniDump disabled. "
"1 (Default) - MiniDump enabled.");
-int ql2xexlogins = 0;
+int ql2xexlogins;
module_param(ql2xexlogins, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xexlogins,
"Number of extended Logins. "
@@ -246,7 +246,7 @@ module_param(ql2xiniexchg, uint, 0644);
MODULE_PARM_DESC(ql2xiniexchg,
"Number of initiator exchanges.");
-int ql2xfwholdabts = 0;
+int ql2xfwholdabts;
module_param(ql2xfwholdabts, int, S_IRUGO);
MODULE_PARM_DESC(ql2xfwholdabts,
"Allow FW to hold status IOCB until ABTS rsp received. "
@@ -281,20 +281,26 @@ MODULE_PARM_DESC(qla2xuseresexchforels,
"Reserve 1/2 of emergency exchanges for ELS.\n"
" 0 (default): disabled");
-/*
- * SCSI host template entry points
- */
-static int qla2xxx_slave_configure(struct scsi_device * device);
-static int qla2xxx_slave_alloc(struct scsi_device *);
-static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time);
-static void qla2xxx_scan_start(struct Scsi_Host *);
-static void qla2xxx_slave_destroy(struct scsi_device *);
-static int qla2xxx_queuecommand(struct Scsi_Host *h, struct scsi_cmnd *cmd);
-static int qla2xxx_eh_abort(struct scsi_cmnd *);
-static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
-static int qla2xxx_eh_target_reset(struct scsi_cmnd *);
-static int qla2xxx_eh_bus_reset(struct scsi_cmnd *);
-static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
+static int ql2xprotmask;
+module_param(ql2xprotmask, int, 0644);
+MODULE_PARM_DESC(ql2xprotmask,
+ "Override DIF/DIX protection capabilities mask\n"
+ "Default is 0 which sets protection mask based on "
+ "capabilities reported by HBA firmware.\n");
+
+static int ql2xprotguard;
+module_param(ql2xprotguard, int, 0644);
+MODULE_PARM_DESC(ql2xprotguard, "Override choice of DIX checksum\n"
+ " 0 -- Let HBA firmware decide\n"
+ " 1 -- Force T10 CRC\n"
+ " 2 -- Force IP checksum\n");
+
+int ql2xdifbundlinginternalbuffers;
+module_param(ql2xdifbundlinginternalbuffers, int, 0644);
+MODULE_PARM_DESC(ql2xdifbundlinginternalbuffers,
+ "Force using internal buffers for DIF information\n"
+ "0 (Default). Based on check.\n"
+ "1 Force using internal buffers\n");
static void qla2x00_clear_drv_active(struct qla_hw_data *);
static void qla2x00_free_device(scsi_qla_host_t *);
@@ -302,38 +308,6 @@ static int qla2xxx_map_queues(struct Scsi_Host *shost);
static void qla2x00_destroy_deferred_work(struct qla_hw_data *);
-struct scsi_host_template qla2xxx_driver_template = {
- .module = THIS_MODULE,
- .name = QLA2XXX_DRIVER_NAME,
- .queuecommand = qla2xxx_queuecommand,
-
- .eh_timed_out = fc_eh_timed_out,
- .eh_abort_handler = qla2xxx_eh_abort,
- .eh_device_reset_handler = qla2xxx_eh_device_reset,
- .eh_target_reset_handler = qla2xxx_eh_target_reset,
- .eh_bus_reset_handler = qla2xxx_eh_bus_reset,
- .eh_host_reset_handler = qla2xxx_eh_host_reset,
-
- .slave_configure = qla2xxx_slave_configure,
-
- .slave_alloc = qla2xxx_slave_alloc,
- .slave_destroy = qla2xxx_slave_destroy,
- .scan_finished = qla2xxx_scan_finished,
- .scan_start = qla2xxx_scan_start,
- .change_queue_depth = scsi_change_queue_depth,
- .map_queues = qla2xxx_map_queues,
- .this_id = -1,
- .cmd_per_lun = 3,
- .use_clustering = ENABLE_CLUSTERING,
- .sg_tablesize = SG_ALL,
-
- .max_sectors = 0xFFFF,
- .shost_attrs = qla2x00_host_attrs,
-
- .supported_mode = MODE_INITIATOR,
- .track_queue_depth = 1,
-};
-
static struct scsi_transport_template *qla2xxx_transport_template = NULL;
struct scsi_transport_template *qla2xxx_transport_vport_template = NULL;
@@ -389,6 +363,7 @@ static void qla_init_base_qpair(struct scsi_qla_host *vha, struct req_que *req,
struct rsp_que *rsp)
{
struct qla_hw_data *ha = vha->hw;
+
rsp->qpair = ha->base_qpair;
rsp->req = req;
ha->base_qpair->hw = ha;
@@ -405,7 +380,7 @@ static void qla_init_base_qpair(struct scsi_qla_host *vha, struct req_que *req,
qla_cpu_update(rsp->qpair, raw_smp_processor_id());
ha->base_qpair->pdev = ha->pdev;
- if (IS_QLA27XX(ha) || IS_QLA83XX(ha))
+ if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha))
ha->base_qpair->reqq_start_iocbs = qla_83xx_start_iocbs;
}
@@ -413,6 +388,7 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
struct rsp_que *rsp)
{
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
+
ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues,
GFP_KERNEL);
if (!ha->req_q_map) {
@@ -558,80 +534,70 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
}
static char *
-qla2x00_pci_info_str(struct scsi_qla_host *vha, char *str)
+qla2x00_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len)
{
struct qla_hw_data *ha = vha->hw;
- static char *pci_bus_modes[] = {
+ static const char *const pci_bus_modes[] = {
"33", "66", "100", "133",
};
uint16_t pci_bus;
- strcpy(str, "PCI");
pci_bus = (ha->pci_attr & (BIT_9 | BIT_10)) >> 9;
if (pci_bus) {
- strcat(str, "-X (");
- strcat(str, pci_bus_modes[pci_bus]);
+ snprintf(str, str_len, "PCI-X (%s MHz)",
+ pci_bus_modes[pci_bus]);
} else {
pci_bus = (ha->pci_attr & BIT_8) >> 8;
- strcat(str, " (");
- strcat(str, pci_bus_modes[pci_bus]);
+ snprintf(str, str_len, "PCI (%s MHz)", pci_bus_modes[pci_bus]);
}
- strcat(str, " MHz)");
- return (str);
+ return str;
}
static char *
-qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str)
+qla24xx_pci_info_str(struct scsi_qla_host *vha, char *str, size_t str_len)
{
- static char *pci_bus_modes[] = { "33", "66", "100", "133", };
+ static const char *const pci_bus_modes[] = {
+ "33", "66", "100", "133",
+ };
struct qla_hw_data *ha = vha->hw;
uint32_t pci_bus;
if (pci_is_pcie(ha->pdev)) {
- char lwstr[6];
uint32_t lstat, lspeed, lwidth;
+ const char *speed_str;
pcie_capability_read_dword(ha->pdev, PCI_EXP_LNKCAP, &lstat);
lspeed = lstat & PCI_EXP_LNKCAP_SLS;
lwidth = (lstat & PCI_EXP_LNKCAP_MLW) >> 4;
- strcpy(str, "PCIe (");
switch (lspeed) {
case 1:
- strcat(str, "2.5GT/s ");
+ speed_str = "2.5GT/s";
break;
case 2:
- strcat(str, "5.0GT/s ");
+ speed_str = "5.0GT/s";
break;
case 3:
- strcat(str, "8.0GT/s ");
+ speed_str = "8.0GT/s";
break;
default:
- strcat(str, "<unknown> ");
+ speed_str = "<unknown>";
break;
}
- snprintf(lwstr, sizeof(lwstr), "x%d)", lwidth);
- strcat(str, lwstr);
+ snprintf(str, str_len, "PCIe (%s x%d)", speed_str, lwidth);
return str;
}
- strcpy(str, "PCI");
pci_bus = (ha->pci_attr & CSRX_PCIX_BUS_MODE_MASK) >> 8;
- if (pci_bus == 0 || pci_bus == 8) {
- strcat(str, " (");
- strcat(str, pci_bus_modes[pci_bus >> 3]);
- } else {
- strcat(str, "-X ");
- if (pci_bus & BIT_2)
- strcat(str, "Mode 2");
- else
- strcat(str, "Mode 1");
- strcat(str, " (");
- strcat(str, pci_bus_modes[pci_bus & ~BIT_2]);
- }
- strcat(str, " MHz)");
+ if (pci_bus == 0 || pci_bus == 8)
+ snprintf(str, str_len, "PCI (%s MHz)",
+ pci_bus_modes[pci_bus >> 3]);
+ else
+ snprintf(str, str_len, "PCI-X Mode %d (%s MHz)",
+ pci_bus & 4 ? 2 : 1,
+ pci_bus_modes[pci_bus & 3]);
return str;
}
@@ -684,13 +650,10 @@ qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str, size_t size)
return str;
}
-void
-qla2x00_sp_free_dma(void *ptr)
+void qla2x00_sp_free_dma(srb_t *sp)
{
- srb_t *sp = ptr;
struct qla_hw_data *ha = sp->vha->hw;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
- void *ctx = GET_CMD_CTX_SP(sp);
if (sp->flags & SRB_DMA_VALID) {
scsi_dma_unmap(cmd);
@@ -703,24 +666,21 @@ qla2x00_sp_free_dma(void *ptr)
sp->flags &= ~SRB_CRC_PROT_DMA_VALID;
}
- if (!ctx)
- goto end;
-
if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
/* List assured to be having elements */
- qla2x00_clean_dsd_pool(ha, ctx);
+ qla2x00_clean_dsd_pool(ha, sp->u.scmd.crc_ctx);
sp->flags &= ~SRB_CRC_CTX_DSD_VALID;
}
if (sp->flags & SRB_CRC_CTX_DMA_VALID) {
- struct crc_context *ctx0 = ctx;
+ struct crc_context *ctx0 = sp->u.scmd.crc_ctx;
dma_pool_free(ha->dl_dma_pool, ctx0, ctx0->crc_ctx_dma);
sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
}
if (sp->flags & SRB_FCP_CMND_DMA_VALID) {
- struct ct6_dsd *ctx1 = ctx;
+ struct ct6_dsd *ctx1 = sp->u.scmd.ct6_ctx;
dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd,
ctx1->fcp_cmnd_dma);
@@ -729,44 +689,30 @@ qla2x00_sp_free_dma(void *ptr)
ha->gbl_dsd_avail += ctx1->dsd_use_cnt;
mempool_free(ctx1, ha->ctx_mempool);
}
-
-end:
- if (sp->type != SRB_NVME_CMD && sp->type != SRB_NVME_LS) {
- CMD_SP(cmd) = NULL;
- qla2x00_rel_sp(sp);
- }
}
-void
-qla2x00_sp_compl(void *ptr, int res)
+void qla2x00_sp_compl(srb_t *sp, int res)
{
- srb_t *sp = ptr;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
+ struct completion *comp = sp->comp;
- cmd->result = res;
-
- if (atomic_read(&sp->ref_count) == 0) {
- ql_dbg(ql_dbg_io, sp->vha, 0x3015,
- "SP reference-count to ZERO -- sp=%p cmd=%p.\n",
- sp, GET_CMD_SP(sp));
- if (ql2xextended_error_logging & ql_dbg_io)
- WARN_ON(atomic_read(&sp->ref_count) == 0);
- return;
- }
- if (!atomic_dec_and_test(&sp->ref_count))
+ if (WARN_ON_ONCE(atomic_read(&sp->ref_count) == 0))
return;
+ atomic_dec(&sp->ref_count);
+
sp->free(sp);
+ cmd->result = res;
+ CMD_SP(cmd) = NULL;
cmd->scsi_done(cmd);
+ if (comp)
+ complete(comp);
}
-void
-qla2xxx_qpair_sp_free_dma(void *ptr)
+void qla2xxx_qpair_sp_free_dma(srb_t *sp)
{
- srb_t *sp = (srb_t *)ptr;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
struct qla_hw_data *ha = sp->fcport->vha->hw;
- void *ctx = GET_CMD_CTX_SP(sp);
if (sp->flags & SRB_DMA_VALID) {
scsi_dma_unmap(cmd);
@@ -779,62 +725,86 @@ qla2xxx_qpair_sp_free_dma(void *ptr)
sp->flags &= ~SRB_CRC_PROT_DMA_VALID;
}
- if (!ctx)
- goto end;
-
if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
/* List assured to be having elements */
- qla2x00_clean_dsd_pool(ha, ctx);
+ qla2x00_clean_dsd_pool(ha, sp->u.scmd.crc_ctx);
sp->flags &= ~SRB_CRC_CTX_DSD_VALID;
}
- if (sp->flags & SRB_CRC_CTX_DMA_VALID) {
- struct crc_context *ctx0 = ctx;
+ if (sp->flags & SRB_DIF_BUNDL_DMA_VALID) {
+ struct crc_context *difctx = sp->u.scmd.crc_ctx;
+ struct dsd_dma *dif_dsd, *nxt_dsd;
- dma_pool_free(ha->dl_dma_pool, ctx, ctx0->crc_ctx_dma);
- sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
+ list_for_each_entry_safe(dif_dsd, nxt_dsd,
+ &difctx->ldif_dma_hndl_list, list) {
+ list_del(&dif_dsd->list);
+ dma_pool_free(ha->dif_bundl_pool, dif_dsd->dsd_addr,
+ dif_dsd->dsd_list_dma);
+ kfree(dif_dsd);
+ difctx->no_dif_bundl--;
+ }
+
+ list_for_each_entry_safe(dif_dsd, nxt_dsd,
+ &difctx->ldif_dsd_list, list) {
+ list_del(&dif_dsd->list);
+ dma_pool_free(ha->dl_dma_pool, dif_dsd->dsd_addr,
+ dif_dsd->dsd_list_dma);
+ kfree(dif_dsd);
+ difctx->no_ldif_dsd--;
+ }
+
+ if (difctx->no_ldif_dsd) {
+ ql_dbg(ql_dbg_tgt+ql_dbg_verbose, sp->vha, 0xe022,
+ "%s: difctx->no_ldif_dsd=%x\n",
+ __func__, difctx->no_ldif_dsd);
+ }
+
+ if (difctx->no_dif_bundl) {
+ ql_dbg(ql_dbg_tgt+ql_dbg_verbose, sp->vha, 0xe022,
+ "%s: difctx->no_dif_bundl=%x\n",
+ __func__, difctx->no_dif_bundl);
+ }
+ sp->flags &= ~SRB_DIF_BUNDL_DMA_VALID;
}
if (sp->flags & SRB_FCP_CMND_DMA_VALID) {
- struct ct6_dsd *ctx1 = ctx;
+ struct ct6_dsd *ctx1 = sp->u.scmd.ct6_ctx;
+
dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd,
ctx1->fcp_cmnd_dma);
list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list);
ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt;
ha->gbl_dsd_avail += ctx1->dsd_use_cnt;
mempool_free(ctx1, ha->ctx_mempool);
+ sp->flags &= ~SRB_FCP_CMND_DMA_VALID;
+ }
+
+ if (sp->flags & SRB_CRC_CTX_DMA_VALID) {
+ struct crc_context *ctx0 = sp->u.scmd.crc_ctx;
+
+ dma_pool_free(ha->dl_dma_pool, ctx0, ctx0->crc_ctx_dma);
+ sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
}
-end:
- CMD_SP(cmd) = NULL;
- qla2xxx_rel_qpair_sp(sp->qpair, sp);
}
-void
-qla2xxx_qpair_sp_compl(void *ptr, int res)
+void qla2xxx_qpair_sp_compl(srb_t *sp, int res)
{
- srb_t *sp = ptr;
struct scsi_cmnd *cmd = GET_CMD_SP(sp);
+ struct completion *comp = sp->comp;
- cmd->result = res;
-
- if (atomic_read(&sp->ref_count) == 0) {
- ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3079,
- "SP reference-count to ZERO -- sp=%p cmd=%p.\n",
- sp, GET_CMD_SP(sp));
- if (ql2xextended_error_logging & ql_dbg_io)
- WARN_ON(atomic_read(&sp->ref_count) == 0);
- return;
- }
- if (!atomic_dec_and_test(&sp->ref_count))
+ if (WARN_ON_ONCE(atomic_read(&sp->ref_count) == 0))
return;
+ atomic_dec(&sp->ref_count);
+
sp->free(sp);
+ cmd->result = res;
+ CMD_SP(cmd) = NULL;
cmd->scsi_done(cmd);
+ if (comp)
+ complete(comp);
}
-/* If we are SP1 here, we need to still take and release the host_lock as SP1
- * does not have the changes necessary to avoid taking host->host_lock.
- */
static int
qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
{
@@ -845,16 +815,18 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
srb_t *sp;
int rval;
- struct qla_qpair *qpair = NULL;
- uint32_t tag;
- uint16_t hwq;
- if (unlikely(test_bit(UNLOADING, &base_vha->dpc_flags))) {
+ if (unlikely(test_bit(UNLOADING, &base_vha->dpc_flags)) ||
+ WARN_ON_ONCE(!rport)) {
cmd->result = DID_NO_CONNECT << 16;
goto qc24_fail_command;
}
if (ha->mqenable) {
+ uint32_t tag;
+ uint16_t hwq;
+ struct qla_qpair *qpair = NULL;
+
if (shost_use_blk_mq(vha->host)) {
tag = blk_mq_unique_tag(cmd->request);
hwq = blk_mq_unique_tag_to_hwq(tag);
@@ -928,9 +900,8 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
else
goto qc24_target_busy;
- sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
- if (!sp)
- goto qc24_host_busy;
+ sp = scsi_cmd_priv(cmd);
+ qla2xxx_init_sp(sp, vha, vha->hw->base_qpair, fcport);
sp->u.scmd.cmd = cmd;
sp->type = SRB_SCSI_CMD;
@@ -951,9 +922,6 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
qc24_host_busy_free_sp:
sp->free(sp);
-qc24_host_busy:
- return SCSI_MLQUEUE_HOST_BUSY;
-
qc24_target_busy:
return SCSI_MLQUEUE_TARGET_BUSY;
@@ -976,7 +944,7 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
srb_t *sp;
int rval;
- rval = fc_remote_port_chkready(rport);
+ rval = rport ? fc_remote_port_chkready(rport) : FC_PORTSTATE_OFFLINE;
if (rval) {
cmd->result = rval;
ql_dbg(ql_dbg_io + ql_dbg_verbose, vha, 0x3076,
@@ -1014,9 +982,8 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
else
goto qc24_target_busy;
- sp = qla2xxx_get_qpair_sp(vha, qpair, fcport, GFP_ATOMIC);
- if (!sp)
- goto qc24_host_busy;
+ sp = scsi_cmd_priv(cmd);
+ qla2xxx_init_sp(sp, vha, qpair, fcport);
sp->u.scmd.cmd = cmd;
sp->type = SRB_SCSI_CMD;
@@ -1040,9 +1007,6 @@ qla2xxx_mqueuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd,
qc24_host_busy_free_sp:
sp->free(sp);
-qc24_host_busy:
- return SCSI_MLQUEUE_HOST_BUSY;
-
qc24_target_busy:
return SCSI_MLQUEUE_TARGET_BUSY;
@@ -1061,8 +1025,8 @@ qc24_fail_command:
* cmd = Scsi Command to wait on.
*
* Return:
- * Not Found : 0
- * Found : 1
+ * Completed in time : QLA_SUCCESS
+ * Did not complete in time : QLA_FUNCTION_FAILED
*/
static int
qla2x00_eh_wait_on_command(struct scsi_cmnd *cmd)
@@ -1217,7 +1181,7 @@ qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha)
static int
sp_get(struct srb *sp)
{
- if (!refcount_inc_not_zero((refcount_t*)&sp->ref_count))
+ if (!refcount_inc_not_zero((refcount_t *)&sp->ref_count))
/* kref get fail */
return ENXIO;
else
@@ -1272,14 +1236,13 @@ static int
qla2xxx_eh_abort(struct scsi_cmnd *cmd)
{
scsi_qla_host_t *vha = shost_priv(cmd->device->host);
+ DECLARE_COMPLETION_ONSTACK(comp);
srb_t *sp;
int ret;
unsigned int id;
uint64_t lun;
- unsigned long flags;
- int rval, wait = 0;
+ int rval;
struct qla_hw_data *ha = vha->hw;
- struct qla_qpair *qpair;
if (qla2x00_isp_reg_stat(ha)) {
ql_log(ql_log_info, vha, 0x8042,
@@ -1290,30 +1253,15 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
ret = fc_block_scsi_eh(cmd);
if (ret != 0)
return ret;
- ret = SUCCESS;
- sp = (srb_t *) CMD_SP(cmd);
- if (!sp)
- return SUCCESS;
-
- qpair = sp->qpair;
- if (!qpair)
- return SUCCESS;
+ sp = scsi_cmd_priv(cmd);
- spin_lock_irqsave(qpair->qp_lock_ptr, flags);
- if (!CMD_SP(cmd)) {
- /* there's a chance an interrupt could clear
- the ptr as part of done & free */
- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+ if (sp->fcport && sp->fcport->deleted)
return SUCCESS;
- }
- if (sp_get(sp)){
- /* ref_count is already 0 */
- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+ /* Return if the command has already finished. */
+ if (sp_get(sp))
return SUCCESS;
- }
- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
id = cmd->device->id;
lun = cmd->device->lun;
@@ -1322,62 +1270,57 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
"Aborting from RISC nexus=%ld:%d:%llu sp=%p cmd=%p handle=%x\n",
vha->host_no, id, lun, sp, cmd, sp->handle);
- /* Get a reference to the sp and drop the lock.*/
-
rval = ha->isp_ops->abort_command(sp);
- if (rval) {
- if (rval == QLA_FUNCTION_PARAMETER_ERROR)
- ret = SUCCESS;
- else
- ret = FAILED;
-
- ql_dbg(ql_dbg_taskm, vha, 0x8003,
- "Abort command mbx failed cmd=%p, rval=%x.\n", cmd, rval);
- } else {
- ql_dbg(ql_dbg_taskm, vha, 0x8004,
- "Abort command mbx success cmd=%p.\n", cmd);
- wait = 1;
- }
-
- spin_lock_irqsave(qpair->qp_lock_ptr, flags);
- /*
- * Clear the slot in the oustanding_cmds array if we can't find the
- * command to reclaim the resources.
- */
- if (rval == QLA_FUNCTION_PARAMETER_ERROR)
- vha->req->outstanding_cmds[sp->handle] = NULL;
-
- /*
- * sp->done will do ref_count--
- * sp_get() took an extra count above
- */
- sp->done(sp, DID_RESET << 16);
+ ql_dbg(ql_dbg_taskm, vha, 0x8003,
+ "Abort command mbx cmd=%p, rval=%x.\n", cmd, rval);
- /* Did the command return during mailbox execution? */
- if (ret == FAILED && !CMD_SP(cmd))
+ switch (rval) {
+ case QLA_SUCCESS:
+ /*
+ * The command has been aborted. That means that the firmware
+ * won't report a completion.
+ */
+ sp->done(sp, DID_ABORT << 16);
ret = SUCCESS;
-
- if (!CMD_SP(cmd))
- wait = 0;
-
- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
-
- /* Wait for the command to be returned. */
- if (wait) {
- if (qla2x00_eh_wait_on_command(cmd) != QLA_SUCCESS) {
- ql_log(ql_log_warn, vha, 0x8006,
- "Abort handler timed out cmd=%p.\n", cmd);
+ break;
+ case QLA_FUNCTION_PARAMETER_ERROR: {
+ /* Wait for the command completion. */
+ uint32_t ratov = ha->r_a_tov/10;
+ uint32_t ratov_j = msecs_to_jiffies(4 * ratov * 1000);
+
+ WARN_ON_ONCE(sp->comp);
+ sp->comp = &comp;
+ if (!wait_for_completion_timeout(&comp, ratov_j)) {
+ ql_dbg(ql_dbg_taskm, vha, 0xffff,
+ "%s: Abort wait timer (4 * R_A_TOV[%d]) expired\n",
+ __func__, ha->r_a_tov);
ret = FAILED;
+ } else {
+ ret = SUCCESS;
}
+ break;
+ }
+ default:
+ /*
+ * Either abort failed or abort and completion raced. Let
+ * the SCSI core retry the abort in the former case.
+ */
+ ret = FAILED;
+ break;
}
+ sp->comp = NULL;
+ atomic_dec(&sp->ref_count);
ql_log(ql_log_info, vha, 0x801c,
- "Abort command issued nexus=%ld:%d:%llu -- %d %x.\n",
- vha->host_no, id, lun, wait, ret);
+ "Abort command issued nexus=%ld:%d:%llu -- %x.\n",
+ vha->host_no, id, lun, ret);
return ret;
}
+/*
+ * Returns: QLA_SUCCESS or QLA_FUNCTION_FAILED.
+ */
int
qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
uint64_t l, enum nexus_wait_type type)
@@ -1451,6 +1394,9 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
if (err != 0)
return err;
+ if (fcport->deleted)
+ return SUCCESS;
+
ql_log(ql_log_info, vha, 0x8009,
"%s RESET ISSUED nexus=%ld:%d:%llu cmd=%p.\n", name, vha->host_no,
cmd->device->id, cmd->device->lun, cmd);
@@ -1462,7 +1408,7 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
goto eh_reset_failed;
}
err = 2;
- if (do_reset(fcport, cmd->device->lun, cmd->request->cpu + 1)
+ if (do_reset(fcport, cmd->device->lun, 1)
!= QLA_SUCCESS) {
ql_log(ql_log_warn, vha, 0x800c,
"do_reset failed for cmd=%p.\n", cmd);
@@ -1565,6 +1511,9 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
return ret;
ret = FAILED;
+ if (qla2x00_chip_is_down(vha))
+ return ret;
+
ql_log(ql_log_info, vha, 0x8012,
"BUS RESET ISSUED nexus=%ld:%d:%llu.\n", vha->host_no, id, lun);
@@ -1749,34 +1698,35 @@ static void qla2x00_abort_srb(struct qla_qpair *qp, srb_t *sp, const int res,
__releases(qp->qp_lock_ptr)
__acquires(qp->qp_lock_ptr)
{
+ DECLARE_COMPLETION_ONSTACK(comp);
scsi_qla_host_t *vha = qp->vha;
struct qla_hw_data *ha = vha->hw;
+ int rval;
- if (sp->type == SRB_NVME_CMD || sp->type == SRB_NVME_LS) {
- if (!sp_get(sp)) {
- /* got sp */
- spin_unlock_irqrestore(qp->qp_lock_ptr, *flags);
- qla_nvme_abort(ha, sp, res);
- spin_lock_irqsave(qp->qp_lock_ptr, *flags);
- }
- } else if (GET_CMD_SP(sp) && !ha->flags.eeh_busy &&
- !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
- !qla2x00_isp_reg_stat(ha) && sp->type == SRB_SCSI_CMD) {
- /*
- * Don't abort commands in adapter during EEH recovery as it's
- * not accessible/responding.
- *
- * Get a reference to the sp and drop the lock. The reference
- * ensures this sp->done() call and not the call in
- * qla2xxx_eh_abort() ends the SCSI cmd (with result 'res').
- */
- if (!sp_get(sp)) {
- spin_unlock_irqrestore(qp->qp_lock_ptr, *flags);
- qla2xxx_eh_abort(GET_CMD_SP(sp));
- spin_lock_irqsave(qp->qp_lock_ptr, *flags);
+ if (sp_get(sp))
+ return;
+ if (sp->type == SRB_NVME_CMD || sp->type == SRB_NVME_LS ||
+ (sp->type == SRB_SCSI_CMD && !ha->flags.eeh_busy &&
+ !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) &&
+ !qla2x00_isp_reg_stat(ha))) {
+ sp->comp = &comp;
+ spin_unlock_irqrestore(qp->qp_lock_ptr, *flags);
+ rval = ha->isp_ops->abort_command(sp);
+
+ switch (rval) {
+ case QLA_SUCCESS:
+ sp->done(sp, res);
+ break;
+ case QLA_FUNCTION_PARAMETER_ERROR:
+ wait_for_completion(&comp);
+ break;
}
+
+ spin_lock_irqsave(qp->qp_lock_ptr, *flags);
+ sp->comp = NULL;
}
- sp->done(sp, res);
+
+ atomic_dec(&sp->ref_count);
}
static void
@@ -1812,15 +1762,10 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
continue;
}
cmd = (struct qla_tgt_cmd *)sp;
- qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
+ cmd->aborted = 1;
break;
case TYPE_TGT_TMCMD:
- /*
- * Currently, only ABTS response gets on the
- * outstanding_cmds[]
- */
- ha->tgt.tgt_ops->free_mcmd(
- (struct qla_tgt_mgmt_cmd *)sp);
+ /* Skip task management functions. */
break;
default:
break;
@@ -1836,8 +1781,13 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
int que;
struct qla_hw_data *ha = vha->hw;
+ /* Continue only if initialization complete. */
+ if (!ha->base_qpair)
+ return;
__qla2x00_abort_all_cmds(ha->base_qpair, res);
+ if (!ha->queue_pair_map)
+ return;
for (que = 0; que < ha->max_qpairs; que++) {
if (!ha->queue_pair_map[que])
continue;
@@ -2513,7 +2463,7 @@ static struct isp_operations qla27xx_isp_ops = {
.config_rings = qla24xx_config_rings,
.reset_adapter = qla24xx_reset_adapter,
.nvram_config = qla81xx_nvram_config,
- .update_fw_options = qla81xx_update_fw_options,
+ .update_fw_options = qla24xx_update_fw_options,
.load_risc = qla81xx_load_risc,
.pci_info_str = qla24xx_pci_info_str,
.fw_version_str = qla24xx_fw_version_str,
@@ -2690,6 +2640,24 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
ha->device_type |= DT_T10_PI;
ha->fw_srisc_address = RISC_START_ADDRESS_2400;
break;
+ case PCI_DEVICE_ID_QLOGIC_ISP2081:
+ case PCI_DEVICE_ID_QLOGIC_ISP2089:
+ ha->isp_type |= DT_ISP2081;
+ ha->device_type |= DT_ZIO_SUPPORTED;
+ ha->device_type |= DT_FWI2;
+ ha->device_type |= DT_IIDMA;
+ ha->device_type |= DT_T10_PI;
+ ha->fw_srisc_address = RISC_START_ADDRESS_2400;
+ break;
+ case PCI_DEVICE_ID_QLOGIC_ISP2281:
+ case PCI_DEVICE_ID_QLOGIC_ISP2289:
+ ha->isp_type |= DT_ISP2281;
+ ha->device_type |= DT_ZIO_SUPPORTED;
+ ha->device_type |= DT_FWI2;
+ ha->device_type |= DT_IIDMA;
+ ha->device_type |= DT_T10_PI;
+ ha->fw_srisc_address = RISC_START_ADDRESS_2400;
+ break;
}
if (IS_QLA82XX(ha))
@@ -2697,7 +2665,8 @@ qla2x00_set_isp_flags(struct qla_hw_data *ha)
else {
/* Get adapter physical port no from interrupt pin register. */
pci_read_config_byte(ha->pdev, PCI_INTERRUPT_PIN, &ha->port_no);
- if (IS_QLA27XX(ha))
+ if (IS_QLA25XX(ha) || IS_QLA2031(ha) ||
+ IS_QLA27XX(ha) || IS_QLA28XX(ha))
ha->port_no--;
else
ha->port_no = !(ha->port_no & 1);
@@ -2794,7 +2763,11 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8044 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2071 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2271 ||
- pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2261) {
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2261 ||
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2081 ||
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2281 ||
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2089 ||
+ pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2289) {
bars = pci_select_bars(pdev, IORESOURCE_MEM);
mem_only = 1;
ql_dbg_pci(ql_dbg_init, pdev, 0x0007,
@@ -2814,6 +2787,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* This may fail but that's ok */
pci_enable_pcie_error_reporting(pdev);
+ /* Turn off T10-DIF when FC-NVMe is enabled */
+ if (ql2xnvmeenable)
+ ql2xenabledif = 0;
+
ha = kzalloc(sizeof(struct qla_hw_data), GFP_KERNEL);
if (!ha) {
ql_log_pci(ql_log_fatal, pdev, 0x0009,
@@ -2843,7 +2820,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
/* Set EEH reset type to fundamental if required by hba */
if (IS_QLA24XX(ha) || IS_QLA25XX(ha) || IS_QLA81XX(ha) ||
- IS_QLA83XX(ha) || IS_QLA27XX(ha))
+ IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
pdev->needs_freset = 1;
ha->prev_topology = 0;
@@ -3022,6 +2999,23 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->flash_data_off = FARX_ACCESS_FLASH_DATA_81XX;
ha->nvram_conf_off = ~0;
ha->nvram_data_off = ~0;
+ } else if (IS_QLA28XX(ha)) {
+ ha->portnum = PCI_FUNC(ha->pdev->devfn);
+ ha->max_fibre_devices = MAX_FIBRE_DEVICES_2400;
+ ha->mbx_count = MAILBOX_REGISTER_COUNT;
+ req_length = REQUEST_ENTRY_CNT_24XX;
+ rsp_length = RESPONSE_ENTRY_CNT_2300;
+ ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX;
+ ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
+ ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
+ ha->gid_list_info_size = 8;
+ ha->optrom_size = OPTROM_SIZE_28XX;
+ ha->nvram_npiv_size = QLA_MAX_VPORTS_QLA25XX;
+ ha->isp_ops = &qla27xx_isp_ops;
+ ha->flash_conf_off = FARX_ACCESS_FLASH_CONF_28XX;
+ ha->flash_data_off = FARX_ACCESS_FLASH_DATA_28XX;
+ ha->nvram_conf_off = ~0;
+ ha->nvram_data_off = ~0;
}
ql_dbg_pci(ql_dbg_init, pdev, 0x001e,
@@ -3146,6 +3140,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ql_log(ql_log_fatal, base_vha, 0x003d,
"Failed to allocate memory for queue pointers..."
"aborting.\n");
+ ret = -ENODEV;
goto probe_failed;
}
@@ -3187,7 +3182,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
req->req_q_out = &ha->iobase->isp24.req_q_out;
rsp->rsp_q_in = &ha->iobase->isp24.rsp_q_in;
rsp->rsp_q_out = &ha->iobase->isp24.rsp_q_out;
- if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha)) {
req->req_q_in = &ha->mqiobase->isp25mq.req_q_in;
req->req_q_out = &ha->mqiobase->isp25mq.req_q_out;
rsp->rsp_q_in = &ha->mqiobase->isp25mq.rsp_q_in;
@@ -3340,18 +3336,22 @@ skip_dpc:
if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif && !ql2xnvmeenable) {
if (ha->fw_attributes & BIT_4) {
int prot = 0, guard;
+
base_vha->flags.difdix_supported = 1;
ql_dbg(ql_dbg_init, base_vha, 0x00f1,
"Registering for DIF/DIX type 1 and 3 protection.\n");
if (ql2xenabledif == 1)
prot = SHOST_DIX_TYPE0_PROTECTION;
- scsi_host_set_prot(host,
- prot | SHOST_DIF_TYPE1_PROTECTION
- | SHOST_DIF_TYPE2_PROTECTION
- | SHOST_DIF_TYPE3_PROTECTION
- | SHOST_DIX_TYPE1_PROTECTION
- | SHOST_DIX_TYPE2_PROTECTION
- | SHOST_DIX_TYPE3_PROTECTION);
+ if (ql2xprotmask)
+ scsi_host_set_prot(host, ql2xprotmask);
+ else
+ scsi_host_set_prot(host,
+ prot | SHOST_DIF_TYPE1_PROTECTION
+ | SHOST_DIF_TYPE2_PROTECTION
+ | SHOST_DIF_TYPE3_PROTECTION
+ | SHOST_DIX_TYPE1_PROTECTION
+ | SHOST_DIX_TYPE2_PROTECTION
+ | SHOST_DIX_TYPE3_PROTECTION);
guard = SHOST_DIX_GUARD_CRC;
@@ -3359,7 +3359,10 @@ skip_dpc:
(ql2xenabledif > 1 || IS_PI_DIFB_DIX0_CAPABLE(ha)))
guard |= SHOST_DIX_GUARD_IP;
- scsi_host_set_guard(host, guard);
+ if (ql2xprotguard)
+ scsi_host_set_guard(host, ql2xprotguard);
+ else
+ scsi_host_set_guard(host, guard);
} else
base_vha->flags.difdix_supported = 0;
}
@@ -3410,7 +3413,8 @@ skip_dpc:
"QLogic %s - %s.\n", ha->model_number, ha->model_desc);
ql_log(ql_log_info, base_vha, 0x00fc,
"ISP%04X: %s @ %s hdma%c host#=%ld fw=%s.\n",
- pdev->device, ha->isp_ops->pci_info_str(base_vha, pci_info),
+ pdev->device, ha->isp_ops->pci_info_str(base_vha, pci_info,
+ sizeof(pci_info)),
pci_name(pdev), ha->flags.enable_64bit_addressing ? '+' : '-',
base_vha->host_no,
ha->isp_ops->fw_version_str(base_vha, fw_str, sizeof(fw_str)));
@@ -3432,6 +3436,12 @@ skip_dpc:
return 0;
probe_failed:
+ if (base_vha->gnl.l) {
+ dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size,
+ base_vha->gnl.l, base_vha->gnl.ldma);
+ base_vha->gnl.l = NULL;
+ }
+
if (base_vha->timer_active)
qla2x00_stop_timer(base_vha);
base_vha->flags.online = 0;
@@ -3515,7 +3525,8 @@ qla2x00_shutdown(struct pci_dev *pdev)
if (ha->eft)
qla2x00_disable_eft_trace(vha);
- if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) {
+ if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha)) {
if (ha->flags.fw_started)
qla2x00_abort_isp_cleanup(vha);
} else {
@@ -3620,7 +3631,8 @@ qla2x00_unmap_iobases(struct qla_hw_data *ha)
if (ha->mqiobase)
iounmap(ha->mqiobase);
- if ((IS_QLA83XX(ha) || IS_QLA27XX(ha)) && ha->msixbase)
+ if ((IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) &&
+ ha->msixbase)
iounmap(ha->msixbase);
}
}
@@ -3663,7 +3675,7 @@ qla2x00_remove_one(struct pci_dev *pdev)
if (!atomic_read(&pdev->enable_cnt)) {
dma_free_coherent(&ha->pdev->dev, base_vha->gnl.size,
base_vha->gnl.l, base_vha->gnl.ldma);
-
+ base_vha->gnl.l = NULL;
scsi_host_put(base_vha->host);
kfree(ha);
pci_set_drvdata(pdev, NULL);
@@ -3671,9 +3683,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
}
qla2x00_wait_for_hba_ready(base_vha);
- qla2x00_wait_for_sess_deletion(base_vha);
-
- if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) {
+ if (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha)) {
if (ha->flags.fw_started)
qla2x00_abort_isp_cleanup(base_vha);
} else if (!IS_QLAFX00(ha)) {
@@ -3688,6 +3699,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
qla2x00_try_to_stop_firmware(base_vha);
}
+ qla2x00_wait_for_sess_deletion(base_vha);
+
/*
* if UNLOAD flag is already set, then continue unload,
* where it was set first.
@@ -3702,6 +3715,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
dma_free_coherent(&ha->pdev->dev,
base_vha->gnl.size, base_vha->gnl.l, base_vha->gnl.ldma);
+ base_vha->gnl.l = NULL;
+
vfree(base_vha->scan.l);
if (IS_QLAFX00(ha))
@@ -3709,8 +3724,6 @@ qla2x00_remove_one(struct pci_dev *pdev)
qla2x00_delete_all_vps(ha, base_vha);
- qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
-
qla2x00_dfs_remove(base_vha);
qla84xx_put_chip(base_vha);
@@ -3800,11 +3813,8 @@ void qla2x00_free_fcports(struct scsi_qla_host *vha)
{
fc_port_t *fcport, *tfcport;
- list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list) {
- list_del(&fcport->list);
- qla2x00_clear_loop_id(fcport);
- kfree(fcport);
- }
+ list_for_each_entry_safe(fcport, tfcport, &vha->vp_fcports, list)
+ qla2x00_free_fcport(fcport);
}
static inline void
@@ -3829,6 +3839,7 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
qla2xxx_wake_dpc(base_vha);
} else {
int now;
+
if (rport) {
ql_dbg(ql_dbg_disc, fcport->vha, 0x2109,
"%s %8phN. rport %p roles %x\n",
@@ -3920,6 +3931,19 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *vha, int defer)
}
}
+static void qla2x00_set_reserved_loop_ids(struct qla_hw_data *ha)
+{
+ int i;
+
+ if (IS_FWI2_CAPABLE(ha))
+ return;
+
+ for (i = 0; i < SNS_FIRST_LOOP_ID; i++)
+ set_bit(i, ha->loop_id_map);
+ set_bit(MANAGEMENT_SERVER, ha->loop_id_map);
+ set_bit(BROADCAST, ha->loop_id_map);
+}
+
/*
* qla2x00_mem_alloc
* Allocates adapter memory.
@@ -4001,9 +4025,86 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
"Failed to allocate memory for fcp_cmnd_dma_pool.\n");
goto fail_dl_dma_pool;
}
+
+ if (ql2xenabledif) {
+ u64 bufsize = DIF_BUNDLING_DMA_POOL_SIZE;
+ struct dsd_dma *dsd, *nxt;
+ uint i;
+ /* Creata a DMA pool of buffers for DIF bundling */
+ ha->dif_bundl_pool = dma_pool_create(name,
+ &ha->pdev->dev, DIF_BUNDLING_DMA_POOL_SIZE, 8, 0);
+ if (!ha->dif_bundl_pool) {
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0024,
+ "%s: failed create dif_bundl_pool\n",
+ __func__);
+ goto fail_dif_bundl_dma_pool;
+ }
+
+ INIT_LIST_HEAD(&ha->pool.good.head);
+ INIT_LIST_HEAD(&ha->pool.unusable.head);
+ ha->pool.good.count = 0;
+ ha->pool.unusable.count = 0;
+ for (i = 0; i < 128; i++) {
+ dsd = kzalloc(sizeof(*dsd), GFP_ATOMIC);
+ if (!dsd) {
+ ql_dbg_pci(ql_dbg_init, ha->pdev,
+ 0xe0ee, "%s: failed alloc dsd\n",
+ __func__);
+ return 1;
+ }
+ ha->dif_bundle_kallocs++;
+
+ dsd->dsd_addr = dma_pool_alloc(
+ ha->dif_bundl_pool, GFP_ATOMIC,
+ &dsd->dsd_list_dma);
+ if (!dsd->dsd_addr) {
+ ql_dbg_pci(ql_dbg_init, ha->pdev,
+ 0xe0ee,
+ "%s: failed alloc ->dsd_addr\n",
+ __func__);
+ kfree(dsd);
+ ha->dif_bundle_kallocs--;
+ continue;
+ }
+ ha->dif_bundle_dma_allocs++;
+
+ /*
+ * if DMA buffer crosses 4G boundary,
+ * put it on bad list
+ */
+ if (MSD(dsd->dsd_list_dma) ^
+ MSD(dsd->dsd_list_dma + bufsize)) {
+ list_add_tail(&dsd->list,
+ &ha->pool.unusable.head);
+ ha->pool.unusable.count++;
+ } else {
+ list_add_tail(&dsd->list,
+ &ha->pool.good.head);
+ ha->pool.good.count++;
+ }
+ }
+
+ /* return the good ones back to the pool */
+ list_for_each_entry_safe(dsd, nxt,
+ &ha->pool.good.head, list) {
+ list_del(&dsd->list);
+ dma_pool_free(ha->dif_bundl_pool,
+ dsd->dsd_addr, dsd->dsd_list_dma);
+ ha->dif_bundle_dma_allocs--;
+ kfree(dsd);
+ ha->dif_bundle_kallocs--;
+ }
+
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0024,
+ "%s: dif dma pool (good=%u unusable=%u)\n",
+ __func__, ha->pool.good.count,
+ ha->pool.unusable.count);
+ }
+
ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0025,
- "dl_dma_pool=%p fcp_cmnd_dma_pool=%p.\n",
- ha->dl_dma_pool, ha->fcp_cmnd_dma_pool);
+ "dl_dma_pool=%p fcp_cmnd_dma_pool=%p dif_bundl_pool=%p.\n",
+ ha->dl_dma_pool, ha->fcp_cmnd_dma_pool,
+ ha->dif_bundl_pool);
}
/* Allocate memory for SNS commands */
@@ -4084,7 +4185,8 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
ha->npiv_info = NULL;
/* Get consistent memory allocated for EX-INIT-CB. */
- if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) {
+ if (IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha)) {
ha->ex_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
&ha->ex_init_cb_dma);
if (!ha->ex_init_cb)
@@ -4126,8 +4228,20 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
goto fail_sfp_data;
}
+ ha->flt = dma_alloc_coherent(&ha->pdev->dev,
+ sizeof(struct qla_flt_header) + FLT_REGIONS_SIZE, &ha->flt_dma,
+ GFP_KERNEL);
+ if (!ha->flt) {
+ ql_dbg_pci(ql_dbg_init, ha->pdev, 0x011b,
+ "Unable to allocate memory for FLT.\n");
+ goto fail_flt_buffer;
+ }
+
return 0;
+fail_flt_buffer:
+ dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE,
+ ha->sfp_data, ha->sfp_data_dma);
fail_sfp_data:
kfree(ha->loop_id_map);
fail_loop_id_map:
@@ -4166,6 +4280,24 @@ fail_free_ms_iocb:
dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt),
ha->sns_cmd, ha->sns_cmd_dma);
fail_dma_pool:
+ if (ql2xenabledif) {
+ struct dsd_dma *dsd, *nxt;
+
+ list_for_each_entry_safe(dsd, nxt, &ha->pool.unusable.head,
+ list) {
+ list_del(&dsd->list);
+ dma_pool_free(ha->dif_bundl_pool, dsd->dsd_addr,
+ dsd->dsd_list_dma);
+ ha->dif_bundle_dma_allocs--;
+ kfree(dsd);
+ ha->dif_bundle_kallocs--;
+ ha->pool.unusable.count--;
+ }
+ dma_pool_destroy(ha->dif_bundl_pool);
+ ha->dif_bundl_pool = NULL;
+ }
+
+fail_dif_bundl_dma_pool:
if (IS_QLA82XX(ha) || ql2xenabledif) {
dma_pool_destroy(ha->fcp_cmnd_dma_pool);
ha->fcp_cmnd_dma_pool = NULL;
@@ -4445,6 +4577,9 @@ qla2x00_free_exchoffld_buffer(struct qla_hw_data *ha)
static void
qla2x00_free_fw_dump(struct qla_hw_data *ha)
{
+ struct fwdt *fwdt = ha->fwdt;
+ uint j;
+
if (ha->fce)
dma_free_coherent(&ha->pdev->dev,
FCE_SIZE, ha->fce, ha->fce_dma);
@@ -4455,11 +4590,10 @@ qla2x00_free_fw_dump(struct qla_hw_data *ha)
if (ha->fw_dump)
vfree(ha->fw_dump);
- if (ha->fw_dump_template)
- vfree(ha->fw_dump_template);
ha->fce = NULL;
ha->fce_dma = 0;
+ ha->flags.fce_enabled = 0;
ha->eft = NULL;
ha->eft_dma = 0;
ha->fw_dumped = 0;
@@ -4467,8 +4601,13 @@ qla2x00_free_fw_dump(struct qla_hw_data *ha)
ha->fw_dump_reading = 0;
ha->fw_dump = NULL;
ha->fw_dump_len = 0;
- ha->fw_dump_template = NULL;
- ha->fw_dump_template_len = 0;
+
+ for (j = 0; j < 2; j++, fwdt++) {
+ if (fwdt->template)
+ vfree(fwdt->template);
+ fwdt->template = NULL;
+ fwdt->length = 0;
+ }
}
/*
@@ -4486,44 +4625,68 @@ qla2x00_mem_free(struct qla_hw_data *ha)
if (ha->mctp_dump)
dma_free_coherent(&ha->pdev->dev, MCTP_DUMP_SIZE, ha->mctp_dump,
ha->mctp_dump_dma);
+ ha->mctp_dump = NULL;
mempool_destroy(ha->srb_mempool);
+ ha->srb_mempool = NULL;
if (ha->dcbx_tlv)
dma_free_coherent(&ha->pdev->dev, DCBX_TLV_DATA_SIZE,
ha->dcbx_tlv, ha->dcbx_tlv_dma);
+ ha->dcbx_tlv = NULL;
if (ha->xgmac_data)
dma_free_coherent(&ha->pdev->dev, XGMAC_DATA_SIZE,
ha->xgmac_data, ha->xgmac_data_dma);
+ ha->xgmac_data = NULL;
if (ha->sns_cmd)
dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt),
ha->sns_cmd, ha->sns_cmd_dma);
+ ha->sns_cmd = NULL;
+ ha->sns_cmd_dma = 0;
if (ha->ct_sns)
dma_free_coherent(&ha->pdev->dev, sizeof(struct ct_sns_pkt),
ha->ct_sns, ha->ct_sns_dma);
+ ha->ct_sns = NULL;
+ ha->ct_sns_dma = 0;
if (ha->sfp_data)
dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE, ha->sfp_data,
ha->sfp_data_dma);
+ ha->sfp_data = NULL;
+
+ if (ha->flt)
+ dma_free_coherent(&ha->pdev->dev, SFP_DEV_SIZE,
+ ha->flt, ha->flt_dma);
+ ha->flt = NULL;
+ ha->flt_dma = 0;
if (ha->ms_iocb)
dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
+ ha->ms_iocb = NULL;
+ ha->ms_iocb_dma = 0;
if (ha->ex_init_cb)
dma_pool_free(ha->s_dma_pool,
ha->ex_init_cb, ha->ex_init_cb_dma);
+ ha->ex_init_cb = NULL;
+ ha->ex_init_cb_dma = 0;
if (ha->async_pd)
dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma);
+ ha->async_pd = NULL;
+ ha->async_pd_dma = 0;
dma_pool_destroy(ha->s_dma_pool);
+ ha->s_dma_pool = NULL;
if (ha->gid_list)
dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha),
ha->gid_list, ha->gid_list_dma);
+ ha->gid_list = NULL;
+ ha->gid_list_dma = 0;
if (IS_QLA82XX(ha)) {
if (!list_empty(&ha->gbl_dsd_list)) {
@@ -4541,57 +4704,58 @@ qla2x00_mem_free(struct qla_hw_data *ha)
}
dma_pool_destroy(ha->dl_dma_pool);
+ ha->dl_dma_pool = NULL;
dma_pool_destroy(ha->fcp_cmnd_dma_pool);
+ ha->fcp_cmnd_dma_pool = NULL;
mempool_destroy(ha->ctx_mempool);
+ ha->ctx_mempool = NULL;
+
+ if (ql2xenabledif && ha->dif_bundl_pool) {
+ struct dsd_dma *dsd, *nxt;
+
+ list_for_each_entry_safe(dsd, nxt, &ha->pool.unusable.head,
+ list) {
+ list_del(&dsd->list);
+ dma_pool_free(ha->dif_bundl_pool, dsd->dsd_addr,
+ dsd->dsd_list_dma);
+ ha->dif_bundle_dma_allocs--;
+ kfree(dsd);
+ ha->dif_bundle_kallocs--;
+ ha->pool.unusable.count--;
+ }
+ list_for_each_entry_safe(dsd, nxt, &ha->pool.good.head, list) {
+ list_del(&dsd->list);
+ dma_pool_free(ha->dif_bundl_pool, dsd->dsd_addr,
+ dsd->dsd_list_dma);
+ ha->dif_bundle_dma_allocs--;
+ kfree(dsd);
+ ha->dif_bundle_kallocs--;
+ }
+ }
+
+ dma_pool_destroy(ha->dif_bundl_pool);
+ ha->dif_bundl_pool = NULL;
qlt_mem_free(ha);
if (ha->init_cb)
dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
ha->init_cb, ha->init_cb_dma);
+ ha->init_cb = NULL;
+ ha->init_cb_dma = 0;
vfree(ha->optrom_buffer);
+ ha->optrom_buffer = NULL;
kfree(ha->nvram);
+ ha->nvram = NULL;
kfree(ha->npiv_info);
+ ha->npiv_info = NULL;
kfree(ha->swl);
+ ha->swl = NULL;
kfree(ha->loop_id_map);
-
- ha->srb_mempool = NULL;
- ha->ctx_mempool = NULL;
- ha->sns_cmd = NULL;
- ha->sns_cmd_dma = 0;
- ha->ct_sns = NULL;
- ha->ct_sns_dma = 0;
- ha->ms_iocb = NULL;
- ha->ms_iocb_dma = 0;
- ha->init_cb = NULL;
- ha->init_cb_dma = 0;
- ha->ex_init_cb = NULL;
- ha->ex_init_cb_dma = 0;
- ha->async_pd = NULL;
- ha->async_pd_dma = 0;
ha->loop_id_map = NULL;
- ha->npiv_info = NULL;
- ha->optrom_buffer = NULL;
- ha->swl = NULL;
- ha->nvram = NULL;
- ha->mctp_dump = NULL;
- ha->dcbx_tlv = NULL;
- ha->xgmac_data = NULL;
- ha->sfp_data = NULL;
-
- ha->s_dma_pool = NULL;
- ha->dl_dma_pool = NULL;
- ha->fcp_cmnd_dma_pool = NULL;
-
- ha->gid_list = NULL;
- ha->gid_list_dma = 0;
-
- ha->tgt.atio_ring = NULL;
- ha->tgt.atio_dma = 0;
- ha->tgt.tgt_vp_map = NULL;
}
struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
@@ -4628,7 +4792,6 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
INIT_LIST_HEAD(&vha->plogi_ack_list);
INIT_LIST_HEAD(&vha->qp_list);
INIT_LIST_HEAD(&vha->gnl.fcports);
- INIT_LIST_HEAD(&vha->nvme_rport_list);
INIT_LIST_HEAD(&vha->gpnid_list);
INIT_WORK(&vha->iocb_work, qla2x00_iocb_work_fn);
@@ -4644,7 +4807,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
if (!vha->gnl.l) {
ql_log(ql_log_fatal, vha, 0xd04a,
"Alloc failed for name list.\n");
- scsi_remove_host(vha->host);
+ scsi_host_put(vha->host);
return NULL;
}
@@ -4656,7 +4819,8 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
"Alloc failed for scan database.\n");
dma_free_coherent(&ha->pdev->dev, vha->gnl.size,
vha->gnl.l, vha->gnl.ldma);
- scsi_remove_host(vha->host);
+ vha->gnl.l = NULL;
+ scsi_host_put(vha->host);
return NULL;
}
INIT_DELAYED_WORK(&vha->scan.scan_work, qla_scan_work_fn);
@@ -4877,6 +5041,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
fcport->fc4_type = FC4_TYPE_OTHER;
fcport->fc4f_nvme = FC4_TYPE_NVME;
}
+
memcpy(fcport->port_name, e->u.new_sess.port_name,
WWN_SIZE);
} else {
@@ -4884,8 +5049,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
"%s %8phC mem alloc fail.\n",
__func__, e->u.new_sess.port_name);
- if (pla)
+ if (pla) {
+ list_del(&pla->list);
kmem_cache_free(qla_tgt_plogi_cachep, pla);
+ }
return;
}
@@ -4916,6 +5083,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
if (fcport) {
fcport->id_changed = 1;
fcport->scan_state = QLA_FCPORT_FOUND;
+ fcport->chip_reset = vha->hw->base_qpair->chip_reset;
memcpy(fcport->node_name, e->u.new_sess.node_name, WWN_SIZE);
if (pla) {
@@ -4995,8 +5163,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
if (free_fcport) {
qla2x00_free_fcport(fcport);
- if (pla)
+ if (pla) {
+ list_del(&pla->list);
kmem_cache_free(qla_tgt_plogi_cachep, pla);
+ }
}
}
@@ -5020,14 +5190,14 @@ qla2x00_do_work(struct scsi_qla_host *vha)
struct qla_work_evt *e, *tmp;
unsigned long flags;
LIST_HEAD(work);
+ int rc;
spin_lock_irqsave(&vha->work_lock, flags);
list_splice_init(&vha->work_list, &work);
spin_unlock_irqrestore(&vha->work_lock, flags);
list_for_each_entry_safe(e, tmp, &work, list) {
- list_del_init(&e->list);
-
+ rc = QLA_SUCCESS;
switch (e->type) {
case QLA_EVT_AEN:
fc_host_post_event(vha->host, fc_get_event_number(),
@@ -5041,7 +5211,7 @@ qla2x00_do_work(struct scsi_qla_host *vha)
e->u.logio.data);
break;
case QLA_EVT_ASYNC_LOGOUT:
- qla2x00_async_logout(vha, e->u.logio.fcport);
+ rc = qla2x00_async_logout(vha, e->u.logio.fcport);
break;
case QLA_EVT_ASYNC_LOGOUT_DONE:
qla2x00_async_logout_done(vha, e->u.logio.fcport,
@@ -5086,7 +5256,7 @@ qla2x00_do_work(struct scsi_qla_host *vha)
qla24xx_do_nack_work(vha, e);
break;
case QLA_EVT_ASYNC_PRLO:
- qla2x00_async_prlo(vha, e->u.logio.fcport);
+ rc = qla2x00_async_prlo(vha, e->u.logio.fcport);
break;
case QLA_EVT_ASYNC_PRLO_DONE:
qla2x00_async_prlo_done(vha, e->u.logio.fcport,
@@ -5119,6 +5289,15 @@ qla2x00_do_work(struct scsi_qla_host *vha)
e->u.fcport.fcport, false);
break;
}
+
+ if (rc == EAGAIN) {
+ /* put 'work' at head of 'vha->work_list' */
+ spin_lock_irqsave(&vha->work_lock, flags);
+ list_splice(&work, &vha->work_list);
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+ break;
+ }
+ list_del_init(&e->list);
if (e->flags & QLA_EVT_FLAG_FREE)
kfree(e);
@@ -5167,9 +5346,8 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
} else {
if (vha->hw->current_topology != ISP_CFG_NL) {
memset(&ea, 0, sizeof(ea));
- ea.event = FCME_RELOGIN;
ea.fcport = fcport;
- qla2x00_fcport_event_handler(vha, &ea);
+ qla24xx_handle_relogin_event(vha, &ea);
} else if (vha->hw->current_topology ==
ISP_CFG_NL) {
fcport->login_retry--;
@@ -5415,6 +5593,7 @@ qla83xx_force_lock_recovery(scsi_qla_host_t *base_vha)
uint32_t idc_lck_rcvry_stage_mask = 0x3;
uint32_t idc_lck_rcvry_owner_mask = 0x3c;
struct qla_hw_data *ha = base_vha->hw;
+
ql_dbg(ql_dbg_p3p, base_vha, 0xb086,
"Trying force recovery of the IDC lock.\n");
@@ -5506,7 +5685,6 @@ exit:
void
qla83xx_idc_lock(scsi_qla_host_t *base_vha, uint16_t requester_id)
{
- uint16_t options = (requester_id << 15) | BIT_6;
uint32_t data;
uint32_t lock_owner;
struct qla_hw_data *ha = base_vha->hw;
@@ -5539,22 +5717,6 @@ retry_lock:
}
return;
-
- /* XXX: IDC-lock implementation using access-control mbx */
-retry_lock2:
- if (qla83xx_access_control(base_vha, options, 0, 0, NULL)) {
- ql_dbg(ql_dbg_p3p, base_vha, 0xb072,
- "Failed to acquire IDC lock. retrying...\n");
- /* Retry/Perform IDC-Lock recovery */
- if (qla83xx_idc_lock_recovery(base_vha) == QLA_SUCCESS) {
- qla83xx_wait_logic();
- goto retry_lock2;
- } else
- ql_log(ql_log_warn, base_vha, 0xb076,
- "IDC Lock recovery FAILED.\n");
- }
-
- return;
}
void
@@ -6483,8 +6645,10 @@ qla2x00_timer(scsi_qla_host_t *vha)
* FC-NVME
* see if the active AEN count has changed from what was last reported.
*/
- if (!vha->vp_idx && (atomic_read(&ha->nvme_active_aen_cnt) !=
- ha->nvme_last_rptd_aen) && ha->zio_mode == QLA_ZIO_MODE_6) {
+ if (!vha->vp_idx &&
+ (atomic_read(&ha->nvme_active_aen_cnt) != ha->nvme_last_rptd_aen) &&
+ ha->zio_mode == QLA_ZIO_MODE_6 &&
+ !ha->flags.host_shutting_down) {
ql_log(ql_log_info, vha, 0x3002,
"nvme: Sched: Set ZIO exchange threshold to %d.\n",
ha->nvme_last_rptd_aen);
@@ -6496,7 +6660,7 @@ qla2x00_timer(scsi_qla_host_t *vha)
if (!vha->vp_idx &&
(atomic_read(&ha->zio_threshold) != ha->last_zio_threshold) &&
(ha->zio_mode == QLA_ZIO_MODE_6) &&
- (IS_QLA83XX(ha) || IS_QLA27XX(ha))) {
+ (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))) {
ql_log(ql_log_info, vha, 0x3002,
"Sched: Set ZIO exchange threshold to %d.\n",
ha->last_zio_threshold);
@@ -6542,7 +6706,6 @@ qla2x00_timer(scsi_qla_host_t *vha)
/* Firmware interface routines. */
-#define FW_BLOBS 11
#define FW_ISP21XX 0
#define FW_ISP22XX 1
#define FW_ISP2300 2
@@ -6554,6 +6717,7 @@ qla2x00_timer(scsi_qla_host_t *vha)
#define FW_ISP2031 8
#define FW_ISP8031 9
#define FW_ISP27XX 10
+#define FW_ISP28XX 11
#define FW_FILE_ISP21XX "ql2100_fw.bin"
#define FW_FILE_ISP22XX "ql2200_fw.bin"
@@ -6566,11 +6730,12 @@ qla2x00_timer(scsi_qla_host_t *vha)
#define FW_FILE_ISP2031 "ql2600_fw.bin"
#define FW_FILE_ISP8031 "ql8300_fw.bin"
#define FW_FILE_ISP27XX "ql2700_fw.bin"
+#define FW_FILE_ISP28XX "ql2800_fw.bin"
static DEFINE_MUTEX(qla_fw_lock);
-static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
+static struct fw_blob qla_fw_blobs[] = {
{ .name = FW_FILE_ISP21XX, .segs = { 0x1000, 0 }, },
{ .name = FW_FILE_ISP22XX, .segs = { 0x1000, 0 }, },
{ .name = FW_FILE_ISP2300, .segs = { 0x800, 0 }, },
@@ -6582,6 +6747,8 @@ static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
{ .name = FW_FILE_ISP2031, },
{ .name = FW_FILE_ISP8031, },
{ .name = FW_FILE_ISP27XX, },
+ { .name = FW_FILE_ISP28XX, },
+ { .name = NULL, },
};
struct fw_blob *
@@ -6612,10 +6779,15 @@ qla2x00_request_firmware(scsi_qla_host_t *vha)
blob = &qla_fw_blobs[FW_ISP8031];
} else if (IS_QLA27XX(ha)) {
blob = &qla_fw_blobs[FW_ISP27XX];
+ } else if (IS_QLA28XX(ha)) {
+ blob = &qla_fw_blobs[FW_ISP28XX];
} else {
return NULL;
}
+ if (!blob->name)
+ return NULL;
+
mutex_lock(&qla_fw_lock);
if (blob->fw)
goto out;
@@ -6625,7 +6797,6 @@ qla2x00_request_firmware(scsi_qla_host_t *vha)
"Failed to load firmware image (%s).\n", blob->name);
blob->fw = NULL;
blob = NULL;
- goto out;
}
out:
@@ -6636,11 +6807,11 @@ out:
static void
qla2x00_release_firmware(void)
{
- int idx;
+ struct fw_blob *blob;
mutex_lock(&qla_fw_lock);
- for (idx = 0; idx < FW_BLOBS; idx++)
- release_firmware(qla_fw_blobs[idx].fw);
+ for (blob = qla_fw_blobs; blob->name; blob++)
+ release_firmware(blob->fw);
mutex_unlock(&qla_fw_lock);
}
@@ -6875,23 +7046,109 @@ qla2xxx_pci_resume(struct pci_dev *pdev)
pci_cleanup_aer_uncorrect_error_status(pdev);
}
+static void
+qla_pci_reset_prepare(struct pci_dev *pdev)
+{
+ scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
+ struct qla_hw_data *ha = base_vha->hw;
+ struct qla_qpair *qpair;
+
+ ql_log(ql_log_warn, base_vha, 0xffff,
+ "%s.\n", __func__);
+
+ /*
+ * PCI FLR/function reset is about to reset the
+ * slot. Stop the chip to stop all DMA access.
+ * It is assumed that pci_reset_done will be called
+ * after FLR to resume Chip operation.
+ */
+ ha->flags.eeh_busy = 1;
+ mutex_lock(&ha->mq_lock);
+ list_for_each_entry(qpair, &base_vha->qp_list, qp_list_elem)
+ qpair->online = 0;
+ mutex_unlock(&ha->mq_lock);
+
+ set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
+ qla2x00_abort_isp_cleanup(base_vha);
+ qla2x00_abort_all_cmds(base_vha, DID_RESET << 16);
+}
+
+static void
+qla_pci_reset_done(struct pci_dev *pdev)
+{
+ scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
+ struct qla_hw_data *ha = base_vha->hw;
+ struct qla_qpair *qpair;
+
+ ql_log(ql_log_warn, base_vha, 0xffff,
+ "%s.\n", __func__);
+
+ /*
+ * FLR just completed by PCI layer. Resume adapter
+ */
+ ha->flags.eeh_busy = 0;
+ mutex_lock(&ha->mq_lock);
+ list_for_each_entry(qpair, &base_vha->qp_list, qp_list_elem)
+ qpair->online = 1;
+ mutex_unlock(&ha->mq_lock);
+
+ base_vha->flags.online = 1;
+ ha->isp_ops->abort_isp(base_vha);
+ clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
+}
+
static int qla2xxx_map_queues(struct Scsi_Host *shost)
{
int rc;
scsi_qla_host_t *vha = (scsi_qla_host_t *)shost->hostdata;
- if (USER_CTRL_IRQ(vha->hw))
+ if (USER_CTRL_IRQ(vha->hw) || !vha->hw->mqiobase)
rc = blk_mq_map_queues(&shost->tag_set);
else
rc = blk_mq_pci_map_queues(&shost->tag_set, vha->hw->pdev);
return rc;
}
+struct scsi_host_template qla2xxx_driver_template = {
+ .module = THIS_MODULE,
+ .name = QLA2XXX_DRIVER_NAME,
+ .queuecommand = qla2xxx_queuecommand,
+
+ .eh_timed_out = fc_eh_timed_out,
+ .eh_abort_handler = qla2xxx_eh_abort,
+ .eh_device_reset_handler = qla2xxx_eh_device_reset,
+ .eh_target_reset_handler = qla2xxx_eh_target_reset,
+ .eh_bus_reset_handler = qla2xxx_eh_bus_reset,
+ .eh_host_reset_handler = qla2xxx_eh_host_reset,
+
+ .slave_configure = qla2xxx_slave_configure,
+
+ .slave_alloc = qla2xxx_slave_alloc,
+ .slave_destroy = qla2xxx_slave_destroy,
+ .scan_finished = qla2xxx_scan_finished,
+ .scan_start = qla2xxx_scan_start,
+ .change_queue_depth = scsi_change_queue_depth,
+ .map_queues = qla2xxx_map_queues,
+ .this_id = -1,
+ .cmd_per_lun = 3,
+ .use_clustering = ENABLE_CLUSTERING,
+ .sg_tablesize = SG_ALL,
+
+ .max_sectors = 0xFFFF,
+ .shost_attrs = qla2x00_host_attrs,
+
+ .supported_mode = MODE_INITIATOR,
+ .track_queue_depth = 1,
+ .cmd_size = sizeof(srb_t),
+};
+
static const struct pci_error_handlers qla2xxx_err_handler = {
.error_detected = qla2xxx_pci_error_detected,
.mmio_enabled = qla2xxx_pci_mmio_enabled,
.slot_reset = qla2xxx_pci_slot_reset,
.resume = qla2xxx_pci_resume,
+ .reset_prepare = qla_pci_reset_prepare,
+ .reset_done = qla_pci_reset_done,
};
static struct pci_device_id qla2xxx_pci_tbl[] = {
@@ -6917,6 +7174,11 @@ static struct pci_device_id qla2xxx_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2071) },
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2271) },
{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2261) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2061) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2081) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2281) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2089) },
+ { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2289) },
{ 0 },
};
MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
@@ -6946,6 +7208,30 @@ qla2x00_module_init(void)
{
int ret = 0;
+ BUILD_BUG_ON(sizeof(cmd_entry_t) != 64);
+ BUILD_BUG_ON(sizeof(cont_a64_entry_t) != 64);
+ BUILD_BUG_ON(sizeof(cont_entry_t) != 64);
+ BUILD_BUG_ON(sizeof(init_cb_t) != 96);
+ BUILD_BUG_ON(sizeof(ms_iocb_entry_t) != 64);
+ BUILD_BUG_ON(sizeof(request_t) != 64);
+ BUILD_BUG_ON(sizeof(struct access_chip_84xx) != 64);
+ BUILD_BUG_ON(sizeof(struct cmd_bidir) != 64);
+ BUILD_BUG_ON(sizeof(struct cmd_nvme) != 64);
+ BUILD_BUG_ON(sizeof(struct cmd_type_6) != 64);
+ BUILD_BUG_ON(sizeof(struct cmd_type_7) != 64);
+ BUILD_BUG_ON(sizeof(struct cmd_type_7_fx00) != 64);
+ BUILD_BUG_ON(sizeof(struct cmd_type_crc_2) != 64);
+ BUILD_BUG_ON(sizeof(struct ct_entry_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct ctio_crc2_to_fw) != 64);
+ BUILD_BUG_ON(sizeof(struct els_entry_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct fxdisc_entry_fx00) != 64);
+ BUILD_BUG_ON(sizeof(struct init_cb_24xx) != 128);
+ BUILD_BUG_ON(sizeof(struct init_cb_81xx) != 128);
+ BUILD_BUG_ON(sizeof(struct pt_ls4_request) != 64);
+ BUILD_BUG_ON(sizeof(struct sns_cmd_pkt) != 2064);
+ BUILD_BUG_ON(sizeof(struct verify_chip_entry_84xx) != 64);
+ BUILD_BUG_ON(sizeof(struct vf_evfp_entry_24xx) != 56);
+
/* Allocate cache for SRBs. */
srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,
SLAB_HWCACHE_ALIGN, NULL);
@@ -7036,14 +7322,15 @@ destroy_cache:
static void __exit
qla2x00_module_exit(void)
{
- unregister_chrdev(apidev_major, QLA2XXX_APIDEV);
pci_unregister_driver(&qla2xxx_pci_driver);
qla2x00_release_firmware();
- kmem_cache_destroy(srb_cachep);
- qlt_exit();
kmem_cache_destroy(ctx_cachep);
- fc_release_transport(qla2xxx_transport_template);
fc_release_transport(qla2xxx_transport_vport_template);
+ if (apidev_major >= 0)
+ unregister_chrdev(apidev_major, QLA2XXX_APIDEV);
+ fc_release_transport(qla2xxx_transport_template);
+ qlt_exit();
+ kmem_cache_destroy(srb_cachep);
}
module_init(qla2x00_module_init);
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 2a3055c799fb..f2d5115b2d8d 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -429,102 +429,104 @@ qla2x00_set_nvram_protection(struct qla_hw_data *ha, int stat)
static inline uint32_t
flash_conf_addr(struct qla_hw_data *ha, uint32_t faddr)
{
- return ha->flash_conf_off | faddr;
+ return ha->flash_conf_off + faddr;
}
static inline uint32_t
flash_data_addr(struct qla_hw_data *ha, uint32_t faddr)
{
- return ha->flash_data_off | faddr;
+ return ha->flash_data_off + faddr;
}
static inline uint32_t
nvram_conf_addr(struct qla_hw_data *ha, uint32_t naddr)
{
- return ha->nvram_conf_off | naddr;
+ return ha->nvram_conf_off + naddr;
}
static inline uint32_t
nvram_data_addr(struct qla_hw_data *ha, uint32_t naddr)
{
- return ha->nvram_data_off | naddr;
+ return ha->nvram_data_off + naddr;
}
-static uint32_t
-qla24xx_read_flash_dword(struct qla_hw_data *ha, uint32_t addr)
+static int
+qla24xx_read_flash_dword(struct qla_hw_data *ha, uint32_t addr, uint32_t *data)
{
- int rval;
- uint32_t cnt, data;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+ ulong cnt = 30000;
WRT_REG_DWORD(&reg->flash_addr, addr & ~FARX_DATA_FLAG);
- /* Wait for READ cycle to complete. */
- rval = QLA_SUCCESS;
- for (cnt = 3000;
- (RD_REG_DWORD(&reg->flash_addr) & FARX_DATA_FLAG) == 0 &&
- rval == QLA_SUCCESS; cnt--) {
- if (cnt)
- udelay(10);
- else
- rval = QLA_FUNCTION_TIMEOUT;
+
+ while (cnt--) {
+ if (RD_REG_DWORD(&reg->flash_addr) & FARX_DATA_FLAG) {
+ *data = RD_REG_DWORD(&reg->flash_data);
+ return QLA_SUCCESS;
+ }
+ udelay(10);
cond_resched();
}
- /* TODO: What happens if we time out? */
- data = 0xDEADDEAD;
- if (rval == QLA_SUCCESS)
- data = RD_REG_DWORD(&reg->flash_data);
-
- return data;
+ ql_log(ql_log_warn, pci_get_drvdata(ha->pdev), 0x7090,
+ "Flash read dword at %x timeout.\n", addr);
+ *data = 0xDEADDEAD;
+ return QLA_FUNCTION_TIMEOUT;
}
-uint32_t *
+int
qla24xx_read_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
uint32_t dwords)
{
- uint32_t i;
+ ulong i;
+ int ret = QLA_SUCCESS;
struct qla_hw_data *ha = vha->hw;
/* Dword reads to flash. */
- for (i = 0; i < dwords; i++, faddr++)
- dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
- flash_data_addr(ha, faddr)));
+ faddr = flash_data_addr(ha, faddr);
+ for (i = 0; i < dwords; i++, faddr++, dwptr++) {
+ ret = qla24xx_read_flash_dword(ha, faddr, dwptr);
+ if (ret != QLA_SUCCESS)
+ break;
+ cpu_to_le32s(dwptr);
+ }
- return dwptr;
+ return ret;
}
static int
qla24xx_write_flash_dword(struct qla_hw_data *ha, uint32_t addr, uint32_t data)
{
- int rval;
- uint32_t cnt;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+ ulong cnt = 500000;
WRT_REG_DWORD(&reg->flash_data, data);
- RD_REG_DWORD(&reg->flash_data); /* PCI Posting. */
WRT_REG_DWORD(&reg->flash_addr, addr | FARX_DATA_FLAG);
- /* Wait for Write cycle to complete. */
- rval = QLA_SUCCESS;
- for (cnt = 500000; (RD_REG_DWORD(&reg->flash_addr) & FARX_DATA_FLAG) &&
- rval == QLA_SUCCESS; cnt--) {
- if (cnt)
- udelay(10);
- else
- rval = QLA_FUNCTION_TIMEOUT;
+
+ while (cnt--) {
+ if (!(RD_REG_DWORD(&reg->flash_addr) & FARX_DATA_FLAG))
+ return QLA_SUCCESS;
+ udelay(10);
cond_resched();
}
- return rval;
+
+ ql_log(ql_log_warn, pci_get_drvdata(ha->pdev), 0x7090,
+ "Flash write dword at %x timeout.\n", addr);
+ return QLA_FUNCTION_TIMEOUT;
}
static void
qla24xx_get_flash_manufacturer(struct qla_hw_data *ha, uint8_t *man_id,
uint8_t *flash_id)
{
- uint32_t ids;
+ uint32_t faddr, ids = 0;
- ids = qla24xx_read_flash_dword(ha, flash_conf_addr(ha, 0x03ab));
- *man_id = LSB(ids);
- *flash_id = MSB(ids);
+ *man_id = *flash_id = 0;
+
+ faddr = flash_conf_addr(ha, 0x03ab);
+ if (!qla24xx_read_flash_dword(ha, faddr, &ids)) {
+ *man_id = LSB(ids);
+ *flash_id = MSB(ids);
+ }
/* Check if man_id and flash_id are valid. */
if (ids != 0xDEADDEAD && (*man_id == 0 || *flash_id == 0)) {
@@ -534,9 +536,11 @@ qla24xx_get_flash_manufacturer(struct qla_hw_data *ha, uint8_t *man_id,
* Example: ATMEL 0x00 01 45 1F
* Extract MFG and Dev ID from last two bytes.
*/
- ids = qla24xx_read_flash_dword(ha, flash_conf_addr(ha, 0x009f));
- *man_id = LSB(ids);
- *flash_id = MSB(ids);
+ faddr = flash_conf_addr(ha, 0x009f);
+ if (!qla24xx_read_flash_dword(ha, faddr, &ids)) {
+ *man_id = LSB(ids);
+ *flash_id = MSB(ids);
+ }
}
}
@@ -545,12 +549,12 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start)
{
const char *loc, *locations[] = { "DEF", "PCI" };
uint32_t pcihdr, pcids;
- uint32_t *dcode;
- uint8_t *buf, *bcode, last_image;
uint16_t cnt, chksum, *wptr;
- struct qla_flt_location *fltl;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
+ struct qla_flt_location *fltl = (void *)req->ring;
+ uint32_t *dcode = (void *)req->ring;
+ uint8_t *buf = (void *)req->ring, *bcode, last_image;
/*
* FLT-location structure resides after the last PCI region.
@@ -571,12 +575,13 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start)
} else if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
*start = FA_FLASH_LAYOUT_ADDR_83;
goto end;
+ } else if (IS_QLA28XX(ha)) {
+ *start = FA_FLASH_LAYOUT_ADDR_28;
+ goto end;
}
+
/* Begin with first PCI expansion ROM header. */
- buf = (uint8_t *)req->ring;
- dcode = (uint32_t *)req->ring;
pcihdr = 0;
- last_image = 1;
do {
/* Verify PCI expansion ROM header. */
qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, 0x20);
@@ -601,22 +606,19 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start)
} while (!last_image);
/* Now verify FLT-location structure. */
- fltl = (struct qla_flt_location *)req->ring;
- qla24xx_read_flash_data(vha, dcode, pcihdr >> 2,
- sizeof(struct qla_flt_location) >> 2);
- if (fltl->sig[0] != 'Q' || fltl->sig[1] != 'F' ||
- fltl->sig[2] != 'L' || fltl->sig[3] != 'T')
+ qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, sizeof(*fltl) >> 2);
+ if (memcmp(fltl->sig, "QFLT", 4))
goto end;
- wptr = (uint16_t *)req->ring;
- cnt = sizeof(struct qla_flt_location) >> 1;
+ wptr = (void *)req->ring;
+ cnt = sizeof(*fltl) / sizeof(*wptr);
for (chksum = 0; cnt--; wptr++)
chksum += le16_to_cpu(*wptr);
if (chksum) {
ql_log(ql_log_fatal, vha, 0x0045,
"Inconsistent FLTL detected: checksum=0x%x.\n", chksum);
ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010e,
- buf, sizeof(struct qla_flt_location));
+ fltl, sizeof(*fltl));
return QLA_FUNCTION_FAILED;
}
@@ -634,7 +636,7 @@ end:
static void
qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
{
- const char *loc, *locations[] = { "DEF", "FLT" };
+ const char *locations[] = { "DEF", "FLT" }, *loc = locations[1];
const uint32_t def_fw[] =
{ FA_RISC_CODE_ADDR, FA_RISC_CODE_ADDR, FA_RISC_CODE_ADDR_81 };
const uint32_t def_boot[] =
@@ -664,20 +666,13 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
const uint32_t fcp_prio_cfg1[] =
{ FA_FCP_PRIO1_ADDR, FA_FCP_PRIO1_ADDR_25,
0 };
- uint32_t def;
- uint16_t *wptr;
- uint16_t cnt, chksum;
- uint32_t start;
- struct qla_flt_header *flt;
- struct qla_flt_region *region;
- struct qla_hw_data *ha = vha->hw;
- struct req_que *req = ha->req_q_map[0];
- def = 0;
- if (IS_QLA25XX(ha))
- def = 1;
- else if (IS_QLA81XX(ha))
- def = 2;
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t def = IS_QLA81XX(ha) ? 2 : IS_QLA25XX(ha) ? 1 : 0;
+ struct qla_flt_header *flt = (void *)ha->flt;
+ struct qla_flt_region *region = (void *)&flt[1];
+ uint16_t *wptr, cnt, chksum;
+ uint32_t start;
/* Assign FCP prio region since older adapters may not have FLT, or
FCP prio region in it's FLT.
@@ -686,12 +681,11 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
fcp_prio_cfg0[def] : fcp_prio_cfg1[def];
ha->flt_region_flt = flt_addr;
- wptr = (uint16_t *)req->ring;
- flt = (struct qla_flt_header *)req->ring;
- region = (struct qla_flt_region *)&flt[1];
- ha->isp_ops->read_optrom(vha, (uint8_t *)req->ring,
- flt_addr << 2, OPTROM_BURST_SIZE);
- if (*wptr == cpu_to_le16(0xffff))
+ wptr = (uint16_t *)ha->flt;
+ ha->isp_ops->read_optrom(vha, (void *)flt, flt_addr << 2,
+ (sizeof(struct qla_flt_header) + FLT_REGIONS_SIZE));
+
+ if (le16_to_cpu(*wptr) == 0xffff)
goto no_flash_data;
if (flt->version != cpu_to_le16(1)) {
ql_log(ql_log_warn, vha, 0x0047,
@@ -701,7 +695,7 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
goto no_flash_data;
}
- cnt = (sizeof(struct qla_flt_header) + le16_to_cpu(flt->length)) >> 1;
+ cnt = (sizeof(*flt) + le16_to_cpu(flt->length)) / sizeof(*wptr);
for (chksum = 0; cnt--; wptr++)
chksum += le16_to_cpu(*wptr);
if (chksum) {
@@ -712,18 +706,20 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
goto no_flash_data;
}
- loc = locations[1];
- cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region);
+ cnt = le16_to_cpu(flt->length) / sizeof(*region);
for ( ; cnt; cnt--, region++) {
/* Store addresses as DWORD offsets. */
start = le32_to_cpu(region->start) >> 2;
ql_dbg(ql_dbg_init, vha, 0x0049,
- "FLT[%02x]: start=0x%x "
- "end=0x%x size=0x%x.\n", le32_to_cpu(region->code) & 0xff,
- start, le32_to_cpu(region->end) >> 2,
- le32_to_cpu(region->size));
-
- switch (le32_to_cpu(region->code) & 0xff) {
+ "FLT[%#x]: start=%#x end=%#x size=%#x.\n",
+ le16_to_cpu(region->code), start,
+ le32_to_cpu(region->end) >> 2,
+ le32_to_cpu(region->size) >> 2);
+ if (region->attribute)
+ ql_log(ql_dbg_init, vha, 0xffff,
+ "Region %x is secure\n", region->code);
+
+ switch (le16_to_cpu(region->code)) {
case FLT_REG_FCOE_FW:
if (!IS_QLA8031(ha))
break;
@@ -753,13 +749,13 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
ha->flt_region_vpd = start;
break;
case FLT_REG_VPD_2:
- if (!IS_QLA27XX(ha))
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
break;
if (ha->port_no == 2)
ha->flt_region_vpd = start;
break;
case FLT_REG_VPD_3:
- if (!IS_QLA27XX(ha))
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
break;
if (ha->port_no == 3)
ha->flt_region_vpd = start;
@@ -777,13 +773,13 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
ha->flt_region_nvram = start;
break;
case FLT_REG_NVRAM_2:
- if (!IS_QLA27XX(ha))
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
break;
if (ha->port_no == 2)
ha->flt_region_nvram = start;
break;
case FLT_REG_NVRAM_3:
- if (!IS_QLA27XX(ha))
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
break;
if (ha->port_no == 3)
ha->flt_region_nvram = start;
@@ -847,36 +843,74 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
ha->flt_region_nvram = start;
break;
case FLT_REG_IMG_PRI_27XX:
- if (IS_QLA27XX(ha))
+ if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
ha->flt_region_img_status_pri = start;
break;
case FLT_REG_IMG_SEC_27XX:
- if (IS_QLA27XX(ha))
+ if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
ha->flt_region_img_status_sec = start;
break;
case FLT_REG_FW_SEC_27XX:
- if (IS_QLA27XX(ha))
+ if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
ha->flt_region_fw_sec = start;
break;
case FLT_REG_BOOTLOAD_SEC_27XX:
- if (IS_QLA27XX(ha))
+ if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
ha->flt_region_boot_sec = start;
break;
+ case FLT_REG_AUX_IMG_PRI_28XX:
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
+ ha->flt_region_aux_img_status_pri = start;
+ break;
+ case FLT_REG_AUX_IMG_SEC_28XX:
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
+ ha->flt_region_aux_img_status_sec = start;
+ break;
+ case FLT_REG_NVRAM_SEC_28XX_0:
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
+ if (ha->port_no == 0)
+ ha->flt_region_nvram_sec = start;
+ break;
+ case FLT_REG_NVRAM_SEC_28XX_1:
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
+ if (ha->port_no == 1)
+ ha->flt_region_nvram_sec = start;
+ break;
+ case FLT_REG_NVRAM_SEC_28XX_2:
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
+ if (ha->port_no == 2)
+ ha->flt_region_nvram_sec = start;
+ break;
+ case FLT_REG_NVRAM_SEC_28XX_3:
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
+ if (ha->port_no == 3)
+ ha->flt_region_nvram_sec = start;
+ break;
case FLT_REG_VPD_SEC_27XX_0:
- if (IS_QLA27XX(ha))
- ha->flt_region_vpd_sec = start;
+ case FLT_REG_VPD_SEC_28XX_0:
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ ha->flt_region_vpd_nvram_sec = start;
+ if (ha->port_no == 0)
+ ha->flt_region_vpd_sec = start;
+ }
break;
case FLT_REG_VPD_SEC_27XX_1:
- if (IS_QLA27XX(ha))
- ha->flt_region_vpd_sec = start;
+ case FLT_REG_VPD_SEC_28XX_1:
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
+ if (ha->port_no == 1)
+ ha->flt_region_vpd_sec = start;
break;
case FLT_REG_VPD_SEC_27XX_2:
- if (IS_QLA27XX(ha))
- ha->flt_region_vpd_sec = start;
+ case FLT_REG_VPD_SEC_28XX_2:
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
+ if (ha->port_no == 2)
+ ha->flt_region_vpd_sec = start;
break;
case FLT_REG_VPD_SEC_27XX_3:
- if (IS_QLA27XX(ha))
- ha->flt_region_vpd_sec = start;
+ case FLT_REG_VPD_SEC_28XX_3:
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
+ if (ha->port_no == 3)
+ ha->flt_region_vpd_sec = start;
break;
}
}
@@ -912,22 +946,19 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha)
#define FLASH_BLK_SIZE_32K 0x8000
#define FLASH_BLK_SIZE_64K 0x10000
const char *loc, *locations[] = { "MID", "FDT" };
+ struct qla_hw_data *ha = vha->hw;
+ struct req_que *req = ha->req_q_map[0];
uint16_t cnt, chksum;
- uint16_t *wptr;
- struct qla_fdt_layout *fdt;
+ uint16_t *wptr = (void *)req->ring;
+ struct qla_fdt_layout *fdt = (struct qla_fdt_layout *)req->ring;
uint8_t man_id, flash_id;
uint16_t mid = 0, fid = 0;
- struct qla_hw_data *ha = vha->hw;
- struct req_que *req = ha->req_q_map[0];
- wptr = (uint16_t *)req->ring;
- fdt = (struct qla_fdt_layout *)req->ring;
- ha->isp_ops->read_optrom(vha, (uint8_t *)req->ring,
- ha->flt_region_fdt << 2, OPTROM_BURST_SIZE);
- if (*wptr == cpu_to_le16(0xffff))
+ ha->isp_ops->read_optrom(vha, fdt, ha->flt_region_fdt << 2,
+ OPTROM_BURST_DWORDS);
+ if (le16_to_cpu(*wptr) == 0xffff)
goto no_flash_data;
- if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' ||
- fdt->sig[3] != 'D')
+ if (memcmp(fdt->sig, "QLID", 4))
goto no_flash_data;
for (cnt = 0, chksum = 0; cnt < sizeof(*fdt) >> 1; cnt++, wptr++)
@@ -938,7 +969,7 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha)
" checksum=0x%x id=%c version0x%x.\n", chksum,
fdt->sig[0], le16_to_cpu(fdt->version));
ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x0113,
- (uint8_t *)fdt, sizeof(*fdt));
+ fdt, sizeof(*fdt));
goto no_flash_data;
}
@@ -958,7 +989,7 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *vha)
ha->fdt_unprotect_sec_cmd = flash_conf_addr(ha, 0x0300 |
fdt->unprotect_sec_cmd);
ha->fdt_protect_sec_cmd = fdt->protect_sec_cmd ?
- flash_conf_addr(ha, 0x0300 | fdt->protect_sec_cmd):
+ flash_conf_addr(ha, 0x0300 | fdt->protect_sec_cmd) :
flash_conf_addr(ha, 0x0336);
}
goto done;
@@ -1019,8 +1050,7 @@ qla2xxx_get_idc_param(scsi_qla_host_t *vha)
return;
wptr = (uint32_t *)req->ring;
- ha->isp_ops->read_optrom(vha, (uint8_t *)req->ring,
- QLA82XX_IDC_PARAM_ADDR , 8);
+ ha->isp_ops->read_optrom(vha, req->ring, QLA82XX_IDC_PARAM_ADDR, 8);
if (*wptr == cpu_to_le32(0xffffffff)) {
ha->fcoe_dev_init_timeout = QLA82XX_ROM_DEV_INIT_TIMEOUT;
@@ -1045,7 +1075,8 @@ qla2xxx_get_flash_info(scsi_qla_host_t *vha)
struct qla_hw_data *ha = vha->hw;
if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha) &&
- !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) && !IS_QLA27XX(ha))
+ !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) &&
+ !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
return QLA_SUCCESS;
ret = qla2xxx_find_flt_start(vha, &flt_addr);
@@ -1081,8 +1112,8 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
if (IS_QLA8044(ha))
return;
- ha->isp_ops->read_optrom(vha, (uint8_t *)&hdr,
- ha->flt_region_npiv_conf << 2, sizeof(struct qla_npiv_header));
+ ha->isp_ops->read_optrom(vha, &hdr, ha->flt_region_npiv_conf << 2,
+ sizeof(struct qla_npiv_header));
if (hdr.version == cpu_to_le16(0xffff))
return;
if (hdr.version != cpu_to_le16(1)) {
@@ -1101,8 +1132,8 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
return;
}
- ha->isp_ops->read_optrom(vha, (uint8_t *)data,
- ha->flt_region_npiv_conf << 2, NPIV_CONFIG_SIZE);
+ ha->isp_ops->read_optrom(vha, data, ha->flt_region_npiv_conf << 2,
+ NPIV_CONFIG_SIZE);
cnt = (sizeof(hdr) + le16_to_cpu(hdr.entries) * sizeof(*entry)) >> 1;
for (wptr = data, chksum = 0; cnt--; wptr++)
@@ -1139,10 +1170,8 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
vid.node_name = wwn_to_u64(entry->node_name);
ql_dbg(ql_dbg_user, vha, 0x7093,
- "NPIV[%02x]: wwpn=%llx "
- "wwnn=%llx vf_id=0x%x Q_qos=0x%x F_qos=0x%x.\n", cnt,
- (unsigned long long)vid.port_name,
- (unsigned long long)vid.node_name,
+ "NPIV[%02x]: wwpn=%llx wwnn=%llx vf_id=%#x Q_qos=%#x F_qos=%#x.\n",
+ cnt, vid.port_name, vid.node_name,
le16_to_cpu(entry->vf_id),
entry->q_qos, entry->f_qos);
@@ -1150,10 +1179,8 @@ qla2xxx_flash_npiv_conf(scsi_qla_host_t *vha)
vport = fc_vport_create(vha->host, 0, &vid);
if (!vport)
ql_log(ql_log_warn, vha, 0x7094,
- "NPIV-Config Failed to create vport [%02x]: "
- "wwpn=%llx wwnn=%llx.\n", cnt,
- (unsigned long long)vid.port_name,
- (unsigned long long)vid.node_name);
+ "NPIV-Config Failed to create vport [%02x]: wwpn=%llx wwnn=%llx.\n",
+ cnt, vid.port_name, vid.node_name);
}
}
done:
@@ -1188,9 +1215,10 @@ done:
static int
qla24xx_protect_flash(scsi_qla_host_t *vha)
{
- uint32_t cnt;
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+ ulong cnt = 300;
+ uint32_t faddr, dword;
if (ha->flags.fac_supported)
return qla81xx_fac_do_write_enable(vha, 0);
@@ -1199,11 +1227,14 @@ qla24xx_protect_flash(scsi_qla_host_t *vha)
goto skip_wrt_protect;
/* Enable flash write-protection and wait for completion. */
- qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101),
- ha->fdt_wrt_disable);
- for (cnt = 300; cnt &&
- qla24xx_read_flash_dword(ha, flash_conf_addr(ha, 0x005)) & BIT_0;
- cnt--) {
+ faddr = flash_conf_addr(ha, 0x101);
+ qla24xx_write_flash_dword(ha, faddr, ha->fdt_wrt_disable);
+ faddr = flash_conf_addr(ha, 0x5);
+ while (cnt--) {
+ if (!qla24xx_read_flash_dword(ha, faddr, &dword)) {
+ if (!(dword & BIT_0))
+ break;
+ }
udelay(10);
}
@@ -1211,7 +1242,6 @@ skip_wrt_protect:
/* Disable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
- RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
return QLA_SUCCESS;
}
@@ -1239,107 +1269,103 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
uint32_t dwords)
{
int ret;
- uint32_t liter;
- uint32_t sec_mask, rest_addr;
- uint32_t fdata;
+ ulong liter;
+ ulong dburst = OPTROM_BURST_DWORDS; /* burst size in dwords */
+ uint32_t sec_mask, rest_addr, fdata;
dma_addr_t optrom_dma;
void *optrom = NULL;
struct qla_hw_data *ha = vha->hw;
- /* Prepare burst-capable write on supported ISPs. */
- if ((IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
- IS_QLA27XX(ha)) &&
- !(faddr & 0xfff) && dwords > OPTROM_BURST_DWORDS) {
- optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
- &optrom_dma, GFP_KERNEL);
- if (!optrom) {
- ql_log(ql_log_warn, vha, 0x7095,
- "Unable to allocate "
- "memory for optrom burst write (%x KB).\n",
- OPTROM_BURST_SIZE / 1024);
- }
- }
+ if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) &&
+ !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+ goto next;
- rest_addr = (ha->fdt_block_size >> 2) - 1;
- sec_mask = ~rest_addr;
+ /* Allocate dma buffer for burst write */
+ optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
+ &optrom_dma, GFP_KERNEL);
+ if (!optrom) {
+ ql_log(ql_log_warn, vha, 0x7095,
+ "Failed allocate burst (%x bytes)\n", OPTROM_BURST_SIZE);
+ }
+next:
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
+ "Unprotect flash...\n");
ret = qla24xx_unprotect_flash(vha);
- if (ret != QLA_SUCCESS) {
+ if (ret) {
ql_log(ql_log_warn, vha, 0x7096,
- "Unable to unprotect flash for update.\n");
+ "Failed to unprotect flash.\n");
goto done;
}
+ rest_addr = (ha->fdt_block_size >> 2) - 1;
+ sec_mask = ~rest_addr;
for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
fdata = (faddr & sec_mask) << 2;
/* Are we at the beginning of a sector? */
- if ((faddr & rest_addr) == 0) {
- /* Do sector unprotect. */
- if (ha->fdt_unprotect_sec_cmd)
- qla24xx_write_flash_dword(ha,
- ha->fdt_unprotect_sec_cmd,
- (fdata & 0xff00) | ((fdata << 16) &
- 0xff0000) | ((fdata >> 16) & 0xff));
+ if (!(faddr & rest_addr)) {
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
+ "Erase sector %#x...\n", faddr);
+
ret = qla24xx_erase_sector(vha, fdata);
- if (ret != QLA_SUCCESS) {
+ if (ret) {
ql_dbg(ql_dbg_user, vha, 0x7007,
- "Unable to erase erase sector: address=%x.\n",
- faddr);
+ "Failed to erase sector %x.\n", faddr);
break;
}
}
- /* Go with burst-write. */
- if (optrom && (liter + OPTROM_BURST_DWORDS) <= dwords) {
- /* Copy data to DMA'ble buffer. */
- memcpy(optrom, dwptr, OPTROM_BURST_SIZE);
+ if (optrom) {
+ /* If smaller than a burst remaining */
+ if (dwords - liter < dburst)
+ dburst = dwords - liter;
+ /* Copy to dma buffer */
+ memcpy(optrom, dwptr, dburst << 2);
+
+ /* Burst write */
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
+ "Write burst (%#lx dwords)...\n", dburst);
ret = qla2x00_load_ram(vha, optrom_dma,
- flash_data_addr(ha, faddr),
- OPTROM_BURST_DWORDS);
- if (ret != QLA_SUCCESS) {
- ql_log(ql_log_warn, vha, 0x7097,
- "Unable to burst-write optrom segment "
- "(%x/%x/%llx).\n", ret,
- flash_data_addr(ha, faddr),
- (unsigned long long)optrom_dma);
- ql_log(ql_log_warn, vha, 0x7098,
- "Reverting to slow-write.\n");
-
- dma_free_coherent(&ha->pdev->dev,
- OPTROM_BURST_SIZE, optrom, optrom_dma);
- optrom = NULL;
- } else {
- liter += OPTROM_BURST_DWORDS - 1;
- faddr += OPTROM_BURST_DWORDS - 1;
- dwptr += OPTROM_BURST_DWORDS - 1;
+ flash_data_addr(ha, faddr), dburst);
+ if (!ret) {
+ liter += dburst - 1;
+ faddr += dburst - 1;
+ dwptr += dburst - 1;
continue;
}
+
+ ql_log(ql_log_warn, vha, 0x7097,
+ "Failed burst-write at %x (%p/%#llx)....\n",
+ flash_data_addr(ha, faddr), optrom,
+ (u64)optrom_dma);
+
+ dma_free_coherent(&ha->pdev->dev,
+ OPTROM_BURST_SIZE, optrom, optrom_dma);
+ optrom = NULL;
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
+ break;
+ ql_log(ql_log_warn, vha, 0x7098,
+ "Reverting to slow write...\n");
}
+ /* Slow write */
ret = qla24xx_write_flash_dword(ha,
flash_data_addr(ha, faddr), cpu_to_le32(*dwptr));
- if (ret != QLA_SUCCESS) {
+ if (ret) {
ql_dbg(ql_dbg_user, vha, 0x7006,
- "Unable to program flash address=%x data=%x.\n",
- faddr, *dwptr);
+ "Failed slopw write %x (%x)\n", faddr, *dwptr);
break;
}
-
- /* Do sector protect. */
- if (ha->fdt_unprotect_sec_cmd &&
- ((faddr & rest_addr) == rest_addr))
- qla24xx_write_flash_dword(ha,
- ha->fdt_protect_sec_cmd,
- (fdata & 0xff00) | ((fdata << 16) &
- 0xff0000) | ((fdata >> 16) & 0xff));
}
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
+ "Protect flash...\n");
ret = qla24xx_protect_flash(vha);
- if (ret != QLA_SUCCESS)
+ if (ret)
ql_log(ql_log_warn, vha, 0x7099,
- "Unable to protect flash after update.\n");
+ "Failed to protect flash\n");
done:
if (optrom)
dma_free_coherent(&ha->pdev->dev,
@@ -1349,7 +1375,7 @@ done:
}
uint8_t *
-qla2x00_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
+qla2x00_read_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr,
uint32_t bytes)
{
uint32_t i;
@@ -1368,27 +1394,30 @@ qla2x00_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
}
uint8_t *
-qla24xx_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
+qla24xx_read_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr,
uint32_t bytes)
{
- uint32_t i;
- uint32_t *dwptr;
struct qla_hw_data *ha = vha->hw;
+ uint32_t *dwptr = buf;
+ uint32_t i;
if (IS_P3P_TYPE(ha))
return buf;
/* Dword reads to flash. */
- dwptr = (uint32_t *)buf;
- for (i = 0; i < bytes >> 2; i++, naddr++)
- dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
- nvram_data_addr(ha, naddr)));
+ naddr = nvram_data_addr(ha, naddr);
+ bytes >>= 2;
+ for (i = 0; i < bytes; i++, naddr++, dwptr++) {
+ if (qla24xx_read_flash_dword(ha, naddr, dwptr))
+ break;
+ cpu_to_le32s(dwptr);
+ }
return buf;
}
int
-qla2x00_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
+qla2x00_write_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr,
uint32_t bytes)
{
int ret, stat;
@@ -1422,14 +1451,14 @@ qla2x00_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
}
int
-qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
+qla24xx_write_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr,
uint32_t bytes)
{
- int ret;
- uint32_t i;
- uint32_t *dwptr;
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+ uint32_t *dwptr = buf;
+ uint32_t i;
+ int ret;
ret = QLA_SUCCESS;
@@ -1446,11 +1475,10 @@ qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
qla24xx_write_flash_dword(ha, nvram_conf_addr(ha, 0x101), 0);
/* Dword writes to flash. */
- dwptr = (uint32_t *)buf;
- for (i = 0; i < bytes >> 2; i++, naddr++, dwptr++) {
- ret = qla24xx_write_flash_dword(ha,
- nvram_data_addr(ha, naddr), cpu_to_le32(*dwptr));
- if (ret != QLA_SUCCESS) {
+ naddr = nvram_data_addr(ha, naddr);
+ bytes >>= 2;
+ for (i = 0; i < bytes; i++, naddr++, dwptr++) {
+ if (qla24xx_write_flash_dword(ha, naddr, cpu_to_le32(*dwptr))) {
ql_dbg(ql_dbg_user, vha, 0x709a,
"Unable to program nvram address=%x data=%x.\n",
naddr, *dwptr);
@@ -1470,31 +1498,34 @@ qla24xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
}
uint8_t *
-qla25xx_read_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
+qla25xx_read_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr,
uint32_t bytes)
{
- uint32_t i;
- uint32_t *dwptr;
struct qla_hw_data *ha = vha->hw;
+ uint32_t *dwptr = buf;
+ uint32_t i;
/* Dword reads to flash. */
- dwptr = (uint32_t *)buf;
- for (i = 0; i < bytes >> 2; i++, naddr++)
- dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
- flash_data_addr(ha, ha->flt_region_vpd_nvram | naddr)));
+ naddr = flash_data_addr(ha, ha->flt_region_vpd_nvram | naddr);
+ bytes >>= 2;
+ for (i = 0; i < bytes; i++, naddr++, dwptr++) {
+ if (qla24xx_read_flash_dword(ha, naddr, dwptr))
+ break;
+
+ cpu_to_le32s(dwptr);
+ }
return buf;
}
+#define RMW_BUFFER_SIZE (64 * 1024)
int
-qla25xx_write_nvram_data(scsi_qla_host_t *vha, uint8_t *buf, uint32_t naddr,
+qla25xx_write_nvram_data(scsi_qla_host_t *vha, void *buf, uint32_t naddr,
uint32_t bytes)
{
struct qla_hw_data *ha = vha->hw;
-#define RMW_BUFFER_SIZE (64 * 1024)
- uint8_t *dbuf;
+ uint8_t *dbuf = vmalloc(RMW_BUFFER_SIZE);
- dbuf = vmalloc(RMW_BUFFER_SIZE);
if (!dbuf)
return QLA_MEMORY_ALLOC_FAILED;
ha->isp_ops->read_optrom(vha, dbuf, ha->flt_region_vpd_nvram << 2,
@@ -1728,7 +1759,7 @@ qla83xx_select_led_port(struct qla_hw_data *ha)
{
uint32_t led_select_value = 0;
- if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
+ if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))
goto out;
if (ha->port_no == 0)
@@ -1749,13 +1780,14 @@ qla83xx_beacon_blink(struct scsi_qla_host *vha)
uint16_t orig_led_cfg[6];
uint32_t led_10_value, led_43_value;
- if (!IS_QLA83XX(ha) && !IS_QLA81XX(ha) && !IS_QLA27XX(ha))
+ if (!IS_QLA83XX(ha) && !IS_QLA81XX(ha) && !IS_QLA27XX(ha) &&
+ !IS_QLA28XX(ha))
return;
if (!ha->beacon_blink_led)
return;
- if (IS_QLA27XX(ha)) {
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
qla2x00_write_ram_word(vha, 0x1003, 0x40000230);
qla2x00_write_ram_word(vha, 0x1004, 0x40000230);
} else if (IS_QLA2031(ha)) {
@@ -1845,7 +1877,7 @@ qla24xx_beacon_on(struct scsi_qla_host *vha)
return QLA_FUNCTION_FAILED;
}
- if (IS_QLA2031(ha) || IS_QLA27XX(ha))
+ if (IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
goto skip_gpio;
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -1885,7 +1917,7 @@ qla24xx_beacon_off(struct scsi_qla_host *vha)
ha->beacon_blink_led = 0;
- if (IS_QLA2031(ha) || IS_QLA27XX(ha))
+ if (IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
goto set_fw_options;
if (IS_QLA8031(ha) || IS_QLA81XX(ha))
@@ -2314,8 +2346,8 @@ qla2x00_resume_hba(struct scsi_qla_host *vha)
scsi_unblock_requests(vha->host);
}
-uint8_t *
-qla2x00_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
+void *
+qla2x00_read_optrom_data(struct scsi_qla_host *vha, void *buf,
uint32_t offset, uint32_t length)
{
uint32_t addr, midpoint;
@@ -2349,12 +2381,12 @@ qla2x00_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
}
int
-qla2x00_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
+qla2x00_write_optrom_data(struct scsi_qla_host *vha, void *buf,
uint32_t offset, uint32_t length)
{
int rval;
- uint8_t man_id, flash_id, sec_number, data;
+ uint8_t man_id, flash_id, sec_number, *data;
uint16_t wd;
uint32_t addr, liter, sec_mask, rest_addr;
struct qla_hw_data *ha = vha->hw;
@@ -2483,7 +2515,7 @@ update_flash:
for (addr = offset, liter = 0; liter < length; liter++,
addr++) {
- data = buf[liter];
+ data = buf + liter;
/* Are we at the beginning of a sector? */
if ((addr & rest_addr) == 0) {
if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
@@ -2551,7 +2583,7 @@ update_flash:
}
}
- if (qla2x00_program_flash_address(ha, addr, data,
+ if (qla2x00_program_flash_address(ha, addr, *data,
man_id, flash_id)) {
rval = QLA_FUNCTION_FAILED;
break;
@@ -2567,8 +2599,8 @@ update_flash:
return rval;
}
-uint8_t *
-qla24xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
+void *
+qla24xx_read_optrom_data(struct scsi_qla_host *vha, void *buf,
uint32_t offset, uint32_t length)
{
struct qla_hw_data *ha = vha->hw;
@@ -2578,7 +2610,7 @@ qla24xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
/* Go with read. */
- qla24xx_read_flash_data(vha, (uint32_t *)buf, offset >> 2, length >> 2);
+ qla24xx_read_flash_data(vha, (void *)buf, offset >> 2, length >> 2);
/* Resume HBA. */
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
@@ -2587,8 +2619,340 @@ qla24xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
return buf;
}
+static int
+qla28xx_extract_sfub_and_verify(struct scsi_qla_host *vha, uint32_t *buf,
+ uint32_t len, uint32_t buf_size_without_sfub, uint8_t *sfub_buf)
+{
+ uint32_t *p, check_sum = 0;
+ int i;
+
+ p = buf + buf_size_without_sfub;
+
+ /* Extract SFUB from end of file */
+ memcpy(sfub_buf, (uint8_t *)p,
+ sizeof(struct secure_flash_update_block));
+
+ for (i = 0; i < (sizeof(struct secure_flash_update_block) >> 2); i++)
+ check_sum += p[i];
+
+ check_sum = (~check_sum) + 1;
+
+ if (check_sum != p[i]) {
+ ql_log(ql_log_warn, vha, 0x7097,
+ "SFUB checksum failed, 0x%x, 0x%x\n",
+ check_sum, p[i]);
+ return QLA_COMMAND_ERROR;
+ }
+
+ return QLA_SUCCESS;
+}
+
+static int
+qla28xx_get_flash_region(struct scsi_qla_host *vha, uint32_t start,
+ struct qla_flt_region *region)
+{
+ struct qla_hw_data *ha = vha->hw;
+ struct qla_flt_header *flt;
+ struct qla_flt_region *flt_reg;
+ uint16_t cnt;
+ int rval = QLA_FUNCTION_FAILED;
+
+ if (!ha->flt)
+ return QLA_FUNCTION_FAILED;
+
+ flt = (struct qla_flt_header *)ha->flt;
+ flt_reg = (struct qla_flt_region *)&flt[1];
+ cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region);
+
+ for (; cnt; cnt--, flt_reg++) {
+ if (flt_reg->start == start) {
+ memcpy((uint8_t *)region, flt_reg,
+ sizeof(struct qla_flt_region));
+ rval = QLA_SUCCESS;
+ break;
+ }
+ }
+
+ return rval;
+}
+
+static int
+qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
+ uint32_t dwords)
+{
+ struct qla_hw_data *ha = vha->hw;
+ ulong liter;
+ ulong dburst = OPTROM_BURST_DWORDS; /* burst size in dwords */
+ uint32_t sec_mask, rest_addr, fdata;
+ void *optrom = NULL;
+ dma_addr_t optrom_dma;
+ int rval;
+ struct secure_flash_update_block *sfub;
+ dma_addr_t sfub_dma;
+ uint32_t offset = faddr << 2;
+ uint32_t buf_size_without_sfub = 0;
+ struct qla_flt_region region;
+ bool reset_to_rom = false;
+ uint32_t risc_size, risc_attr = 0;
+ uint32_t *fw_array = NULL;
+
+ /* Retrieve region info - must be a start address passed in */
+ rval = qla28xx_get_flash_region(vha, offset, &region);
+
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Invalid address %x - not a region start address\n",
+ offset);
+ goto done;
+ }
+
+ /* Allocate dma buffer for burst write */
+ optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
+ &optrom_dma, GFP_KERNEL);
+ if (!optrom) {
+ ql_log(ql_log_warn, vha, 0x7095,
+ "Failed allocate burst (%x bytes)\n", OPTROM_BURST_SIZE);
+ rval = QLA_COMMAND_ERROR;
+ goto done;
+ }
+
+ /*
+ * If adapter supports secure flash and region is secure
+ * extract secure flash update block (SFUB) and verify
+ */
+ if (ha->flags.secure_adapter && region.attribute) {
+
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
+ "Region %x is secure\n", region.code);
+
+ if (region.code == FLT_REG_FW ||
+ region.code == FLT_REG_FW_SEC_27XX) {
+ fw_array = dwptr;
+
+ /* 1st fw array */
+ risc_size = be32_to_cpu(fw_array[3]);
+ risc_attr = be32_to_cpu(fw_array[9]);
+
+ buf_size_without_sfub = risc_size;
+ fw_array += risc_size;
+
+ /* 2nd fw array */
+ risc_size = be32_to_cpu(fw_array[3]);
+
+ buf_size_without_sfub += risc_size;
+ fw_array += risc_size;
+
+ /* 1st dump template */
+ risc_size = be32_to_cpu(fw_array[2]);
+
+ /* skip header and ignore checksum */
+ buf_size_without_sfub += risc_size;
+ fw_array += risc_size;
+
+ if (risc_attr & BIT_9) {
+ /* 2nd dump template */
+ risc_size = be32_to_cpu(fw_array[2]);
+
+ /* skip header and ignore checksum */
+ buf_size_without_sfub += risc_size;
+ fw_array += risc_size;
+ }
+ } else {
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
+ "Secure region %x not supported\n",
+ region.code);
+ rval = QLA_COMMAND_ERROR;
+ goto done;
+ }
+
+ sfub = dma_alloc_coherent(&ha->pdev->dev,
+ sizeof(struct secure_flash_update_block), &sfub_dma,
+ GFP_KERNEL);
+ if (!sfub) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Unable to allocate memory for SFUB\n");
+ rval = QLA_COMMAND_ERROR;
+ goto done;
+ }
+
+ rval = qla28xx_extract_sfub_and_verify(vha, dwptr, dwords,
+ buf_size_without_sfub, (uint8_t *)sfub);
+
+ if (rval != QLA_SUCCESS)
+ goto done;
+
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
+ "SFUB extract and verify successful\n");
+ }
+
+ rest_addr = (ha->fdt_block_size >> 2) - 1;
+ sec_mask = ~rest_addr;
+
+ /* Lock semaphore */
+ rval = qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_LOCK);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Unable to lock flash semaphore.");
+ goto done;
+ }
+
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
+ "Unprotect flash...\n");
+ rval = qla24xx_unprotect_flash(vha);
+ if (rval) {
+ qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_UNLOCK);
+ ql_log(ql_log_warn, vha, 0x7096, "Failed unprotect flash\n");
+ goto done;
+ }
+
+ for (liter = 0; liter < dwords; liter++, faddr++) {
+ fdata = (faddr & sec_mask) << 2;
+
+ /* If start of sector */
+ if (!(faddr & rest_addr)) {
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
+ "Erase sector %#x...\n", faddr);
+ rval = qla24xx_erase_sector(vha, fdata);
+ if (rval) {
+ ql_dbg(ql_dbg_user, vha, 0x7007,
+ "Failed erase sector %#x\n", faddr);
+ goto write_protect;
+ }
+ }
+ }
+
+ if (ha->flags.secure_adapter) {
+ /*
+ * If adapter supports secure flash but FW doesn't,
+ * disable write protect, release semaphore and reset
+ * chip to execute ROM code in order to update region securely
+ */
+ if (!ha->flags.secure_fw) {
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
+ "Disable Write and Release Semaphore.");
+ rval = qla24xx_protect_flash(vha);
+ if (rval != QLA_SUCCESS) {
+ qla81xx_fac_semaphore_access(vha,
+ FAC_SEMAPHORE_UNLOCK);
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Unable to protect flash.");
+ goto done;
+ }
+
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
+ "Reset chip to ROM.");
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ set_bit(ISP_ABORT_TO_ROM, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ rval = qla2x00_wait_for_chip_reset(vha);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Unable to reset to ROM code.");
+ goto done;
+ }
+ reset_to_rom = true;
+ ha->flags.fac_supported = 0;
+
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
+ "Lock Semaphore");
+ rval = qla2xxx_write_remote_register(vha,
+ FLASH_SEMAPHORE_REGISTER_ADDR, 0x00020002);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Unable to lock flash semaphore.");
+ goto done;
+ }
+
+ /* Unprotect flash */
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
+ "Enable Write.");
+ rval = qla2x00_write_ram_word(vha, 0x7ffd0101, 0);
+ if (rval) {
+ ql_log(ql_log_warn, vha, 0x7096,
+ "Failed unprotect flash\n");
+ goto done;
+ }
+ }
+
+ /* If region is secure, send Secure Flash MB Cmd */
+ if (region.attribute && buf_size_without_sfub) {
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
+ "Sending Secure Flash MB Cmd\n");
+ rval = qla28xx_secure_flash_update(vha, 0, region.code,
+ buf_size_without_sfub, sfub_dma,
+ sizeof(struct secure_flash_update_block));
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Secure Flash MB Cmd failed %x.", rval);
+ goto write_protect;
+ }
+ }
+
+ }
+
+ /* re-init flash offset */
+ faddr = offset >> 2;
+
+ for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
+ fdata = (faddr & sec_mask) << 2;
+
+ /* If smaller than a burst remaining */
+ if (dwords - liter < dburst)
+ dburst = dwords - liter;
+
+ /* Copy to dma buffer */
+ memcpy(optrom, dwptr, dburst << 2);
+
+ /* Burst write */
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
+ "Write burst (%#lx dwords)...\n", dburst);
+ rval = qla2x00_load_ram(vha, optrom_dma,
+ flash_data_addr(ha, faddr), dburst);
+ if (rval != QLA_SUCCESS) {
+ ql_log(ql_log_warn, vha, 0x7097,
+ "Failed burst write at %x (%p/%#llx)...\n",
+ flash_data_addr(ha, faddr), optrom,
+ (u64)optrom_dma);
+ break;
+ }
+
+ liter += dburst - 1;
+ faddr += dburst - 1;
+ dwptr += dburst - 1;
+ continue;
+ }
+
+write_protect:
+ ql_log(ql_log_warn + ql_dbg_verbose, vha, 0x7095,
+ "Protect flash...\n");
+ rval = qla24xx_protect_flash(vha);
+ if (rval) {
+ qla81xx_fac_semaphore_access(vha, FAC_SEMAPHORE_UNLOCK);
+ ql_log(ql_log_warn, vha, 0x7099,
+ "Failed protect flash\n");
+ }
+
+ if (reset_to_rom == true) {
+ /* Schedule DPC to restart the RISC */
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+
+ rval = qla2x00_wait_for_hba_online(vha);
+ if (rval != QLA_SUCCESS)
+ ql_log(ql_log_warn, vha, 0xffff,
+ "Adapter did not come out of reset\n");
+ }
+
+done:
+ if (optrom)
+ dma_free_coherent(&ha->pdev->dev,
+ OPTROM_BURST_SIZE, optrom, optrom_dma);
+
+ return rval;
+}
+
int
-qla24xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
+qla24xx_write_optrom_data(struct scsi_qla_host *vha, void *buf,
uint32_t offset, uint32_t length)
{
int rval;
@@ -2599,8 +2963,12 @@ qla24xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
/* Go with write. */
- rval = qla24xx_write_flash_data(vha, (uint32_t *)buf, offset >> 2,
- length >> 2);
+ if (IS_QLA28XX(ha))
+ rval = qla28xx_write_flash_data(vha, (uint32_t *)buf,
+ offset >> 2, length >> 2);
+ else
+ rval = qla24xx_write_flash_data(vha, (uint32_t *)buf,
+ offset >> 2, length >> 2);
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
scsi_unblock_requests(vha->host);
@@ -2608,8 +2976,8 @@ qla24xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
return rval;
}
-uint8_t *
-qla25xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
+void *
+qla25xx_read_optrom_data(struct scsi_qla_host *vha, void *buf,
uint32_t offset, uint32_t length)
{
int rval;
@@ -2620,7 +2988,7 @@ qla25xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
struct qla_hw_data *ha = vha->hw;
if (IS_QLA25XX(ha) || IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
- IS_QLA27XX(ha))
+ IS_QLA27XX(ha) || IS_QLA28XX(ha))
goto try_fast;
if (offset & 0xfff)
goto slow_read;
@@ -2628,6 +2996,8 @@ qla25xx_read_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
goto slow_read;
try_fast:
+ if (offset & 0xff)
+ goto slow_read;
optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE,
&optrom_dma, GFP_KERNEL);
if (!optrom) {
@@ -2874,7 +3244,7 @@ qla2x00_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
"Dumping fw "
"ver from flash:.\n");
ql_dump_buffer(ql_dbg_init + ql_dbg_buffer, vha, 0x010b,
- (uint8_t *)dbyte, 8);
+ dbyte, 32);
if ((dcode[0] == 0xffff && dcode[1] == 0xffff &&
dcode[2] == 0xffff && dcode[3] == 0xffff) ||
@@ -2905,8 +3275,8 @@ qla82xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
{
int ret = QLA_SUCCESS;
uint32_t pcihdr, pcids;
- uint32_t *dcode;
- uint8_t *bcode;
+ uint32_t *dcode = mbuf;
+ uint8_t *bcode = mbuf;
uint8_t code_type, last_image;
struct qla_hw_data *ha = vha->hw;
@@ -2918,17 +3288,14 @@ qla82xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));
memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
- dcode = mbuf;
-
/* Begin with first PCI expansion ROM header. */
pcihdr = ha->flt_region_boot << 2;
last_image = 1;
do {
/* Verify PCI expansion ROM header. */
- ha->isp_ops->read_optrom(vha, (uint8_t *)dcode, pcihdr,
- 0x20 * 4);
+ ha->isp_ops->read_optrom(vha, dcode, pcihdr, 0x20 * 4);
bcode = mbuf + (pcihdr % 4);
- if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) {
+ if (memcmp(bcode, "\x55\xaa", 2)) {
/* No signature */
ql_log(ql_log_fatal, vha, 0x0154,
"No matching ROM signature.\n");
@@ -2939,13 +3306,11 @@ qla82xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
/* Locate PCI data structure. */
pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]);
- ha->isp_ops->read_optrom(vha, (uint8_t *)dcode, pcids,
- 0x20 * 4);
+ ha->isp_ops->read_optrom(vha, dcode, pcids, 0x20 * 4);
bcode = mbuf + (pcihdr % 4);
/* Validate signature of PCI data structure. */
- if (bcode[0x0] != 'P' || bcode[0x1] != 'C' ||
- bcode[0x2] != 'I' || bcode[0x3] != 'R') {
+ if (memcmp(bcode, "PCIR", 4)) {
/* Incorrect header. */
ql_log(ql_log_fatal, vha, 0x0155,
"PCI data struct not found pcir_adr=%x.\n", pcids);
@@ -2996,8 +3361,7 @@ qla82xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
/* Read firmware image information. */
memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
dcode = mbuf;
- ha->isp_ops->read_optrom(vha, (uint8_t *)dcode, ha->flt_region_fw << 2,
- 0x20);
+ ha->isp_ops->read_optrom(vha, dcode, ha->flt_region_fw << 2, 0x20);
bcode = mbuf + (pcihdr % 4);
/* Validate signature of PCI data structure. */
@@ -3019,15 +3383,14 @@ int
qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
{
int ret = QLA_SUCCESS;
- uint32_t pcihdr, pcids;
- uint32_t *dcode;
- uint8_t *bcode;
+ uint32_t pcihdr = 0, pcids = 0;
+ uint32_t *dcode = mbuf;
+ uint8_t *bcode = mbuf;
uint8_t code_type, last_image;
int i;
struct qla_hw_data *ha = vha->hw;
uint32_t faddr = 0;
-
- pcihdr = pcids = 0;
+ struct active_regions active_regions = { };
if (IS_P3P_TYPE(ha))
return ret;
@@ -3040,18 +3403,19 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));
memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
- dcode = mbuf;
pcihdr = ha->flt_region_boot << 2;
- if (IS_QLA27XX(ha) &&
- qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
- pcihdr = ha->flt_region_boot_sec << 2;
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ qla27xx_get_active_image(vha, &active_regions);
+ if (active_regions.global == QLA27XX_SECONDARY_IMAGE) {
+ pcihdr = ha->flt_region_boot_sec << 2;
+ }
+ }
- last_image = 1;
do {
/* Verify PCI expansion ROM header. */
qla24xx_read_flash_data(vha, dcode, pcihdr >> 2, 0x20);
bcode = mbuf + (pcihdr % 4);
- if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) {
+ if (memcmp(bcode, "\x55\xaa", 2)) {
/* No signature */
ql_log(ql_log_fatal, vha, 0x0059,
"No matching ROM signature.\n");
@@ -3066,11 +3430,11 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
bcode = mbuf + (pcihdr % 4);
/* Validate signature of PCI data structure. */
- if (bcode[0x0] != 'P' || bcode[0x1] != 'C' ||
- bcode[0x2] != 'I' || bcode[0x3] != 'R') {
+ if (memcmp(bcode, "PCIR", 4)) {
/* Incorrect header. */
ql_log(ql_log_fatal, vha, 0x005a,
"PCI data struct not found pcir_adr=%x.\n", pcids);
+ ql_dump_buffer(ql_dbg_init, vha, 0x0059, dcode, 32);
ret = QLA_FUNCTION_FAILED;
break;
}
@@ -3117,30 +3481,24 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
/* Read firmware image information. */
memset(ha->fw_revision, 0, sizeof(ha->fw_revision));
- dcode = mbuf;
faddr = ha->flt_region_fw;
- if (IS_QLA27XX(ha) &&
- qla27xx_find_valid_image(vha) == QLA27XX_SECONDARY_IMAGE)
- faddr = ha->flt_region_fw_sec;
-
- qla24xx_read_flash_data(vha, dcode, faddr + 4, 4);
- for (i = 0; i < 4; i++)
- dcode[i] = be32_to_cpu(dcode[i]);
+ if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+ qla27xx_get_active_image(vha, &active_regions);
+ if (active_regions.global == QLA27XX_SECONDARY_IMAGE)
+ faddr = ha->flt_region_fw_sec;
+ }
- if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff &&
- dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) ||
- (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 &&
- dcode[3] == 0)) {
+ qla24xx_read_flash_data(vha, dcode, faddr, 8);
+ if (qla24xx_risc_firmware_invalid(dcode)) {
ql_log(ql_log_warn, vha, 0x005f,
"Unrecognized fw revision at %x.\n",
ha->flt_region_fw * 4);
+ ql_dump_buffer(ql_dbg_init, vha, 0x005f, dcode, 32);
} else {
- ha->fw_revision[0] = dcode[0];
- ha->fw_revision[1] = dcode[1];
- ha->fw_revision[2] = dcode[2];
- ha->fw_revision[3] = dcode[3];
+ for (i = 0; i < 4; i++)
+ ha->fw_revision[i] = be32_to_cpu(dcode[4+i]);
ql_dbg(ql_dbg_init, vha, 0x0060,
- "Firmware revision %d.%d.%d (%x).\n",
+ "Firmware revision (flash) %u.%u.%u (%x).\n",
ha->fw_revision[0], ha->fw_revision[1],
ha->fw_revision[2], ha->fw_revision[3]);
}
@@ -3152,20 +3510,17 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
}
memset(ha->gold_fw_version, 0, sizeof(ha->gold_fw_version));
- dcode = mbuf;
- ha->isp_ops->read_optrom(vha, (uint8_t *)dcode,
- ha->flt_region_gold_fw << 2, 32);
-
- if (dcode[4] == 0xFFFFFFFF && dcode[5] == 0xFFFFFFFF &&
- dcode[6] == 0xFFFFFFFF && dcode[7] == 0xFFFFFFFF) {
+ faddr = ha->flt_region_gold_fw;
+ qla24xx_read_flash_data(vha, (void *)dcode, ha->flt_region_gold_fw, 8);
+ if (qla24xx_risc_firmware_invalid(dcode)) {
ql_log(ql_log_warn, vha, 0x0056,
- "Unrecognized golden fw at 0x%x.\n",
- ha->flt_region_gold_fw * 4);
+ "Unrecognized golden fw at %#x.\n", faddr);
+ ql_dump_buffer(ql_dbg_init, vha, 0x0056, dcode, 32);
return ret;
}
- for (i = 4; i < 8; i++)
- ha->gold_fw_version[i-4] = be32_to_cpu(dcode[i]);
+ for (i = 0; i < 4; i++)
+ ha->gold_fw_version[i] = be32_to_cpu(dcode[4+i]);
return ret;
}
@@ -3237,7 +3592,7 @@ qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha)
fcp_prio_addr = ha->flt_region_fcp_prio;
/* first read the fcp priority data header from flash */
- ha->isp_ops->read_optrom(vha, (uint8_t *)ha->fcp_prio_cfg,
+ ha->isp_ops->read_optrom(vha, ha->fcp_prio_cfg,
fcp_prio_addr << 2, FCP_PRIO_CFG_HDR_SIZE);
if (!qla24xx_fcp_prio_cfg_valid(vha, ha->fcp_prio_cfg, 0))
@@ -3248,7 +3603,7 @@ qla24xx_read_fcp_prio_cfg(scsi_qla_host_t *vha)
len = ha->fcp_prio_cfg->num_entries * FCP_PRIO_CFG_ENTRY_SIZE;
max_len = FCP_PRIO_CFG_SIZE - FCP_PRIO_CFG_HDR_SIZE;
- ha->isp_ops->read_optrom(vha, (uint8_t *)&ha->fcp_prio_cfg->entry[0],
+ ha->isp_ops->read_optrom(vha, &ha->fcp_prio_cfg->entry[0],
fcp_prio_addr << 2, (len < max_len ? len : max_len));
/* revalidate the entire FCP priority config data, including entries */
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 49d35562623a..59fb97335d3f 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -184,6 +184,7 @@ static inline int qlt_issue_marker(struct scsi_qla_host *vha, int vha_locked)
/* Send marker if required */
if (unlikely(vha->marker_needed != 0)) {
int rc = qla2x00_issue_marker(vha, vha_locked);
+
if (rc != QLA_SUCCESS) {
ql_dbg(ql_dbg_tgt, vha, 0xe03d,
"qla_target(%d): issue_marker() failed\n",
@@ -196,18 +197,17 @@ static inline int qlt_issue_marker(struct scsi_qla_host *vha, int vha_locked)
static inline
struct scsi_qla_host *qlt_find_host_by_d_id(struct scsi_qla_host *vha,
- uint8_t *d_id)
+ be_id_t d_id)
{
struct scsi_qla_host *host;
- uint32_t key = 0;
+ uint32_t key;
- if ((vha->d_id.b.area == d_id[1]) && (vha->d_id.b.domain == d_id[0]) &&
- (vha->d_id.b.al_pa == d_id[2]))
+ if (vha->d_id.b.area == d_id.area &&
+ vha->d_id.b.domain == d_id.domain &&
+ vha->d_id.b.al_pa == d_id.al_pa)
return vha;
- key = (uint32_t)d_id[0] << 16;
- key |= (uint32_t)d_id[1] << 8;
- key |= (uint32_t)d_id[2];
+ key = be_to_port_id(d_id).b24;
host = btree_lookup32(&vha->hw->tgt.host_map, key);
if (!host)
@@ -365,9 +365,9 @@ static bool qlt_24xx_atio_pkt_all_vps(struct scsi_qla_host *vha,
ql_dbg(ql_dbg_tgt, vha, 0xe03e,
"qla_target(%d): Received ATIO_TYPE7 "
"with unknown d_id %x:%x:%x\n", vha->vp_idx,
- atio->u.isp24.fcp_hdr.d_id[0],
- atio->u.isp24.fcp_hdr.d_id[1],
- atio->u.isp24.fcp_hdr.d_id[2]);
+ atio->u.isp24.fcp_hdr.d_id.domain,
+ atio->u.isp24.fcp_hdr.d_id.area,
+ atio->u.isp24.fcp_hdr.d_id.al_pa);
qlt_queue_unknown_atio(vha, atio, ha_locked);
@@ -557,6 +557,7 @@ static int qla24xx_post_nack_work(struct scsi_qla_host *vha, fc_port_t *fcport,
struct imm_ntfy_from_isp *ntfy, int type)
{
struct qla_work_evt *e;
+
e = qla2x00_alloc_work(vha, QLA_EVT_NACK);
if (!e)
return QLA_FUNCTION_FAILED;
@@ -567,10 +568,8 @@ static int qla24xx_post_nack_work(struct scsi_qla_host *vha, fc_port_t *fcport,
return qla2x00_post_work(vha, e);
}
-static
-void qla2x00_async_nack_sp_done(void *s, int res)
+static void qla2x00_async_nack_sp_done(srb_t *sp, int res)
{
- struct srb *sp = (struct srb *)s;
struct scsi_qla_host *vha = sp->vha;
unsigned long flags;
@@ -660,14 +659,14 @@ int qla24xx_async_notify_ack(scsi_qla_host_t *vha, fc_port_t *fcport,
sp->u.iocb_cmd.u.nack.ntfy = ntfy;
sp->done = qla2x00_async_nack_sp_done;
- rval = qla2x00_start_sp(sp);
- if (rval != QLA_SUCCESS)
- goto done_free_sp;
-
ql_dbg(ql_dbg_disc, vha, 0x20f4,
"Async-%s %8phC hndl %x %s\n",
sp->name, fcport->port_name, sp->handle, c);
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS)
+ goto done_free_sp;
+
return rval;
done_free_sp:
@@ -680,34 +679,31 @@ done:
void qla24xx_do_nack_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
{
fc_port_t *t;
- unsigned long flags;
switch (e->u.nack.type) {
case SRB_NACK_PRLI:
+ t = e->u.nack.fcport;
+ flush_work(&t->del_work);
+ flush_work(&t->free_work);
mutex_lock(&vha->vha_tgt.tgt_mutex);
t = qlt_create_sess(vha, e->u.nack.fcport, 0);
mutex_unlock(&vha->vha_tgt.tgt_mutex);
if (t) {
ql_log(ql_log_info, vha, 0xd034,
"%s create sess success %p", __func__, t);
- spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
/* create sess has an extra kref */
vha->hw->tgt.tgt_ops->put_sess(e->u.nack.fcport);
- spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
}
break;
}
qla24xx_async_notify_ack(vha, e->u.nack.fcport,
- (struct imm_ntfy_from_isp*)e->u.nack.iocb, e->u.nack.type);
+ (struct imm_ntfy_from_isp *)e->u.nack.iocb, e->u.nack.type);
}
void qla24xx_delete_sess_fn(struct work_struct *work)
{
fc_port_t *fcport = container_of(work, struct fc_port, del_work);
struct qla_hw_data *ha = fcport->vha->hw;
- unsigned long flags;
-
- spin_lock_irqsave(&ha->tgt.sess_lock, flags);
if (fcport->se_sess) {
ha->tgt.tgt_ops->shutdown_sess(fcport);
@@ -715,7 +711,6 @@ void qla24xx_delete_sess_fn(struct work_struct *work)
} else {
qlt_unreg_sess(fcport);
}
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
}
/*
@@ -784,8 +779,9 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
fcport->port_name, sess->loop_id);
sess->local = 0;
}
- ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+
+ ha->tgt.tgt_ops->put_sess(sess);
}
/*
@@ -799,6 +795,8 @@ qlt_plogi_ack_find_add(struct scsi_qla_host *vha, port_id_t *id,
{
struct qlt_plogi_ack_t *pla;
+ lockdep_assert_held(&vha->hw->hardware_lock);
+
list_for_each_entry(pla, &vha->plogi_ack_list, list) {
if (pla->id.b24 == id->b24) {
ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x210d,
@@ -1014,6 +1012,12 @@ void qlt_free_session_done(struct work_struct *work)
else
logout_started = true;
}
+ } /* if sess->logout_on_delete */
+
+ if (sess->nvme_flag & NVME_FLAG_REGISTERED &&
+ !(sess->nvme_flag & NVME_FLAG_DELETING)) {
+ sess->nvme_flag |= NVME_FLAG_DELETING;
+ qla_nvme_unregister_remote_port(sess);
}
}
@@ -1075,6 +1079,7 @@ void qlt_free_session_done(struct work_struct *work)
struct qlt_plogi_ack_t *con =
sess->plogi_link[QLT_PLOGI_LINK_CONFLICT];
struct imm_ntfy_from_isp *iocb;
+
own = sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN];
if (con) {
@@ -1164,14 +1169,8 @@ void qlt_unreg_sess(struct fc_port *sess)
sess->last_rscn_gen = sess->rscn_gen;
sess->last_login_gen = sess->login_gen;
- if (sess->nvme_flag & NVME_FLAG_REGISTERED &&
- !(sess->nvme_flag & NVME_FLAG_DELETING)) {
- sess->nvme_flag |= NVME_FLAG_DELETING;
- schedule_work(&sess->nvme_del_work);
- } else {
- INIT_WORK(&sess->free_work, qlt_free_session_done);
- schedule_work(&sess->free_work);
- }
+ INIT_WORK(&sess->free_work, qlt_free_session_done);
+ schedule_work(&sess->free_work);
}
EXPORT_SYMBOL(qlt_unreg_sess);
@@ -1218,7 +1217,6 @@ static void qla24xx_chk_fcp_state(struct fc_port *sess)
sess->logout_on_delete = 0;
sess->logo_ack_needed = 0;
sess->fw_login_state = DSC_LS_PORT_UNAVAIL;
- sess->scan_state = 0;
}
}
@@ -1293,13 +1291,12 @@ static void qlt_clear_tgt_db(struct qla_tgt *tgt)
/* At this point tgt could be already dead */
}
-static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id,
+static int qla24xx_get_loop_id(struct scsi_qla_host *vha, be_id_t s_id,
uint16_t *loop_id)
{
struct qla_hw_data *ha = vha->hw;
dma_addr_t gid_list_dma;
- struct gid_list_info *gid_list;
- char *id_iter;
+ struct gid_list_info *gid_list, *gid;
int res, rc, i;
uint16_t entries;
@@ -1322,18 +1319,17 @@ static int qla24xx_get_loop_id(struct scsi_qla_host *vha, const uint8_t *s_id,
goto out_free_id_list;
}
- id_iter = (char *)gid_list;
+ gid = gid_list;
res = -ENOENT;
for (i = 0; i < entries; i++) {
- struct gid_list_info *gid = (struct gid_list_info *)id_iter;
- if ((gid->al_pa == s_id[2]) &&
- (gid->area == s_id[1]) &&
- (gid->domain == s_id[0])) {
+ if (gid->al_pa == s_id.al_pa &&
+ gid->area == s_id.area &&
+ gid->domain == s_id.domain) {
*loop_id = le16_to_cpu(gid->loop_id);
res = 0;
break;
}
- id_iter += ha->gid_list_info_size;
+ gid = (void *)gid + ha->gid_list_info_size;
}
out_free_id_list:
@@ -1590,11 +1586,10 @@ static void qlt_release(struct qla_tgt *tgt)
struct qla_qpair_hint *h;
struct qla_hw_data *ha = vha->hw;
- if ((vha->vha_tgt.qla_tgt != NULL) && !tgt->tgt_stop &&
- !tgt->tgt_stopped)
+ if (!tgt->tgt_stop && !tgt->tgt_stopped)
qlt_stop_phase1(tgt);
- if ((vha->vha_tgt.qla_tgt != NULL) && !tgt->tgt_stopped)
+ if (!tgt->tgt_stopped)
qlt_stop_phase2(tgt);
for (i = 0; i < vha->hw->max_qpairs + 1; i++) {
@@ -1780,12 +1775,8 @@ static int qlt_build_abts_resp_iocb(struct qla_tgt_mgmt_cmd *mcmd)
resp->fcp_hdr_le.f_ctl[1] = *p++;
resp->fcp_hdr_le.f_ctl[2] = *p;
- resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.s_id[0];
- resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.s_id[1];
- resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.s_id[2];
- resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.d_id[0];
- resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.d_id[1];
- resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.d_id[2];
+ resp->fcp_hdr_le.d_id = abts->fcp_hdr_le.s_id;
+ resp->fcp_hdr_le.s_id = abts->fcp_hdr_le.d_id;
resp->exchange_addr_to_abort = abts->exchange_addr_to_abort;
if (mcmd->fc_tm_rsp == FCP_TMF_CMPL) {
@@ -1856,19 +1847,11 @@ static void qlt_24xx_send_abts_resp(struct qla_qpair *qpair,
resp->fcp_hdr_le.f_ctl[1] = *p++;
resp->fcp_hdr_le.f_ctl[2] = *p;
if (ids_reversed) {
- resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.d_id[0];
- resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.d_id[1];
- resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.d_id[2];
- resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.s_id[0];
- resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.s_id[1];
- resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.s_id[2];
+ resp->fcp_hdr_le.d_id = abts->fcp_hdr_le.d_id;
+ resp->fcp_hdr_le.s_id = abts->fcp_hdr_le.s_id;
} else {
- resp->fcp_hdr_le.d_id[0] = abts->fcp_hdr_le.s_id[0];
- resp->fcp_hdr_le.d_id[1] = abts->fcp_hdr_le.s_id[1];
- resp->fcp_hdr_le.d_id[2] = abts->fcp_hdr_le.s_id[2];
- resp->fcp_hdr_le.s_id[0] = abts->fcp_hdr_le.d_id[0];
- resp->fcp_hdr_le.s_id[1] = abts->fcp_hdr_le.d_id[1];
- resp->fcp_hdr_le.s_id[2] = abts->fcp_hdr_le.d_id[2];
+ resp->fcp_hdr_le.d_id = abts->fcp_hdr_le.s_id;
+ resp->fcp_hdr_le.s_id = abts->fcp_hdr_le.d_id;
}
resp->exchange_addr_to_abort = abts->exchange_addr_to_abort;
if (status == FCP_TMF_CMPL) {
@@ -1935,18 +1918,14 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha,
tmp = (CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_TERMINATE);
if (mcmd) {
- ctio->initiator_id[0] = entry->fcp_hdr_le.s_id[0];
- ctio->initiator_id[1] = entry->fcp_hdr_le.s_id[1];
- ctio->initiator_id[2] = entry->fcp_hdr_le.s_id[2];
+ ctio->initiator_id = entry->fcp_hdr_le.s_id;
if (mcmd->flags & QLA24XX_MGMT_ABORT_IO_ATTR_VALID)
tmp |= (mcmd->abort_io_attr << 9);
else if (qpair->retry_term_cnt & 1)
tmp |= (0x4 << 9);
} else {
- ctio->initiator_id[0] = entry->fcp_hdr_le.d_id[0];
- ctio->initiator_id[1] = entry->fcp_hdr_le.d_id[1];
- ctio->initiator_id[2] = entry->fcp_hdr_le.d_id[2];
+ ctio->initiator_id = entry->fcp_hdr_le.d_id;
if (qpair->retry_term_cnt & 1)
tmp |= (0x4 << 9);
@@ -1980,8 +1959,7 @@ static void qlt_24xx_retry_term_exchange(struct scsi_qla_host *vha,
* XXX does not go through the list of other port (which may have cmds
* for the same lun)
*/
-static void abort_cmds_for_lun(struct scsi_qla_host *vha,
- u64 lun, uint8_t *s_id)
+static void abort_cmds_for_lun(struct scsi_qla_host *vha, u64 lun, be_id_t s_id)
{
struct qla_tgt_sess_op *op;
struct qla_tgt_cmd *cmd;
@@ -2157,7 +2135,7 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
struct qla_hw_data *ha = vha->hw;
struct fc_port *sess;
uint32_t tag = abts->exchange_addr_to_abort;
- uint8_t s_id[3];
+ be_id_t s_id;
int rc;
unsigned long flags;
@@ -2181,13 +2159,11 @@ static void qlt_24xx_handle_abts(struct scsi_qla_host *vha,
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf011,
"qla_target(%d): task abort (s_id=%x:%x:%x, "
- "tag=%d, param=%x)\n", vha->vp_idx, abts->fcp_hdr_le.s_id[2],
- abts->fcp_hdr_le.s_id[1], abts->fcp_hdr_le.s_id[0], tag,
+ "tag=%d, param=%x)\n", vha->vp_idx, abts->fcp_hdr_le.s_id.domain,
+ abts->fcp_hdr_le.s_id.area, abts->fcp_hdr_le.s_id.al_pa, tag,
le32_to_cpu(abts->fcp_hdr_le.parameter));
- s_id[0] = abts->fcp_hdr_le.s_id[2];
- s_id[1] = abts->fcp_hdr_le.s_id[1];
- s_id[2] = abts->fcp_hdr_le.s_id[0];
+ s_id = le_id_to_be(abts->fcp_hdr_le.s_id);
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id);
@@ -2251,9 +2227,7 @@ static void qlt_24xx_send_task_mgmt_ctio(struct qla_qpair *qpair,
ctio->nport_handle = mcmd->sess->loop_id;
ctio->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
ctio->vp_index = ha->vp_idx;
- ctio->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
- ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
- ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
+ ctio->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id);
ctio->exchange_addr = atio->u.isp24.exchange_addr;
temp = (atio->u.isp24.attr << 9)|
CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS;
@@ -2310,9 +2284,7 @@ void qlt_send_resp_ctio(struct qla_qpair *qpair, struct qla_tgt_cmd *cmd,
ctio->nport_handle = cmd->sess->loop_id;
ctio->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
ctio->vp_index = vha->vp_idx;
- ctio->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
- ctio->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
- ctio->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
+ ctio->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id);
ctio->exchange_addr = atio->u.isp24.exchange_addr;
temp = (atio->u.isp24.attr << 9) |
CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS;
@@ -2482,6 +2454,7 @@ static void qlt_unmap_sg(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
{
struct qla_hw_data *ha;
struct qla_qpair *qpair;
+
if (!cmd->sg_mapped)
return;
@@ -2612,9 +2585,7 @@ static int qlt_24xx_build_ctio_pkt(struct qla_qpair *qpair,
pkt->handle |= CTIO_COMPLETION_HANDLE_MARK;
pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id);
pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
- pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
- pkt->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
- pkt->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
+ pkt->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id);
pkt->exchange_addr = atio->u.isp24.exchange_addr;
temp = atio->u.isp24.attr << 9;
pkt->u.status0.flags |= cpu_to_le16(temp);
@@ -2632,7 +2603,7 @@ static int qlt_24xx_build_ctio_pkt(struct qla_qpair *qpair,
static void qlt_load_cont_data_segments(struct qla_tgt_prm *prm)
{
int cnt;
- uint32_t *dword_ptr;
+ struct dsd64 *cur_dsd;
/* Build continuation packets */
while (prm->seg_cnt > 0) {
@@ -2653,19 +2624,13 @@ static void qlt_load_cont_data_segments(struct qla_tgt_prm *prm)
cont_pkt64->sys_define = 0;
cont_pkt64->entry_type = CONTINUE_A64_TYPE;
- dword_ptr = (uint32_t *)&cont_pkt64->dseg_0_address;
+ cur_dsd = cont_pkt64->dsd;
/* Load continuation entry data segments */
for (cnt = 0;
cnt < QLA_TGT_DATASEGS_PER_CONT_24XX && prm->seg_cnt;
cnt++, prm->seg_cnt--) {
- *dword_ptr++ =
- cpu_to_le32(lower_32_bits
- (sg_dma_address(prm->sg)));
- *dword_ptr++ = cpu_to_le32(upper_32_bits
- (sg_dma_address(prm->sg)));
- *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg));
-
+ append_dsd64(&cur_dsd, prm->sg);
prm->sg = sg_next(prm->sg);
}
}
@@ -2678,13 +2643,13 @@ static void qlt_load_cont_data_segments(struct qla_tgt_prm *prm)
static void qlt_load_data_segments(struct qla_tgt_prm *prm)
{
int cnt;
- uint32_t *dword_ptr;
+ struct dsd64 *cur_dsd;
struct ctio7_to_24xx *pkt24 = (struct ctio7_to_24xx *)prm->pkt;
pkt24->u.status0.transfer_length = cpu_to_le32(prm->cmd->bufflen);
/* Setup packet address segment pointer */
- dword_ptr = pkt24->u.status0.dseg_0_address;
+ cur_dsd = &pkt24->u.status0.dsd;
/* Set total data segment count */
if (prm->seg_cnt)
@@ -2692,8 +2657,8 @@ static void qlt_load_data_segments(struct qla_tgt_prm *prm)
if (prm->seg_cnt == 0) {
/* No data transfer */
- *dword_ptr++ = 0;
- *dword_ptr = 0;
+ cur_dsd->address = 0;
+ cur_dsd->length = 0;
return;
}
@@ -2703,14 +2668,7 @@ static void qlt_load_data_segments(struct qla_tgt_prm *prm)
for (cnt = 0;
(cnt < QLA_TGT_DATASEGS_PER_CMD_24XX) && prm->seg_cnt;
cnt++, prm->seg_cnt--) {
- *dword_ptr++ =
- cpu_to_le32(lower_32_bits(sg_dma_address(prm->sg)));
-
- *dword_ptr++ = cpu_to_le32(upper_32_bits(
- sg_dma_address(prm->sg)));
-
- *dword_ptr++ = cpu_to_le32(sg_dma_len(prm->sg));
-
+ append_dsd64(&cur_dsd, prm->sg);
prm->sg = sg_next(prm->sg);
}
@@ -3034,12 +2992,11 @@ qla_tgt_set_dif_tags(struct qla_tgt_cmd *cmd, struct crc_context *ctx,
static inline int
qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm)
{
- uint32_t *cur_dsd;
+ struct dsd64 *cur_dsd;
uint32_t transfer_length = 0;
uint32_t data_bytes;
uint32_t dif_bytes;
uint8_t bundling = 1;
- uint8_t *clr_ptr;
struct crc_context *crc_ctx_pkt = NULL;
struct qla_hw_data *ha;
struct ctio_crc2_to_fw *pkt;
@@ -3141,9 +3098,7 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm)
pkt->handle |= CTIO_COMPLETION_HANDLE_MARK;
pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id);
pkt->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
- pkt->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
- pkt->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
- pkt->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
+ pkt->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id);
pkt->exchange_addr = atio->u.isp24.exchange_addr;
/* silence compile warning */
@@ -3168,15 +3123,11 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm)
/* Allocate CRC context from global pool */
crc_ctx_pkt = cmd->ctx =
- dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC, &crc_ctx_dma);
+ dma_pool_zalloc(ha->dl_dma_pool, GFP_ATOMIC, &crc_ctx_dma);
if (!crc_ctx_pkt)
goto crc_queuing_error;
- /* Zero out CTX area. */
- clr_ptr = (uint8_t *)crc_ctx_pkt;
- memset(clr_ptr, 0, sizeof(*crc_ctx_pkt));
-
crc_ctx_pkt->crc_ctx_dma = crc_ctx_dma;
INIT_LIST_HEAD(&crc_ctx_pkt->dsd_list);
@@ -3185,12 +3136,11 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm)
qla_tgt_set_dif_tags(cmd, crc_ctx_pkt, &fw_prot_opts);
- pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma));
- pkt->crc_context_address[1] = cpu_to_le32(MSD(crc_ctx_dma));
+ put_unaligned_le64(crc_ctx_dma, &pkt->crc_context_address);
pkt->crc_context_len = CRC_CONTEXT_LEN_FW;
if (!bundling) {
- cur_dsd = (uint32_t *) &crc_ctx_pkt->u.nobundling.data_address;
+ cur_dsd = &crc_ctx_pkt->u.nobundling.data_dsd[0];
} else {
/*
* Configure Bundling if we need to fetch interlaving
@@ -3200,7 +3150,7 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm)
crc_ctx_pkt->u.bundling.dif_byte_count = cpu_to_le32(dif_bytes);
crc_ctx_pkt->u.bundling.dseg_count =
cpu_to_le16(prm->tot_dsds - prm->prot_seg_cnt);
- cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.data_address;
+ cur_dsd = &crc_ctx_pkt->u.bundling.data_dsd[0];
}
/* Finish the common fields of CRC pkt */
@@ -3233,9 +3183,9 @@ qlt_build_ctio_crc2_pkt(struct qla_qpair *qpair, struct qla_tgt_prm *prm)
/* Walks dif segments */
pkt->add_flags |= CTIO_CRC2_AF_DIF_DSD_ENA;
- cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address;
+ cur_dsd = &crc_ctx_pkt->u.bundling.dif_dsd;
if (qla24xx_walk_and_build_prot_sglist(ha, NULL, cur_dsd,
- prm->prot_seg_cnt, &tc))
+ prm->prot_seg_cnt, cmd))
goto crc_queuing_error;
}
return QLA_SUCCESS;
@@ -3262,14 +3212,11 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
unsigned long flags = 0;
int res;
- if (cmd->sess && cmd->sess->deleted) {
+ if (!qpair->fw_started || (cmd->reset_count != qpair->chip_reset) ||
+ (cmd->sess && cmd->sess->deleted)) {
cmd->state = QLA_TGT_STATE_PROCESSED;
- if (cmd->sess->logout_completed)
- /* no need to terminate. FW already freed exchange. */
- qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
- else
- qlt_send_term_exchange(qpair, cmd, &cmd->atio, 0, 0);
- return 0;
+ res = 0;
+ goto free;
}
ql_dbg_qp(ql_dbg_tgt, qpair, 0xe018,
@@ -3280,9 +3227,8 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status,
&full_req_cnt);
- if (unlikely(res != 0)) {
- return res;
- }
+ if (unlikely(res != 0))
+ goto free;
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
@@ -3297,13 +3243,13 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
* previous life, just abort the processing.
*/
cmd->state = QLA_TGT_STATE_PROCESSED;
- qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
ql_dbg_qp(ql_dbg_async, qpair, 0xe101,
"RESET-RSP online/active/old-count/new-count = %d/%d/%d/%d.\n",
vha->flags.online, qla2x00_reset_active(vha),
cmd->reset_count, qpair->chip_reset);
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
- return 0;
+ res = 0;
+ goto free;
}
/* Does F/W have an IOCBs for this request */
@@ -3389,9 +3335,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
cmd->state = QLA_TGT_STATE_PROCESSED; /* Mid-level is done processing */
- spin_lock(&cmd->cmd_lock);
cmd->cmd_sent_to_fw = 1;
- spin_unlock(&cmd->cmd_lock);
cmd->ctio_flags = le16_to_cpu(pkt->u.status0.flags);
/* Memory Barrier */
@@ -3408,6 +3352,8 @@ out_unmap_unlock:
qlt_unmap_sg(vha, cmd);
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+free:
+ vha->hw->tgt.tgt_ops->free_cmd(cmd);
return res;
}
EXPORT_SYMBOL(qlt_xmit_response);
@@ -3438,8 +3384,10 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
* Either the port is not online or this request was from
* previous life, just abort the processing.
*/
- cmd->state = QLA_TGT_STATE_NEED_DATA;
- qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
+ cmd->aborted = 1;
+ cmd->write_data_transferred = 0;
+ cmd->state = QLA_TGT_STATE_DATA_IN;
+ vha->hw->tgt.tgt_ops->handle_data(cmd);
ql_dbg_qp(ql_dbg_async, qpair, 0xe102,
"RESET-XFR online/active/old-count/new-count = %d/%d/%d/%d.\n",
vha->flags.online, qla2x00_reset_active(vha),
@@ -3470,9 +3418,7 @@ int qlt_rdy_to_xfer(struct qla_tgt_cmd *cmd)
qlt_load_data_segments(&prm);
cmd->state = QLA_TGT_STATE_NEED_DATA;
- spin_lock(&cmd->cmd_lock);
cmd->cmd_sent_to_fw = 1;
- spin_unlock(&cmd->cmd_lock);
cmd->ctio_flags = le16_to_cpu(pkt->u.status0.flags);
/* Memory Barrier */
@@ -3651,33 +3597,11 @@ static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha,
static void qlt_send_term_imm_notif(struct scsi_qla_host *vha,
struct imm_ntfy_from_isp *imm, int ha_locked)
{
- unsigned long flags = 0;
int rc;
- if (ha_locked) {
- rc = __qlt_send_term_imm_notif(vha, imm);
-
-#if 0 /* Todo */
- if (rc == -ENOMEM)
- qlt_alloc_qfull_cmd(vha, imm, 0, 0);
-#else
- if (rc) {
- }
-#endif
- goto done;
- }
-
- spin_lock_irqsave(&vha->hw->hardware_lock, flags);
+ WARN_ON_ONCE(!ha_locked);
rc = __qlt_send_term_imm_notif(vha, imm);
-
-#if 0 /* Todo */
- if (rc == -ENOMEM)
- qlt_alloc_qfull_cmd(vha, imm, 0, 0);
-#endif
-
-done:
- if (!ha_locked)
- spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
+ pr_debug("rc = %d\n", rc);
}
/*
@@ -3727,9 +3651,7 @@ static int __qlt_send_term_exchange(struct qla_qpair *qpair,
ctio24->nport_handle = CTIO7_NHANDLE_UNRECOGNIZED;
ctio24->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
ctio24->vp_index = vha->vp_idx;
- ctio24->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
- ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
- ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
+ ctio24->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id);
ctio24->exchange_addr = atio->u.isp24.exchange_addr;
temp = (atio->u.isp24.attr << 9) | CTIO7_FLAGS_STATUS_MODE_1 |
CTIO7_FLAGS_TERMINATE;
@@ -3918,6 +3840,7 @@ static int qlt_term_ctio_exchange(struct qla_qpair *qpair, void *ctio,
if (ctio != NULL) {
struct ctio7_from_24xx *c = (struct ctio7_from_24xx *)ctio;
+
term = !(c->flags &
cpu_to_le16(OF_TERM_EXCH));
} else
@@ -3982,39 +3905,6 @@ static void *qlt_ctio_to_cmd(struct scsi_qla_host *vha,
return cmd;
}
-/* hardware_lock should be held by caller. */
-void
-qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
-{
- struct qla_hw_data *ha = vha->hw;
-
- if (cmd->sg_mapped)
- qlt_unmap_sg(vha, cmd);
-
- /* TODO: fix debug message type and ids. */
- if (cmd->state == QLA_TGT_STATE_PROCESSED) {
- ql_dbg(ql_dbg_io, vha, 0xff00,
- "HOST-ABORT: state=PROCESSED.\n");
- } else if (cmd->state == QLA_TGT_STATE_NEED_DATA) {
- cmd->write_data_transferred = 0;
- cmd->state = QLA_TGT_STATE_DATA_IN;
-
- ql_dbg(ql_dbg_io, vha, 0xff01,
- "HOST-ABORT: state=DATA_IN.\n");
-
- ha->tgt.tgt_ops->handle_data(cmd);
- return;
- } else {
- ql_dbg(ql_dbg_io, vha, 0xff03,
- "HOST-ABORT: state=BAD(%d).\n",
- cmd->state);
- dump_stack();
- }
-
- cmd->trc_flags |= TRC_FLUSH;
- ha->tgt.tgt_ops->free_cmd(cmd);
-}
-
/*
* ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
*/
@@ -4036,7 +3926,7 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha,
return;
}
- cmd = (struct qla_tgt_cmd *)qlt_ctio_to_cmd(vha, rsp, handle, ctio);
+ cmd = qlt_ctio_to_cmd(vha, rsp, handle, ctio);
if (cmd == NULL)
return;
@@ -4194,8 +4084,6 @@ static inline int qlt_get_fcp_task_attr(struct scsi_qla_host *vha,
return fcp_task_attr;
}
-static struct fc_port *qlt_make_local_sess(struct scsi_qla_host *,
- uint8_t *);
/*
* Process context for I/O path into tcm_qla2xxx code
*/
@@ -4247,9 +4135,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
/*
* Drop extra session reference from qlt_handle_cmd_for_atio().
*/
- spin_lock_irqsave(&ha->tgt.sess_lock, flags);
ha->tgt.tgt_ops->put_sess(sess);
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return;
out_term:
@@ -4266,9 +4152,7 @@ out_term:
percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
- spin_lock_irqsave(&ha->tgt.sess_lock, flags);
ha->tgt.tgt_ops->put_sess(sess);
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
}
static void qlt_do_work(struct work_struct *work)
@@ -4442,9 +4326,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
return -ENODEV;
}
- id.b.al_pa = atio->u.isp24.fcp_hdr.s_id[2];
- id.b.area = atio->u.isp24.fcp_hdr.s_id[1];
- id.b.domain = atio->u.isp24.fcp_hdr.s_id[0];
+ id = be_to_port_id(atio->u.isp24.fcp_hdr.s_id);
if (IS_SW_RESV_ADDR(id))
return -EBUSY;
@@ -4476,9 +4358,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,
if (!cmd) {
ql_dbg(ql_dbg_io, vha, 0x3062,
"qla_target(%d): Allocation of cmd failed\n", vha->vp_idx);
- spin_lock_irqsave(&ha->tgt.sess_lock, flags);
ha->tgt.tgt_ops->put_sess(sess);
- spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
return -EBUSY;
}
@@ -4777,6 +4657,7 @@ static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id)
list_for_each_entry(op, &vha->unknown_atio_list, cmd_list) {
uint32_t op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id);
+
if (op_key == key) {
op->aborted = true;
count++;
@@ -4785,6 +4666,7 @@ static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id)
list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
uint32_t cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id);
+
if (cmd_key == key) {
cmd->aborted = 1;
count++;
@@ -4806,6 +4688,8 @@ static int qlt_handle_login(struct scsi_qla_host *vha,
struct qlt_plogi_ack_t *pla;
unsigned long flags;
+ lockdep_assert_held(&vha->hw->hardware_lock);
+
wwn = wwn_to_u64(iocb->u.isp24.port_name);
port_id.b.domain = iocb->u.isp24.port_id[2];
@@ -4889,8 +4773,10 @@ static int qlt_handle_login(struct scsi_qla_host *vha,
__func__, sess->port_name, sec);
}
- if (!conflict_sess)
+ if (!conflict_sess) {
+ list_del(&pla->list);
kmem_cache_free(qla_tgt_plogi_cachep, pla);
+ }
qlt_send_term_imm_notif(vha, iocb, 1);
goto out;
@@ -4979,6 +4865,8 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
int res = 0;
unsigned long flags;
+ lockdep_assert_held(&ha->hardware_lock);
+
wwn = wwn_to_u64(iocb->u.isp24.port_name);
port_id.b.domain = iocb->u.isp24.port_id[2];
@@ -5055,6 +4943,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
if (sess != NULL) {
bool delete = false;
int sec;
+
spin_lock_irqsave(&tgt->ha->tgt.sess_lock, flags);
switch (sess->fw_login_state) {
case DSC_LS_PLOGI_PEND:
@@ -5207,6 +5096,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
case ELS_ADISC:
{
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
+
if (tgt->link_reinit_iocb_pending) {
qlt_send_notify_ack(ha->base_qpair,
&tgt->link_reinit_iocb, 0, 0, 0, 0, 0, 0);
@@ -5253,6 +5143,8 @@ static void qlt_handle_imm_notify(struct scsi_qla_host *vha,
int send_notify_ack = 1;
uint16_t status;
+ lockdep_assert_held(&ha->hardware_lock);
+
status = le16_to_cpu(iocb->u.isp2x.status);
switch (status) {
case IMM_NTFY_LIP_RESET:
@@ -5270,6 +5162,7 @@ static void qlt_handle_imm_notify(struct scsi_qla_host *vha,
case IMM_NTFY_LIP_LINK_REINIT:
{
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
+
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf033,
"qla_target(%d): LINK REINIT (loop %#x, "
"subcode %x)\n", vha->vp_idx,
@@ -5389,10 +5282,7 @@ static int __qlt_send_busy(struct qla_qpair *qpair,
u16 temp;
port_id_t id;
- id.b.al_pa = atio->u.isp24.fcp_hdr.s_id[2];
- id.b.area = atio->u.isp24.fcp_hdr.s_id[1];
- id.b.domain = atio->u.isp24.fcp_hdr.s_id[0];
- id.b.rsvd_1 = 0;
+ id = be_to_port_id(atio->u.isp24.fcp_hdr.s_id);
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
sess = qla2x00_find_fcport_by_nportid(vha, &id, 1);
@@ -5420,9 +5310,7 @@ static int __qlt_send_busy(struct qla_qpair *qpair,
ctio24->nport_handle = sess->loop_id;
ctio24->timeout = cpu_to_le16(QLA_TGT_TIMEOUT);
ctio24->vp_index = vha->vp_idx;
- ctio24->initiator_id[0] = atio->u.isp24.fcp_hdr.s_id[2];
- ctio24->initiator_id[1] = atio->u.isp24.fcp_hdr.s_id[1];
- ctio24->initiator_id[2] = atio->u.isp24.fcp_hdr.s_id[0];
+ ctio24->initiator_id = be_id_to_le(atio->u.isp24.fcp_hdr.s_id);
ctio24->exchange_addr = atio->u.isp24.exchange_addr;
temp = (atio->u.isp24.attr << 9) |
CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS |
@@ -5820,8 +5708,7 @@ static void qlt_handle_abts_completion(struct scsi_qla_host *vha,
struct qla_tgt_mgmt_cmd *mcmd;
struct qla_hw_data *ha = vha->hw;
- mcmd = (struct qla_tgt_mgmt_cmd *)qlt_ctio_to_cmd(vha, rsp,
- pkt->handle, pkt);
+ mcmd = qlt_ctio_to_cmd(vha, rsp, pkt->handle, pkt);
if (mcmd == NULL && h != QLA_TGT_SKIP_HANDLE) {
ql_dbg(ql_dbg_async, vha, 0xe064,
"qla_target(%d): ABTS Comp without mcmd\n",
@@ -5854,7 +5741,7 @@ static void qlt_handle_abts_completion(struct scsi_qla_host *vha,
entry->error_subcode2);
ha->tgt.tgt_ops->free_mcmd(mcmd);
}
- } else {
+ } else if (mcmd) {
ha->tgt.tgt_ops->free_mcmd(mcmd);
}
}
@@ -5883,6 +5770,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha,
case CTIO_TYPE7:
{
struct ctio7_from_24xx *entry = (struct ctio7_from_24xx *)pkt;
+
qlt_do_ctio_completion(vha, rsp, entry->handle,
le16_to_cpu(entry->status)|(pkt->entry_status << 16),
entry);
@@ -5893,6 +5781,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha,
{
struct atio_from_isp *atio = (struct atio_from_isp *)pkt;
int rc;
+
if (atio->u.isp2x.status !=
cpu_to_le16(ATIO_CDB_VALID)) {
ql_dbg(ql_dbg_tgt, vha, 0xe05e,
@@ -5941,6 +5830,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha,
case CONTINUE_TGT_IO_TYPE:
{
struct ctio_to_2xxx *entry = (struct ctio_to_2xxx *)pkt;
+
qlt_do_ctio_completion(vha, rsp, entry->handle,
le16_to_cpu(entry->status)|(pkt->entry_status << 16),
entry);
@@ -5950,6 +5840,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha,
case CTIO_A64_TYPE:
{
struct ctio_to_2xxx *entry = (struct ctio_to_2xxx *)pkt;
+
qlt_do_ctio_completion(vha, rsp, entry->handle,
le16_to_cpu(entry->status)|(pkt->entry_status << 16),
entry);
@@ -5964,6 +5855,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha,
case NOTIFY_ACK_TYPE:
if (tgt->notify_ack_expected > 0) {
struct nack_to_isp *entry = (struct nack_to_isp *)pkt;
+
ql_dbg(ql_dbg_tgt, vha, 0xe036,
"NOTIFY_ACK seq %08x status %x\n",
le16_to_cpu(entry->u.isp2x.seq_id),
@@ -6203,21 +6095,21 @@ static fc_port_t *qlt_get_port_database(struct scsi_qla_host *vha,
/* Must be called under tgt_mutex */
static struct fc_port *qlt_make_local_sess(struct scsi_qla_host *vha,
- uint8_t *s_id)
+ be_id_t s_id)
{
struct fc_port *sess = NULL;
fc_port_t *fcport = NULL;
int rc, global_resets;
uint16_t loop_id = 0;
- if ((s_id[0] == 0xFF) && (s_id[1] == 0xFC)) {
+ if (s_id.domain == 0xFF && s_id.area == 0xFC) {
/*
* This is Domain Controller, so it should be
* OK to drop SCSI commands from it.
*/
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf042,
"Unable to find initiator with S_ID %x:%x:%x",
- s_id[0], s_id[1], s_id[2]);
+ s_id.domain, s_id.area, s_id.al_pa);
return NULL;
}
@@ -6234,12 +6126,12 @@ retry:
ql_log(ql_log_info, vha, 0xf071,
"qla_target(%d): Unable to find "
"initiator with S_ID %x:%x:%x",
- vha->vp_idx, s_id[0], s_id[1],
- s_id[2]);
+ vha->vp_idx, s_id.domain, s_id.area, s_id.al_pa);
if (rc == -ENOENT) {
qlt_port_logo_t logo;
- sid_to_portid(s_id, &logo.id);
+
+ logo.id = be_to_port_id(s_id);
logo.cmd_count = 1;
qlt_send_first_logo(vha, &logo);
}
@@ -6278,8 +6170,7 @@ static void qlt_abort_work(struct qla_tgt *tgt,
struct qla_hw_data *ha = vha->hw;
struct fc_port *sess = NULL;
unsigned long flags = 0, flags2 = 0;
- uint32_t be_s_id;
- uint8_t s_id[3];
+ be_id_t s_id;
int rc;
spin_lock_irqsave(&ha->tgt.sess_lock, flags2);
@@ -6287,12 +6178,9 @@ static void qlt_abort_work(struct qla_tgt *tgt,
if (tgt->tgt_stop)
goto out_term2;
- s_id[0] = prm->abts.fcp_hdr_le.s_id[2];
- s_id[1] = prm->abts.fcp_hdr_le.s_id[1];
- s_id[2] = prm->abts.fcp_hdr_le.s_id[0];
+ s_id = le_id_to_be(prm->abts.fcp_hdr_le.s_id);
- sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha,
- (unsigned char *)&be_s_id);
+ sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha, s_id);
if (!sess) {
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
@@ -6318,16 +6206,15 @@ static void qlt_abort_work(struct qla_tgt *tgt,
}
rc = __qlt_24xx_handle_abts(vha, &prm->abts, sess);
- ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
+ ha->tgt.tgt_ops->put_sess(sess);
+
if (rc != 0)
goto out_term;
return;
out_term2:
- if (sess)
- ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2);
out_term:
@@ -6343,9 +6230,9 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
struct atio_from_isp *a = &prm->tm_iocb2;
struct scsi_qla_host *vha = tgt->vha;
struct qla_hw_data *ha = vha->hw;
- struct fc_port *sess = NULL;
+ struct fc_port *sess;
unsigned long flags;
- uint8_t *s_id = NULL; /* to hide compiler warnings */
+ be_id_t s_id;
int rc;
u64 unpacked_lun;
int fn;
@@ -6369,7 +6256,6 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
goto out_term2;
} else {
if (sess->deleted) {
- sess = NULL;
goto out_term2;
}
@@ -6377,7 +6263,6 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
ql_dbg(ql_dbg_tgt_tmr, vha, 0xf020,
"%s: kref_get fail %8phC\n",
__func__, sess->port_name);
- sess = NULL;
goto out_term2;
}
}
@@ -6388,16 +6273,15 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
scsilun_to_int((struct scsi_lun *)&a->u.isp24.fcp_cmnd.lun);
rc = qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0);
- ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
+ ha->tgt.tgt_ops->put_sess(sess);
+
if (rc != 0)
goto out_term;
return;
out_term2:
- if (sess)
- ha->tgt.tgt_ops->put_sess(sess);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
out_term:
qlt_send_term_exchange(ha->base_qpair, NULL, &prm->tm_iocb2, 1, 0);
@@ -6502,6 +6386,7 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
unsigned long flags;
struct qla_qpair *qpair = ha->queue_pair_map[i];
+
h = &tgt->qphints[i + 1];
INIT_LIST_HEAD(&h->hint_elem);
if (qpair) {
@@ -6575,22 +6460,10 @@ void qlt_remove_target_resources(struct qla_hw_data *ha)
static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn,
unsigned char *b)
{
- int i;
-
- pr_debug("qla2xxx HW vha->node_name: ");
- for (i = 0; i < WWN_SIZE; i++)
- pr_debug("%02x ", vha->node_name[i]);
- pr_debug("\n");
- pr_debug("qla2xxx HW vha->port_name: ");
- for (i = 0; i < WWN_SIZE; i++)
- pr_debug("%02x ", vha->port_name[i]);
- pr_debug("\n");
-
- pr_debug("qla2xxx passed configfs WWPN: ");
+ pr_debug("qla2xxx HW vha->node_name: %8phC\n", vha->node_name);
+ pr_debug("qla2xxx HW vha->port_name: %8phC\n", vha->port_name);
put_unaligned_be64(wwpn, b);
- for (i = 0; i < WWN_SIZE; i++)
- pr_debug("%02x ", b[i]);
- pr_debug("\n");
+ pr_debug("qla2xxx passed configfs WWPN: %8phC\n", b);
}
/**
@@ -6751,6 +6624,8 @@ qlt_enable_vha(struct scsi_qla_host *vha)
if (vha->qlini_mode == QLA2XXX_INI_MODE_ENABLED)
return;
+ if (ha->tgt.num_act_qpairs > ha->max_qpairs)
+ ha->tgt.num_act_qpairs = ha->max_qpairs;
spin_lock_irqsave(&ha->hardware_lock, flags);
tgt->tgt_stopped = 0;
qlt_set_mode(vha);
@@ -6765,7 +6640,8 @@ qlt_enable_vha(struct scsi_qla_host *vha)
} else {
set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags);
qla2xxx_wake_dpc(base_vha);
- qla2x00_wait_for_hba_online(base_vha);
+ WARN_ON_ONCE(qla2x00_wait_for_hba_online(base_vha) !=
+ QLA_SUCCESS);
}
mutex_unlock(&ha->optrom_mutex);
}
@@ -6796,7 +6672,9 @@ static void qlt_disable_vha(struct scsi_qla_host *vha)
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
- qla2x00_wait_for_hba_online(vha);
+ if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
+ ql_dbg(ql_dbg_tgt, vha, 0xe081,
+ "qla2x00_wait_for_hba_online() failed\n");
}
/*
@@ -6895,7 +6773,7 @@ qlt_24xx_process_atio_queue(struct scsi_qla_host *vha, uint8_t ha_locked)
*/
ql_log(ql_log_warn, vha, 0xd03c,
"corrupted fcp frame SID[%3phN] OXID[%04x] EXCG[%x] %64phN\n",
- pkt->u.isp24.fcp_hdr.s_id,
+ &pkt->u.isp24.fcp_hdr.s_id,
be16_to_cpu(pkt->u.isp24.fcp_hdr.ox_id),
le32_to_cpu(pkt->u.isp24.exchange_addr), pkt);
@@ -6940,7 +6818,7 @@ qlt_24xx_config_rings(struct scsi_qla_host *vha)
RD_REG_DWORD(ISP_ATIO_Q_OUT(vha));
if (ha->flags.msix_enabled) {
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
if (IS_QLA2071(ha)) {
/* 4 ports Baker: Enable Interrupt Handshake */
icb->msix_atio = 0;
@@ -6955,7 +6833,7 @@ qlt_24xx_config_rings(struct scsi_qla_host *vha)
}
} else {
/* INTx|MSI */
- if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
icb->msix_atio = 0;
icb->firmware_options_2 |= BIT_26;
ql_dbg(ql_dbg_init, vha, 0xf072,
@@ -7204,7 +7082,8 @@ qlt_probe_one_stage1(struct scsi_qla_host *base_vha, struct qla_hw_data *ha)
if (!QLA_TGT_MODE_ENABLED())
return;
- if ((ql2xenablemsix == 0) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
+ if ((ql2xenablemsix == 0) || IS_QLA83XX(ha) || IS_QLA27XX(ha) ||
+ IS_QLA28XX(ha)) {
ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in;
ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out;
} else {
@@ -7331,7 +7210,10 @@ qlt_mem_free(struct qla_hw_data *ha)
sizeof(struct atio_from_isp), ha->tgt.atio_ring,
ha->tgt.atio_dma);
}
+ ha->tgt.atio_ring = NULL;
+ ha->tgt.atio_dma = 0;
kfree(ha->tgt.tgt_vp_map);
+ ha->tgt.tgt_vp_map = NULL;
}
/* vport_slock to be held by the caller */
@@ -7415,6 +7297,9 @@ int __init qlt_init(void)
{
int ret;
+ BUILD_BUG_ON(sizeof(struct ctio7_to_24xx) != 64);
+ BUILD_BUG_ON(sizeof(struct ctio_to_2xxx) != 64);
+
if (!qlt_parse_ini_mode()) {
ql_log(ql_log_fatal, NULL, 0xe06b,
"qlt_parse_ini_mode() failed\n");
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 577e1786a3f1..ee3f7cca60f4 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -29,6 +29,7 @@
#define __QLA_TARGET_H
#include "qla_def.h"
+#include "qla_dsd.h"
/*
* Must be changed on any change in any initiator visible interfaces or
@@ -224,12 +225,7 @@ struct ctio_to_2xxx {
uint16_t reserved_1[3];
uint16_t scsi_status;
uint32_t transfer_length;
- uint32_t dseg_0_address; /* Data segment 0 address. */
- uint32_t dseg_0_length; /* Data segment 0 length. */
- uint32_t dseg_1_address; /* Data segment 1 address. */
- uint32_t dseg_1_length; /* Data segment 1 length. */
- uint32_t dseg_2_address; /* Data segment 2 address. */
- uint32_t dseg_2_length; /* Data segment 2 length. */
+ struct dsd32 dsd[3];
} __packed;
#define ATIO_PATH_INVALID 0x07
#define ATIO_CANT_PROV_CAP 0x16
@@ -260,9 +256,9 @@ struct ctio_to_2xxx {
struct fcp_hdr {
uint8_t r_ctl;
- uint8_t d_id[3];
+ be_id_t d_id;
uint8_t cs_ctl;
- uint8_t s_id[3];
+ be_id_t s_id;
uint8_t type;
uint8_t f_ctl[3];
uint8_t seq_id;
@@ -274,9 +270,9 @@ struct fcp_hdr {
} __packed;
struct fcp_hdr_le {
- uint8_t d_id[3];
+ le_id_t d_id;
uint8_t r_ctl;
- uint8_t s_id[3];
+ le_id_t s_id;
uint8_t cs_ctl;
uint8_t f_ctl[3];
uint8_t type;
@@ -415,7 +411,7 @@ struct ctio7_to_24xx {
uint16_t dseg_count; /* Data segment count. */
uint8_t vp_index;
uint8_t add_flags;
- uint8_t initiator_id[3];
+ le_id_t initiator_id;
uint8_t reserved;
uint32_t exchange_addr;
union {
@@ -429,10 +425,7 @@ struct ctio7_to_24xx {
uint32_t reserved2;
uint32_t transfer_length;
uint32_t reserved3;
- /* Data segment 0 address. */
- uint32_t dseg_0_address[2];
- /* Data segment 0 length. */
- uint32_t dseg_0_length;
+ struct dsd64 dsd;
} status0;
struct {
uint16_t sense_length;
@@ -514,7 +507,7 @@ struct ctio_crc2_to_fw {
uint8_t add_flags; /* additional flags */
#define CTIO_CRC2_AF_DIF_DSD_ENA BIT_3
- uint8_t initiator_id[3]; /* initiator ID */
+ le_id_t initiator_id; /* initiator ID */
uint8_t reserved1;
uint32_t exchange_addr; /* rcv exchange address */
uint16_t reserved2;
@@ -526,10 +519,10 @@ struct ctio_crc2_to_fw {
uint32_t reserved5;
__le32 transfer_length; /* total fc transfer length */
uint32_t reserved6;
- __le32 crc_context_address[2];/* Data segment address. */
+ __le64 crc_context_address __packed; /* Data segment address. */
uint16_t crc_context_len; /* Data segment length. */
uint16_t reserved_1; /* MUST be set to 0. */
-} __packed;
+};
/* CTIO Type CRC_x Status IOCB */
struct ctio_crc_from_fw {
@@ -698,7 +691,7 @@ struct qla_tgt_func_tmpl {
struct fc_port *(*find_sess_by_loop_id)(struct scsi_qla_host *,
const uint16_t);
struct fc_port *(*find_sess_by_s_id)(struct scsi_qla_host *,
- const uint8_t *);
+ const be_id_t);
void (*clear_nacl_from_fcport_map)(struct fc_port *);
void (*put_sess)(struct fc_port *);
void (*shutdown_sess)(struct fc_port *);
@@ -855,7 +848,7 @@ enum trace_flags {
TRC_CTIO_ERR = BIT_11,
TRC_CTIO_DONE = BIT_12,
TRC_CTIO_ABORTED = BIT_13,
- TRC_CTIO_STRANGE= BIT_14,
+ TRC_CTIO_STRANGE = BIT_14,
TRC_CMD_DONE = BIT_15,
TRC_CMD_CHK_STOP = BIT_16,
TRC_CMD_FREE = BIT_17,
@@ -889,10 +882,14 @@ struct qla_tgt_cmd {
unsigned int term_exchg:1;
unsigned int cmd_sent_to_fw:1;
unsigned int cmd_in_wq:1;
- unsigned int aborted:1;
- unsigned int data_work:1;
- unsigned int data_work_free:1;
- unsigned int released:1;
+
+ /*
+ * This variable may be set from outside the LIO and I/O completion
+ * callback functions. Do not declare this member variable as a
+ * bitfield to avoid a read-modify-write operation when this variable
+ * is set.
+ */
+ unsigned int aborted;
struct scatterlist *sg; /* cmd data buffer SG vector */
int sg_cnt; /* SG segments count */
@@ -924,10 +921,12 @@ struct qla_tgt_cmd {
uint8_t scsi_status, sense_key, asc, ascq;
struct crc_context *ctx;
- uint8_t *cdb;
+ const uint8_t *cdb;
uint64_t lba;
uint16_t a_guard, e_guard, a_app_tag, e_app_tag;
uint32_t a_ref_tag, e_ref_tag;
+#define DIF_BUNDL_DMA_VALID 1
+ uint16_t prot_flags;
uint64_t jiffies_at_alloc;
uint64_t jiffies_at_free;
@@ -1040,22 +1039,11 @@ static inline bool qla_dual_mode_enabled(struct scsi_qla_host *ha)
return (ha->host->active_mode == MODE_DUAL);
}
-static inline uint32_t sid_to_key(const uint8_t *s_id)
-{
- uint32_t key;
-
- key = (((unsigned long)s_id[0] << 16) |
- ((unsigned long)s_id[1] << 8) |
- (unsigned long)s_id[2]);
- return key;
-}
-
-static inline void sid_to_portid(const uint8_t *s_id, port_id_t *p)
+static inline uint32_t sid_to_key(const be_id_t s_id)
{
- memset(p, 0, sizeof(*p));
- p->b.domain = s_id[0];
- p->b.area = s_id[1];
- p->b.al_pa = s_id[2];
+ return s_id.domain << 16 |
+ s_id.area << 8 |
+ s_id.al_pa;
}
/*
@@ -1101,7 +1089,5 @@ extern void qlt_do_generation_tick(struct scsi_qla_host *, int *);
void qlt_send_resp_ctio(struct qla_qpair *, struct qla_tgt_cmd *, uint8_t,
uint8_t, uint8_t, uint8_t);
-extern void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *,
- struct qla_tgt_cmd *);
#endif /* __QLA_TARGET_H */
diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c
index 0ccd06f11f12..294d77c02cdf 100644
--- a/drivers/scsi/qla2xxx/qla_tmpl.c
+++ b/drivers/scsi/qla2xxx/qla_tmpl.c
@@ -7,103 +7,9 @@
#include "qla_def.h"
#include "qla_tmpl.h"
-/* note default template is in big endian */
-static const uint32_t ql27xx_fwdt_default_template[] = {
- 0x63000000, 0xa4000000, 0x7c050000, 0x00000000,
- 0x30000000, 0x01000000, 0x00000000, 0xc0406eb4,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x04010000, 0x14000000, 0x00000000,
- 0x02000000, 0x44000000, 0x09010000, 0x10000000,
- 0x00000000, 0x02000000, 0x01010000, 0x1c000000,
- 0x00000000, 0x02000000, 0x00600000, 0x00000000,
- 0xc0000000, 0x01010000, 0x1c000000, 0x00000000,
- 0x02000000, 0x00600000, 0x00000000, 0xcc000000,
- 0x01010000, 0x1c000000, 0x00000000, 0x02000000,
- 0x10600000, 0x00000000, 0xd4000000, 0x01010000,
- 0x1c000000, 0x00000000, 0x02000000, 0x700f0000,
- 0x00000060, 0xf0000000, 0x00010000, 0x18000000,
- 0x00000000, 0x02000000, 0x00700000, 0x041000c0,
- 0x00010000, 0x18000000, 0x00000000, 0x02000000,
- 0x10700000, 0x041000c0, 0x00010000, 0x18000000,
- 0x00000000, 0x02000000, 0x40700000, 0x041000c0,
- 0x01010000, 0x1c000000, 0x00000000, 0x02000000,
- 0x007c0000, 0x01000000, 0xc0000000, 0x00010000,
- 0x18000000, 0x00000000, 0x02000000, 0x007c0000,
- 0x040300c4, 0x00010000, 0x18000000, 0x00000000,
- 0x02000000, 0x007c0000, 0x040100c0, 0x01010000,
- 0x1c000000, 0x00000000, 0x02000000, 0x007c0000,
- 0x00000000, 0xc0000000, 0x00010000, 0x18000000,
- 0x00000000, 0x02000000, 0x007c0000, 0x04200000,
- 0x0b010000, 0x18000000, 0x00000000, 0x02000000,
- 0x0c000000, 0x00000000, 0x02010000, 0x20000000,
- 0x00000000, 0x02000000, 0x700f0000, 0x040100fc,
- 0xf0000000, 0x000000b0, 0x02010000, 0x20000000,
- 0x00000000, 0x02000000, 0x700f0000, 0x040100fc,
- 0xf0000000, 0x000010b0, 0x02010000, 0x20000000,
- 0x00000000, 0x02000000, 0x700f0000, 0x040100fc,
- 0xf0000000, 0x000020b0, 0x02010000, 0x20000000,
- 0x00000000, 0x02000000, 0x700f0000, 0x040100fc,
- 0xf0000000, 0x000030b0, 0x02010000, 0x20000000,
- 0x00000000, 0x02000000, 0x700f0000, 0x040100fc,
- 0xf0000000, 0x000040b0, 0x02010000, 0x20000000,
- 0x00000000, 0x02000000, 0x700f0000, 0x040100fc,
- 0xf0000000, 0x000050b0, 0x02010000, 0x20000000,
- 0x00000000, 0x02000000, 0x700f0000, 0x040100fc,
- 0xf0000000, 0x000060b0, 0x02010000, 0x20000000,
- 0x00000000, 0x02000000, 0x700f0000, 0x040100fc,
- 0xf0000000, 0x000070b0, 0x02010000, 0x20000000,
- 0x00000000, 0x02000000, 0x700f0000, 0x040100fc,
- 0xf0000000, 0x000080b0, 0x02010000, 0x20000000,
- 0x00000000, 0x02000000, 0x700f0000, 0x040100fc,
- 0xf0000000, 0x000090b0, 0x02010000, 0x20000000,
- 0x00000000, 0x02000000, 0x700f0000, 0x040100fc,
- 0xf0000000, 0x0000a0b0, 0x00010000, 0x18000000,
- 0x00000000, 0x02000000, 0x0a000000, 0x040100c0,
- 0x00010000, 0x18000000, 0x00000000, 0x02000000,
- 0x0a000000, 0x04200080, 0x00010000, 0x18000000,
- 0x00000000, 0x02000000, 0x00be0000, 0x041000c0,
- 0x00010000, 0x18000000, 0x00000000, 0x02000000,
- 0x10be0000, 0x041000c0, 0x00010000, 0x18000000,