[PATCH v3 26/57] scsi: fnic: Enable lock context analysis
Bart Van Assche <[email protected]> Thu, 30 Jul 2026 15:45:09 -0700
| Newsgroups | org.kernel.vger.linux-scsi |
|---|---|
| Message-ID | <d10f7eaef0e297d1b78d1ba484b05686e185d8c7.1785451174.git.bvanassche@acm.org> |
Document locking requirements with __must_hold(). Suppress complaints about conditional locking in fnic_device_reset() with __acquire() and __release(). Acked-by: Karan Tilak Kumar <[email protected]> Signed-off-by: Bart Van Assche <[email protected]> --- drivers/scsi/fnic/Makefile | 3 ++ drivers/scsi/fnic/fdls_disc.c | 52 +++++++++++++++++++++++++++++++++-- drivers/scsi/fnic/fip.c | 2 ++ drivers/scsi/fnic/fnic_fcs.c | 6 ++++ drivers/scsi/fnic/fnic_scsi.c | 4 +++ 5 files changed, 65 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/fnic/Makefile b/drivers/scsi/fnic/Makefile index 48c5e0cb8ca6..22a463380dee 100644 --- a/drivers/scsi/fnic/Makefile +++ b/drivers/scsi/fnic/Makefile @@ -1,4 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 + +CONTEXT_ANALYSIS := y + obj-$(CONFIG_FCOE_FNIC) += fnic.o fnic-y := \ diff --git a/drivers/scsi/fnic/fdls_disc.c b/drivers/scsi/fnic/fdls_disc.c index 8cb40466872f..e64fe1097e37 100644 --- a/drivers/scsi/fnic/fdls_disc.c +++ b/drivers/scsi/fnic/fdls_disc.c @@ -417,6 +417,7 @@ static void fdls_reset_oxid_pool(struct fnic_iport_s *iport) } void fnic_del_fabric_timer_sync(struct fnic *fnic) + __must_hold(&fnic->fnic_lock) { fnic->iport.fabric.del_timer_inprogress = 1; spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); @@ -425,8 +426,8 @@ void fnic_del_fabric_timer_sync(struct fnic *fnic) fnic->iport.fabric.del_timer_inprogress = 0; } -void fnic_del_tport_timer_sync(struct fnic *fnic, - struct fnic_tport_s *tport) +void fnic_del_tport_timer_sync(struct fnic *fnic, struct fnic_tport_s *tport) + __must_hold(&fnic->fnic_lock) { tport->del_timer_inprogress = 1; spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags); @@ -437,6 +438,7 @@ void fnic_del_tport_timer_sync(struct fnic *fnic, static void fdls_start_fabric_timer(struct fnic_iport_s *iport, int timeout) + __must_hold(&iport->fnic->fnic_lock) { u64 fabric_tov; struct fnic *fnic = iport->fnic; @@ -462,6 +464,7 @@ fdls_start_fabric_timer(struct fnic_iport_s *iport, int timeout) static void fdls_start_tport_timer(struct fnic_iport_s *iport, struct fnic_tport_s *tport, int timeout) + __must_hold(&iport->fnic->fnic_lock) { u64 fabric_tov; struct fnic *fnic = iport->fnic; @@ -717,6 +720,7 @@ int fdls_send_ls_req_abts(struct fnic_iport_s *iport, void fdls_send_tport_abts(struct fnic_iport_s *iport, struct fnic_tport_s *tport) + __must_hold(&iport->fnic->fnic_lock) { uint8_t *frame; uint8_t s_id[3]; @@ -760,7 +764,9 @@ fdls_send_tport_abts(struct fnic_iport_s *iport, /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */ fdls_start_tport_timer(iport, tport, 2 * iport->e_d_tov); } + static void fdls_send_fabric_abts(struct fnic_iport_s *iport) + __must_hold(&iport->fnic->fnic_lock) { uint8_t *frame; uint8_t s_id[3]; @@ -932,6 +938,7 @@ static void fdls_send_fdmi_abts(struct fnic_iport_s *iport) } static void fdls_send_fabric_flogi(struct fnic_iport_s *iport) + __must_hold(&iport->fnic->fnic_lock) { uint8_t *frame; struct fc_std_flogi *pflogi; @@ -992,6 +999,7 @@ static void fdls_send_fabric_flogi(struct fnic_iport_s *iport) } static void fdls_send_fabric_plogi(struct fnic_iport_s *iport) + __must_hold(&iport->fnic->fnic_lock) { uint8_t *frame; struct fc_std_flogi *pplogi; @@ -1084,6 +1092,7 @@ static void fdls_send_fdmi_plogi(struct fnic_iport_s *iport) } static void fdls_send_rpn_id(struct fnic_iport_s *iport) + __must_hold(&iport->fnic->fnic_lock) { uint8_t *frame; struct fc_std_rpn_id *prpn_id; @@ -1143,6 +1152,7 @@ static void fdls_send_rpn_id(struct fnic_iport_s *iport) } static void fdls_send_scr(struct fnic_iport_s *iport) + __must_hold(&iport->fnic->fnic_lock) { uint8_t *frame; struct fc_std_scr *pscr; @@ -1198,6 +1208,7 @@ static void fdls_send_scr(struct fnic_iport_s *iport) } static void fdls_send_gpn_ft(struct fnic_iport_s *iport, int fdls_state) + __must_hold(&iport->fnic->fnic_lock) { uint8_t *frame; struct fc_std_gpn_ft *pgpn_ft; @@ -1257,6 +1268,7 @@ static void fdls_send_gpn_ft(struct fnic_iport_s *iport, int fdls_state) static void fdls_send_tgt_adisc(struct fnic_iport_s *iport, struct fnic_tport_s *tport) + __must_hold(&iport->fnic->fnic_lock) { uint8_t *frame; struct fc_std_els_adisc *padisc; @@ -1322,6 +1334,7 @@ fdls_send_tgt_adisc(struct fnic_iport_s *iport, struct fnic_tport_s *tport) } bool fdls_delete_tport(struct fnic_iport_s *iport, struct fnic_tport_s *tport) + __must_hold(&iport->fnic->fnic_lock) { struct fnic_tport_event_s *tport_del_evt; struct fnic *fnic = iport->fnic; @@ -1387,6 +1400,7 @@ bool fdls_delete_tport(struct fnic_iport_s *iport, struct fnic_tport_s *tport) static void fdls_send_tgt_plogi(struct fnic_iport_s *iport, struct fnic_tport_s *tport) + __must_hold(&iport->fnic->fnic_lock) { uint8_t *frame; struct fc_std_flogi *pplogi; @@ -1455,6 +1469,7 @@ fnic_fc_plogi_rsp_rdf(struct fnic_iport_s *iport, } static void fdls_send_register_fc4_types(struct fnic_iport_s *iport) + __must_hold(&iport->fnic->fnic_lock) { uint8_t *frame; struct fc_std_rft_id *prft_id; @@ -1522,6 +1537,7 @@ static void fdls_send_register_fc4_types(struct fnic_iport_s *iport) } static void fdls_send_register_fc4_features(struct fnic_iport_s *iport) + __must_hold(&iport->fnic->fnic_lock) { uint8_t *frame; struct fc_std_rff_id *prff_id; @@ -1581,6 +1597,7 @@ static void fdls_send_register_fc4_features(struct fnic_iport_s *iport) static void fdls_send_tgt_prli(struct fnic_iport_s *iport, struct fnic_tport_s *tport) + __must_hold(&iport->fnic->fnic_lock) { uint8_t *frame; struct fc_std_els_prli *pprli; @@ -1662,6 +1679,7 @@ fdls_send_tgt_prli(struct fnic_iport_s *iport, struct fnic_tport_s *tport) * Currently this assumes to be called with fnic lock held. */ void fdls_send_fabric_logo(struct fnic_iport_s *iport) + __must_hold(&iport->fnic->fnic_lock) { uint8_t *frame; struct fc_std_logo *plogo; @@ -1761,6 +1779,7 @@ void fdls_tgt_logout(struct fnic_iport_s *iport, struct fnic_tport_s *tport) } static void fdls_tgt_discovery_start(struct fnic_iport_s *iport) + __must_hold(&iport->fnic->fnic_lock) { struct fnic_tport_s *tport, *next; u32 old_link_down_cnt = iport->fnic->link_down_cnt; @@ -1811,6 +1830,7 @@ static void fdls_tgt_discovery_start(struct fnic_iport_s *iport) * pointing to it will be freed later */ static void fdls_target_restart_nexus(struct fnic_tport_s *tport) + __must_hold(&((struct fnic_iport_s *)tport->iport)->fnic->fnic_lock) { struct fnic_iport_s *iport = tport->iport; struct fnic_tport_s *new_tport = NULL; @@ -2617,6 +2637,7 @@ static void fdls_tport_timer_callback(struct timer_list *t) } static void fnic_fdls_start_flogi(struct fnic_iport_s *iport) + __must_hold(&iport->fnic->fnic_lock) { iport->fabric.retry_counter = 0; fdls_send_fabric_flogi(iport); @@ -2625,6 +2646,7 @@ static void fnic_fdls_start_flogi(struct fnic_iport_s *iport) } static void fnic_fdls_start_plogi(struct fnic_iport_s *iport) + __must_hold(&iport->fnic->fnic_lock) { iport->fabric.retry_counter = 0; fdls_send_fabric_plogi(iport); @@ -2643,6 +2665,7 @@ static void fnic_fdls_start_plogi(struct fnic_iport_s *iport) static void fdls_process_tgt_adisc_rsp(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) + __must_hold(&iport->fnic->fnic_lock) { uint32_t tgt_fcid; struct fnic_tport_s *tport; @@ -2733,6 +2756,7 @@ fdls_process_tgt_adisc_rsp(struct fnic_iport_s *iport, static void fdls_process_tgt_plogi_rsp(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) + __must_hold(&iport->fnic->fnic_lock) { uint32_t tgt_fcid; struct fnic_tport_s *tport; @@ -2767,6 +2791,8 @@ fdls_process_tgt_plogi_rsp(struct fnic_iport_s *iport, if (tport->state != FDLS_TGT_STATE_PLOGI) { FNIC_FCS_DBG(KERN_INFO, fnic, "PLOGI rsp recvd in wrong state. Drop the frame and restart nexus"); + /* Tell the compiler that tport->iport == iport. */ + __assume_ctx_lock(&((struct fnic_iport_s *)tport->iport)->fnic->fnic_lock); fdls_target_restart_nexus(tport); return; } @@ -2854,9 +2880,11 @@ fdls_process_tgt_plogi_rsp(struct fnic_iport_s *iport, fdls_set_tport_state(tport, FDLS_TGT_STATE_PRLI); fdls_send_tgt_prli(iport, tport); } + static void fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) + __must_hold(&iport->fnic->fnic_lock) { uint32_t tgt_fcid; struct fnic_tport_s *tport; @@ -2893,6 +2921,8 @@ fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport, if (tport->state != FDLS_TGT_STATE_PRLI) { FNIC_FCS_DBG(KERN_INFO, fnic, "PRLI rsp recvd in wrong state. Drop frame. Restarting nexus"); + /* Tell the compiler that tport->iport == iport. */ + __assume_ctx_lock(&((struct fnic_iport_s *)tport->iport)->fnic->fnic_lock); fdls_target_restart_nexus(tport); return; } @@ -3025,6 +3055,7 @@ fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport, static void fdls_process_rff_id_rsp(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) + __must_hold(&iport->fnic->fnic_lock) { struct fnic *fnic = iport->fnic; struct fnic_fdls_fabric_s *fdls = &iport->fabric; @@ -3098,6 +3129,7 @@ fdls_process_rff_id_rsp(struct fnic_iport_s *iport, static void fdls_process_rft_id_rsp(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) + __must_hold(&iport->fnic->fnic_lock) { struct fnic_fdls_fabric_s *fdls = &iport->fabric; struct fc_std_rft_id *rft_rsp = (struct fc_std_rft_id *) fchdr; @@ -3173,6 +3205,7 @@ fdls_process_rft_id_rsp(struct fnic_iport_s *iport, static void fdls_process_rpn_id_rsp(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) + __must_hold(&iport->fnic->fnic_lock) { struct fnic_fdls_fabric_s *fdls = &iport->fabric; struct fc_std_rpn_id *rpn_rsp = (struct fc_std_rpn_id *) fchdr; @@ -3243,6 +3276,7 @@ fdls_process_rpn_id_rsp(struct fnic_iport_s *iport, static void fdls_process_scr_rsp(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) + __must_hold(&iport->fnic->fnic_lock) { struct fnic_fdls_fabric_s *fdls = &iport->fabric; struct fc_std_scr *scr_rsp = (struct fc_std_scr *) fchdr; @@ -3315,6 +3349,7 @@ fdls_process_scr_rsp(struct fnic_iport_s *iport, static void fdls_process_gpn_ft_tgt_list(struct fnic_iport_s *iport, struct fc_frame_header *fchdr, int len) + __must_hold(&iport->fnic->fnic_lock) { struct fc_gpn_ft_rsp_iu *gpn_ft_tgt; struct fnic_tport_s *tport, *next; @@ -3413,6 +3448,7 @@ fdls_process_gpn_ft_tgt_list(struct fnic_iport_s *iport, static void fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, struct fc_frame_header *fchdr, int len) + __must_hold(&iport->fnic->fnic_lock) { struct fnic_fdls_fabric_s *fdls = &iport->fabric; struct fc_std_gpn_ft *gpn_ft_rsp = (struct fc_std_gpn_ft *) fchdr; @@ -3549,6 +3585,7 @@ fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport, static void fdls_process_fabric_logo_rsp(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) + __must_hold(&iport->fnic->fnic_lock) { struct fc_std_flogi *flogo_rsp = (struct fc_std_flogi *) fchdr; struct fnic_fdls_fabric_s *fdls = &iport->fabric; @@ -3602,6 +3639,7 @@ fdls_process_fabric_logo_rsp(struct fnic_iport_s *iport, static void fdls_process_flogi_rsp(struct fnic_iport_s *iport, struct fc_frame_header *fchdr, void *rx_frame) + __must_hold(&iport->fnic->fnic_lock) { struct fnic_fdls_fabric_s *fabric = &iport->fabric; struct fc_std_flogi *flogi_rsp = (struct fc_std_flogi *) fchdr; @@ -3741,6 +3779,7 @@ fdls_process_flogi_rsp(struct fnic_iport_s *iport, static void fdls_process_fabric_plogi_rsp(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) + __must_hold(&iport->fnic->fnic_lock) { struct fc_std_flogi *plogi_rsp = (struct fc_std_flogi *) fchdr; struct fc_std_els_rjt_rsp *els_rjt = (struct fc_std_els_rjt_rsp *) fchdr; @@ -4002,6 +4041,7 @@ static void fdls_process_fdmi_abts_rsp(struct fnic_iport_s *iport, static void fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) + __must_hold(&iport->fnic->fnic_lock) { uint32_t s_id; struct fc_std_abts_ba_acc *ba_acc = (struct fc_std_abts_ba_acc *)fchdr; @@ -4359,6 +4399,7 @@ fdls_process_els_req(struct fnic_iport_s *iport, struct fc_frame_header *fchdr, static void fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) + __must_hold(&iport->fnic->fnic_lock) { uint32_t s_id; struct fnic_tport_s *tport; @@ -4548,6 +4589,7 @@ fdls_process_plogi_req(struct fnic_iport_s *iport, static void fdls_process_logo_req(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) + __must_hold(&iport->fnic->fnic_lock) { struct fc_std_logo *logo = (struct fc_std_logo *)fchdr; uint32_t nport_id; @@ -4588,6 +4630,8 @@ fdls_process_logo_req(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) FNIC_FCS_DBG(KERN_ERR, fnic, "tport fcid 0x%x: Canceling disc timer\n", tport->fcid); + /* Tell the compiler that tport->iport == iport. */ + __assume_ctx_lock(&((struct fnic_iport_s *)tport->iport)->fnic->fnic_lock); fnic_del_tport_timer_sync(fnic, tport); tport->timer_pending = 0; } @@ -4625,6 +4669,7 @@ fdls_process_logo_req(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) static void fdls_process_rscn(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) + __must_hold(&iport->fnic->fnic_lock) { struct fc_std_rscn *rscn; struct fc_els_rscn_page *rscn_port = NULL; @@ -4758,6 +4803,7 @@ fdls_process_rscn(struct fnic_iport_s *iport, struct fc_frame_header *fchdr) } void fnic_fdls_disc_start(struct fnic_iport_s *iport) + __must_hold(&iport->fnic->fnic_lock) { struct fnic *fnic = iport->fnic; @@ -5102,6 +5148,7 @@ fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport, void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame, int len, int fchdr_offset) + __must_hold(&iport->fnic->fnic_lock) { struct fc_frame_header *fchdr; uint32_t s_id = 0; @@ -5223,6 +5270,7 @@ void fnic_fdls_disc_init(struct fnic_iport_s *iport) } void fnic_fdls_link_down(struct fnic_iport_s *iport) + __must_hold(&iport->fnic->fnic_lock) { struct fnic_tport_s *tport, *next; struct fnic *fnic = iport->fnic; diff --git a/drivers/scsi/fnic/fip.c b/drivers/scsi/fnic/fip.c index 21d08a710f0d..6bca0dd89ee1 100644 --- a/drivers/scsi/fnic/fip.c +++ b/drivers/scsi/fnic/fip.c @@ -602,6 +602,7 @@ void fnic_common_fip_cleanup(struct fnic *fnic) * and clean up and restart the vlan discovery. */ void fnic_fcoe_process_cvl(struct fnic *fnic, struct fip_header *fiph) + __must_hold(&fnic->fnic_lock) { struct fnic_iport_s *iport = &fnic->iport; struct fip_cvl *cvl_msg = (struct fip_cvl *)fiph; @@ -678,6 +679,7 @@ void fnic_fcoe_process_cvl(struct fnic *fnic, struct fip_header *fiph) * @frame: Received ethernet frame */ int fdls_fip_recv_frame(struct fnic *fnic, void *frame) + __must_hold(&fnic->fnic_lock) { struct ethhdr *eth = (struct ethhdr *)frame; struct fip_header *fiph; diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c index b00672ef8b00..d1d860275b60 100644 --- a/drivers/scsi/fnic/fnic_fcs.c +++ b/drivers/scsi/fnic/fnic_fcs.c @@ -944,6 +944,7 @@ void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf) void fnic_fdls_add_tport(struct fnic_iport_s *iport, struct fnic_tport_s *tport, unsigned long flags) + __must_hold(&iport->fnic->fnic_lock) { struct fnic *fnic = iport->fnic; struct fc_rport *rport; @@ -983,6 +984,7 @@ fnic_fdls_add_tport(struct fnic_iport_s *iport, struct fnic_tport_s *tport, void fnic_fdls_remove_tport(struct fnic_iport_s *iport, struct fnic_tport_s *tport, unsigned long flags) + __must_hold(&iport->fnic->fnic_lock) { struct fnic *fnic = iport->fnic; struct rport_dd_data_s *rdd_data; @@ -1032,6 +1034,8 @@ void fnic_delete_fcp_tports(struct fnic *fnic) unsigned long flags; spin_lock_irqsave(&fnic->fnic_lock, flags); + /* Tell the compiler that fnic->iport.fnic == fnic. */ + __assume_ctx_lock(&fnic->iport.fnic->fnic_lock); list_for_each_entry_safe(tport, next, &fnic->iport.tport_list, links) { FNIC_FCS_DBG(KERN_INFO, fnic, "removing fcp rport fcid: 0x%x", tport->fcid); @@ -1059,6 +1063,8 @@ void fnic_tport_event_handler(struct work_struct *work) struct fnic_tport_s *tport; spin_lock_irqsave(&fnic->fnic_lock, flags); + /* Tell the compiler that fnic->iport.fnic == fnic. */ + __assume_ctx_lock(&fnic->iport.fnic->fnic_lock); list_for_each_entry_safe(cur_evt, next, &fnic->tport_event_list, links) { tport = cur_evt->arg1; switch (cur_evt->event) { diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index 9607684bc610..afd6bf03b02d 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -2641,6 +2641,8 @@ int fnic_device_reset(struct scsi_cmnd *sc) * allocated by mid layer. */ mutex_lock(&fnic->sgreset_mutex); + /* Fake __release() to keep the lock context analyzer happy. */ + __release(&fnic->sgreset_mutex); mqtag = fnic->fnic_max_tag_id; new_sc = 1; } else { @@ -2826,6 +2828,8 @@ int fnic_device_reset(struct scsi_cmnd *sc) if (new_sc) { fnic->sgreset_sc = NULL; + /* Fake __acquire() to keep the lock context analyzer happy. */ + __acquire(&fnic->sgreset_mutex); mutex_unlock(&fnic->sgreset_mutex); }