diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/ses.c | 38 |
1 files changed, 10 insertions, 28 deletions
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c index eba183c428cf..80bfece1a2de 100644 --- a/drivers/scsi/ses.c +++ b/drivers/scsi/ses.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/enclosure.h> | 27 | #include <linux/enclosure.h> |
28 | #include <asm/unaligned.h> | ||
28 | 29 | ||
29 | #include <scsi/scsi.h> | 30 | #include <scsi/scsi.h> |
30 | #include <scsi/scsi_cmnd.h> | 31 | #include <scsi/scsi_cmnd.h> |
@@ -448,27 +449,18 @@ static void ses_enclosure_data_process(struct enclosure_device *edev, | |||
448 | static void ses_match_to_enclosure(struct enclosure_device *edev, | 449 | static void ses_match_to_enclosure(struct enclosure_device *edev, |
449 | struct scsi_device *sdev) | 450 | struct scsi_device *sdev) |
450 | { | 451 | { |
451 | unsigned char *buf; | ||
452 | unsigned char *desc; | 452 | unsigned char *desc; |
453 | unsigned int vpd_len; | ||
454 | struct efd efd = { | 453 | struct efd efd = { |
455 | .addr = 0, | 454 | .addr = 0, |
456 | }; | 455 | }; |
457 | 456 | ||
458 | buf = kmalloc(INIT_ALLOC_SIZE, GFP_KERNEL); | ||
459 | if (!buf || scsi_get_vpd_page(sdev, 0x83, buf, INIT_ALLOC_SIZE)) | ||
460 | goto free; | ||
461 | |||
462 | ses_enclosure_data_process(edev, to_scsi_device(edev->edev.parent), 0); | 457 | ses_enclosure_data_process(edev, to_scsi_device(edev->edev.parent), 0); |
463 | 458 | ||
464 | vpd_len = ((buf[2] << 8) | buf[3]) + 4; | 459 | if (!sdev->vpd_pg83_len) |
465 | kfree(buf); | 460 | return; |
466 | buf = kmalloc(vpd_len, GFP_KERNEL); | ||
467 | if (!buf ||scsi_get_vpd_page(sdev, 0x83, buf, vpd_len)) | ||
468 | goto free; | ||
469 | 461 | ||
470 | desc = buf + 4; | 462 | desc = sdev->vpd_pg83 + 4; |
471 | while (desc < buf + vpd_len) { | 463 | while (desc < sdev->vpd_pg83 + sdev->vpd_pg83_len) { |
472 | enum scsi_protocol proto = desc[0] >> 4; | 464 | enum scsi_protocol proto = desc[0] >> 4; |
473 | u8 code_set = desc[0] & 0x0f; | 465 | u8 code_set = desc[0] & 0x0f; |
474 | u8 piv = desc[1] & 0x80; | 466 | u8 piv = desc[1] & 0x80; |
@@ -478,25 +470,15 @@ static void ses_match_to_enclosure(struct enclosure_device *edev, | |||
478 | 470 | ||
479 | if (piv && code_set == 1 && assoc == 1 | 471 | if (piv && code_set == 1 && assoc == 1 |
480 | && proto == SCSI_PROTOCOL_SAS && type == 3 && len == 8) | 472 | && proto == SCSI_PROTOCOL_SAS && type == 3 && len == 8) |
481 | efd.addr = (u64)desc[4] << 56 | | 473 | efd.addr = get_unaligned_be64(&desc[4]); |
482 | (u64)desc[5] << 48 | | ||
483 | (u64)desc[6] << 40 | | ||
484 | (u64)desc[7] << 32 | | ||
485 | (u64)desc[8] << 24 | | ||
486 | (u64)desc[9] << 16 | | ||
487 | (u64)desc[10] << 8 | | ||
488 | (u64)desc[11]; | ||
489 | 474 | ||
490 | desc += len + 4; | 475 | desc += len + 4; |
491 | } | 476 | } |
492 | if (!efd.addr) | 477 | if (efd.addr) { |
493 | goto free; | 478 | efd.dev = &sdev->sdev_gendev; |
494 | 479 | ||
495 | efd.dev = &sdev->sdev_gendev; | 480 | enclosure_for_each_device(ses_enclosure_find_by_addr, &efd); |
496 | 481 | } | |
497 | enclosure_for_each_device(ses_enclosure_find_by_addr, &efd); | ||
498 | free: | ||
499 | kfree(buf); | ||
500 | } | 482 | } |
501 | 483 | ||
502 | static int ses_intf_add(struct device *cdev, | 484 | static int ses_intf_add(struct device *cdev, |