Skip to content

Commit

Permalink
fjes: fix memleaks in fjes_hw_setup
Browse files Browse the repository at this point in the history
In fjes_hw_setup, it allocates several memory and delay the deallocation
to the fjes_hw_exit in fjes_probe through the following call chain:

fjes_probe
  |-> fjes_hw_init
        |-> fjes_hw_setup
  |-> fjes_hw_exit

However, when fjes_hw_setup fails, fjes_hw_exit won't be called and thus
all the resources allocated in fjes_hw_setup will be leaked. In this
patch, we free those resources in fjes_hw_setup and prevents such leaks.

Fixes: 2fcbca6 ("fjes: platform_driver's .probe and .remove routine")
Signed-off-by: Zhipeng Lu <alexious@zju.edu.cn>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://lore.kernel.org/r/20240122172445.3841883-1-alexious@zju.edu.cn
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Zhipeng Lu authored and Jakub Kicinski committed Jan 25, 2024
1 parent 77be224 commit f6cc4b6
Showing 1 changed file with 30 additions and 7 deletions.
37 changes: 30 additions & 7 deletions drivers/net/fjes/fjes_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,21 +221,25 @@ static int fjes_hw_setup(struct fjes_hw *hw)

mem_size = FJES_DEV_REQ_BUF_SIZE(hw->max_epid);
hw->hw_info.req_buf = kzalloc(mem_size, GFP_KERNEL);
if (!(hw->hw_info.req_buf))
return -ENOMEM;
if (!(hw->hw_info.req_buf)) {
result = -ENOMEM;
goto free_ep_info;
}

hw->hw_info.req_buf_size = mem_size;

mem_size = FJES_DEV_RES_BUF_SIZE(hw->max_epid);
hw->hw_info.res_buf = kzalloc(mem_size, GFP_KERNEL);
if (!(hw->hw_info.res_buf))
return -ENOMEM;
if (!(hw->hw_info.res_buf)) {
result = -ENOMEM;
goto free_req_buf;
}

hw->hw_info.res_buf_size = mem_size;

result = fjes_hw_alloc_shared_status_region(hw);
if (result)
return result;
goto free_res_buf;

hw->hw_info.buffer_share_bit = 0;
hw->hw_info.buffer_unshare_reserve_bit = 0;
Expand All @@ -246,11 +250,11 @@ static int fjes_hw_setup(struct fjes_hw *hw)

result = fjes_hw_alloc_epbuf(&buf_pair->tx);
if (result)
return result;
goto free_epbuf;

result = fjes_hw_alloc_epbuf(&buf_pair->rx);
if (result)
return result;
goto free_epbuf;

spin_lock_irqsave(&hw->rx_status_lock, flags);
fjes_hw_setup_epbuf(&buf_pair->tx, mac,
Expand All @@ -273,6 +277,25 @@ static int fjes_hw_setup(struct fjes_hw *hw)
fjes_hw_init_command_registers(hw, &param);

return 0;

free_epbuf:
for (epidx = 0; epidx < hw->max_epid ; epidx++) {
if (epidx == hw->my_epid)
continue;
fjes_hw_free_epbuf(&hw->ep_shm_info[epidx].tx);
fjes_hw_free_epbuf(&hw->ep_shm_info[epidx].rx);
}
fjes_hw_free_shared_status_region(hw);
free_res_buf:
kfree(hw->hw_info.res_buf);
hw->hw_info.res_buf = NULL;
free_req_buf:
kfree(hw->hw_info.req_buf);
hw->hw_info.req_buf = NULL;
free_ep_info:
kfree(hw->ep_shm_info);
hw->ep_shm_info = NULL;
return result;
}

static void fjes_hw_cleanup(struct fjes_hw *hw)
Expand Down

0 comments on commit f6cc4b6

Please sign in to comment.