Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b8415da authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Sasha Levin
Browse files

scsi: bfa: Fix function pointer type mismatch for hcb_qe->cbfn



[ Upstream commit b69600231f751304db914c63b937f7098ed2895c ]

Some callback functions used here take a boolean argument, others take a
status argument. This breaks KCFI type checking, so clang now warns about
the function pointer cast:

drivers/scsi/bfa/bfad_bsg.c:2138:29: error: cast from 'void (*)(void *, enum bfa_status)' to 'bfa_cb_cbfn_t' (aka 'void (*)(void *, enum bfa_boolean)') converts to incompatible function type [-Werror,-Wcast-function-type-strict]

Assuming the code is actually correct here and the callers always match the
argument types of the callee, rework this to replace the explicit cast with
a union of the two pointer types. This does not change the behavior of the
code, so if something is actually broken here, a larger rework may be
necessary.

Fixes: 37ea0558 ("[SCSI] bfa: Added support to collect and reset fcport stats")
Fixes: 3ec4f2c8 ("[SCSI] bfa: Added support to configure QOS and collect stats.")
Reviewed-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/r/20240222124433.2046570-1-arnd@kernel.org


Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 2b38dbd7
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@
struct bfa_s;

typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
typedef void (*bfa_cb_cbfn_status_t) (void *cbarg, bfa_status_t status);

/*
 * Interrupt message handlers
@@ -437,4 +436,12 @@ struct bfa_cb_pending_q_s {
	(__qe)->data = (__data);				\
} while (0)

#define bfa_pending_q_init_status(__qe, __cbfn, __cbarg, __data) do {	\
	bfa_q_qe_init(&((__qe)->hcb_qe.qe));			\
	(__qe)->hcb_qe.cbfn_status = (__cbfn);			\
	(__qe)->hcb_qe.cbarg = (__cbarg);			\
	(__qe)->hcb_qe.pre_rmv = BFA_TRUE;			\
	(__qe)->data = (__data);				\
} while (0)

#endif /* __BFA_H__ */
+1 −3
Original line number Diff line number Diff line
@@ -1907,15 +1907,13 @@ bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q)
	struct list_head		*qe;
	struct list_head		*qen;
	struct bfa_cb_qe_s	*hcb_qe;
	bfa_cb_cbfn_status_t	cbfn;

	list_for_each_safe(qe, qen, comp_q) {
		hcb_qe = (struct bfa_cb_qe_s *) qe;
		if (hcb_qe->pre_rmv) {
			/* qe is invalid after return, dequeue before cbfn() */
			list_del(qe);
			cbfn = (bfa_cb_cbfn_status_t)(hcb_qe->cbfn);
			cbfn(hcb_qe->cbarg, hcb_qe->fw_status);
			hcb_qe->cbfn_status(hcb_qe->cbarg, hcb_qe->fw_status);
		} else
			hcb_qe->cbfn(hcb_qe->cbarg, BFA_TRUE);
	}
+6 −2
Original line number Diff line number Diff line
@@ -362,13 +362,17 @@ struct bfa_reqq_wait_s {
};

typedef void (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
typedef void (*bfa_cb_cbfn_status_t) (void *cbarg, bfa_status_t status);

/*
 * Generic BFA callback element.
 */
struct bfa_cb_qe_s {
	struct list_head	qe;
	union {
		bfa_cb_cbfn_status_t	cbfn_status;
		bfa_cb_cbfn_t		cbfn;
	};
	bfa_boolean_t	once;
	bfa_boolean_t	pre_rmv;	/* set for stack based qe(s) */
	bfa_status_t	fw_status;	/* to access fw status in comp proc */
+4 −7
Original line number Diff line number Diff line
@@ -2135,8 +2135,7 @@ bfad_iocmd_fcport_get_stats(struct bfad_s *bfad, void *cmd)
	struct bfa_cb_pending_q_s cb_qe;

	init_completion(&fcomp.comp);
	bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
			   &fcomp, &iocmd->stats);
	bfa_pending_q_init_status(&cb_qe, bfad_hcb_comp, &fcomp, &iocmd->stats);
	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_fcport_get_stats(&bfad->bfa, &cb_qe);
	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -2159,7 +2158,7 @@ bfad_iocmd_fcport_reset_stats(struct bfad_s *bfad, void *cmd)
	struct bfa_cb_pending_q_s cb_qe;

	init_completion(&fcomp.comp);
	bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp, &fcomp, NULL);
	bfa_pending_q_init_status(&cb_qe, bfad_hcb_comp, &fcomp, NULL);

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	iocmd->status = bfa_fcport_clear_stats(&bfad->bfa, &cb_qe);
@@ -2443,8 +2442,7 @@ bfad_iocmd_qos_get_stats(struct bfad_s *bfad, void *cmd)
	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);

	init_completion(&fcomp.comp);
	bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
			   &fcomp, &iocmd->stats);
	bfa_pending_q_init_status(&cb_qe, bfad_hcb_comp, &fcomp, &iocmd->stats);

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc));
@@ -2474,8 +2472,7 @@ bfad_iocmd_qos_reset_stats(struct bfad_s *bfad, void *cmd)
	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);

	init_completion(&fcomp.comp);
	bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
			   &fcomp, NULL);
	bfa_pending_q_init_status(&cb_qe, bfad_hcb_comp, &fcomp, NULL);

	spin_lock_irqsave(&bfad->bfad_lock, flags);
	WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc));