summaryrefslogtreecommitdiff
path: root/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/bnx2fc/bnx2fc_fcoe.c')
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_fcoe.c74
1 files changed, 67 insertions, 7 deletions
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index 93b5a0012417..7dfe709a7138 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -4,7 +4,8 @@
* FIP/FCoE packets, listen to link events etc.
*
* Copyright (c) 2008-2013 Broadcom Corporation
- * Copyright (c) 2014-2015 QLogic Corporation
+ * Copyright (c) 2014-2016 QLogic Corporation
+ * Copyright (c) 2016-2017 Cavium Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -351,7 +352,7 @@ static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
cp = kmap_atomic(skb_frag_page(frag)) + frag->page_offset;
} else {
- cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
+ cp = skb_put(skb, tlen);
}
memset(cp, 0, sizeof(*cp));
@@ -522,10 +523,12 @@ static void bnx2fc_recv_frame(struct sk_buff *skb)
struct fcoe_crc_eof crc_eof;
struct fc_frame *fp;
struct fc_lport *vn_port;
- struct fcoe_port *port;
+ struct fcoe_port *port, *phys_port;
u8 *mac = NULL;
u8 *dest_mac = NULL;
struct fcoe_hdr *hp;
+ struct bnx2fc_interface *interface;
+ struct fcoe_ctlr *ctlr;
fr = fcoe_dev_from_skb(skb);
lport = fr->fr_dev;
@@ -561,8 +564,19 @@ static void bnx2fc_recv_frame(struct sk_buff *skb)
return;
}
+ phys_port = lport_priv(lport);
+ interface = phys_port->priv;
+ ctlr = bnx2fc_to_ctlr(interface);
+
fh = fc_frame_header_get(fp);
+ if (ntoh24(&dest_mac[3]) != ntoh24(fh->fh_d_id)) {
+ BNX2FC_HBA_DBG(lport, "FC frame d_id mismatch with MAC %pM.\n",
+ dest_mac);
+ kfree_skb(skb);
+ return;
+ }
+
vn_port = fc_vport_id_lookup(lport, ntoh24(fh->fh_d_id));
if (vn_port) {
port = lport_priv(vn_port);
@@ -572,6 +586,14 @@ static void bnx2fc_recv_frame(struct sk_buff *skb)
return;
}
}
+ if (ctlr->state) {
+ if (!ether_addr_equal(mac, ctlr->dest_addr)) {
+ BNX2FC_HBA_DBG(lport, "Wrong source address: mac:%pM dest_addr:%pM.\n",
+ mac, ctlr->dest_addr);
+ kfree_skb(skb);
+ return;
+ }
+ }
if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
fh->fh_type == FC_TYPE_FCP) {
/* Drop FCP data. We dont this in L2 path */
@@ -597,6 +619,18 @@ static void bnx2fc_recv_frame(struct sk_buff *skb)
return;
}
+ /*
+ * If the destination ID from the frame header does not match what we
+ * have on record for lport and the search for a NPIV port came up
+ * empty then this is not addressed to our port so simply drop it.
+ */
+ if (lport->port_id != ntoh24(fh->fh_d_id) && !vn_port) {
+ BNX2FC_HBA_DBG(lport, "Dropping frame due to destination mismatch: lport->port_id=%x fh->d_id=%x.\n",
+ lport->port_id, ntoh24(fh->fh_d_id));
+ kfree_skb(skb);
+ return;
+ }
+
stats = per_cpu_ptr(lport->stats, smp_processor_id());
stats->RxFrames++;
stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
@@ -663,15 +697,17 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
if (!fw_stats)
return NULL;
+ mutex_lock(&hba->hba_stats_mutex);
+
bnx2fc_stats = fc_get_host_stats(shost);
init_completion(&hba->stat_req_done);
if (bnx2fc_send_stat_req(hba))
- return bnx2fc_stats;
+ goto unlock_stats_mutex;
rc = wait_for_completion_timeout(&hba->stat_req_done, (2 * HZ));
if (!rc) {
BNX2FC_HBA_DBG(lport, "FW stat req timed out\n");
- return bnx2fc_stats;
+ goto unlock_stats_mutex;
}
BNX2FC_STATS(hba, rx_stat2, fc_crc_cnt);
bnx2fc_stats->invalid_crc_count += hba->bfw_stats.fc_crc_cnt;
@@ -693,6 +729,9 @@ static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
memcpy(&hba->prev_stats, hba->stats_buffer,
sizeof(struct fcoe_statistics_params));
+
+unlock_stats_mutex:
+ mutex_unlock(&hba->hba_stats_mutex);
return bnx2fc_stats;
}
@@ -1340,6 +1379,7 @@ static struct bnx2fc_hba *bnx2fc_hba_create(struct cnic_dev *cnic)
}
spin_lock_init(&hba->hba_lock);
mutex_init(&hba->hba_mutex);
+ mutex_init(&hba->hba_stats_mutex);
hba->cnic = cnic;
@@ -2099,6 +2139,9 @@ static uint bnx2fc_npiv_create_vports(struct fc_lport *lport,
{
struct fc_vport_identifiers vpid;
uint i, created = 0;
+ u64 wwnn = 0;
+ char wwpn_str[32];
+ char wwnn_str[32];
if (npiv_tbl->count > MAX_NPIV_ENTRIES) {
BNX2FC_HBA_DBG(lport, "Exceeded count max of npiv table\n");
@@ -2117,11 +2160,23 @@ static uint bnx2fc_npiv_create_vports(struct fc_lport *lport,
vpid.disable = false;
for (i = 0; i < npiv_tbl->count; i++) {
- vpid.node_name = wwn_to_u64(npiv_tbl->wwnn[i]);
+ wwnn = wwn_to_u64(npiv_tbl->wwnn[i]);
+ if (wwnn == 0) {
+ /*
+ * If we get a 0 element from for the WWNN then assume
+ * the WWNN should be the same as the physical port.
+ */
+ wwnn = lport->wwnn;
+ }
+ vpid.node_name = wwnn;
vpid.port_name = wwn_to_u64(npiv_tbl->wwpn[i]);
scnprintf(vpid.symbolic_name, sizeof(vpid.symbolic_name),
"NPIV[%u]:%016llx-%016llx",
created, vpid.port_name, vpid.node_name);
+ fcoe_wwn_to_str(vpid.node_name, wwnn_str, sizeof(wwnn_str));
+ fcoe_wwn_to_str(vpid.port_name, wwpn_str, sizeof(wwpn_str));
+ BNX2FC_HBA_DBG(lport, "Creating vport %s:%s.\n", wwnn_str,
+ wwpn_str);
if (fc_vport_create(lport->host, 0, &vpid))
created++;
else
@@ -2518,6 +2573,11 @@ static void bnx2fc_ulp_exit(struct cnic_dev *dev)
bnx2fc_hba_destroy(hba);
}
+static void bnx2fc_rport_terminate_io(struct fc_rport *rport)
+{
+ /* This is a no-op */
+}
+
/**
* bnx2fc_fcoe_reset - Resets the fcoe
*
@@ -2854,7 +2914,7 @@ static struct fc_function_template bnx2fc_transport_function = {
.issue_fc_host_lip = bnx2fc_fcoe_reset,
- .terminate_rport_io = fc_rport_terminate_io,
+ .terminate_rport_io = bnx2fc_rport_terminate_io,
.vport_create = bnx2fc_vport_create,
.vport_delete = bnx2fc_vport_destroy,