Commit 8719a1c3 authored by Gustavo A. R. Silva's avatar Gustavo A. R. Silva Committed by David S. Miller
Browse files

bna: Avoid clashing function prototypes

When built with Control Flow Integrity, function prototypes between
caller and function declaration must match. These mismatches are visible
at compile time with the new -Wcast-function-type-strict in Clang[1].

Fix a total of 227 warnings like these:

drivers/net/ethernet/brocade/bna/bna_enet.c:519:3: warning: cast from 'void (*)(struct bna_ethport *, enum bna_ethport_event)' to 'bfa_fsm_t' (aka 'void (*)(void *, int)') converts to incompatible function type [-Wcast-function-type-strict]
                bfa_fsm_set_state(ethport, bna_ethport_sm_down);
                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The bna state machine code heavily overloads its state machine functions,
so these have been separated into their own sets of structs, enums,
typedefs, and helper functions. There are almost zero binary code changes,
all seem to be related to header file line numbers changing, or the
addition of the new stats helper.

Important to mention is that while I was manually implementing this changes
I was staring at this[2] patch from Kees Cook. Thanks, Kees. :)

Link: https://github.com/KSPP/linux/issues/240
[1] https://reviews.llvm.org/D134831
[2] https://lore.kernel.org/linux-hardening/20220929230334.2109344-1-keescook@chromium.org/


Reviewed-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarGustavo A. R. Silva <gustavoars@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8bd8dcc5
Loading
Loading
Loading
Loading
+38 −22
Original line number Diff line number Diff line
@@ -18,15 +18,43 @@

/* BFA state machine interfaces */

typedef void (*bfa_sm_t)(void *sm, int event);

/* For converting from state machine function to state encoding. */
struct bfa_sm_table {
	bfa_sm_t	sm;	/*!< state machine function	*/
	int		state;	/*!< state machine encoding	*/
	char		*name;	/*!< state name for display	*/
};
#define BFA_SM(_sm)		((bfa_sm_t)(_sm))
#define BFA_SM_TABLE(n, s, e, t)				\
struct s;							\
enum e;								\
typedef void (*t)(struct s *, enum e);				\
								\
struct n ## _sm_table_s {					\
	t		sm;	/* state machine function */	\
	int		state;	/* state machine encoding */	\
	char		*name;	/* state name for display */	\
};								\
								\
static inline int						\
n ## _sm_to_state(struct n ## _sm_table_s *smt, t sm)		\
{								\
	int	i = 0;						\
								\
	while (smt[i].sm && smt[i].sm != sm)			\
		i++;						\
	return smt[i].state;					\
}

BFA_SM_TABLE(iocpf,	bfa_iocpf,	iocpf_event,	bfa_fsm_iocpf_t)
BFA_SM_TABLE(ioc,	bfa_ioc,	ioc_event,	bfa_fsm_ioc_t)
BFA_SM_TABLE(cmdq,	bfa_msgq_cmdq,	cmdq_event,	bfa_fsm_msgq_cmdq_t)
BFA_SM_TABLE(rspq,	bfa_msgq_rspq,	rspq_event,	bfa_fsm_msgq_rspq_t)

BFA_SM_TABLE(ioceth,	bna_ioceth,	bna_ioceth_event, bna_fsm_ioceth_t)
BFA_SM_TABLE(enet,	bna_enet,	bna_enet_event, bna_fsm_enet_t)
BFA_SM_TABLE(ethport,	bna_ethport,	bna_ethport_event, bna_fsm_ethport_t)
BFA_SM_TABLE(tx,	bna_tx,		bna_tx_event,	bna_fsm_tx_t)
BFA_SM_TABLE(rxf,	bna_rxf,	bna_rxf_event, bna_fsm_rxf_t)
BFA_SM_TABLE(rx,	bna_rx,		bna_rx_event,	bna_fsm_rx_t)

#undef BFA_SM_TABLE

#define BFA_SM(_sm)	(_sm)

/* State machine with entry actions. */
typedef void (*bfa_fsm_t)(void *fsm, int event);
@@ -41,24 +69,12 @@ typedef void (*bfa_fsm_t)(void *fsm, int event);
	static void oc ## _sm_ ## st ## _entry(otype * fsm)

#define bfa_fsm_set_state(_fsm, _state) do {				\
	(_fsm)->fsm = (bfa_fsm_t)(_state);				\
	(_fsm)->fsm = (_state);						\
	_state ## _entry(_fsm);						\
} while (0)

#define bfa_fsm_send_event(_fsm, _event)	((_fsm)->fsm((_fsm), (_event)))
#define bfa_fsm_cmp_state(_fsm, _state)					\
	((_fsm)->fsm == (bfa_fsm_t)(_state))

static inline int
bfa_sm_to_state(const struct bfa_sm_table *smt, bfa_sm_t sm)
{
	int	i = 0;

	while (smt[i].sm && smt[i].sm != sm)
		i++;
	return smt[i].state;
}

#define bfa_fsm_cmp_state(_fsm, _state)		((_fsm)->fsm == (_state))
/* Generic wait counter. */

typedef void (*bfa_wc_resume_t) (void *cbarg);
+5 −5
Original line number Diff line number Diff line
@@ -114,7 +114,7 @@ bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc, enum ioc_event);

static struct bfa_sm_table ioc_sm_table[] = {
static struct ioc_sm_table_s ioc_sm_table[] = {
	{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
	{BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
	{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
@@ -183,7 +183,7 @@ bfa_fsm_state_decl(bfa_iocpf, disabling_sync, struct bfa_iocpf,
						enum iocpf_event);
bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf, enum iocpf_event);

static struct bfa_sm_table iocpf_sm_table[] = {
static struct iocpf_sm_table_s iocpf_sm_table[] = {
	{BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},
	{BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},
	{BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},
@@ -2860,12 +2860,12 @@ static enum bfa_ioc_state
bfa_ioc_get_state(struct bfa_ioc *ioc)
{
	enum bfa_iocpf_state iocpf_st;
	enum bfa_ioc_state ioc_st = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
	enum bfa_ioc_state ioc_st = ioc_sm_to_state(ioc_sm_table, ioc->fsm);

	if (ioc_st == BFA_IOC_ENABLING ||
		ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {

		iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
		iocpf_st = iocpf_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);

		switch (iocpf_st) {
		case BFA_IOCPF_SEMWAIT:
@@ -2983,7 +2983,7 @@ bfa_nw_iocpf_timeout(struct bfa_ioc *ioc)
{
	enum bfa_iocpf_state iocpf_st;

	iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
	iocpf_st = iocpf_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);

	if (iocpf_st == BFA_IOCPF_HWINIT)
		bfa_ioc_poll_fwinit(ioc);
+6 −2
Original line number Diff line number Diff line
@@ -147,16 +147,20 @@ struct bfa_ioc_notify {
	(__notify)->cbarg = (__cbarg);				\
} while (0)

enum iocpf_event;

struct bfa_iocpf {
	bfa_fsm_t		fsm;
	void (*fsm)(struct bfa_iocpf *s, enum iocpf_event e);
	struct bfa_ioc		*ioc;
	bool			fw_mismatch_notified;
	bool			auto_recover;
	u32			poll_time;
};

enum ioc_event;

struct bfa_ioc {
	bfa_fsm_t		fsm;
	void (*fsm)(struct bfa_ioc *s, enum ioc_event e);
	struct bfa		*bfa;
	struct bfa_pcidev	pcidev;
	struct timer_list	ioc_timer;
+6 −2
Original line number Diff line number Diff line
@@ -55,8 +55,10 @@ enum bfa_msgq_cmdq_flags {
	BFA_MSGQ_CMDQ_F_DB_UPDATE	= 1,
};

enum cmdq_event;

struct bfa_msgq_cmdq {
	bfa_fsm_t			fsm;
	void (*fsm)(struct bfa_msgq_cmdq *s, enum cmdq_event e);
	enum bfa_msgq_cmdq_flags flags;

	u16			producer_index;
@@ -81,8 +83,10 @@ enum bfa_msgq_rspq_flags {

typedef void (*bfa_msgq_mcfunc_t)(void *cbarg, struct bfi_msgq_mhdr *mhdr);

enum rspq_event;

struct bfa_msgq_rspq {
	bfa_fsm_t			fsm;
	void (*fsm)(struct bfa_msgq_rspq *s, enum rspq_event e);
	enum bfa_msgq_rspq_flags flags;

	u16			producer_index;
+3 −3
Original line number Diff line number Diff line
@@ -1257,7 +1257,7 @@ bna_enet_mtu_get(struct bna_enet *enet)
void
bna_enet_enable(struct bna_enet *enet)
{
	if (enet->fsm != (bfa_sm_t)bna_enet_sm_stopped)
	if (enet->fsm != bna_enet_sm_stopped)
		return;

	enet->flags |= BNA_ENET_F_ENABLED;
@@ -1751,12 +1751,12 @@ bna_ioceth_uninit(struct bna_ioceth *ioceth)
void
bna_ioceth_enable(struct bna_ioceth *ioceth)
{
	if (ioceth->fsm == (bfa_fsm_t)bna_ioceth_sm_ready) {
	if (ioceth->fsm == bna_ioceth_sm_ready) {
		bnad_cb_ioceth_ready(ioceth->bna->bnad);
		return;
	}

	if (ioceth->fsm == (bfa_fsm_t)bna_ioceth_sm_stopped)
	if (ioceth->fsm == bna_ioceth_sm_stopped)
		bfa_fsm_send_event(ioceth, IOCETH_E_ENABLE);
}

Loading