Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[linux-2.6-microblaze.git] / drivers / scsi / qedf / qedf_main.c
index d3f73d8..90394ce 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  QLogic FCoE Offload Driver
- *  Copyright (c) 2016-2017 Cavium Inc.
+ *  Copyright (c) 2016-2018 Cavium Inc.
  *
  *  This software is available under the terms of the GNU General Public License
  *  (GPL) Version 2, available from the file COPYING in the main directory of
@@ -44,20 +44,20 @@ module_param_named(debug, qedf_debug, uint, S_IRUGO);
 MODULE_PARM_DESC(debug, " Debug mask. Pass '1' to enable default debugging"
        " mask");
 
-static uint qedf_fipvlan_retries = 30;
+static uint qedf_fipvlan_retries = 60;
 module_param_named(fipvlan_retries, qedf_fipvlan_retries, int, S_IRUGO);
 MODULE_PARM_DESC(fipvlan_retries, " Number of FIP VLAN requests to attempt "
-       "before giving up (default 30)");
+       "before giving up (default 60)");
 
 static uint qedf_fallback_vlan = QEDF_FALLBACK_VLAN;
 module_param_named(fallback_vlan, qedf_fallback_vlan, int, S_IRUGO);
 MODULE_PARM_DESC(fallback_vlan, " VLAN ID to try if fip vlan request fails "
        "(default 1002).");
 
-static uint qedf_default_prio = QEDF_DEFAULT_PRIO;
+static int qedf_default_prio = -1;
 module_param_named(default_prio, qedf_default_prio, int, S_IRUGO);
-MODULE_PARM_DESC(default_prio, " Default 802.1q priority for FIP and FCoE"
-       " traffic (default 3).");
+MODULE_PARM_DESC(default_prio, " Override 802.1q priority for FIP and FCoE"
+       " traffic (value between 0 and 7, default 3).");
 
 uint qedf_dump_frames;
 module_param_named(dump_frames, qedf_dump_frames, int, S_IRUGO | S_IWUSR);
@@ -89,6 +89,11 @@ module_param_named(retry_delay, qedf_retry_delay, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(retry_delay, " Enable/disable handling of FCP_RSP IU retry "
        "delay handling (default off).");
 
+static bool qedf_dcbx_no_wait;
+module_param_named(dcbx_no_wait, qedf_dcbx_no_wait, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dcbx_no_wait, " Do not wait for DCBX convergence to start "
+       "sending FIP VLAN requests on link up (Default: off).");
+
 static uint qedf_dp_module;
 module_param_named(dp_module, qedf_dp_module, uint, S_IRUGO);
 MODULE_PARM_DESC(dp_module, " bit flags control for verbose printk passed "
@@ -109,9 +114,9 @@ static struct kmem_cache *qedf_io_work_cache;
 void qedf_set_vlan_id(struct qedf_ctx *qedf, int vlan_id)
 {
        qedf->vlan_id = vlan_id;
-       qedf->vlan_id |= qedf_default_prio << VLAN_PRIO_SHIFT;
+       qedf->vlan_id |= qedf->prio << VLAN_PRIO_SHIFT;
        QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "Setting vlan_id=%04x "
-                  "prio=%d.\n", vlan_id, qedf_default_prio);
+                  "prio=%d.\n", vlan_id, qedf->prio);
 }
 
 /* Returns true if we have a valid vlan, false otherwise */
@@ -480,6 +485,11 @@ static void qedf_link_update(void *dev, struct qed_link_output *link)
        struct qedf_ctx *qedf = (struct qedf_ctx *)dev;
 
        if (link->link_up) {
+               if (atomic_read(&qedf->link_state) == QEDF_LINK_UP) {
+                       QEDF_INFO((&qedf->dbg_ctx), QEDF_LOG_DISC,
+                           "Ignoring link up event as link is already up.\n");
+                       return;
+               }
                QEDF_ERR(&(qedf->dbg_ctx), "LINK UP (%d GB/s).\n",
                    link->speed / 1000);
 
@@ -489,7 +499,8 @@ static void qedf_link_update(void *dev, struct qed_link_output *link)
                atomic_set(&qedf->link_state, QEDF_LINK_UP);
                qedf_update_link_speed(qedf, link);
 
-               if (atomic_read(&qedf->dcbx) == QEDF_DCBX_DONE) {
+               if (atomic_read(&qedf->dcbx) == QEDF_DCBX_DONE ||
+                   qedf_dcbx_no_wait) {
                        QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
                             "DCBx done.\n");
                        if (atomic_read(&qedf->link_down_tmo_valid) > 0)
@@ -515,7 +526,7 @@ static void qedf_link_update(void *dev, struct qed_link_output *link)
                            "Starting link down tmo.\n");
                        atomic_set(&qedf->link_down_tmo_valid, 1);
                }
-               qedf->vlan_id  = 0;
+               qedf->vlan_id = 0;
                qedf_update_link_speed(qedf, link);
                queue_delayed_work(qedf->link_update_wq, &qedf->link_update,
                    qedf_link_down_tmo * HZ);
@@ -526,6 +537,7 @@ static void qedf_link_update(void *dev, struct qed_link_output *link)
 static void qedf_dcbx_handler(void *dev, struct qed_dcbx_get *get, u32 mib_type)
 {
        struct qedf_ctx *qedf = (struct qedf_ctx *)dev;
+       u8 tmp_prio;
 
        QEDF_ERR(&(qedf->dbg_ctx), "DCBx event valid=%d enabled=%d fcoe "
            "prio=%d.\n", get->operational.valid, get->operational.enabled,
@@ -541,7 +553,26 @@ static void qedf_dcbx_handler(void *dev, struct qed_dcbx_get *get, u32 mib_type)
 
                atomic_set(&qedf->dcbx, QEDF_DCBX_DONE);
 
-               if (atomic_read(&qedf->link_state) == QEDF_LINK_UP) {
+               /*
+                * Set the 8021q priority in the following manner:
+                *
+                * 1. If a modparam is set use that
+                * 2. If the value is not between 0..7 use the default
+                * 3. Use the priority we get from the DCBX app tag
+                */
+               tmp_prio = get->operational.app_prio.fcoe;
+               if (qedf_default_prio > -1)
+                       qedf->prio = qedf_default_prio;
+               else if (tmp_prio < 0 || tmp_prio > 7) {
+                       QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
+                           "FIP/FCoE prio %d out of range, setting to %d.\n",
+                           tmp_prio, QEDF_DEFAULT_PRIO);
+                       qedf->prio = QEDF_DEFAULT_PRIO;
+               } else
+                       qedf->prio = tmp_prio;
+
+               if (atomic_read(&qedf->link_state) == QEDF_LINK_UP &&
+                   !qedf_dcbx_no_wait) {
                        if (atomic_read(&qedf->link_down_tmo_valid) > 0)
                                queue_delayed_work(qedf->link_update_wq,
                                    &qedf->link_recovery, 0);
@@ -614,16 +645,6 @@ static int qedf_eh_abort(struct scsi_cmnd *sc_cmd)
                goto out;
        }
 
-       if (!test_bit(QEDF_CMD_OUTSTANDING, &io_req->flags) ||
-           test_bit(QEDF_CMD_IN_CLEANUP, &io_req->flags) ||
-           test_bit(QEDF_CMD_IN_ABORT, &io_req->flags)) {
-               QEDF_ERR(&(qedf->dbg_ctx), "io_req xid=0x%x already in "
-                         "cleanup or abort processing or already "
-                         "completed.\n", io_req->xid);
-               rc = SUCCESS;
-               goto out;
-       }
-
        QEDF_ERR(&(qedf->dbg_ctx), "Aborting io_req sc_cmd=%p xid=0x%x "
                  "fp_idx=%d.\n", sc_cmd, io_req->xid, io_req->fp_idx);
 
@@ -705,7 +726,6 @@ static void qedf_ctx_soft_reset(struct fc_lport *lport)
 
        /* For host reset, essentially do a soft link up/down */
        atomic_set(&qedf->link_state, QEDF_LINK_DOWN);
-       atomic_set(&qedf->dcbx, QEDF_DCBX_PENDING);
        queue_delayed_work(qedf->link_update_wq, &qedf->link_update,
            0);
        qedf_wait_for_upload(qedf);
@@ -720,6 +740,22 @@ static int qedf_eh_host_reset(struct scsi_cmnd *sc_cmd)
 {
        struct fc_lport *lport;
        struct qedf_ctx *qedf;
+       struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
+       struct fc_rport_libfc_priv *rp = rport->dd_data;
+       struct qedf_rport *fcport = (struct qedf_rport *)&rp[1];
+       int rval;
+
+       rval = fc_remote_port_chkready(rport);
+
+       if (rval) {
+               QEDF_ERR(NULL, "device_reset rport not ready\n");
+               return FAILED;
+       }
+
+       if (fcport == NULL) {
+               QEDF_ERR(NULL, "device_reset: rport is NULL\n");
+               return FAILED;
+       }
 
        lport = shost_priv(sc_cmd->device->host);
        qedf = lport_priv(lport);
@@ -1109,7 +1145,7 @@ static int qedf_offload_connection(struct qedf_ctx *qedf,
        conn_info.vlan_tag = qedf->vlan_id <<
            FCOE_CONN_OFFLOAD_RAMROD_DATA_VLAN_ID_SHIFT;
        conn_info.vlan_tag |=
-           qedf_default_prio << FCOE_CONN_OFFLOAD_RAMROD_DATA_PRIORITY_SHIFT;
+           qedf->prio << FCOE_CONN_OFFLOAD_RAMROD_DATA_PRIORITY_SHIFT;
        conn_info.flags |= (FCOE_CONN_OFFLOAD_RAMROD_DATA_B_VLAN_FLAG_MASK <<
            FCOE_CONN_OFFLOAD_RAMROD_DATA_B_VLAN_FLAG_SHIFT);
 
@@ -1649,6 +1685,15 @@ static int qedf_vport_destroy(struct fc_vport *vport)
        struct Scsi_Host *shost = vport_to_shost(vport);
        struct fc_lport *n_port = shost_priv(shost);
        struct fc_lport *vn_port = vport->dd_data;
+       struct qedf_ctx *qedf = lport_priv(vn_port);
+
+       if (!qedf) {
+               QEDF_ERR(NULL, "qedf is NULL.\n");
+               goto out;
+       }
+
+       /* Set unloading bit on vport qedf_ctx to prevent more I/O */
+       set_bit(QEDF_UNLOADING, &qedf->flags);
 
        mutex_lock(&n_port->lp_mutex);
        list_del(&vn_port->list);
@@ -1675,6 +1720,7 @@ static int qedf_vport_destroy(struct fc_vport *vport)
        if (vn_port->host)
                scsi_host_put(vn_port->host);
 
+out:
        return 0;
 }
 
@@ -2109,7 +2155,8 @@ static int qedf_setup_int(struct qedf_ctx *qedf)
            QEDF_SIMD_HANDLER_NUM, qedf_simd_int_handler);
        qedf->int_info.used_cnt = 1;
 
-       return 0;
+       QEDF_ERR(&qedf->dbg_ctx, "Only MSI-X supported. Failing probe.\n");
+       return -EINVAL;
 }
 
 /* Main function for libfc frame reception */
@@ -2195,6 +2242,7 @@ static void qedf_recv_frame(struct qedf_ctx *qedf,
        if (ntoh24(&dest_mac[3]) != ntoh24(fh->fh_d_id)) {
                QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
                    "FC frame d_id mismatch with MAC %pM.\n", dest_mac);
+               kfree_skb(skb);
                return;
        }
 
@@ -2983,8 +3031,17 @@ static int __qedf_probe(struct pci_dev *pdev, int mode)
        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);
-
+       INIT_DELAYED_WORK(&qedf->grcdump_work, qedf_wq_grcdump);
        qedf->fipvlan_retries = qedf_fipvlan_retries;
+       /* Set a default prio in case DCBX doesn't converge */
+       if (qedf_default_prio > -1) {
+               /*
+                * This is the case where we pass a modparam in so we want to
+                * honor it even if dcbx doesn't converge.
+                */
+               qedf->prio = qedf_default_prio;
+       } else
+               qedf->prio = QEDF_DEFAULT_PRIO;
 
        /*
         * Common probe. Takes care of basic hardware init and pci_*
@@ -3214,7 +3271,8 @@ static int __qedf_probe(struct pci_dev *pdev, int mode)
         * unload process.
         */
        if (mode != QEDF_MODE_RECOVERY) {
-               qedf->grcdump_size = qed_ops->common->dbg_grc_size(qedf->cdev);
+               qedf->grcdump_size =
+                   qed_ops->common->dbg_all_data_size(qedf->cdev);
                if (qedf->grcdump_size) {
                        rc = qedf_alloc_grc_dump_buf(&qedf->grcdump,
                            qedf->grcdump_size);
@@ -3398,6 +3456,15 @@ static void qedf_remove(struct pci_dev *pdev)
        __qedf_remove(pdev, QEDF_MODE_NORMAL);
 }
 
+void qedf_wq_grcdump(struct work_struct *work)
+{
+       struct qedf_ctx *qedf =
+           container_of(work, struct qedf_ctx, grcdump_work.work);
+
+       QEDF_ERR(&(qedf->dbg_ctx), "Collecting GRC dump.\n");
+       qedf_capture_grc_dump(qedf);
+}
+
 /*
  * Protocol TLV handler
  */
@@ -3508,6 +3575,17 @@ static int __init qedf_init(void)
        if (qedf_debug == QEDF_LOG_DEFAULT)
                qedf_debug = QEDF_DEFAULT_LOG_MASK;
 
+       /*
+        * Check that default prio for FIP/FCoE traffic is between 0..7 if a
+        * value has been set
+        */
+       if (qedf_default_prio > -1)
+               if (qedf_default_prio > 7) {
+                       qedf_default_prio = QEDF_DEFAULT_PRIO;
+                       QEDF_ERR(NULL, "FCoE/FIP priority out of range, resetting to %d.\n",
+                           QEDF_DEFAULT_PRIO);
+               }
+
        /* Print driver banner */
        QEDF_INFO(NULL, QEDF_LOG_INFO, "%s v%s.\n", QEDF_DESCR,
                   QEDF_VERSION);