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

Revert "OMAPFB: simplify locking"

This reverts commit b41deecbda70067b26a3a7704fdf967a7940935b.

The simpler locking causes huge latencies when two processes use the
omapfb, even if they use different framebuffers.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

+132 -79
+59 -9
drivers/video/omap2/omapfb/omapfb-ioctl.c
··· 85 85 goto out; 86 86 } 87 87 88 + /* Take the locks in a specific order to keep lockdep happy */ 89 + if (old_rg->id < new_rg->id) { 90 + omapfb_get_mem_region(old_rg); 91 + omapfb_get_mem_region(new_rg); 92 + } else if (new_rg->id < old_rg->id) { 93 + omapfb_get_mem_region(new_rg); 94 + omapfb_get_mem_region(old_rg); 95 + } else 96 + omapfb_get_mem_region(old_rg); 97 + 88 98 if (pi->enabled && !new_rg->size) { 89 99 /* 90 100 * This plane's memory was freed, can't enable it ··· 146 136 goto undo; 147 137 } 148 138 139 + /* Release the locks in a specific order to keep lockdep happy */ 140 + if (old_rg->id > new_rg->id) { 141 + omapfb_put_mem_region(old_rg); 142 + omapfb_put_mem_region(new_rg); 143 + } else if (new_rg->id > old_rg->id) { 144 + omapfb_put_mem_region(new_rg); 145 + omapfb_put_mem_region(old_rg); 146 + } else 147 + omapfb_put_mem_region(old_rg); 148 + 149 149 return 0; 150 150 151 151 undo: ··· 166 146 167 147 ovl->set_overlay_info(ovl, &old_info); 168 148 put_mem: 149 + /* Release the locks in a specific order to keep lockdep happy */ 150 + if (old_rg->id > new_rg->id) { 151 + omapfb_put_mem_region(old_rg); 152 + omapfb_put_mem_region(new_rg); 153 + } else if (new_rg->id > old_rg->id) { 154 + omapfb_put_mem_region(new_rg); 155 + omapfb_put_mem_region(old_rg); 156 + } else 157 + omapfb_put_mem_region(old_rg); 169 158 out: 170 159 dev_err(fbdev->dev, "setup_plane failed\n"); 171 160 ··· 224 195 if (display && display->driver->sync) 225 196 display->driver->sync(display); 226 197 227 - mutex_lock(&fbi->mm_lock); 228 - 229 198 rg = ofbi->region; 199 + 200 + down_write_nested(&rg->lock, rg->id); 201 + atomic_inc(&rg->lock_count); 230 202 231 203 if (rg->size == size && rg->type == mi->type) 232 204 goto out; ··· 261 231 } 262 232 263 233 out: 264 - mutex_unlock(&fbi->mm_lock); 234 + atomic_dec(&rg->lock_count); 235 + up_write(&rg->lock); 236 + 265 237 return r; 266 238 } 267 239 ··· 272 240 struct omapfb_info *ofbi = FB2OFB(fbi); 273 241 struct omapfb2_mem_region *rg; 274 242 275 - rg = ofbi->region; 243 + rg = omapfb_get_mem_region(ofbi->region); 276 244 memset(mi, 0, sizeof(*mi)); 277 245 278 246 mi->size = rg->size; 279 247 mi->type = rg->type; 248 + 249 + omapfb_put_mem_region(rg); 280 250 281 251 return 0; 282 252 } ··· 318 284 if (mode != OMAPFB_AUTO_UPDATE && mode != OMAPFB_MANUAL_UPDATE) 319 285 return -EINVAL; 320 286 287 + omapfb_lock(fbdev); 288 + 321 289 d = get_display_data(fbdev, display); 322 290 323 - if (d->update_mode == mode) 291 + if (d->update_mode == mode) { 292 + omapfb_unlock(fbdev); 324 293 return 0; 294 + } 325 295 326 296 r = 0; 327 297 ··· 341 303 r = -EINVAL; 342 304 } 343 305 306 + omapfb_unlock(fbdev); 307 + 344 308 return r; 345 309 } 346 310 ··· 357 317 if (!display) 358 318 return -EINVAL; 359 319 320 + omapfb_lock(fbdev); 321 + 360 322 d = get_display_data(fbdev, display); 361 323 362 324 *mode = d->update_mode; 325 + 326 + omapfb_unlock(fbdev); 363 327 364 328 return 0; 365 329 } ··· 424 380 struct omapfb_color_key *ck) 425 381 { 426 382 struct omapfb_info *ofbi = FB2OFB(fbi); 383 + struct omapfb2_device *fbdev = ofbi->fbdev; 427 384 int r; 428 385 int i; 429 386 struct omap_overlay_manager *mgr = NULL; 387 + 388 + omapfb_lock(fbdev); 430 389 431 390 for (i = 0; i < ofbi->num_overlays; i++) { 432 391 if (ofbi->overlays[i]->manager) { ··· 445 398 446 399 r = _omapfb_set_color_key(mgr, ck); 447 400 err: 401 + omapfb_unlock(fbdev); 402 + 448 403 return r; 449 404 } 450 405 ··· 454 405 struct omapfb_color_key *ck) 455 406 { 456 407 struct omapfb_info *ofbi = FB2OFB(fbi); 408 + struct omapfb2_device *fbdev = ofbi->fbdev; 457 409 struct omap_overlay_manager *mgr = NULL; 458 410 int r = 0; 459 411 int i; 412 + 413 + omapfb_lock(fbdev); 460 414 461 415 for (i = 0; i < ofbi->num_overlays; i++) { 462 416 if (ofbi->overlays[i]->manager) { ··· 475 423 476 424 *ck = omapfb_color_keys[mgr->id]; 477 425 err: 426 + omapfb_unlock(fbdev); 427 + 478 428 return r; 479 429 } 480 430 ··· 602 548 } p; 603 549 604 550 int r = 0; 605 - 606 - omapfb_lock(fbdev); 607 551 608 552 switch (cmd) { 609 553 case OMAPFB_SYNC_GFX: ··· 907 855 dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd); 908 856 r = -EINVAL; 909 857 } 910 - 911 - omapfb_unlock(fbdev); 912 858 913 859 if (r < 0) 914 860 DBG("ioctl failed: %d\n", r);
+30 -10
drivers/video/omap2/omapfb/omapfb-main.c
··· 672 672 673 673 DBG("check_fb_var %d\n", ofbi->id); 674 674 675 + WARN_ON(!atomic_read(&ofbi->region->lock_count)); 676 + 675 677 r = fb_mode_to_dss_mode(var, &mode); 676 678 if (r) { 677 679 DBG("cannot convert var to omap dss mode\n"); ··· 855 853 int rotation = var->rotate; 856 854 int i; 857 855 856 + WARN_ON(!atomic_read(&ofbi->region->lock_count)); 857 + 858 858 for (i = 0; i < ofbi->num_overlays; i++) { 859 859 if (ovl != ofbi->overlays[i]) 860 860 continue; ··· 948 944 fill_fb(fbi); 949 945 #endif 950 946 947 + WARN_ON(!atomic_read(&ofbi->region->lock_count)); 948 + 951 949 for (i = 0; i < ofbi->num_overlays; i++) { 952 950 ovl = ofbi->overlays[i]; 953 951 ··· 1008 1002 static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) 1009 1003 { 1010 1004 struct omapfb_info *ofbi = FB2OFB(fbi); 1011 - struct omapfb2_device *fbdev = ofbi->fbdev; 1012 1005 int r; 1013 1006 1014 1007 DBG("check_var(%d)\n", FB2OFB(fbi)->id); 1015 1008 1016 - omapfb_lock(fbdev); 1009 + omapfb_get_mem_region(ofbi->region); 1017 1010 1018 1011 r = check_fb_var(fbi, var); 1019 1012 1020 - omapfb_unlock(fbdev); 1013 + omapfb_put_mem_region(ofbi->region); 1021 1014 1022 1015 return r; 1023 1016 } ··· 1025 1020 static int omapfb_set_par(struct fb_info *fbi) 1026 1021 { 1027 1022 struct omapfb_info *ofbi = FB2OFB(fbi); 1028 - struct omapfb2_device *fbdev = ofbi->fbdev; 1029 1023 int r; 1030 1024 1031 1025 DBG("set_par(%d)\n", FB2OFB(fbi)->id); 1032 1026 1033 - omapfb_lock(fbdev); 1027 + omapfb_get_mem_region(ofbi->region); 1034 1028 1035 1029 set_fb_fix(fbi); 1036 1030 ··· 1040 1036 r = omapfb_apply_changes(fbi, 0); 1041 1037 1042 1038 out: 1043 - omapfb_unlock(fbdev); 1039 + omapfb_put_mem_region(ofbi->region); 1044 1040 1045 1041 return r; 1046 1042 } ··· 1049 1045 struct fb_info *fbi) 1050 1046 { 1051 1047 struct omapfb_info *ofbi = FB2OFB(fbi); 1052 - struct omapfb2_device *fbdev = ofbi->fbdev; 1053 1048 struct fb_var_screeninfo new_var; 1054 1049 int r; 1055 1050 ··· 1064 1061 1065 1062 fbi->var = new_var; 1066 1063 1067 - omapfb_lock(fbdev); 1064 + omapfb_get_mem_region(ofbi->region); 1068 1065 1069 1066 r = omapfb_apply_changes(fbi, 0); 1070 1067 1071 - omapfb_unlock(fbdev); 1068 + omapfb_put_mem_region(ofbi->region); 1072 1069 1073 1070 return r; 1074 1071 } ··· 1077 1074 { 1078 1075 struct omapfb2_mem_region *rg = vma->vm_private_data; 1079 1076 1077 + omapfb_get_mem_region(rg); 1080 1078 atomic_inc(&rg->map_count); 1079 + omapfb_put_mem_region(rg); 1081 1080 } 1082 1081 1083 1082 static void mmap_user_close(struct vm_area_struct *vma) 1084 1083 { 1085 1084 struct omapfb2_mem_region *rg = vma->vm_private_data; 1086 1085 1086 + omapfb_get_mem_region(rg); 1087 1087 atomic_dec(&rg->map_count); 1088 + omapfb_put_mem_region(rg); 1088 1089 } 1089 1090 1090 1091 static struct vm_operations_struct mmap_user_ops = { ··· 1112 1105 return -EINVAL; 1113 1106 off = vma->vm_pgoff << PAGE_SHIFT; 1114 1107 1115 - rg = ofbi->region; 1108 + rg = omapfb_get_mem_region(ofbi->region); 1116 1109 1117 1110 start = omapfb_get_region_paddr(ofbi); 1118 1111 len = fix->smem_len; ··· 1140 1133 /* vm_ops.open won't be called for mmap itself. */ 1141 1134 atomic_inc(&rg->map_count); 1142 1135 1136 + omapfb_put_mem_region(rg); 1137 + 1143 1138 return 0; 1144 1139 1145 1140 error: 1141 + omapfb_put_mem_region(ofbi->region); 1142 + 1146 1143 return r; 1147 1144 } 1148 1145 ··· 1913 1902 1914 1903 ofbi->region = &fbdev->regions[i]; 1915 1904 ofbi->region->id = i; 1905 + init_rwsem(&ofbi->region->lock); 1916 1906 1917 1907 /* assign these early, so that fb alloc can use them */ 1918 1908 ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : ··· 1945 1933 /* setup fb_infos */ 1946 1934 for (i = 0; i < fbdev->num_fbs; i++) { 1947 1935 struct fb_info *fbi = fbdev->fbs[i]; 1936 + struct omapfb_info *ofbi = FB2OFB(fbi); 1948 1937 1938 + omapfb_get_mem_region(ofbi->region); 1949 1939 r = omapfb_fb_init(fbdev, fbi); 1940 + omapfb_put_mem_region(ofbi->region); 1941 + 1950 1942 if (r) { 1951 1943 dev_err(fbdev->dev, "failed to setup fb_info\n"); 1952 1944 return r; ··· 1982 1966 1983 1967 for (i = 0; i < fbdev->num_fbs; i++) { 1984 1968 struct fb_info *fbi = fbdev->fbs[i]; 1969 + struct omapfb_info *ofbi = FB2OFB(fbi); 1985 1970 1971 + omapfb_get_mem_region(ofbi->region); 1986 1972 r = omapfb_apply_changes(fbi, 1); 1973 + omapfb_put_mem_region(ofbi->region); 1974 + 1987 1975 if (r) { 1988 1976 dev_err(fbdev->dev, "failed to change mode\n"); 1989 1977 return r;
+27 -60
drivers/video/omap2/omapfb/omapfb-sysfs.c
··· 49 49 { 50 50 struct fb_info *fbi = dev_get_drvdata(dev); 51 51 struct omapfb_info *ofbi = FB2OFB(fbi); 52 - struct omapfb2_device *fbdev = ofbi->fbdev; 53 52 struct omapfb2_mem_region *rg; 54 53 int rot_type; 55 54 int r; ··· 62 63 63 64 if (!lock_fb_info(fbi)) 64 65 return -ENODEV; 65 - omapfb_lock(fbdev); 66 66 67 67 r = 0; 68 68 if (rot_type == ofbi->rotation_type) 69 69 goto out; 70 70 71 - rg = ofbi->region; 71 + rg = omapfb_get_mem_region(ofbi->region); 72 72 73 73 if (rg->size) { 74 74 r = -EBUSY; ··· 81 83 * need to do any further parameter checking at this point. 82 84 */ 83 85 put_region: 86 + omapfb_put_mem_region(rg); 84 87 out: 85 - omapfb_unlock(fbdev); 86 88 unlock_fb_info(fbi); 87 89 88 90 return r ? r : count; ··· 104 106 { 105 107 struct fb_info *fbi = dev_get_drvdata(dev); 106 108 struct omapfb_info *ofbi = FB2OFB(fbi); 107 - struct omapfb2_device *fbdev = ofbi->fbdev; 108 109 bool mirror; 109 110 int r; 110 111 struct fb_var_screeninfo new_var; ··· 114 117 115 118 if (!lock_fb_info(fbi)) 116 119 return -ENODEV; 117 - omapfb_lock(fbdev); 118 120 119 121 ofbi->mirror = mirror; 122 + 123 + omapfb_get_mem_region(ofbi->region); 120 124 121 125 memcpy(&new_var, &fbi->var, sizeof(new_var)); 122 126 r = check_fb_var(fbi, &new_var); ··· 133 135 134 136 r = count; 135 137 out: 136 - omapfb_unlock(fbdev); 138 + omapfb_put_mem_region(ofbi->region); 139 + 137 140 unlock_fb_info(fbi); 138 141 139 142 return r; ··· 273 274 274 275 DBG("detaching %d\n", ofbi->overlays[i]->id); 275 276 277 + omapfb_get_mem_region(ofbi->region); 278 + 276 279 omapfb_overlay_enable(ovl, 0); 277 280 278 281 if (ovl->manager) 279 282 ovl->manager->apply(ovl->manager); 283 + 284 + omapfb_put_mem_region(ofbi->region); 280 285 281 286 for (t = i + 1; t < ofbi->num_overlays; t++) { 282 287 ofbi->rotation[t-1] = ofbi->rotation[t]; ··· 314 311 } 315 312 316 313 if (added) { 314 + omapfb_get_mem_region(ofbi->region); 315 + 317 316 r = omapfb_apply_changes(fbi, 0); 317 + 318 + omapfb_put_mem_region(ofbi->region); 318 319 319 320 if (r) 320 321 goto out; ··· 337 330 { 338 331 struct fb_info *fbi = dev_get_drvdata(dev); 339 332 struct omapfb_info *ofbi = FB2OFB(fbi); 340 - struct omapfb2_device *fbdev = ofbi->fbdev; 341 333 ssize_t l = 0; 342 334 int t; 343 335 344 336 if (!lock_fb_info(fbi)) 345 337 return -ENODEV; 346 - omapfb_lock(fbdev); 347 338 348 339 for (t = 0; t < ofbi->num_overlays; t++) { 349 340 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", ··· 350 345 351 346 l += snprintf(buf + l, PAGE_SIZE - l, "\n"); 352 347 353 - omapfb_unlock(fbdev); 354 348 unlock_fb_info(fbi); 355 349 356 350 return l; ··· 360 356 { 361 357 struct fb_info *fbi = dev_get_drvdata(dev); 362 358 struct omapfb_info *ofbi = FB2OFB(fbi); 363 - struct omapfb2_device *fbdev = ofbi->fbdev; 364 359 int num_ovls = 0, r, i; 365 360 int len; 366 361 bool changed = false; ··· 371 368 372 369 if (!lock_fb_info(fbi)) 373 370 return -ENODEV; 374 - omapfb_lock(fbdev); 375 371 376 372 if (len > 0) { 377 373 char *p = (char *)buf; ··· 407 405 for (i = 0; i < num_ovls; ++i) 408 406 ofbi->rotation[i] = rotation[i]; 409 407 408 + omapfb_get_mem_region(ofbi->region); 409 + 410 410 r = omapfb_apply_changes(fbi, 0); 411 + 412 + omapfb_put_mem_region(ofbi->region); 413 + 411 414 if (r) 412 415 goto out; 413 416 ··· 421 414 422 415 r = count; 423 416 out: 424 - omapfb_unlock(fbdev); 425 417 unlock_fb_info(fbi); 426 418 427 419 return r; ··· 431 425 { 432 426 struct fb_info *fbi = dev_get_drvdata(dev); 433 427 struct omapfb_info *ofbi = FB2OFB(fbi); 434 - struct omapfb2_device *fbdev = ofbi->fbdev; 435 - int r; 436 428 437 - if (!lock_fb_info(fbi)) 438 - return -ENODEV; 439 - omapfb_lock(fbdev); 440 - 441 - r = snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size); 442 - 443 - omapfb_unlock(fbdev); 444 - unlock_fb_info(fbi); 445 - 446 - return r; 429 + return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size); 447 430 } 448 431 449 432 static ssize_t store_size(struct device *dev, struct device_attribute *attr, ··· 455 460 456 461 if (!lock_fb_info(fbi)) 457 462 return -ENODEV; 458 - omapfb_lock(fbdev); 459 463 460 464 if (display && display->driver->sync) 461 465 display->driver->sync(display); 462 466 463 - mutex_lock(&fbi->mm_lock); 464 - 465 467 rg = ofbi->region; 468 + 469 + down_write_nested(&rg->lock, rg->id); 470 + atomic_inc(&rg->lock_count); 466 471 467 472 if (atomic_read(&rg->map_count)) { 468 473 r = -EBUSY; ··· 496 501 497 502 r = count; 498 503 out: 499 - mutex_unlock(&fbi->mm_lock); 500 - omapfb_unlock(fbdev); 504 + atomic_dec(&rg->lock_count); 505 + up_write(&rg->lock); 506 + 501 507 unlock_fb_info(fbi); 502 508 503 509 return r; ··· 509 513 { 510 514 struct fb_info *fbi = dev_get_drvdata(dev); 511 515 struct omapfb_info *ofbi = FB2OFB(fbi); 512 - struct omapfb2_device *fbdev = ofbi->fbdev; 513 - int r; 514 516 515 - if (!lock_fb_info(fbi)) 516 - return -ENODEV; 517 - omapfb_lock(fbdev); 518 - 519 - r = snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr); 520 - 521 - omapfb_unlock(fbdev); 522 - unlock_fb_info(fbi); 523 - 524 - return r; 517 + return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr); 525 518 } 526 519 527 520 static ssize_t show_virt(struct device *dev, ··· 526 541 struct device_attribute *attr, char *buf) 527 542 { 528 543 struct fb_info *fbi = dev_get_drvdata(dev); 529 - struct omapfb_info *ofbi = FB2OFB(fbi); 530 - struct omapfb2_device *fbdev = ofbi->fbdev; 531 544 enum omapfb_update_mode mode; 532 545 int r; 533 546 534 - if (!lock_fb_info(fbi)) 535 - return -ENODEV; 536 - omapfb_lock(fbdev); 537 - 538 547 r = omapfb_get_update_mode(fbi, &mode); 539 - 540 - omapfb_unlock(fbdev); 541 - unlock_fb_info(fbi); 542 548 543 549 if (r) 544 550 return r; ··· 541 565 const char *buf, size_t count) 542 566 { 543 567 struct fb_info *fbi = dev_get_drvdata(dev); 544 - struct omapfb_info *ofbi = FB2OFB(fbi); 545 - struct omapfb2_device *fbdev = ofbi->fbdev; 546 568 unsigned mode; 547 569 int r; 548 570 ··· 548 574 if (r) 549 575 return r; 550 576 551 - if (!lock_fb_info(fbi)) 552 - return -ENODEV; 553 - omapfb_lock(fbdev); 554 - 555 577 r = omapfb_set_update_mode(fbi, mode); 556 578 if (r) 557 579 return r; 558 - 559 - omapfb_unlock(fbdev); 560 - unlock_fb_info(fbi); 561 580 562 581 return count; 563 582 }
+16
drivers/video/omap2/omapfb/omapfb.h
··· 62 62 bool alloc; /* allocated by the driver */ 63 63 bool map; /* kernel mapped by the driver */ 64 64 atomic_t map_count; 65 + struct rw_semaphore lock; 66 + atomic_t lock_count; 65 67 }; 66 68 67 69 /* appended to fb_info */ ··· 189 187 return ovl->enable(ovl); 190 188 else 191 189 return ovl->disable(ovl); 190 + } 191 + 192 + static inline struct omapfb2_mem_region * 193 + omapfb_get_mem_region(struct omapfb2_mem_region *rg) 194 + { 195 + down_read_nested(&rg->lock, rg->id); 196 + atomic_inc(&rg->lock_count); 197 + return rg; 198 + } 199 + 200 + static inline void omapfb_put_mem_region(struct omapfb2_mem_region *rg) 201 + { 202 + atomic_dec(&rg->lock_count); 203 + up_read(&rg->lock); 192 204 } 193 205 194 206 #endif