Certain 64-bit systems (e.g. Amlogic Meson GX) require buffers to be used for DMA to be 8-byte-aligned. struct sdio_func has an embedded small DMA buffer not meeting this requirement. When testing switching to descriptor chain mode in meson-gx driver SDIO is broken therefore. Fix this by allocating the small DMA buffer separately as kmalloc ensures that the returned memory area is properly aligned for every basic data type.
Unified · Split
| @@ -267,7 +267,7 @@ static void sdio_release_func(struct device *dev) · 266 unmodified lines | |||
| 267 | sdio_free_func_cis(func); | 267 | sdio_free_func_cis(func); |
| 268 | 268 | ||
| 269 | kfree(func->info); | 269 | kfree(func->info); |
| 270 | 270 | kfree(func->tmpbuf); | |
| 271 | kfree(func); | 271 | kfree(func); |
| 272 | } | 272 | } |
| 273 | 273 | ||
| @@ -282,6 +282,16 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card) · 8 unmodified lines | |||
| 282 | if (!func) | 282 | if (!func) |
| 283 | return ERR_PTR(-ENOMEM); | 283 | return ERR_PTR(-ENOMEM); |
| 284 | 284 | ||
| 285 | /* | ||
| 286 | * allocate buffer separately to make sure it's properly aligned for | ||
| 287 | * DMA usage (incl. 64 bit DMA) | ||
| 288 | */ | ||
| 289 | func->tmpbuf = kmalloc(4, GFP_KERNEL); | ||
| 290 | if (!func->tmpbuf) { | ||
| 291 | kfree(func); | ||
| 292 | return ERR_PTR(-ENOMEM); | ||
| 293 | } | ||
| 294 | |||
| 285 | func->card = card; | 295 | func->card = card; |
| 286 | 296 | ||
| 287 | device_initialize(&func->dev); | 297 | device_initialize(&func->dev); |
| @@ -53,7 +53,7 @@ struct sdio_func { · 52 unmodified lines | |||
| 53 | unsigned int state; /* function state */ | 53 | unsigned int state; /* function state */ |
| 54 | #define SDIO_STATE_PRESENT (1<<0) /* present in sysfs */ | 54 | #define SDIO_STATE_PRESENT (1<<0) /* present in sysfs */ |
| 55 | 55 | ||
| 56 | u8 tmpbuf[4]; /* DMA:able scratch buffer */ | 56 | u8 *tmpbuf; /* DMA:able scratch buffer */ |
| 57 | 57 | ||
| 58 | unsigned num_info; /* number of info strings */ | 58 | unsigned num_info; /* number of info strings */ |
| 59 | const char **info; /* info strings */ | 59 | const char **info; /* info strings */ |