summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qedf/qedf_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qedf/qedf_main.c')
-rw-r--r--drivers/scsi/qedf/qedf_main.c113
1 files changed, 82 insertions, 31 deletions
diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index 1d13c9ca517d..7c0064500cc5 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -18,6 +18,7 @@
#include <linux/kthread.h>
#include <scsi/libfc.h>
#include <scsi/scsi_host.h>
+#include <scsi/fc_frame.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/cpu.h>
@@ -42,7 +43,7 @@ MODULE_PARM_DESC(dev_loss_tmo, " dev_loss_tmo setting for attached "
uint qedf_debug = QEDF_LOG_INFO;
module_param_named(debug, qedf_debug, uint, S_IRUGO);
-MODULE_PARM_DESC(qedf_debug, " Debug mask. Pass '1' to enable default debugging"
+MODULE_PARM_DESC(debug, " Debug mask. Pass '1' to enable default debugging"
" mask");
static uint qedf_fipvlan_retries = 30;
@@ -163,7 +164,7 @@ static void qedf_handle_link_update(struct work_struct *work)
QEDF_WARN(&(qedf->dbg_ctx), "Did not receive FIP VLAN "
"response, falling back to default VLAN %d.\n",
qedf_fallback_vlan);
- qedf_set_vlan_id(qedf, QEDF_FALLBACK_VLAN);
+ qedf_set_vlan_id(qedf, qedf_fallback_vlan);
/*
* Zero out data_src_addr so we'll update it with the new
@@ -187,6 +188,50 @@ static void qedf_handle_link_update(struct work_struct *work)
}
}
+#define QEDF_FCOE_MAC_METHOD_GRANGED_MAC 1
+#define QEDF_FCOE_MAC_METHOD_FCF_MAP 2
+#define QEDF_FCOE_MAC_METHOD_FCOE_SET_MAC 3
+static void qedf_set_data_src_addr(struct qedf_ctx *qedf, struct fc_frame *fp)
+{
+ u8 *granted_mac;
+ struct fc_frame_header *fh = fc_frame_header_get(fp);
+ u8 fc_map[3];
+ int method = 0;
+
+ /* Get granted MAC address from FIP FLOGI payload */
+ granted_mac = fr_cb(fp)->granted_mac;
+
+ /*
+ * We set the source MAC for FCoE traffic based on the Granted MAC
+ * address from the switch.
+ *
+ * If granted_mac is non-zero, we used that.
+ * If the granted_mac is zeroed out, created the FCoE MAC based on
+ * the sel_fcf->fc_map and the d_id fo the FLOGI frame.
+ * If sel_fcf->fc_map is 0 then we use the default FCF-MAC plus the
+ * d_id of the FLOGI frame.
+ */
+ if (!is_zero_ether_addr(granted_mac)) {
+ ether_addr_copy(qedf->data_src_addr, granted_mac);
+ method = QEDF_FCOE_MAC_METHOD_GRANGED_MAC;
+ } else if (qedf->ctlr.sel_fcf->fc_map != 0) {
+ hton24(fc_map, qedf->ctlr.sel_fcf->fc_map);
+ qedf->data_src_addr[0] = fc_map[0];
+ qedf->data_src_addr[1] = fc_map[1];
+ qedf->data_src_addr[2] = fc_map[2];
+ qedf->data_src_addr[3] = fh->fh_d_id[0];
+ qedf->data_src_addr[4] = fh->fh_d_id[1];
+ qedf->data_src_addr[5] = fh->fh_d_id[2];
+ method = QEDF_FCOE_MAC_METHOD_FCF_MAP;
+ } else {
+ fc_fcoe_set_mac(qedf->data_src_addr, fh->fh_d_id);
+ method = QEDF_FCOE_MAC_METHOD_FCOE_SET_MAC;
+ }
+
+ QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
+ "QEDF data_src_mac=%pM method=%d.\n", qedf->data_src_addr, method);
+}
+
static void qedf_flogi_resp(struct fc_seq *seq, struct fc_frame *fp,
void *arg)
{
@@ -212,6 +257,10 @@ static void qedf_flogi_resp(struct fc_seq *seq, struct fc_frame *fp,
/* Log stats for FLOGI reject */
if (fc_frame_payload_op(fp) == ELS_LS_RJT)
qedf->flogi_failed++;
+ else if (fc_frame_payload_op(fp) == ELS_LS_ACC) {
+ /* Set the source MAC we will use for FCoE traffic */
+ qedf_set_data_src_addr(qedf, fp);
+ }
/* Complete flogi_compl so we can proceed to sending ADISCs */
complete(&qedf->flogi_compl);
@@ -312,8 +361,9 @@ static void qedf_link_recovery(struct work_struct *work)
/* Since the link when down and up to verify which vlan we're on */
qedf->fipvlan_retries = qedf_fipvlan_retries;
rc = qedf_initiate_fipvlan_req(qedf);
+ /* If getting the VLAN fails, set the VLAN to the fallback one */
if (!rc)
- return;
+ qedf_set_vlan_id(qedf, qedf_fallback_vlan);
/*
* We need to wait for an FCF to be selected due to the
@@ -629,16 +679,6 @@ static int qedf_eh_device_reset(struct scsi_cmnd *sc_cmd)
return qedf_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET);
}
-static int qedf_eh_bus_reset(struct scsi_cmnd *sc_cmd)
-{
- QEDF_ERR(NULL, "BUS RESET Issued...\n");
- /*
- * Essentially a no-op but return SUCCESS to prevent
- * unnecessary escalation to the host reset handler.
- */
- return SUCCESS;
-}
-
void qedf_wait_for_upload(struct qedf_ctx *qedf)
{
while (1) {
@@ -716,7 +756,6 @@ static struct scsi_host_template qedf_host_template = {
.eh_abort_handler = qedf_eh_abort,
.eh_device_reset_handler = qedf_eh_device_reset, /* lun reset */
.eh_target_reset_handler = qedf_eh_target_reset, /* target reset */
- .eh_bus_reset_handler = qedf_eh_bus_reset,
.eh_host_reset_handler = qedf_eh_host_reset,
.slave_configure = qedf_slave_configure,
.dma_boundary = QED_HW_DMA_BOUNDARY,
@@ -915,6 +954,10 @@ static int qedf_xmit(struct fc_lport *lport, struct fc_frame *fp)
skb->mac_len = elen;
skb->protocol = htons(ETH_P_FCOE);
+ /*
+ * Add VLAN tag to non-offload FCoE frame based on current stored VLAN
+ * for FIP/FCoE traffic.
+ */
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), qedf->vlan_id);
/* fill up mac and fcoe headers */
@@ -927,7 +970,7 @@ static int qedf_xmit(struct fc_lport *lport, struct fc_frame *fp)
ether_addr_copy(eh->h_dest, qedf->ctlr.dest_addr);
/* Set the source MAC address */
- fc_fcoe_set_mac(eh->h_source, fh->fh_s_id);
+ ether_addr_copy(eh->h_source, qedf->data_src_addr);
hp = (struct fcoe_hdr *)(eh + 1);
memset(hp, 0, sizeof(*hp));
@@ -1025,7 +1068,6 @@ static int qedf_offload_connection(struct qedf_ctx *qedf,
{
struct qed_fcoe_params_offload conn_info;
u32 port_id;
- u8 lport_src_id[3];
int rval;
uint16_t total_sqe = (fcport->sq_mem_size / sizeof(struct fcoe_wqe));
@@ -1054,11 +1096,7 @@ static int qedf_offload_connection(struct qedf_ctx *qedf,
(dma_addr_t)(*(u64 *)(fcport->sq_pbl + 8));
/* Need to use our FCoE MAC for the offload session */
- port_id = fc_host_port_id(qedf->lport->host);
- lport_src_id[2] = (port_id & 0x000000FF);
- lport_src_id[1] = (port_id & 0x0000FF00) >> 8;
- lport_src_id[0] = (port_id & 0x00FF0000) >> 16;
- fc_fcoe_set_mac(conn_info.src_mac, lport_src_id);
+ ether_addr_copy(conn_info.src_mac, qedf->data_src_addr);
ether_addr_copy(conn_info.dst_mac, qedf->ctlr.dest_addr);
@@ -1347,7 +1385,6 @@ static void qedf_fcoe_ctlr_setup(struct qedf_ctx *qedf)
fcoe_ctlr_init(&qedf->ctlr, FIP_ST_AUTO);
qedf->ctlr.send = qedf_fip_send;
- qedf->ctlr.update_mac = qedf_update_src_mac;
qedf->ctlr.get_src_addr = qedf_get_src_mac;
ether_addr_copy(qedf->ctlr.ctl_src_addr, qedf->mac);
}
@@ -2939,7 +2976,7 @@ static int __qedf_probe(struct pci_dev *pdev, int mode)
sprintf(host_buf, "qedf_%u_link",
qedf->lport->host->host_no);
- qedf->link_update_wq = create_singlethread_workqueue(host_buf);
+ qedf->link_update_wq = create_workqueue(host_buf);
INIT_DELAYED_WORK(&qedf->link_update, qedf_handle_link_update);
INIT_DELAYED_WORK(&qedf->link_recovery, qedf_link_recovery);
@@ -3056,9 +3093,24 @@ static int __qedf_probe(struct pci_dev *pdev, int mode)
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "MAC address is %pM.\n",
qedf->mac);
- /* Set the WWNN and WWPN based on the MAC address */
- qedf->wwnn = fcoe_wwn_from_mac(qedf->mac, 1, 0);
- qedf->wwpn = fcoe_wwn_from_mac(qedf->mac, 2, 0);
+ /*
+ * Set the WWNN and WWPN in the following way:
+ *
+ * If the info we get from qed is non-zero then use that to set the
+ * WWPN and WWNN. Otherwise fall back to use fcoe_wwn_from_mac() based
+ * on the MAC address.
+ */
+ if (qedf->dev_info.wwnn != 0 && qedf->dev_info.wwpn != 0) {
+ QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
+ "Setting WWPN and WWNN from qed dev_info.\n");
+ qedf->wwnn = qedf->dev_info.wwnn;
+ qedf->wwpn = qedf->dev_info.wwpn;
+ } else {
+ QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
+ "Setting WWPN and WWNN using fcoe_wwn_from_mac().\n");
+ qedf->wwnn = fcoe_wwn_from_mac(qedf->mac, 1, 0);
+ qedf->wwpn = fcoe_wwn_from_mac(qedf->mac, 2, 0);
+ }
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "WWNN=%016llx "
"WWPN=%016llx.\n", qedf->wwnn, qedf->wwpn);
@@ -3094,7 +3146,7 @@ static int __qedf_probe(struct pci_dev *pdev, int mode)
/* Start LL2 processing thread */
snprintf(host_buf, 20, "qedf_%d_ll2", host->host_no);
qedf->ll2_recv_wq =
- create_singlethread_workqueue(host_buf);
+ create_workqueue(host_buf);
if (!qedf->ll2_recv_wq) {
QEDF_ERR(&(qedf->dbg_ctx), "Failed to LL2 workqueue.\n");
goto err7;
@@ -3114,8 +3166,7 @@ static int __qedf_probe(struct pci_dev *pdev, int mode)
}
set_bit(QEDF_LL2_STARTED, &qedf->flags);
- /* hw will be insterting vlan tag*/
- qedf->vlan_hw_insert = 1;
+ /* Set initial FIP/FCoE VLAN to NULL */
qedf->vlan_id = 0;
/*
@@ -3137,7 +3188,7 @@ static int __qedf_probe(struct pci_dev *pdev, int mode)
sprintf(host_buf, "qedf_%u_timer", qedf->lport->host->host_no);
qedf->timer_work_queue =
- create_singlethread_workqueue(host_buf);
+ create_workqueue(host_buf);
if (!qedf->timer_work_queue) {
QEDF_ERR(&(qedf->dbg_ctx), "Failed to start timer "
"workqueue.\n");
@@ -3148,7 +3199,7 @@ static int __qedf_probe(struct pci_dev *pdev, int mode)
if (mode != QEDF_MODE_RECOVERY) {
sprintf(host_buf, "qedf_%u_dpc",
qedf->lport->host->host_no);
- qedf->dpc_wq = create_singlethread_workqueue(host_buf);
+ qedf->dpc_wq = create_workqueue(host_buf);
}
/*