diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/scsi/scsi.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/scsi/scsi.c')
-rw-r--r-- | drivers/scsi/scsi.c | 52 |
1 files changed, 22 insertions, 30 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index dd098cad337b..1c08f6164658 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -940,10 +940,16 @@ EXPORT_SYMBOL(scsi_adjust_queue_depth); | |||
940 | */ | 940 | */ |
941 | int scsi_track_queue_full(struct scsi_device *sdev, int depth) | 941 | int scsi_track_queue_full(struct scsi_device *sdev, int depth) |
942 | { | 942 | { |
943 | if ((jiffies >> 4) == sdev->last_queue_full_time) | 943 | |
944 | /* | ||
945 | * Don't let QUEUE_FULLs on the same | ||
946 | * jiffies count, they could all be from | ||
947 | * same event. | ||
948 | */ | ||
949 | if ((jiffies >> 4) == (sdev->last_queue_full_time >> 4)) | ||
944 | return 0; | 950 | return 0; |
945 | 951 | ||
946 | sdev->last_queue_full_time = (jiffies >> 4); | 952 | sdev->last_queue_full_time = jiffies; |
947 | if (sdev->last_queue_full_depth != depth) { | 953 | if (sdev->last_queue_full_depth != depth) { |
948 | sdev->last_queue_full_count = 1; | 954 | sdev->last_queue_full_count = 1; |
949 | sdev->last_queue_full_depth = depth; | 955 | sdev->last_queue_full_depth = depth; |
@@ -1012,6 +1018,8 @@ static int scsi_vpd_inquiry(struct scsi_device *sdev, unsigned char *buffer, | |||
1012 | * scsi_get_vpd_page - Get Vital Product Data from a SCSI device | 1018 | * scsi_get_vpd_page - Get Vital Product Data from a SCSI device |
1013 | * @sdev: The device to ask | 1019 | * @sdev: The device to ask |
1014 | * @page: Which Vital Product Data to return | 1020 | * @page: Which Vital Product Data to return |
1021 | * @buf: where to store the VPD | ||
1022 | * @buf_len: number of bytes in the VPD buffer area | ||
1015 | * | 1023 | * |
1016 | * SCSI devices may optionally supply Vital Product Data. Each 'page' | 1024 | * SCSI devices may optionally supply Vital Product Data. Each 'page' |
1017 | * of VPD is defined in the appropriate SCSI document (eg SPC, SBC). | 1025 | * of VPD is defined in the appropriate SCSI document (eg SPC, SBC). |
@@ -1020,55 +1028,39 @@ static int scsi_vpd_inquiry(struct scsi_device *sdev, unsigned char *buffer, | |||
1020 | * responsible for calling kfree() on this pointer when it is no longer | 1028 | * responsible for calling kfree() on this pointer when it is no longer |
1021 | * needed. If we cannot retrieve the VPD page this routine returns %NULL. | 1029 | * needed. If we cannot retrieve the VPD page this routine returns %NULL. |
1022 | */ | 1030 | */ |
1023 | unsigned char *scsi_get_vpd_page(struct scsi_device *sdev, u8 page) | 1031 | int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf, |
1032 | int buf_len) | ||
1024 | { | 1033 | { |
1025 | int i, result; | 1034 | int i, result; |
1026 | unsigned int len; | ||
1027 | const unsigned int init_vpd_len = 255; | ||
1028 | unsigned char *buf = kmalloc(init_vpd_len, GFP_KERNEL); | ||
1029 | |||
1030 | if (!buf) | ||
1031 | return NULL; | ||
1032 | 1035 | ||
1033 | /* Ask for all the pages supported by this device */ | 1036 | /* Ask for all the pages supported by this device */ |
1034 | result = scsi_vpd_inquiry(sdev, buf, 0, init_vpd_len); | 1037 | result = scsi_vpd_inquiry(sdev, buf, 0, buf_len); |
1035 | if (result) | 1038 | if (result) |
1036 | goto fail; | 1039 | goto fail; |
1037 | 1040 | ||
1038 | /* If the user actually wanted this page, we can skip the rest */ | 1041 | /* If the user actually wanted this page, we can skip the rest */ |
1039 | if (page == 0) | 1042 | if (page == 0) |
1040 | return buf; | 1043 | return -EINVAL; |
1041 | 1044 | ||
1042 | for (i = 0; i < buf[3]; i++) | 1045 | for (i = 0; i < min((int)buf[3], buf_len - 4); i++) |
1043 | if (buf[i + 4] == page) | 1046 | if (buf[i + 4] == page) |
1044 | goto found; | 1047 | goto found; |
1048 | |||
1049 | if (i < buf[3] && i > buf_len) | ||
1050 | /* ran off the end of the buffer, give us benefit of doubt */ | ||
1051 | goto found; | ||
1045 | /* The device claims it doesn't support the requested page */ | 1052 | /* The device claims it doesn't support the requested page */ |
1046 | goto fail; | 1053 | goto fail; |
1047 | 1054 | ||
1048 | found: | 1055 | found: |
1049 | result = scsi_vpd_inquiry(sdev, buf, page, 255); | 1056 | result = scsi_vpd_inquiry(sdev, buf, page, buf_len); |
1050 | if (result) | ||
1051 | goto fail; | ||
1052 | |||
1053 | /* | ||
1054 | * Some pages are longer than 255 bytes. The actual length of | ||
1055 | * the page is returned in the header. | ||
1056 | */ | ||
1057 | len = ((buf[2] << 8) | buf[3]) + 4; | ||
1058 | if (len <= init_vpd_len) | ||
1059 | return buf; | ||
1060 | |||
1061 | kfree(buf); | ||
1062 | buf = kmalloc(len, GFP_KERNEL); | ||
1063 | result = scsi_vpd_inquiry(sdev, buf, page, len); | ||
1064 | if (result) | 1057 | if (result) |
1065 | goto fail; | 1058 | goto fail; |
1066 | 1059 | ||
1067 | return buf; | 1060 | return 0; |
1068 | 1061 | ||
1069 | fail: | 1062 | fail: |
1070 | kfree(buf); | 1063 | return -EINVAL; |
1071 | return NULL; | ||
1072 | } | 1064 | } |
1073 | EXPORT_SYMBOL_GPL(scsi_get_vpd_page); | 1065 | EXPORT_SYMBOL_GPL(scsi_get_vpd_page); |
1074 | 1066 | ||