diff options
author | Chad Dupuis <cdupuis@marvell.com> | 2019-03-26 03:38:47 -0400 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2019-03-27 21:54:52 -0400 |
commit | a66c6cd2a8ade6150364687f5872934a7e623fb2 (patch) | |
tree | 13080abaab6228800b53f5dfd81b417f2be04163 /drivers/scsi/qedf | |
parent | 627cc7dd73f6aa3025398507c729b97fb19c270b (diff) |
scsi: qedf: Wait for upload and link down processing during soft ctx reset
- Wait for all the connections to get uploaded.
Signed-off-by: Chad Dupuis <cdupuis@marvell.com>
Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/qedf')
-rw-r--r-- | drivers/scsi/qedf/qedf.h | 4 | ||||
-rw-r--r-- | drivers/scsi/qedf/qedf_fip.c | 4 | ||||
-rw-r--r-- | drivers/scsi/qedf/qedf_main.c | 60 |
3 files changed, 57 insertions, 11 deletions
diff --git a/drivers/scsi/qedf/qedf.h b/drivers/scsi/qedf/qedf.h index fb7d0d5ffa67..1e0d1429ed48 100644 --- a/drivers/scsi/qedf/qedf.h +++ b/drivers/scsi/qedf/qedf.h | |||
@@ -500,7 +500,7 @@ extern void qedf_set_vlan_id(struct qedf_ctx *qedf, int vlan_id); | |||
500 | extern void qedf_create_sysfs_ctx_attr(struct qedf_ctx *qedf); | 500 | extern void qedf_create_sysfs_ctx_attr(struct qedf_ctx *qedf); |
501 | extern void qedf_remove_sysfs_ctx_attr(struct qedf_ctx *qedf); | 501 | extern void qedf_remove_sysfs_ctx_attr(struct qedf_ctx *qedf); |
502 | extern void qedf_capture_grc_dump(struct qedf_ctx *qedf); | 502 | extern void qedf_capture_grc_dump(struct qedf_ctx *qedf); |
503 | extern void qedf_wait_for_upload(struct qedf_ctx *qedf); | 503 | bool qedf_wait_for_upload(struct qedf_ctx *qedf); |
504 | extern void qedf_process_unsol_compl(struct qedf_ctx *qedf, uint16_t que_idx, | 504 | extern void qedf_process_unsol_compl(struct qedf_ctx *qedf, uint16_t que_idx, |
505 | struct fcoe_cqe *cqe); | 505 | struct fcoe_cqe *cqe); |
506 | extern void qedf_restart_rport(struct qedf_rport *fcport); | 506 | extern void qedf_restart_rport(struct qedf_rport *fcport); |
@@ -514,6 +514,8 @@ extern void qedf_get_protocol_tlv_data(void *dev, void *data); | |||
514 | extern void qedf_fp_io_handler(struct work_struct *work); | 514 | extern void qedf_fp_io_handler(struct work_struct *work); |
515 | extern void qedf_get_generic_tlv_data(void *dev, struct qed_generic_tlvs *data); | 515 | extern void qedf_get_generic_tlv_data(void *dev, struct qed_generic_tlvs *data); |
516 | extern void qedf_wq_grcdump(struct work_struct *work); | 516 | extern void qedf_wq_grcdump(struct work_struct *work); |
517 | void qedf_stag_change_work(struct work_struct *work); | ||
518 | void qedf_ctx_soft_reset(struct fc_lport *lport); | ||
517 | 519 | ||
518 | #define FCOE_WORD_TO_BYTE 4 | 520 | #define FCOE_WORD_TO_BYTE 4 |
519 | #define QEDF_MAX_TASK_NUM 0xFFFF | 521 | #define QEDF_MAX_TASK_NUM 0xFFFF |
diff --git a/drivers/scsi/qedf/qedf_fip.c b/drivers/scsi/qedf/qedf_fip.c index e669679e6a3b..53c5eca55061 100644 --- a/drivers/scsi/qedf/qedf_fip.c +++ b/drivers/scsi/qedf/qedf_fip.c | |||
@@ -236,9 +236,7 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb) | |||
236 | QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, | 236 | QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, |
237 | "do_reset=%d.\n", do_reset); | 237 | "do_reset=%d.\n", do_reset); |
238 | if (do_reset) { | 238 | if (do_reset) { |
239 | fcoe_ctlr_link_down(&qedf->ctlr); | 239 | qedf_ctx_soft_reset(qedf->lport); |
240 | qedf_wait_for_upload(qedf); | ||
241 | fcoe_ctlr_link_up(&qedf->ctlr); | ||
242 | } | 240 | } |
243 | kfree_skb(skb); | 241 | kfree_skb(skb); |
244 | } else { | 242 | } else { |
diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index bc787ce0b526..ad72a1eb3bca 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c | |||
@@ -156,7 +156,8 @@ static void qedf_handle_link_update(struct work_struct *work) | |||
156 | container_of(work, struct qedf_ctx, link_update.work); | 156 | container_of(work, struct qedf_ctx, link_update.work); |
157 | int rc; | 157 | int rc; |
158 | 158 | ||
159 | QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "Entered.\n"); | 159 | QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, "Entered. link_state=%d.\n", |
160 | atomic_read(&qedf->link_state)); | ||
160 | 161 | ||
161 | if (atomic_read(&qedf->link_state) == QEDF_LINK_UP) { | 162 | if (atomic_read(&qedf->link_state) == QEDF_LINK_UP) { |
162 | rc = qedf_initiate_fipvlan_req(qedf); | 163 | rc = qedf_initiate_fipvlan_req(qedf); |
@@ -194,7 +195,9 @@ static void qedf_handle_link_update(struct work_struct *work) | |||
194 | QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, | 195 | QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, |
195 | "Calling fcoe_ctlr_link_down().\n"); | 196 | "Calling fcoe_ctlr_link_down().\n"); |
196 | fcoe_ctlr_link_down(&qedf->ctlr); | 197 | fcoe_ctlr_link_down(&qedf->ctlr); |
197 | qedf_wait_for_upload(qedf); | 198 | if (qedf_wait_for_upload(qedf) == false) |
199 | QEDF_ERR(&qedf->dbg_ctx, | ||
200 | "Could not upload all sessions.\n"); | ||
198 | /* Reset the number of FIP VLAN retries */ | 201 | /* Reset the number of FIP VLAN retries */ |
199 | qedf->fipvlan_retries = qedf_fipvlan_retries; | 202 | qedf->fipvlan_retries = qedf_fipvlan_retries; |
200 | } | 203 | } |
@@ -780,22 +783,42 @@ static int qedf_eh_device_reset(struct scsi_cmnd *sc_cmd) | |||
780 | return qedf_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET); | 783 | return qedf_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET); |
781 | } | 784 | } |
782 | 785 | ||
783 | void qedf_wait_for_upload(struct qedf_ctx *qedf) | 786 | bool qedf_wait_for_upload(struct qedf_ctx *qedf) |
784 | { | 787 | { |
788 | struct qedf_rport *fcport = NULL; | ||
789 | |||
785 | while (1) { | 790 | while (1) { |
786 | if (atomic_read(&qedf->num_offloads)) | 791 | if (atomic_read(&qedf->num_offloads)) |
787 | QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, | 792 | QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, |
788 | "Waiting for all uploads to complete.\n"); | 793 | "Waiting for all uploads to complete.\n"); |
789 | else | 794 | else |
790 | break; | 795 | return true; |
791 | msleep(500); | 796 | msleep(500); |
792 | } | 797 | } |
798 | |||
799 | rcu_read_lock(); | ||
800 | list_for_each_entry_rcu(fcport, &qedf->fcports, peers) { | ||
801 | if (fcport && test_bit(QEDF_RPORT_SESSION_READY, | ||
802 | &fcport->flags)) { | ||
803 | if (fcport->rdata) | ||
804 | QEDF_ERR(&qedf->dbg_ctx, | ||
805 | "Waiting for fcport %p portid=%06x.\n", | ||
806 | fcport, fcport->rdata->ids.port_id); | ||
807 | } else { | ||
808 | QEDF_ERR(&qedf->dbg_ctx, | ||
809 | "Waiting for fcport %p.\n", fcport); | ||
810 | } | ||
811 | } | ||
812 | rcu_read_unlock(); | ||
813 | return false; | ||
814 | |||
793 | } | 815 | } |
794 | 816 | ||
795 | /* Performs soft reset of qedf_ctx by simulating a link down/up */ | 817 | /* Performs soft reset of qedf_ctx by simulating a link down/up */ |
796 | static void qedf_ctx_soft_reset(struct fc_lport *lport) | 818 | void qedf_ctx_soft_reset(struct fc_lport *lport) |
797 | { | 819 | { |
798 | struct qedf_ctx *qedf; | 820 | struct qedf_ctx *qedf; |
821 | struct qed_link_output if_link; | ||
799 | 822 | ||
800 | if (lport->vport) { | 823 | if (lport->vport) { |
801 | QEDF_ERR(NULL, "Cannot issue host reset on NPIV port.\n"); | 824 | QEDF_ERR(NULL, "Cannot issue host reset on NPIV port.\n"); |
@@ -806,11 +829,32 @@ static void qedf_ctx_soft_reset(struct fc_lport *lport) | |||
806 | 829 | ||
807 | /* For host reset, essentially do a soft link up/down */ | 830 | /* For host reset, essentially do a soft link up/down */ |
808 | atomic_set(&qedf->link_state, QEDF_LINK_DOWN); | 831 | atomic_set(&qedf->link_state, QEDF_LINK_DOWN); |
832 | QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, | ||
833 | "Queuing link down work.\n"); | ||
809 | queue_delayed_work(qedf->link_update_wq, &qedf->link_update, | 834 | queue_delayed_work(qedf->link_update_wq, &qedf->link_update, |
810 | 0); | 835 | 0); |
811 | qedf_wait_for_upload(qedf); | 836 | |
837 | if (qedf_wait_for_upload(qedf) == false) { | ||
838 | QEDF_ERR(&qedf->dbg_ctx, "Could not upload all sessions.\n"); | ||
839 | WARN_ON(atomic_read(&qedf->num_offloads)); | ||
840 | } | ||
841 | |||
842 | /* Before setting link up query physical link state */ | ||
843 | qed_ops->common->get_link(qedf->cdev, &if_link); | ||
844 | /* Bail if the physical link is not up */ | ||
845 | if (!if_link.link_up) { | ||
846 | QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, | ||
847 | "Physical link is not up.\n"); | ||
848 | return; | ||
849 | } | ||
850 | /* Flush and wait to make sure link down is processed */ | ||
851 | flush_delayed_work(&qedf->link_update); | ||
852 | msleep(500); | ||
853 | |||
812 | atomic_set(&qedf->link_state, QEDF_LINK_UP); | 854 | atomic_set(&qedf->link_state, QEDF_LINK_UP); |
813 | qedf->vlan_id = 0; | 855 | qedf->vlan_id = 0; |
856 | QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, | ||
857 | "Queue link up work.\n"); | ||
814 | queue_delayed_work(qedf->link_update_wq, &qedf->link_update, | 858 | queue_delayed_work(qedf->link_update_wq, &qedf->link_update, |
815 | 0); | 859 | 0); |
816 | } | 860 | } |
@@ -3453,7 +3497,9 @@ static void __qedf_remove(struct pci_dev *pdev, int mode) | |||
3453 | fcoe_ctlr_link_down(&qedf->ctlr); | 3497 | fcoe_ctlr_link_down(&qedf->ctlr); |
3454 | else | 3498 | else |
3455 | fc_fabric_logoff(qedf->lport); | 3499 | fc_fabric_logoff(qedf->lport); |
3456 | qedf_wait_for_upload(qedf); | 3500 | |
3501 | if (qedf_wait_for_upload(qedf) == false) | ||
3502 | QEDF_ERR(&qedf->dbg_ctx, "Could not upload all sessions.\n"); | ||
3457 | 3503 | ||
3458 | #ifdef CONFIG_DEBUG_FS | 3504 | #ifdef CONFIG_DEBUG_FS |
3459 | qedf_dbg_host_exit(&(qedf->dbg_ctx)); | 3505 | qedf_dbg_host_exit(&(qedf->dbg_ctx)); |