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

scsi: Rework the code for caching Vital Product Data (VPD)

Introduce the scsi_get_vpd_buf() and scsi_update_vpd_page()
functions. The only functional change in this patch is that if updating
page 0x80 fails that it is attempted to update page 0x83.

Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
Acked-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Shane Seymour <shane.seymour@hpe.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Johannes Thumshirn <jthumshirn@suse.de>
Cc: Shane M Seymour <shane.seymour@hpe.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Bart Van Assche and committed by
Martin K. Petersen
1e3f720a 26e3e3cb

+66 -78
+66 -78
drivers/scsi/scsi.c
··· 412 412 EXPORT_SYMBOL_GPL(scsi_get_vpd_page); 413 413 414 414 /** 415 + * scsi_get_vpd_buf - Get Vital Product Data from a SCSI device 416 + * @sdev: The device to ask 417 + * @page: Which Vital Product Data to return 418 + * @len: Upon success, the VPD length will be stored in *@len. 419 + * 420 + * Returns %NULL upon failure. 421 + */ 422 + static unsigned char *scsi_get_vpd_buf(struct scsi_device *sdev, u8 page, 423 + int *len) 424 + { 425 + unsigned char *vpd_buf; 426 + int vpd_len = SCSI_VPD_PG_LEN, result; 427 + 428 + retry_pg: 429 + vpd_buf = kmalloc(vpd_len, GFP_KERNEL); 430 + if (!vpd_buf) 431 + return NULL; 432 + 433 + result = scsi_vpd_inquiry(sdev, vpd_buf, page, vpd_len); 434 + if (result < 0) { 435 + kfree(vpd_buf); 436 + return NULL; 437 + } 438 + if (result > vpd_len) { 439 + vpd_len = result; 440 + kfree(vpd_buf); 441 + goto retry_pg; 442 + } 443 + 444 + *len = result; 445 + 446 + return vpd_buf; 447 + } 448 + 449 + static void scsi_update_vpd_page(struct scsi_device *sdev, u8 page, 450 + unsigned char __rcu **sdev_vpd_buf, 451 + int *sdev_vpd_len) 452 + { 453 + unsigned char *vpd_buf; 454 + int len; 455 + 456 + vpd_buf = scsi_get_vpd_buf(sdev, page, &len); 457 + if (!vpd_buf) 458 + return; 459 + 460 + mutex_lock(&sdev->inquiry_mutex); 461 + rcu_swap_protected(*sdev_vpd_buf, vpd_buf, 462 + lockdep_is_held(&sdev->inquiry_mutex)); 463 + *sdev_vpd_len = len; 464 + mutex_unlock(&sdev->inquiry_mutex); 465 + 466 + synchronize_rcu(); 467 + 468 + kfree(vpd_buf); 469 + } 470 + 471 + /** 415 472 * scsi_attach_vpd - Attach Vital Product Data to a SCSI device structure 416 473 * @sdev: The device to ask 417 474 * ··· 479 422 */ 480 423 void scsi_attach_vpd(struct scsi_device *sdev) 481 424 { 482 - int result, i; 483 - int vpd_len = SCSI_VPD_PG_LEN; 484 - int pg80_supported = 0; 485 - int pg83_supported = 0; 486 - unsigned char __rcu *vpd_buf, *orig_vpd_buf = NULL; 425 + int i, vpd_len; 426 + unsigned char *vpd_buf; 487 427 488 428 if (!scsi_device_supports_vpd(sdev)) 489 429 return; 490 430 491 - retry_pg0: 492 - vpd_buf = kmalloc(vpd_len, GFP_KERNEL); 431 + /* Ask for all the pages supported by this device */ 432 + vpd_buf = scsi_get_vpd_buf(sdev, 0, &vpd_len); 493 433 if (!vpd_buf) 494 434 return; 495 435 496 - /* Ask for all the pages supported by this device */ 497 - result = scsi_vpd_inquiry(sdev, vpd_buf, 0, vpd_len); 498 - if (result < 0) { 499 - kfree(vpd_buf); 500 - return; 501 - } 502 - if (result > vpd_len) { 503 - vpd_len = result; 504 - kfree(vpd_buf); 505 - goto retry_pg0; 506 - } 507 - 508 - for (i = 4; i < result; i++) { 436 + for (i = 4; i < vpd_len; i++) { 509 437 if (vpd_buf[i] == 0x80) 510 - pg80_supported = 1; 438 + scsi_update_vpd_page(sdev, 0x80, &sdev->vpd_pg80, 439 + &sdev->vpd_pg80_len); 511 440 if (vpd_buf[i] == 0x83) 512 - pg83_supported = 1; 441 + scsi_update_vpd_page(sdev, 0x83, &sdev->vpd_pg83, 442 + &sdev->vpd_pg83_len); 513 443 } 514 444 kfree(vpd_buf); 515 - vpd_len = SCSI_VPD_PG_LEN; 516 - 517 - if (pg80_supported) { 518 - retry_pg80: 519 - vpd_buf = kmalloc(vpd_len, GFP_KERNEL); 520 - if (!vpd_buf) 521 - return; 522 - 523 - result = scsi_vpd_inquiry(sdev, vpd_buf, 0x80, vpd_len); 524 - if (result < 0) { 525 - kfree(vpd_buf); 526 - return; 527 - } 528 - if (result > vpd_len) { 529 - vpd_len = result; 530 - kfree(vpd_buf); 531 - goto retry_pg80; 532 - } 533 - mutex_lock(&sdev->inquiry_mutex); 534 - orig_vpd_buf = sdev->vpd_pg80; 535 - sdev->vpd_pg80_len = result; 536 - rcu_assign_pointer(sdev->vpd_pg80, vpd_buf); 537 - mutex_unlock(&sdev->inquiry_mutex); 538 - synchronize_rcu(); 539 - if (orig_vpd_buf) { 540 - kfree(orig_vpd_buf); 541 - orig_vpd_buf = NULL; 542 - } 543 - vpd_len = SCSI_VPD_PG_LEN; 544 - } 545 - 546 - if (pg83_supported) { 547 - retry_pg83: 548 - vpd_buf = kmalloc(vpd_len, GFP_KERNEL); 549 - if (!vpd_buf) 550 - return; 551 - 552 - result = scsi_vpd_inquiry(sdev, vpd_buf, 0x83, vpd_len); 553 - if (result < 0) { 554 - kfree(vpd_buf); 555 - return; 556 - } 557 - if (result > vpd_len) { 558 - vpd_len = result; 559 - kfree(vpd_buf); 560 - goto retry_pg83; 561 - } 562 - mutex_lock(&sdev->inquiry_mutex); 563 - orig_vpd_buf = sdev->vpd_pg83; 564 - sdev->vpd_pg83_len = result; 565 - rcu_assign_pointer(sdev->vpd_pg83, vpd_buf); 566 - mutex_unlock(&sdev->inquiry_mutex); 567 - synchronize_rcu(); 568 - if (orig_vpd_buf) 569 - kfree(orig_vpd_buf); 570 - } 571 445 } 572 446 573 447 /**