drivers: can: add user_data to state change callback
Add optional user data argument to can_set_state_change_callback() to comply with Zephyr API design guidelines. Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
parent
3457118540
commit
e919db3222
13 changed files with 59 additions and 25 deletions
|
@ -236,10 +236,12 @@ int can_loopback_recover(const struct device *dev, k_timeout_t timeout)
|
||||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||||
|
|
||||||
static void can_loopback_set_state_change_callback(const struct device *dev,
|
static void can_loopback_set_state_change_callback(const struct device *dev,
|
||||||
can_state_change_callback_t cb)
|
can_state_change_callback_t cb,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
ARG_UNUSED(dev);
|
ARG_UNUSED(dev);
|
||||||
ARG_UNUSED(cb);
|
ARG_UNUSED(cb);
|
||||||
|
ARG_UNUSED(user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int can_loopback_get_core_clock(const struct device *dev, uint32_t *rate)
|
int can_loopback_get_core_clock(const struct device *dev, uint32_t *rate)
|
||||||
|
|
|
@ -461,11 +461,12 @@ static void can_mcan_state_change_handler(const struct can_mcan_config *cfg,
|
||||||
enum can_state state;
|
enum can_state state;
|
||||||
struct can_bus_err_cnt err_cnt;
|
struct can_bus_err_cnt err_cnt;
|
||||||
const can_state_change_callback_t cb = data->state_change_cb;
|
const can_state_change_callback_t cb = data->state_change_cb;
|
||||||
|
void *cb_data = data->state_change_cb_data;
|
||||||
|
|
||||||
state = can_mcan_get_state(cfg, &err_cnt);
|
state = can_mcan_get_state(cfg, &err_cnt);
|
||||||
|
|
||||||
if (cb != NULL) {
|
if (cb != NULL) {
|
||||||
cb(state, err_cnt);
|
cb(state, err_cnt, cb_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,7 @@ struct can_mcan_data {
|
||||||
void *cb_arg_std[NUM_STD_FILTER_DATA];
|
void *cb_arg_std[NUM_STD_FILTER_DATA];
|
||||||
void *cb_arg_ext[NUM_EXT_FILTER_DATA];
|
void *cb_arg_ext[NUM_EXT_FILTER_DATA];
|
||||||
can_state_change_callback_t state_change_cb;
|
can_state_change_callback_t state_change_cb;
|
||||||
|
void *state_change_cb_data;
|
||||||
uint32_t std_filt_rtr;
|
uint32_t std_filt_rtr;
|
||||||
uint32_t std_filt_rtr_mask;
|
uint32_t std_filt_rtr_mask;
|
||||||
uint8_t ext_filt_rtr;
|
uint8_t ext_filt_rtr;
|
||||||
|
|
|
@ -563,11 +563,13 @@ static void mcp2515_remove_rx_filter(const struct device *dev, int filter_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mcp2515_set_state_change_callback(const struct device *dev,
|
static void mcp2515_set_state_change_callback(const struct device *dev,
|
||||||
can_state_change_callback_t cb)
|
can_state_change_callback_t cb,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct mcp2515_data *dev_data = DEV_DATA(dev);
|
struct mcp2515_data *dev_data = DEV_DATA(dev);
|
||||||
|
|
||||||
dev_data->state_change_cb = cb;
|
dev_data->state_change_cb = cb;
|
||||||
|
dev_data->state_change_cb_data = user_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mcp2515_rx_filter(const struct device *dev,
|
static void mcp2515_rx_filter(const struct device *dev,
|
||||||
|
@ -673,6 +675,7 @@ static void mcp2515_handle_errors(const struct device *dev)
|
||||||
{
|
{
|
||||||
struct mcp2515_data *dev_data = DEV_DATA(dev);
|
struct mcp2515_data *dev_data = DEV_DATA(dev);
|
||||||
can_state_change_callback_t state_change_cb = dev_data->state_change_cb;
|
can_state_change_callback_t state_change_cb = dev_data->state_change_cb;
|
||||||
|
void *state_change_cb_data = dev_data->state_change_cb_data;
|
||||||
enum can_state state;
|
enum can_state state;
|
||||||
struct can_bus_err_cnt err_cnt;
|
struct can_bus_err_cnt err_cnt;
|
||||||
|
|
||||||
|
@ -680,7 +683,7 @@ static void mcp2515_handle_errors(const struct device *dev)
|
||||||
|
|
||||||
if (state_change_cb && dev_data->old_state != state) {
|
if (state_change_cb && dev_data->old_state != state) {
|
||||||
dev_data->old_state = state;
|
dev_data->old_state = state;
|
||||||
state_change_cb(state, err_cnt);
|
state_change_cb(state, err_cnt, state_change_cb_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ struct mcp2515_data {
|
||||||
void *cb_arg[CONFIG_CAN_MAX_FILTER];
|
void *cb_arg[CONFIG_CAN_MAX_FILTER];
|
||||||
struct zcan_filter filter[CONFIG_CAN_MAX_FILTER];
|
struct zcan_filter filter[CONFIG_CAN_MAX_FILTER];
|
||||||
can_state_change_callback_t state_change_cb;
|
can_state_change_callback_t state_change_cb;
|
||||||
|
void *state_change_cb_data;
|
||||||
|
|
||||||
/* general data */
|
/* general data */
|
||||||
struct k_mutex mutex;
|
struct k_mutex mutex;
|
||||||
|
|
|
@ -117,6 +117,7 @@ struct mcux_flexcan_data {
|
||||||
struct mcux_flexcan_tx_callback tx_cbs[MCUX_FLEXCAN_MAX_TX];
|
struct mcux_flexcan_tx_callback tx_cbs[MCUX_FLEXCAN_MAX_TX];
|
||||||
enum can_state state;
|
enum can_state state;
|
||||||
can_state_change_callback_t state_change_cb;
|
can_state_change_callback_t state_change_cb;
|
||||||
|
void *state_change_cb_data;
|
||||||
struct can_timing timing;
|
struct can_timing timing;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -423,11 +424,13 @@ static int mcux_flexcan_add_rx_filter(const struct device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mcux_flexcan_set_state_change_callback(const struct device *dev,
|
static void mcux_flexcan_set_state_change_callback(const struct device *dev,
|
||||||
can_state_change_callback_t callback)
|
can_state_change_callback_t callback,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct mcux_flexcan_data *data = dev->data;
|
struct mcux_flexcan_data *data = dev->data;
|
||||||
|
|
||||||
data->state_change_cb = callback;
|
data->state_change_cb = callback;
|
||||||
|
data->state_change_cb_data = user_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum can_state mcux_flexcan_get_state(const struct device *dev,
|
static enum can_state mcux_flexcan_get_state(const struct device *dev,
|
||||||
|
@ -518,6 +521,7 @@ static inline void mcux_flexcan_transfer_error_status(const struct device *dev,
|
||||||
const struct mcux_flexcan_config *config = dev->config;
|
const struct mcux_flexcan_config *config = dev->config;
|
||||||
struct mcux_flexcan_data *data = dev->data;
|
struct mcux_flexcan_data *data = dev->data;
|
||||||
const can_state_change_callback_t cb = data->state_change_cb;
|
const can_state_change_callback_t cb = data->state_change_cb;
|
||||||
|
void *cb_data = data->state_change_cb_data;
|
||||||
|
|
||||||
can_tx_callback_t function;
|
can_tx_callback_t function;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
@ -551,7 +555,7 @@ static inline void mcux_flexcan_transfer_error_status(const struct device *dev,
|
||||||
data->state = state;
|
data->state = state;
|
||||||
|
|
||||||
if (cb) {
|
if (cb) {
|
||||||
cb(state, err_cnt);
|
cb(state, err_cnt, cb_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,11 +81,13 @@ static enum can_state mcux_mcan_get_state(const struct device *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mcux_mcan_set_state_change_callback(const struct device *dev,
|
static void mcux_mcan_set_state_change_callback(const struct device *dev,
|
||||||
can_state_change_callback_t cb)
|
can_state_change_callback_t cb,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct mcux_mcan_data *data = dev->data;
|
struct mcux_mcan_data *data = dev->data;
|
||||||
|
|
||||||
data->mcan.state_change_cb = cb;
|
data->mcan.state_change_cb = cb;
|
||||||
|
data->mcan.state_change_cb_data = user_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mcux_mcan_get_core_clock(const struct device *dev, uint32_t *rate)
|
static int mcux_mcan_get_core_clock(const struct device *dev, uint32_t *rate)
|
||||||
|
|
|
@ -199,6 +199,7 @@ struct can_rcar_data {
|
||||||
void *rx_callback_arg[CONFIG_CAN_RCAR_MAX_FILTER];
|
void *rx_callback_arg[CONFIG_CAN_RCAR_MAX_FILTER];
|
||||||
struct zcan_filter filter[CONFIG_CAN_RCAR_MAX_FILTER];
|
struct zcan_filter filter[CONFIG_CAN_RCAR_MAX_FILTER];
|
||||||
can_state_change_callback_t state_change_cb;
|
can_state_change_callback_t state_change_cb;
|
||||||
|
void *state_change_cb_data;
|
||||||
enum can_state state;
|
enum can_state state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -251,6 +252,7 @@ static void can_rcar_state_change(const struct device *dev, uint32_t newstate)
|
||||||
const struct can_rcar_cfg *config = DEV_CAN_CFG(dev);
|
const struct can_rcar_cfg *config = DEV_CAN_CFG(dev);
|
||||||
struct can_rcar_data *data = DEV_CAN_DATA(dev);
|
struct can_rcar_data *data = DEV_CAN_DATA(dev);
|
||||||
const can_state_change_callback_t cb = data->state_change_cb;
|
const can_state_change_callback_t cb = data->state_change_cb;
|
||||||
|
void *state_change_cb_data = data->state_change_cb_data;
|
||||||
struct can_bus_err_cnt err_cnt;
|
struct can_bus_err_cnt err_cnt;
|
||||||
|
|
||||||
if (data->state == newstate) {
|
if (data->state == newstate) {
|
||||||
|
@ -265,7 +267,7 @@ static void can_rcar_state_change(const struct device *dev, uint32_t newstate)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
can_rcar_get_error_count(config, &err_cnt);
|
can_rcar_get_error_count(config, &err_cnt);
|
||||||
cb(newstate, err_cnt);
|
cb(newstate, err_cnt, state_change_cb_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void can_rcar_error(const struct device *dev)
|
static void can_rcar_error(const struct device *dev)
|
||||||
|
@ -657,11 +659,13 @@ unlock:
|
||||||
}
|
}
|
||||||
|
|
||||||
static void can_rcar_set_state_change_callback(const struct device *dev,
|
static void can_rcar_set_state_change_callback(const struct device *dev,
|
||||||
can_state_change_callback_t cb)
|
can_state_change_callback_t cb,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct can_rcar_data *data = DEV_CAN_DATA(dev);
|
struct can_rcar_data *data = DEV_CAN_DATA(dev);
|
||||||
|
|
||||||
data->state_change_cb = cb;
|
data->state_change_cb = cb;
|
||||||
|
data->state_change_cb_data = user_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum can_state can_rcar_get_state(const struct device *dev,
|
static enum can_state can_rcar_get_state(const struct device *dev,
|
||||||
|
@ -862,6 +866,7 @@ static int can_rcar_init(const struct device *dev)
|
||||||
memset(data->rx_callback, 0, sizeof(data->rx_callback));
|
memset(data->rx_callback, 0, sizeof(data->rx_callback));
|
||||||
data->state = CAN_ERROR_ACTIVE;
|
data->state = CAN_ERROR_ACTIVE;
|
||||||
data->state_change_cb = NULL;
|
data->state_change_cb = NULL;
|
||||||
|
data->state_change_cb_data = NULL;
|
||||||
|
|
||||||
/* reset the registers */
|
/* reset the registers */
|
||||||
ret = clock_control_off(config->clock_dev,
|
ret = clock_control_off(config->clock_dev,
|
||||||
|
|
|
@ -123,6 +123,7 @@ static inline void can_stm32_bus_state_change_isr(CAN_TypeDef *can,
|
||||||
struct can_bus_err_cnt err_cnt;
|
struct can_bus_err_cnt err_cnt;
|
||||||
enum can_state state;
|
enum can_state state;
|
||||||
const can_state_change_callback_t cb = data->state_change_cb;
|
const can_state_change_callback_t cb = data->state_change_cb;
|
||||||
|
void *state_change_cb_data = data->state_change_cb_data;
|
||||||
|
|
||||||
if (!(can->ESR & CAN_ESR_EPVF) && !(can->ESR & CAN_ESR_BOFF)) {
|
if (!(can->ESR & CAN_ESR_EPVF) && !(can->ESR & CAN_ESR_BOFF)) {
|
||||||
return;
|
return;
|
||||||
|
@ -140,7 +141,7 @@ static inline void can_stm32_bus_state_change_isr(CAN_TypeDef *can,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cb != NULL) {
|
if (cb != NULL) {
|
||||||
cb(state, err_cnt);
|
cb(state, err_cnt, state_change_cb_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,6 +442,7 @@ static int can_stm32_init(const struct device *dev)
|
||||||
data->mb1.tx_callback = NULL;
|
data->mb1.tx_callback = NULL;
|
||||||
data->mb2.tx_callback = NULL;
|
data->mb2.tx_callback = NULL;
|
||||||
data->state_change_cb = NULL;
|
data->state_change_cb = NULL;
|
||||||
|
data->state_change_cb_data = NULL;
|
||||||
|
|
||||||
data->filter_usage = (1ULL << CAN_MAX_NUMBER_OF_FILTERS) - 1ULL;
|
data->filter_usage = (1ULL << CAN_MAX_NUMBER_OF_FILTERS) - 1ULL;
|
||||||
(void)memset(data->rx_cb, 0, sizeof(data->rx_cb));
|
(void)memset(data->rx_cb, 0, sizeof(data->rx_cb));
|
||||||
|
@ -525,13 +527,15 @@ static int can_stm32_init(const struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void can_stm32_set_state_change_callback(const struct device *dev,
|
static void can_stm32_set_state_change_callback(const struct device *dev,
|
||||||
can_state_change_callback_t cb)
|
can_state_change_callback_t cb,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct can_stm32_data *data = DEV_DATA(dev);
|
struct can_stm32_data *data = DEV_DATA(dev);
|
||||||
const struct can_stm32_config *cfg = DEV_CFG(dev);
|
const struct can_stm32_config *cfg = DEV_CFG(dev);
|
||||||
CAN_TypeDef *can = cfg->can;
|
CAN_TypeDef *can = cfg->can;
|
||||||
|
|
||||||
data->state_change_cb = cb;
|
data->state_change_cb = cb;
|
||||||
|
data->state_change_cb_data = user_data;
|
||||||
|
|
||||||
if (cb == NULL) {
|
if (cb == NULL) {
|
||||||
can->IER &= ~CAN_IER_EPVIE;
|
can->IER &= ~CAN_IER_EPVIE;
|
||||||
|
|
|
@ -65,6 +65,7 @@ struct can_stm32_data {
|
||||||
can_rx_callback_t rx_cb[CONFIG_CAN_MAX_FILTER];
|
can_rx_callback_t rx_cb[CONFIG_CAN_MAX_FILTER];
|
||||||
void *cb_arg[CONFIG_CAN_MAX_FILTER];
|
void *cb_arg[CONFIG_CAN_MAX_FILTER];
|
||||||
can_state_change_callback_t state_change_cb;
|
can_state_change_callback_t state_change_cb;
|
||||||
|
void *state_change_cb_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct can_stm32_config {
|
struct can_stm32_config {
|
||||||
|
|
|
@ -56,11 +56,13 @@ void can_stm32fd_clock_enable(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void can_stm32fd_set_state_change_callback(const struct device *dev,
|
void can_stm32fd_set_state_change_callback(const struct device *dev,
|
||||||
can_state_change_callback_t cb)
|
can_state_change_callback_t cb,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
struct can_stm32fd_data *data = DEV_DATA(dev);
|
struct can_stm32fd_data *data = DEV_DATA(dev);
|
||||||
|
|
||||||
data->mcan_data.state_change_cb = cb;
|
data->mcan_data.state_change_cb = cb;
|
||||||
|
data->mcan_data.state_change_cb_data = user_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int can_stm32fd_init(const struct device *dev)
|
static int can_stm32fd_init(const struct device *dev)
|
||||||
|
|
|
@ -268,7 +268,7 @@ typedef void (*can_tx_callback_t)(int error, void *user_data);
|
||||||
* @brief Defines the application callback handler function signature for receiving.
|
* @brief Defines the application callback handler function signature for receiving.
|
||||||
*
|
*
|
||||||
* @param frame Received frame.
|
* @param frame Received frame.
|
||||||
* @param user_data User data provided when the filter was attached.
|
* @param user_data User data provided when the filter was added.
|
||||||
*/
|
*/
|
||||||
typedef void (*can_rx_callback_t)(struct zcan_frame *frame, void *user_data);
|
typedef void (*can_rx_callback_t)(struct zcan_frame *frame, void *user_data);
|
||||||
|
|
||||||
|
@ -276,10 +276,13 @@ typedef void (*can_rx_callback_t)(struct zcan_frame *frame, void *user_data);
|
||||||
* @typedef can_state_change_callback_t
|
* @typedef can_state_change_callback_t
|
||||||
* @brief Defines the state change callback handler function signature
|
* @brief Defines the state change callback handler function signature
|
||||||
*
|
*
|
||||||
* @param state State of the CAN controller.
|
* @param state State of the CAN controller.
|
||||||
* @param err_cnt CAN controller error counter values.
|
* @param err_cnt CAN controller error counter values.
|
||||||
|
* @param user_data User data provided the callback was set.
|
||||||
*/
|
*/
|
||||||
typedef void (*can_state_change_callback_t)(enum can_state state, struct can_bus_err_cnt err_cnt);
|
typedef void (*can_state_change_callback_t)(enum can_state state,
|
||||||
|
struct can_bus_err_cnt err_cnt,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @cond INTERNAL_HIDDEN
|
* @cond INTERNAL_HIDDEN
|
||||||
|
@ -351,7 +354,8 @@ typedef enum can_state (*can_get_state_t)(const struct device *dev,
|
||||||
* See @a can_set_state_change_callback() for argument description
|
* See @a can_set_state_change_callback() for argument description
|
||||||
*/
|
*/
|
||||||
typedef void(*can_set_state_change_callback_t)(const struct device *dev,
|
typedef void(*can_set_state_change_callback_t)(const struct device *dev,
|
||||||
can_state_change_callback_t callback);
|
can_state_change_callback_t callback,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef can_get_core_clock_t
|
* @typedef can_get_core_clock_t
|
||||||
|
@ -861,15 +865,17 @@ static inline int z_impl_can_recover(const struct device *dev, k_timeout_t timeo
|
||||||
* Only one callback can be registered per controller. Calling this function
|
* Only one callback can be registered per controller. Calling this function
|
||||||
* again overrides any previously registered callback.
|
* again overrides any previously registered callback.
|
||||||
*
|
*
|
||||||
* @param dev Pointer to the device structure for the driver instance.
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
* @param callback Callback function.
|
* @param callback Callback function.
|
||||||
|
* @param user_data User data to pass to callback function.
|
||||||
*/
|
*/
|
||||||
static inline void can_set_state_change_callback(const struct device *dev,
|
static inline void can_set_state_change_callback(const struct device *dev,
|
||||||
can_state_change_callback_t callback)
|
can_state_change_callback_t callback,
|
||||||
|
void *user_data)
|
||||||
{
|
{
|
||||||
const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
|
const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
|
||||||
|
|
||||||
return api->set_state_change_callback(dev, callback);
|
return api->set_state_change_callback(dev, callback, user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
@ -1214,7 +1220,7 @@ __deprecated static inline void can_detach(const struct device *dev, int filter_
|
||||||
__deprecated static inline void can_register_state_change_isr(const struct device *dev,
|
__deprecated static inline void can_register_state_change_isr(const struct device *dev,
|
||||||
can_state_change_callback_t isr)
|
can_state_change_callback_t isr)
|
||||||
{
|
{
|
||||||
can_set_state_change_callback(dev, isr);
|
can_set_state_change_callback(dev, isr, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @endcond */
|
/** @endcond */
|
||||||
|
|
|
@ -165,11 +165,13 @@ void state_change_work_handler(struct k_work *work)
|
||||||
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
|
||||||
}
|
}
|
||||||
|
|
||||||
void state_change_callback(enum can_state state, struct can_bus_err_cnt err_cnt)
|
void state_change_callback(enum can_state state, struct can_bus_err_cnt err_cnt, void *user_data)
|
||||||
{
|
{
|
||||||
|
struct k_work *work = (struct k_work *)user_data;
|
||||||
|
|
||||||
current_state = state;
|
current_state = state;
|
||||||
current_err_cnt = err_cnt;
|
current_err_cnt = err_cnt;
|
||||||
k_work_submit(&state_change_work);
|
k_work_submit(work);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
|
@ -257,7 +259,7 @@ void main(void)
|
||||||
printk("ERROR spawning poll_state_thread\n");
|
printk("ERROR spawning poll_state_thread\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
can_set_state_change_callback(can_dev, state_change_callback);
|
can_set_state_change_callback(can_dev, state_change_callback, &state_change_work);
|
||||||
|
|
||||||
printk("Finished init.\n");
|
printk("Finished init.\n");
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue