Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fsi: Aspeed: Add mutex to protect HW access

There is nothing to prevent multiple commands being executed
simultaneously. Add a mutex to prevent this.

Fixes: 606397d67f41 ("fsi: Add ast2600 master driver")
Reviewed-by: Joel Stanley <joel@jms.id.au>
Reviewed-by: Milton Miller <miltonm@us.ibm.com>
Signed-off-by: Eddie James <eajames@linux.ibm.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
Link: https://lore.kernel.org/r/20201120004929.185239-1-joel@jms.id.au
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Eddie James and committed by
Greg Kroah-Hartman
dfd7f2c1 fe34761d

+29 -16
+29 -16
drivers/fsi/fsi-master-aspeed.c
··· 8 8 #include <linux/io.h> 9 9 #include <linux/mfd/syscon.h> 10 10 #include <linux/module.h> 11 + #include <linux/mutex.h> 11 12 #include <linux/of.h> 12 13 #include <linux/platform_device.h> 13 14 #include <linux/regmap.h> ··· 20 19 21 20 struct fsi_master_aspeed { 22 21 struct fsi_master master; 22 + struct mutex lock; /* protect HW access */ 23 23 struct device *dev; 24 24 void __iomem *base; 25 25 struct clk *clk; ··· 256 254 addr |= id << 21; 257 255 addr += link * FSI_HUB_LINK_SIZE; 258 256 257 + mutex_lock(&aspeed->lock); 258 + 259 259 switch (size) { 260 260 case 1: 261 261 ret = opb_readb(aspeed, fsi_base + addr, val); ··· 269 265 ret = opb_readl(aspeed, fsi_base + addr, val); 270 266 break; 271 267 default: 272 - return -EINVAL; 268 + ret = -EINVAL; 269 + goto done; 273 270 } 274 271 275 272 ret = check_errors(aspeed, ret); 276 - if (ret) 277 - return ret; 278 - 279 - return 0; 273 + done: 274 + mutex_unlock(&aspeed->lock); 275 + return ret; 280 276 } 281 277 282 278 static int aspeed_master_write(struct fsi_master *master, int link, ··· 291 287 addr |= id << 21; 292 288 addr += link * FSI_HUB_LINK_SIZE; 293 289 290 + mutex_lock(&aspeed->lock); 291 + 294 292 switch (size) { 295 293 case 1: 296 294 ret = opb_writeb(aspeed, fsi_base + addr, *(u8 *)val); ··· 304 298 ret = opb_writel(aspeed, fsi_base + addr, *(__be32 *)val); 305 299 break; 306 300 default: 307 - return -EINVAL; 301 + ret = -EINVAL; 302 + goto done; 308 303 } 309 304 310 305 ret = check_errors(aspeed, ret); 311 - if (ret) 312 - return ret; 313 - 314 - return 0; 306 + done: 307 + mutex_unlock(&aspeed->lock); 308 + return ret; 315 309 } 316 310 317 311 static int aspeed_master_link_enable(struct fsi_master *master, int link, ··· 326 320 327 321 reg = cpu_to_be32(0x80000000 >> bit); 328 322 329 - if (!enable) 330 - return opb_writel(aspeed, ctrl_base + FSI_MCENP0 + (4 * idx), 331 - reg); 323 + mutex_lock(&aspeed->lock); 324 + 325 + if (!enable) { 326 + ret = opb_writel(aspeed, ctrl_base + FSI_MCENP0 + (4 * idx), reg); 327 + goto done; 328 + } 332 329 333 330 ret = opb_writel(aspeed, ctrl_base + FSI_MSENP0 + (4 * idx), reg); 334 331 if (ret) 335 - return ret; 332 + goto done; 336 333 337 334 mdelay(FSI_LINK_ENABLE_SETUP_TIME); 338 - 339 - return 0; 335 + done: 336 + mutex_unlock(&aspeed->lock); 337 + return ret; 340 338 } 341 339 342 340 static int aspeed_master_term(struct fsi_master *master, int link, uint8_t id) ··· 441 431 { 442 432 struct fsi_master_aspeed *aspeed = dev_get_drvdata(dev); 443 433 434 + mutex_lock(&aspeed->lock); 444 435 gpiod_set_value(aspeed->cfam_reset_gpio, 1); 445 436 usleep_range(900, 1000); 446 437 gpiod_set_value(aspeed->cfam_reset_gpio, 0); 438 + mutex_unlock(&aspeed->lock); 447 439 448 440 return count; 449 441 } ··· 609 597 610 598 dev_set_drvdata(&pdev->dev, aspeed); 611 599 600 + mutex_init(&aspeed->lock); 612 601 aspeed_master_init(aspeed); 613 602 614 603 rc = fsi_master_register(&aspeed->master);