]> git.ipfire.org Git - people/arne_f/kernel.git/blobdiff - drivers/scsi/qedf/qedf_main.c
Merge branch 'fixes' into misc
[people/arne_f/kernel.git] / drivers / scsi / qedf / qedf_main.c
index 1d13c9ca517de7e2cec033bdf050498fafbfeccc..7c0064500cc528a9d8c29e3ecd4ff66f005717d6 100644 (file)
@@ -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);
        }
 
        /*