scsi: qedi: Add PCI shutdown handler support
authorManish Rangankar <mrangankar@marvell.com>
Thu, 19 Mar 2020 08:38:11 +0000 (01:38 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 27 Mar 2020 02:38:54 +0000 (22:38 -0400)
Add PCI shutdown handler support for supporting wake-on-lan feature.

Link: https://lore.kernel.org/r/20200319083811.19499-3-mrangankar@marvell.com
Signed-off-by: Manish Rangankar <mrangankar@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qedi/qedi.h
drivers/scsi/qedi/qedi_gbl.h
drivers/scsi/qedi/qedi_iscsi.c
drivers/scsi/qedi/qedi_iscsi.h
drivers/scsi/qedi/qedi_main.c

index 812e368..9498279 100644 (file)
@@ -36,6 +36,7 @@ struct qedi_endpoint;
  */
 #define QEDI_MODE_NORMAL       0
 #define QEDI_MODE_RECOVERY     1
+#define QEDI_MODE_SHUTDOWN     2
 
 #define ISCSI_WQE_SET_PTU_INVALIDATE   1
 #define QEDI_MAX_ISCSI_TASK            4096
@@ -278,6 +279,7 @@ struct qedi_ctx {
 #define QEDI_IOTHREAD_WAKE     2
 #define QEDI_IN_RECOVERY       5
 #define QEDI_IN_OFFLINE                6
+#define QEDI_IN_SHUTDOWN       7
 
        u8 mac[ETH_ALEN];
        u32 src_ip[4];
index 8ba7c77..116645c 100644 (file)
@@ -73,5 +73,6 @@ void qedi_remove_sysfs_ctx_attr(struct qedi_ctx *qedi);
 void qedi_clearsq(struct qedi_ctx *qedi,
                  struct qedi_conn *qedi_conn,
                  struct iscsi_task *task);
+void qedi_clear_session_ctx(struct iscsi_cls_session *cls_sess);
 
 #endif
index 8829880..1f4a5fb 100644 (file)
@@ -392,6 +392,7 @@ static int qedi_conn_bind(struct iscsi_cls_session *cls_session,
 
        qedi_ep->conn = qedi_conn;
        qedi_conn->ep = qedi_ep;
+       qedi_conn->iscsi_ep = ep;
        qedi_conn->iscsi_conn_id = qedi_ep->iscsi_cid;
        qedi_conn->fw_cid = qedi_ep->fw_cid;
        qedi_conn->cmd_cleanup_req = 0;
@@ -782,6 +783,9 @@ static int qedi_task_xmit(struct iscsi_task *task)
        struct qedi_cmd *cmd = task->dd_data;
        struct scsi_cmnd *sc = task->sc;
 
+       if (test_bit(QEDI_IN_SHUTDOWN, &qedi_conn->qedi->flags))
+               return -ENODEV;
+
        cmd->state = 0;
        cmd->task = NULL;
        cmd->use_slowpath = false;
@@ -1596,6 +1600,20 @@ void qedi_process_iscsi_error(struct qedi_endpoint *ep,
                qedi_start_conn_recovery(qedi_conn->qedi, qedi_conn);
 }
 
+void qedi_clear_session_ctx(struct iscsi_cls_session *cls_sess)
+{
+       struct iscsi_session *session = cls_sess->dd_data;
+       struct iscsi_conn *conn = session->leadconn;
+       struct qedi_conn *qedi_conn = conn->dd_data;
+
+       if (iscsi_is_session_online(cls_sess))
+               qedi_ep_disconnect(qedi_conn->iscsi_ep);
+
+       qedi_conn_destroy(qedi_conn->cls_conn);
+
+       qedi_session_destroy(cls_sess);
+}
+
 void qedi_process_tcp_error(struct qedi_endpoint *ep,
                            struct iscsi_eqe_data *data)
 {
index 67c3b73..39dc27c 100644 (file)
@@ -149,6 +149,7 @@ struct qedi_conn {
        struct iscsi_cls_conn *cls_conn;
        struct qedi_ctx *qedi;
        struct qedi_endpoint *ep;
+       struct iscsi_endpoint *iscsi_ep;
        struct list_head active_cmd_list;
        spinlock_t list_lock;           /* internal conn lock */
        u32 active_cmd_count;
index cfa705a..b995b19 100644 (file)
@@ -2344,7 +2344,11 @@ static void __qedi_remove(struct pci_dev *pdev, int mode)
        struct qedi_ctx *qedi = pci_get_drvdata(pdev);
        int rval;
 
-       if (mode == QEDI_MODE_NORMAL) {
+       if (mode == QEDI_MODE_SHUTDOWN)
+               iscsi_host_for_each_session(qedi->shost,
+                                           qedi_clear_session_ctx);
+
+       if (mode == QEDI_MODE_NORMAL || mode == QEDI_MODE_SHUTDOWN) {
                if (qedi->tmf_thread) {
                        flush_workqueue(qedi->tmf_thread);
                        destroy_workqueue(qedi->tmf_thread);
@@ -2384,7 +2388,7 @@ static void __qedi_remove(struct pci_dev *pdev, int mode)
 
        qedi_destroy_fp(qedi);
 
-       if (mode == QEDI_MODE_NORMAL) {
+       if (mode == QEDI_MODE_NORMAL || mode == QEDI_MODE_SHUTDOWN) {
                qedi_release_cid_que(qedi);
                qedi_cm_free_mem(qedi);
                qedi_free_uio(qedi->udev);
@@ -2404,6 +2408,16 @@ static void __qedi_remove(struct pci_dev *pdev, int mode)
        }
 }
 
+static void qedi_shutdown(struct pci_dev *pdev)
+{
+       struct qedi_ctx *qedi = pci_get_drvdata(pdev);
+
+       QEDI_ERR(&qedi->dbg_ctx, "%s: Shutdown qedi\n", __func__);
+       if (test_and_set_bit(QEDI_IN_SHUTDOWN, &qedi->flags))
+               return;
+       __qedi_remove(pdev, QEDI_MODE_SHUTDOWN);
+}
+
 static int __qedi_probe(struct pci_dev *pdev, int mode)
 {
        struct qedi_ctx *qedi;
@@ -2740,6 +2754,7 @@ static struct pci_driver qedi_pci_driver = {
        .id_table = qedi_pci_tbl,
        .probe = qedi_probe,
        .remove = qedi_remove,
+       .shutdown = qedi_shutdown,
 };
 
 static int __init qedi_init(void)