Re: [PATCH v2 5/5] ipmi: ssif_bmc: add unit test for state machine

From: Corey Minyard

Date: Fri Apr 03 2026 - 10:32:54 EST


On Fri, Apr 03, 2026 at 10:12:45PM +0800, Jian Zhang wrote:
> > 2026年4月3日 21:14,Corey Minyard <corey@xxxxxxxxxxx> 写道:
> >
> > On Fri, Apr 03, 2026 at 05:06:02PM +0800, Jian Zhang wrote:
> >> Add some unit test for state machine when in SSIF_ABORTING state.
> >>
> >> Fixes: dd2bc5cc9e25 ("ipmi: ssif_bmc: Add SSIF BMC driver")
> >> Signed-off-by: Jian Zhang <zhangjian.3032@xxxxxxxxxxxxx>
> >> ---
> >> v2: remove undefined symbol response_in_send
> >>
> >> drivers/char/ipmi/Kconfig | 10 +
> >> drivers/char/ipmi/ssif_bmc.c | 401 +++++++++++++++++++++++++++++++++++
> >> 2 files changed, 411 insertions(+)
> >>
> >> diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
> >> index 92bed266d07c..709820f80266 100644
> >> --- a/drivers/char/ipmi/Kconfig
> >> +++ b/drivers/char/ipmi/Kconfig
> >> @@ -187,6 +187,16 @@ config SSIF_IPMI_BMC
> >> The driver implements the BMC side of the SMBus system
> >> interface (SSIF).
> >>
> >> +config SSIF_IPMI_BMC_KUNIT_TEST
> >> + bool "KUnit tests for SSIF IPMI BMC driver" if !KUNIT_ALL_TESTS
> >> + depends on KUNIT=y
> >> + depends on SSIF_IPMI_BMC=y
> >
> > Any reason for the "=y" in the above two?
> >
> > It's best to remove them if they are not needed so it can work in a
> > module. I can make that change, there's no need for a new series for
> > that.
>
> Nothing special and agree, Thanks.
> There’s one more thing that needs adjustment as well.
> Sorry about that—I picked it from dev-6.1 without testing (at the time there was a build error, so I didn’t run the unit tests).
> The test “ssif_bmc_test_restart_after_invalid_length” also needs to be removed. I do have a local patch regarding the length limitation,
> but it still needs thorough testing. Sorry again, I’m not very familiar with it yet, I’ll pay more attention in the future!

In that case, can you re-send just patch 5?

Thanks,

-corey

>
> - Jian
> >
> > Oh, and I forgot to say in the reply on the first change, thanks Quan
> > for reviewing these.
> >
> > -corey
> >
> >> + default KUNIT_ALL_TESTS
> >> + help
> >> + This option builds unit tests that exercise the SSIF BMC state
> >> + machine, including request handling, response transmission,
> >> + and error paths such as aborted or truncated transfers.
> >> +
> >> config IPMB_DEVICE_INTERFACE
> >> tristate 'IPMB Interface handler'
> >> depends on I2C
> >> diff --git a/drivers/char/ipmi/ssif_bmc.c b/drivers/char/ipmi/ssif_bmc.c
> >> index 646a1e9ffbb7..726626126cea 100644
> >> --- a/drivers/char/ipmi/ssif_bmc.c
> >> +++ b/drivers/char/ipmi/ssif_bmc.c
> >> @@ -18,6 +18,9 @@
> >> #include <linux/timer.h>
> >> #include <linux/jiffies.h>
> >> #include <linux/ipmi_ssif_bmc.h>
> >> +#if IS_ENABLED(CONFIG_SSIF_IPMI_BMC_KUNIT_TEST)
> >> +#include <kunit/test.h>
> >> +#endif
> >>
> >> #define DEVICE_NAME "ipmi-ssif-host"
> >>
> >> @@ -886,6 +889,404 @@ static struct i2c_driver ssif_bmc_driver = {
> >> .id_table = ssif_bmc_id,
> >> };
> >>
> >> +#if IS_ENABLED(CONFIG_SSIF_IPMI_BMC_KUNIT_TEST)
> >> +struct ssif_bmc_test_ctx {
> >> + struct ssif_bmc_ctx ssif_bmc;
> >> + struct i2c_client client;
> >> + struct i2c_adapter adapter;
> >> + struct i2c_algorithm algo;
> >> +};
> >> +
> >> +static int ssif_bmc_test_init(struct kunit *test)
> >> +{
> >> + struct ssif_bmc_test_ctx *test_ctx;
> >> +
> >> + test_ctx = kunit_kzalloc(test, sizeof(*test_ctx), GFP_KERNEL);
> >> + if (!test_ctx)
> >> + return -ENOMEM;
> >> +
> >> + test_ctx->adapter.algo = &test_ctx->algo;
> >> + test_ctx->client.addr = 0x20;
> >> + test_ctx->client.adapter = &test_ctx->adapter;
> >> +
> >> + spin_lock_init(&test_ctx->ssif_bmc.lock);
> >> + init_waitqueue_head(&test_ctx->ssif_bmc.wait_queue);
> >> + test_ctx->ssif_bmc.client = &test_ctx->client;
> >> + i2c_set_clientdata(&test_ctx->client, &test_ctx->ssif_bmc);
> >> +
> >> + test->priv = test_ctx;
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +static void ssif_bmc_test_exit(struct kunit *test)
> >> +{
> >> + struct ssif_bmc_test_ctx *test_ctx = test->priv;
> >> +
> >> + if (test_ctx->ssif_bmc.response_timer_inited)
> >> + timer_delete_sync(&test_ctx->ssif_bmc.response_timer);
> >> +}
> >> +
> >> +static int ssif_bmc_test_run_event_val(struct ssif_bmc_test_ctx *test_ctx,
> >> + enum i2c_slave_event event,
> >> + u8 *value)
> >> +{
> >> + return ssif_bmc_cb(&test_ctx->client, event, value);
> >> +}
> >> +
> >> +static int ssif_bmc_test_run_event(struct ssif_bmc_test_ctx *test_ctx,
> >> + enum i2c_slave_event event, u8 value)
> >> +{
> >> + return ssif_bmc_test_run_event_val(test_ctx, event, &value);
> >> +}
> >> +
> >> +static void ssif_bmc_test_singlepart_req(struct kunit *test)
> >> +{
> >> + struct ssif_bmc_test_ctx *test_ctx = test->priv;
> >> + struct ssif_bmc_ctx *ssif_bmc = &test_ctx->ssif_bmc;
> >> +
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_REQUESTED,
> >> + GET_8BIT_ADDR(test_ctx->client.addr));
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED,
> >> + SSIF_IPMI_SINGLEPART_WRITE);
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 2);
> >> +
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 0xaa);
> >> +
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 0x55);
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_STOP, 0), -EBUSY);
> >> +
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->state, SSIF_READY);
> >> + KUNIT_EXPECT_TRUE(test, ssif_bmc->request_available);
> >> + KUNIT_EXPECT_TRUE(test, ssif_bmc->busy);
> >> + KUNIT_EXPECT_FALSE(test, ssif_bmc->aborting);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->request.len, 2);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->request.payload[0], 0xaa);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->request.payload[1], 0x55);
> >> + KUNIT_EXPECT_TRUE(test, ssif_bmc->response_timer_inited);
> >> +}
> >> +
> >> +static void ssif_bmc_test_restart_write_without_stop(struct kunit *test)
> >> +{
> >> + struct ssif_bmc_test_ctx *test_ctx = test->priv;
> >> + struct ssif_bmc_ctx *ssif_bmc = &test_ctx->ssif_bmc;
> >> +
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_REQUESTED,
> >> + GET_8BIT_ADDR(test_ctx->client.addr)), 0);
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED,
> >> + SSIF_IPMI_SINGLEPART_WRITE), 0);
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 2), 0);
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 0xde), 0);
> >> +
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->state, SSIF_REQ_RECVING);
> >> +
> >> + /* Write transaction, without stop, and new request coming */
> >> + ssif_bmc_test_singlepart_req(test);
> >> +}
> >> +
> >> +
> >> +static void ssif_bmc_test_restart_after_invalid_command(struct kunit *test)
> >> +{
> >> + struct ssif_bmc_test_ctx *test_ctx = test->priv;
> >> + struct ssif_bmc_ctx *ssif_bmc = &test_ctx->ssif_bmc;
> >> +
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_REQUESTED,
> >> + GET_8BIT_ADDR(test_ctx->client.addr)), 0);
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 0xff), 0);
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 1), 0);
> >> +
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->state, SSIF_ABORTING);
> >> + KUNIT_EXPECT_TRUE(test, ssif_bmc->aborting);
> >> +
> >> + /* After An Invalid Command, expect could handle new request */
> >> + ssif_bmc_test_singlepart_req(test);
> >> +}
> >> +
> >> +static void ssif_bmc_test_restart_after_invalid_length(struct kunit *test)
> >> +{
> >> + struct ssif_bmc_test_ctx *test_ctx = test->priv;
> >> + struct ssif_bmc_ctx *ssif_bmc = &test_ctx->ssif_bmc;
> >> + int i;
> >> +
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_REQUESTED,
> >> + GET_8BIT_ADDR(test_ctx->client.addr)), 0);
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED,
> >> + SSIF_IPMI_SINGLEPART_WRITE), 0);
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED,
> >> + MAX_PAYLOAD_PER_TRANSACTION + 1), 0);
> >> +
> >> + for (i = 0; i < MAX_PAYLOAD_PER_TRANSACTION + 1; i++)
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx,
> >> + I2C_SLAVE_WRITE_RECEIVED, i), 0);
> >> +
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_STOP, 0), 0);
> >> + KUNIT_EXPECT_TRUE(test, ssif_bmc->aborting);
> >> + KUNIT_EXPECT_FALSE(test, ssif_bmc->request_available);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->state, SSIF_REQ_RECVING);
> >> +
> >> + ssif_bmc_test_singlepart_req(test);
> >> +}
> >> +
> >> +static void ssif_bmc_test_singlepart_read_response_completion(struct kunit *test)
> >> +{
> >> + struct ssif_bmc_test_ctx *test_ctx = test->priv;
> >> + struct ssif_bmc_ctx *ssif_bmc = &test_ctx->ssif_bmc;
> >> + u8 value;
> >> +
> >> + ssif_bmc->state = SSIF_SMBUS_CMD;
> >> + ssif_bmc->part_buf.smbus_cmd = SSIF_IPMI_SINGLEPART_READ;
> >> + ssif_bmc->response.len = 2;
> >> + ssif_bmc->response.payload[0] = 0x11;
> >> + ssif_bmc->response.payload[1] = 0x22;
> >> + ssif_bmc->response_in_progress = true;
> >> + ssif_bmc->is_singlepart_read = true;
> >> + ssif_bmc->pec_support = true;
> >> +
> >> + value = 0;
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event_val(test_ctx, I2C_SLAVE_READ_REQUESTED,
> >> + &value), 0);
> >> + KUNIT_EXPECT_EQ(test, value, 2);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->state, SSIF_RES_SENDING);
> >> +
> >> + value = 0;
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event_val(test_ctx, I2C_SLAVE_READ_PROCESSED,
> >> + &value), 0);
> >> + KUNIT_EXPECT_EQ(test, value, 0x11);
> >> +
> >> + value = 0;
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event_val(test_ctx, I2C_SLAVE_READ_PROCESSED,
> >> + &value), 0);
> >> + KUNIT_EXPECT_EQ(test, value, 0x22);
> >> +
> >> + value = 0;
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event_val(test_ctx, I2C_SLAVE_READ_PROCESSED,
> >> + &value), 0);
> >> + KUNIT_EXPECT_EQ(test, value, ssif_bmc->part_buf.pec);
> >> +
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_STOP, 0), 0);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->state, SSIF_READY);
> >> + KUNIT_EXPECT_FALSE(test, ssif_bmc->response_in_progress);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->response.len, 0);
> >> +}
> >> +
> >> +static void ssif_bmc_test_stop_during_start_discards_partial_request(struct kunit *test)
> >> +{
> >> + struct ssif_bmc_test_ctx *test_ctx = test->priv;
> >> + struct ssif_bmc_ctx *ssif_bmc = &test_ctx->ssif_bmc;
> >> +
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_REQUESTED,
> >> + GET_8BIT_ADDR(test_ctx->client.addr)), 0);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->state, SSIF_START);
> >> +
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_STOP, 0), 0);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->state, SSIF_READY);
> >> + KUNIT_EXPECT_FALSE(test, ssif_bmc->request_available);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->msg_idx, 0);
> >> +
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_REQUESTED,
> >> + GET_8BIT_ADDR(test_ctx->client.addr)), 0);
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED,
> >> + SSIF_IPMI_SINGLEPART_WRITE), 0);
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 1), 0);
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 0x77), 0);
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_STOP, 0), -EBUSY);
> >> +
> >> + KUNIT_EXPECT_TRUE(test, ssif_bmc->request_available);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->request.len, 1);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->request.payload[0], 0x77);
> >> +}
> >> +
> >> +static void ssif_bmc_test_read_interrupts_partial_write(struct kunit *test)
> >> +{
> >> + struct ssif_bmc_test_ctx *test_ctx = test->priv;
> >> + struct ssif_bmc_ctx *ssif_bmc = &test_ctx->ssif_bmc;
> >> + u8 value = 0xff;
> >> +
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_REQUESTED,
> >> + GET_8BIT_ADDR(test_ctx->client.addr)), 0);
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED,
> >> + SSIF_IPMI_SINGLEPART_WRITE), 0);
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 2), 0);
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 0xab), 0);
> >> +
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->state, SSIF_REQ_RECVING);
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event_val(test_ctx, I2C_SLAVE_READ_REQUESTED,
> >> + &value), 0);
> >> + KUNIT_EXPECT_EQ(test, value, 0);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->state, SSIF_ABORTING);
> >> +
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_STOP, 0), 0);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->state, SSIF_READY);
> >> + KUNIT_EXPECT_FALSE(test, ssif_bmc->request_available);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->request.len, 0);
> >> +
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_REQUESTED,
> >> + GET_8BIT_ADDR(test_ctx->client.addr)), 0);
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED,
> >> + SSIF_IPMI_SINGLEPART_WRITE), 0);
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 1), 0);
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 0xcd), 0);
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_STOP, 0), -EBUSY);
> >> +
> >> + KUNIT_EXPECT_TRUE(test, ssif_bmc->request_available);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->request.len, 1);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->request.payload[0], 0xcd);
> >> +}
> >> +
> >> +static void ssif_bmc_test_write_interrupts_response_send(struct kunit *test)
> >> +{
> >> + struct ssif_bmc_test_ctx *test_ctx = test->priv;
> >> + struct ssif_bmc_ctx *ssif_bmc = &test_ctx->ssif_bmc;
> >> + u8 value = 0;
> >> +
> >> + ssif_bmc->state = SSIF_SMBUS_CMD;
> >> + ssif_bmc->part_buf.smbus_cmd = SSIF_IPMI_SINGLEPART_READ;
> >> + ssif_bmc->response.len = 1;
> >> + ssif_bmc->response.payload[0] = 0x66;
> >> + ssif_bmc->response_in_progress = true;
> >> + ssif_bmc->is_singlepart_read = true;
> >> +
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event_val(test_ctx, I2C_SLAVE_READ_REQUESTED,
> >> + &value), 0);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->state, SSIF_RES_SENDING);
> >> +
> >> + /* READ_REQUESTED transaction */
> >> + ssif_bmc_test_singlepart_req(test);
> >> +}
> >> +
> >> +static void ssif_bmc_test_write_interrupts_response_sending(struct kunit *test)
> >> +{
> >> + struct ssif_bmc_test_ctx *test_ctx = test->priv;
> >> + struct ssif_bmc_ctx *ssif_bmc = &test_ctx->ssif_bmc;
> >> + u8 value = 0;
> >> +
> >> + ssif_bmc->state = SSIF_SMBUS_CMD;
> >> + ssif_bmc->part_buf.smbus_cmd = SSIF_IPMI_SINGLEPART_READ;
> >> + ssif_bmc->response.len = 1;
> >> + ssif_bmc->response.payload[0] = 0x66;
> >> + ssif_bmc->response_in_progress = true;
> >> + ssif_bmc->is_singlepart_read = true;
> >> +
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event_val(test_ctx, I2C_SLAVE_READ_REQUESTED,
> >> + &value), 0);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->state, SSIF_RES_SENDING);
> >> +
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event_val(test_ctx, I2C_SLAVE_READ_PROCESSED,
> >> + &value), 0);
> >> + KUNIT_EXPECT_EQ(test, value, 0x66);
> >> +
> >> + /* READ_REQUESTED transaction */
> >> + ssif_bmc_test_singlepart_req(test);
> >> +}
> >> +
> >> +static void ssif_bmc_test_timeout_interrupt_allows_retry(struct kunit *test)
> >> +{
> >> + struct ssif_bmc_test_ctx *test_ctx = test->priv;
> >> + struct ssif_bmc_ctx *ssif_bmc = &test_ctx->ssif_bmc;
> >> +
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_REQUESTED,
> >> + GET_8BIT_ADDR(test_ctx->client.addr)), 0);
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED,
> >> + SSIF_IPMI_SINGLEPART_WRITE), 0);
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 1), 0);
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 0x21), 0);
> >> + KUNIT_ASSERT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_STOP, 0), -EBUSY);
> >> +
> >> + KUNIT_ASSERT_TRUE(test, timer_pending(&ssif_bmc->response_timer));
> >> + timer_delete_sync(&ssif_bmc->response_timer);
> >> + response_timeout(&ssif_bmc->response_timer);
> >> +
> >> + KUNIT_EXPECT_FALSE(test, ssif_bmc->busy);
> >> + KUNIT_EXPECT_TRUE(test, ssif_bmc->aborting);
> >> + KUNIT_EXPECT_FALSE(test, ssif_bmc->response_timer_inited);
> >> +
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_REQUESTED,
> >> + GET_8BIT_ADDR(test_ctx->client.addr)), 0);
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED,
> >> + SSIF_IPMI_SINGLEPART_WRITE), 0);
> >> + KUNIT_EXPECT_FALSE(test, ssif_bmc->aborting);
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 1), 0);
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_WRITE_RECEIVED, 0x22), 0);
> >> + KUNIT_EXPECT_EQ(test,
> >> + ssif_bmc_test_run_event(test_ctx, I2C_SLAVE_STOP, 0), -EBUSY);
> >> +
> >> + KUNIT_EXPECT_TRUE(test, ssif_bmc->request_available);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->request.len, 1);
> >> + KUNIT_EXPECT_EQ(test, ssif_bmc->request.payload[0], 0x22);
> >> +}
> >> +
> >> +static struct kunit_case ssif_bmc_test_cases[] = {
> >> + KUNIT_CASE(ssif_bmc_test_singlepart_req),
> >> + KUNIT_CASE(ssif_bmc_test_restart_write_without_stop),
> >> + KUNIT_CASE(ssif_bmc_test_restart_after_invalid_command),
> >> + KUNIT_CASE(ssif_bmc_test_restart_after_invalid_length),
> >> + KUNIT_CASE(ssif_bmc_test_singlepart_read_response_completion),
> >> + KUNIT_CASE(ssif_bmc_test_stop_during_start_discards_partial_request),
> >> + KUNIT_CASE(ssif_bmc_test_read_interrupts_partial_write),
> >> + KUNIT_CASE(ssif_bmc_test_write_interrupts_response_send),
> >> + KUNIT_CASE(ssif_bmc_test_write_interrupts_response_sending),
> >> + KUNIT_CASE(ssif_bmc_test_timeout_interrupt_allows_retry),
> >> + {}
> >> +};
> >> +
> >> +static struct kunit_suite ssif_bmc_test_suite = {
> >> + .name = "ssif_bmc_test",
> >> + .init = ssif_bmc_test_init,
> >> + .exit = ssif_bmc_test_exit,
> >> + .test_cases = ssif_bmc_test_cases,
> >> +};
> >> +
> >> +kunit_test_suite(ssif_bmc_test_suite);
> >> +#endif
> >> +
> >> module_i2c_driver(ssif_bmc_driver);
> >>
> >> MODULE_AUTHOR("Quan Nguyen <quan@xxxxxxxxxxxxxxxxxxxxxx>");
> >> --
> >> 2.20.1