1*9b81a87cSHonghui Jiang // SPDX-License-Identifier: GPL-2.0 2*9b81a87cSHonghui Jiang // KUnit tests for the SPI core DMA mapping error paths. 3*9b81a87cSHonghui Jiang // 4*9b81a87cSHonghui Jiang // A mapping error must clear all SG tables and *_sg_mapped flags while 5*9b81a87cSHonghui Jiang // cur_{tx,rx}_dma_dev identify the devices used for the attempted mapping. 6*9b81a87cSHonghui Jiang // Zero-length transfers make sg_alloc_table() fail with -EINVAL, providing 7*9b81a87cSHonghui Jiang // deterministic failure injection without test hooks. 8*9b81a87cSHonghui Jiang 9*9b81a87cSHonghui Jiang #include <kunit/device.h> 10*9b81a87cSHonghui Jiang #include <kunit/test.h> 11*9b81a87cSHonghui Jiang #include <linux/dma-mapping.h> 12*9b81a87cSHonghui Jiang #include <linux/limits.h> 13*9b81a87cSHonghui Jiang #include <linux/spi/spi.h> 14*9b81a87cSHonghui Jiang 15*9b81a87cSHonghui Jiang #include "../internals.h" 16*9b81a87cSHonghui Jiang 17*9b81a87cSHonghui Jiang MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); 18*9b81a87cSHonghui Jiang 19*9b81a87cSHonghui Jiang #define SPI_DMA_TEST_LEN 256 20*9b81a87cSHonghui Jiang #define SPI_DMA_TEST_XFERS 2 21*9b81a87cSHonghui Jiang 22*9b81a87cSHonghui Jiang struct spi_dma_test_ctx { 23*9b81a87cSHonghui Jiang struct spi_controller *ctlr; 24*9b81a87cSHonghui Jiang struct spi_device *spi; 25*9b81a87cSHonghui Jiang struct device *dma_dev; 26*9b81a87cSHonghui Jiang struct device *stale_dma_dev; 27*9b81a87cSHonghui Jiang struct spi_transfer xfer[SPI_DMA_TEST_XFERS]; 28*9b81a87cSHonghui Jiang struct spi_message msg; 29*9b81a87cSHonghui Jiang void *buf[SPI_DMA_TEST_XFERS * 2]; 30*9b81a87cSHonghui Jiang }; 31*9b81a87cSHonghui Jiang 32*9b81a87cSHonghui Jiang static bool spi_dma_test_can_dma(struct spi_controller *ctlr, 33*9b81a87cSHonghui Jiang struct spi_device *spi, 34*9b81a87cSHonghui Jiang struct spi_transfer *xfer) 35*9b81a87cSHonghui Jiang { 36*9b81a87cSHonghui Jiang /* Opt every transfer into the core DMA mapping path. */ 37*9b81a87cSHonghui Jiang return true; 38*9b81a87cSHonghui Jiang } 39*9b81a87cSHonghui Jiang 40*9b81a87cSHonghui Jiang /* 41*9b81a87cSHonghui Jiang * A bare controller is sufficient because the mapping helpers do not 42*9b81a87cSHonghui Jiang * dereference ctlr->dev. With dma_tx and dma_rx unset, both directions use 43*9b81a87cSHonghui Jiang * dma_map_dev, so the controller need not be registered. 44*9b81a87cSHonghui Jiang */ 45*9b81a87cSHonghui Jiang static struct spi_dma_test_ctx *spi_dma_test_ctx_new(struct kunit *test) 46*9b81a87cSHonghui Jiang { 47*9b81a87cSHonghui Jiang struct spi_dma_test_ctx *ctx; 48*9b81a87cSHonghui Jiang 49*9b81a87cSHonghui Jiang ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 50*9b81a87cSHonghui Jiang KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); 51*9b81a87cSHonghui Jiang 52*9b81a87cSHonghui Jiang ctx->dma_dev = kunit_device_register(test, "spi-dma-error-path"); 53*9b81a87cSHonghui Jiang KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->dma_dev); 54*9b81a87cSHonghui Jiang ctx->stale_dma_dev = 55*9b81a87cSHonghui Jiang kunit_device_register(test, "spi-dma-stale-device"); 56*9b81a87cSHonghui Jiang KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->stale_dma_dev); 57*9b81a87cSHonghui Jiang 58*9b81a87cSHonghui Jiang /* Keep both devices valid if an assertion aborts the test. */ 59*9b81a87cSHonghui Jiang KUNIT_ASSERT_EQ(test, 0, 60*9b81a87cSHonghui Jiang dma_coerce_mask_and_coherent(ctx->dma_dev, 61*9b81a87cSHonghui Jiang DMA_BIT_MASK(64))); 62*9b81a87cSHonghui Jiang KUNIT_ASSERT_EQ(test, 0, 63*9b81a87cSHonghui Jiang dma_coerce_mask_and_coherent(ctx->stale_dma_dev, 64*9b81a87cSHonghui Jiang DMA_BIT_MASK(64))); 65*9b81a87cSHonghui Jiang 66*9b81a87cSHonghui Jiang ctx->ctlr = kunit_kzalloc(test, sizeof(*ctx->ctlr), GFP_KERNEL); 67*9b81a87cSHonghui Jiang KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->ctlr); 68*9b81a87cSHonghui Jiang 69*9b81a87cSHonghui Jiang ctx->spi = kunit_kzalloc(test, sizeof(*ctx->spi), GFP_KERNEL); 70*9b81a87cSHonghui Jiang KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->spi); 71*9b81a87cSHonghui Jiang 72*9b81a87cSHonghui Jiang ctx->ctlr->can_dma = spi_dma_test_can_dma; 73*9b81a87cSHonghui Jiang ctx->ctlr->dma_map_dev = ctx->dma_dev; 74*9b81a87cSHonghui Jiang /* Normally initialized by spi_register_controller(). */ 75*9b81a87cSHonghui Jiang ctx->ctlr->max_dma_len = INT_MAX; 76*9b81a87cSHonghui Jiang 77*9b81a87cSHonghui Jiang ctx->spi->controller = ctx->ctlr; 78*9b81a87cSHonghui Jiang spi_message_init(&ctx->msg); 79*9b81a87cSHonghui Jiang ctx->msg.spi = ctx->spi; 80*9b81a87cSHonghui Jiang 81*9b81a87cSHonghui Jiang return ctx; 82*9b81a87cSHonghui Jiang } 83*9b81a87cSHonghui Jiang 84*9b81a87cSHonghui Jiang static void *spi_dma_test_buf(struct kunit *test, struct spi_dma_test_ctx *ctx, 85*9b81a87cSHonghui Jiang unsigned int slot) 86*9b81a87cSHonghui Jiang { 87*9b81a87cSHonghui Jiang KUNIT_ASSERT_LT(test, slot, ARRAY_SIZE(ctx->buf)); 88*9b81a87cSHonghui Jiang 89*9b81a87cSHonghui Jiang ctx->buf[slot] = kunit_kzalloc(test, SPI_DMA_TEST_LEN, GFP_KERNEL); 90*9b81a87cSHonghui Jiang KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->buf[slot]); 91*9b81a87cSHonghui Jiang 92*9b81a87cSHonghui Jiang return ctx->buf[slot]; 93*9b81a87cSHonghui Jiang } 94*9b81a87cSHonghui Jiang 95*9b81a87cSHonghui Jiang /* 96*9b81a87cSHonghui Jiang * Emulate DMA devices retained from an earlier message. Using valid devices 97*9b81a87cSHonghui Jiang * also lets the unfixed path reach the assertions instead of dereferencing 98*9b81a87cSHonghui Jiang * NULL during cleanup. 99*9b81a87cSHonghui Jiang */ 100*9b81a87cSHonghui Jiang static void spi_dma_test_pin_stale_dma_devs(struct spi_dma_test_ctx *ctx) 101*9b81a87cSHonghui Jiang { 102*9b81a87cSHonghui Jiang ctx->ctlr->cur_tx_dma_dev = ctx->stale_dma_dev; 103*9b81a87cSHonghui Jiang ctx->ctlr->cur_rx_dma_dev = ctx->stale_dma_dev; 104*9b81a87cSHonghui Jiang } 105*9b81a87cSHonghui Jiang 106*9b81a87cSHonghui Jiang static void spi_dma_test_assert_dma_devs_published(struct kunit *test, 107*9b81a87cSHonghui Jiang struct spi_dma_test_ctx *ctx) 108*9b81a87cSHonghui Jiang { 109*9b81a87cSHonghui Jiang KUNIT_ASSERT_PTR_EQ(test, ctx->ctlr->cur_tx_dma_dev, ctx->dma_dev); 110*9b81a87cSHonghui Jiang KUNIT_ASSERT_PTR_EQ(test, ctx->ctlr->cur_rx_dma_dev, ctx->dma_dev); 111*9b81a87cSHonghui Jiang } 112*9b81a87cSHonghui Jiang 113*9b81a87cSHonghui Jiang static void spi_dma_test_assert_nothing_mapped(struct kunit *test, 114*9b81a87cSHonghui Jiang struct spi_dma_test_ctx *ctx, 115*9b81a87cSHonghui Jiang unsigned int nr_xfers) 116*9b81a87cSHonghui Jiang { 117*9b81a87cSHonghui Jiang unsigned int i; 118*9b81a87cSHonghui Jiang 119*9b81a87cSHonghui Jiang for (i = 0; i < nr_xfers; i++) { 120*9b81a87cSHonghui Jiang KUNIT_ASSERT_FALSE_MSG(test, ctx->xfer[i].tx_sg_mapped, 121*9b81a87cSHonghui Jiang "xfer[%u] still claims a TX mapping after __spi_map_msg() failed", 122*9b81a87cSHonghui Jiang i); 123*9b81a87cSHonghui Jiang KUNIT_ASSERT_FALSE_MSG(test, ctx->xfer[i].rx_sg_mapped, 124*9b81a87cSHonghui Jiang "xfer[%u] still claims an RX mapping after __spi_map_msg() failed", 125*9b81a87cSHonghui Jiang i); 126*9b81a87cSHonghui Jiang KUNIT_EXPECT_NULL(test, ctx->xfer[i].tx_sg.sgl); 127*9b81a87cSHonghui Jiang KUNIT_EXPECT_EQ(test, ctx->xfer[i].tx_sg.orig_nents, 0U); 128*9b81a87cSHonghui Jiang KUNIT_EXPECT_EQ(test, ctx->xfer[i].tx_sg.nents, 0U); 129*9b81a87cSHonghui Jiang KUNIT_EXPECT_NULL(test, ctx->xfer[i].rx_sg.sgl); 130*9b81a87cSHonghui Jiang KUNIT_EXPECT_EQ(test, ctx->xfer[i].rx_sg.orig_nents, 0U); 131*9b81a87cSHonghui Jiang KUNIT_EXPECT_EQ(test, ctx->xfer[i].rx_sg.nents, 0U); 132*9b81a87cSHonghui Jiang } 133*9b81a87cSHonghui Jiang } 134*9b81a87cSHonghui Jiang 135*9b81a87cSHonghui Jiang /* 136*9b81a87cSHonghui Jiang * xfer0 maps TX and RX; zero-length xfer1 then fails its TX mapping. 137*9b81a87cSHonghui Jiang * The failure must unwind xfer0 and update cur_*_dma_dev. 138*9b81a87cSHonghui Jiang */ 139*9b81a87cSHonghui Jiang static void spi_dma_later_tx_fail_rolls_back_earlier(struct kunit *test) 140*9b81a87cSHonghui Jiang { 141*9b81a87cSHonghui Jiang struct spi_dma_test_ctx *ctx = spi_dma_test_ctx_new(test); 142*9b81a87cSHonghui Jiang int ret; 143*9b81a87cSHonghui Jiang 144*9b81a87cSHonghui Jiang ctx->xfer[0].tx_buf = spi_dma_test_buf(test, ctx, 0); 145*9b81a87cSHonghui Jiang ctx->xfer[0].rx_buf = spi_dma_test_buf(test, ctx, 1); 146*9b81a87cSHonghui Jiang ctx->xfer[0].len = SPI_DMA_TEST_LEN; 147*9b81a87cSHonghui Jiang 148*9b81a87cSHonghui Jiang ctx->xfer[1].tx_buf = spi_dma_test_buf(test, ctx, 2); 149*9b81a87cSHonghui Jiang ctx->xfer[1].rx_buf = NULL; 150*9b81a87cSHonghui Jiang ctx->xfer[1].len = 0; /* forces -EINVAL */ 151*9b81a87cSHonghui Jiang 152*9b81a87cSHonghui Jiang spi_message_add_tail(&ctx->xfer[0], &ctx->msg); 153*9b81a87cSHonghui Jiang spi_message_add_tail(&ctx->xfer[1], &ctx->msg); 154*9b81a87cSHonghui Jiang 155*9b81a87cSHonghui Jiang spi_dma_test_pin_stale_dma_devs(ctx); 156*9b81a87cSHonghui Jiang 157*9b81a87cSHonghui Jiang ret = __spi_map_msg(ctx->ctlr, &ctx->msg); 158*9b81a87cSHonghui Jiang KUNIT_ASSERT_EQ(test, ret, -EINVAL); 159*9b81a87cSHonghui Jiang 160*9b81a87cSHonghui Jiang spi_dma_test_assert_dma_devs_published(test, ctx); 161*9b81a87cSHonghui Jiang spi_dma_test_assert_nothing_mapped(test, ctx, SPI_DMA_TEST_XFERS); 162*9b81a87cSHonghui Jiang 163*9b81a87cSHonghui Jiang KUNIT_EXPECT_EQ(test, 0, __spi_unmap_msg(ctx->ctlr, &ctx->msg)); 164*9b81a87cSHonghui Jiang } 165*9b81a87cSHonghui Jiang 166*9b81a87cSHonghui Jiang /* 167*9b81a87cSHonghui Jiang * xfer0 maps TX and RX; zero-length RX-only xfer1 then fails. 168*9b81a87cSHonghui Jiang * The failure must unwind xfer0 without leaving either mapping flag set. 169*9b81a87cSHonghui Jiang */ 170*9b81a87cSHonghui Jiang static void spi_dma_later_rx_fail_rolls_back_earlier(struct kunit *test) 171*9b81a87cSHonghui Jiang { 172*9b81a87cSHonghui Jiang struct spi_dma_test_ctx *ctx = spi_dma_test_ctx_new(test); 173*9b81a87cSHonghui Jiang int ret; 174*9b81a87cSHonghui Jiang 175*9b81a87cSHonghui Jiang ctx->xfer[0].tx_buf = spi_dma_test_buf(test, ctx, 0); 176*9b81a87cSHonghui Jiang ctx->xfer[0].rx_buf = spi_dma_test_buf(test, ctx, 1); 177*9b81a87cSHonghui Jiang ctx->xfer[0].len = SPI_DMA_TEST_LEN; 178*9b81a87cSHonghui Jiang 179*9b81a87cSHonghui Jiang ctx->xfer[1].tx_buf = NULL; 180*9b81a87cSHonghui Jiang ctx->xfer[1].rx_buf = spi_dma_test_buf(test, ctx, 2); 181*9b81a87cSHonghui Jiang ctx->xfer[1].len = 0; /* forces -EINVAL */ 182*9b81a87cSHonghui Jiang 183*9b81a87cSHonghui Jiang spi_message_add_tail(&ctx->xfer[0], &ctx->msg); 184*9b81a87cSHonghui Jiang spi_message_add_tail(&ctx->xfer[1], &ctx->msg); 185*9b81a87cSHonghui Jiang 186*9b81a87cSHonghui Jiang spi_dma_test_pin_stale_dma_devs(ctx); 187*9b81a87cSHonghui Jiang 188*9b81a87cSHonghui Jiang ret = __spi_map_msg(ctx->ctlr, &ctx->msg); 189*9b81a87cSHonghui Jiang KUNIT_ASSERT_EQ(test, ret, -EINVAL); 190*9b81a87cSHonghui Jiang 191*9b81a87cSHonghui Jiang spi_dma_test_assert_dma_devs_published(test, ctx); 192*9b81a87cSHonghui Jiang spi_dma_test_assert_nothing_mapped(test, ctx, SPI_DMA_TEST_XFERS); 193*9b81a87cSHonghui Jiang 194*9b81a87cSHonghui Jiang KUNIT_EXPECT_EQ(test, 0, __spi_unmap_msg(ctx->ctlr, &ctx->msg)); 195*9b81a87cSHonghui Jiang } 196*9b81a87cSHonghui Jiang 197*9b81a87cSHonghui Jiang /* Ensure the error unwind does not affect successful mappings. */ 198*9b81a87cSHonghui Jiang static void spi_dma_map_success_publishes_dma_devs(struct kunit *test) 199*9b81a87cSHonghui Jiang { 200*9b81a87cSHonghui Jiang struct spi_dma_test_ctx *ctx = spi_dma_test_ctx_new(test); 201*9b81a87cSHonghui Jiang int ret; 202*9b81a87cSHonghui Jiang 203*9b81a87cSHonghui Jiang ctx->xfer[0].tx_buf = spi_dma_test_buf(test, ctx, 0); 204*9b81a87cSHonghui Jiang ctx->xfer[0].rx_buf = spi_dma_test_buf(test, ctx, 1); 205*9b81a87cSHonghui Jiang ctx->xfer[0].len = SPI_DMA_TEST_LEN; 206*9b81a87cSHonghui Jiang 207*9b81a87cSHonghui Jiang spi_message_add_tail(&ctx->xfer[0], &ctx->msg); 208*9b81a87cSHonghui Jiang 209*9b81a87cSHonghui Jiang ret = __spi_map_msg(ctx->ctlr, &ctx->msg); 210*9b81a87cSHonghui Jiang KUNIT_ASSERT_EQ(test, ret, 0); 211*9b81a87cSHonghui Jiang 212*9b81a87cSHonghui Jiang KUNIT_EXPECT_TRUE(test, ctx->xfer[0].tx_sg_mapped); 213*9b81a87cSHonghui Jiang KUNIT_EXPECT_TRUE(test, ctx->xfer[0].rx_sg_mapped); 214*9b81a87cSHonghui Jiang KUNIT_EXPECT_PTR_EQ(test, ctx->ctlr->cur_tx_dma_dev, ctx->dma_dev); 215*9b81a87cSHonghui Jiang KUNIT_EXPECT_PTR_EQ(test, ctx->ctlr->cur_rx_dma_dev, ctx->dma_dev); 216*9b81a87cSHonghui Jiang 217*9b81a87cSHonghui Jiang KUNIT_EXPECT_EQ(test, 0, __spi_unmap_msg(ctx->ctlr, &ctx->msg)); 218*9b81a87cSHonghui Jiang 219*9b81a87cSHonghui Jiang KUNIT_EXPECT_FALSE(test, ctx->xfer[0].tx_sg_mapped); 220*9b81a87cSHonghui Jiang KUNIT_EXPECT_FALSE(test, ctx->xfer[0].rx_sg_mapped); 221*9b81a87cSHonghui Jiang KUNIT_EXPECT_NULL(test, ctx->xfer[0].tx_sg.sgl); 222*9b81a87cSHonghui Jiang KUNIT_EXPECT_NULL(test, ctx->xfer[0].rx_sg.sgl); 223*9b81a87cSHonghui Jiang } 224*9b81a87cSHonghui Jiang 225*9b81a87cSHonghui Jiang /* A transfer without buffers requires no DMA mapping. */ 226*9b81a87cSHonghui Jiang static void spi_dma_map_nothing_is_success(struct kunit *test) 227*9b81a87cSHonghui Jiang { 228*9b81a87cSHonghui Jiang struct spi_dma_test_ctx *ctx = spi_dma_test_ctx_new(test); 229*9b81a87cSHonghui Jiang int ret; 230*9b81a87cSHonghui Jiang 231*9b81a87cSHonghui Jiang ctx->xfer[0].tx_buf = NULL; 232*9b81a87cSHonghui Jiang ctx->xfer[0].rx_buf = NULL; 233*9b81a87cSHonghui Jiang ctx->xfer[0].len = SPI_DMA_TEST_LEN; 234*9b81a87cSHonghui Jiang 235*9b81a87cSHonghui Jiang spi_message_add_tail(&ctx->xfer[0], &ctx->msg); 236*9b81a87cSHonghui Jiang 237*9b81a87cSHonghui Jiang ret = __spi_map_msg(ctx->ctlr, &ctx->msg); 238*9b81a87cSHonghui Jiang KUNIT_EXPECT_EQ(test, ret, 0); 239*9b81a87cSHonghui Jiang 240*9b81a87cSHonghui Jiang spi_dma_test_assert_nothing_mapped(test, ctx, 1); 241*9b81a87cSHonghui Jiang } 242*9b81a87cSHonghui Jiang 243*9b81a87cSHonghui Jiang static struct kunit_case spi_dma_error_path_cases[] = { 244*9b81a87cSHonghui Jiang KUNIT_CASE(spi_dma_later_tx_fail_rolls_back_earlier), 245*9b81a87cSHonghui Jiang KUNIT_CASE(spi_dma_later_rx_fail_rolls_back_earlier), 246*9b81a87cSHonghui Jiang KUNIT_CASE(spi_dma_map_success_publishes_dma_devs), 247*9b81a87cSHonghui Jiang KUNIT_CASE(spi_dma_map_nothing_is_success), 248*9b81a87cSHonghui Jiang {} 249*9b81a87cSHonghui Jiang }; 250*9b81a87cSHonghui Jiang 251*9b81a87cSHonghui Jiang static struct kunit_suite spi_dma_error_path_suite = { 252*9b81a87cSHonghui Jiang .name = "spi_dma", 253*9b81a87cSHonghui Jiang .test_cases = spi_dma_error_path_cases, 254*9b81a87cSHonghui Jiang }; 255*9b81a87cSHonghui Jiang 256*9b81a87cSHonghui Jiang kunit_test_suite(spi_dma_error_path_suite); 257*9b81a87cSHonghui Jiang 258*9b81a87cSHonghui Jiang MODULE_DESCRIPTION("KUnit tests for SPI core DMA mapping"); 259*9b81a87cSHonghui Jiang MODULE_LICENSE("GPL"); 260