diff options
author | Manish Rangankar <mrangankar@marvell.com> | 2020-03-19 01:38:11 -0700 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2020-03-26 22:38:54 -0400 |
commit | 4f93c4bf0f748f9d0f5e9764ba69ec16c368922a (patch) | |
tree | b394d6ab5c7f5177f4618c1dfad59e907002ecf0 /drivers/scsi/qedi | |
parent | 4b1068f5d74b6cc92319bd7eba40809b1222e73f (diff) |
scsi: qedi: Add PCI shutdown handler support
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>
Diffstat (limited to 'drivers/scsi/qedi')
-rw-r--r-- | drivers/scsi/qedi/qedi.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qedi/qedi_gbl.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qedi/qedi_iscsi.c | 18 | ||||
-rw-r--r-- | drivers/scsi/qedi/qedi_iscsi.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qedi/qedi_main.c | 19 |
5 files changed, 39 insertions, 2 deletions
diff --git a/drivers/scsi/qedi/qedi.h b/drivers/scsi/qedi/qedi.h index 812e368cf100..9498279ae80d 100644 --- a/drivers/scsi/qedi/qedi.h +++ b/drivers/scsi/qedi/qedi.h @@ -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]; diff --git a/drivers/scsi/qedi/qedi_gbl.h b/drivers/scsi/qedi/qedi_gbl.h index 8ba7c771ce4d..116645c08c71 100644 --- a/drivers/scsi/qedi/qedi_gbl.h +++ b/drivers/scsi/qedi/qedi_gbl.h @@ -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 diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index 8829880a54c3..1f4a5fb00a05 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -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) { diff --git a/drivers/scsi/qedi/qedi_iscsi.h b/drivers/scsi/qedi/qedi_iscsi.h index 67c3b7349271..39dc27c85e3c 100644 --- a/drivers/scsi/qedi/qedi_iscsi.h +++ b/drivers/scsi/qedi/qedi_iscsi.h @@ -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; diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index cfa705aa16a6..b995b19865ca 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -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) |