diff options
author | Hannes Reinecke <hare@suse.de> | 2016-04-04 05:44:04 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2016-04-04 12:07:42 -0400 |
commit | 78db6e30281aa056a6773cb4def00afc158c097f (patch) | |
tree | 1eb35641be9d2663fb56ce70e35e7889237954be | |
parent | 06dbde5f3a44248fc02e24d662ac4849202abb48 (diff) |
scsi: add scsi_set_sense_field_pointer()
Add a function to set the field pointer for SCSI sense codes.
Signed-off-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r-- | drivers/scsi/scsi_common.c | 53 | ||||
-rw-r--r-- | include/scsi/scsi_common.h | 1 |
2 files changed, 54 insertions, 0 deletions
diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c index ce79de822e46..b1383a71400e 100644 --- a/drivers/scsi/scsi_common.c +++ b/drivers/scsi/scsi_common.c | |||
@@ -293,3 +293,56 @@ int scsi_set_sense_information(u8 *buf, int buf_len, u64 info) | |||
293 | return 0; | 293 | return 0; |
294 | } | 294 | } |
295 | EXPORT_SYMBOL(scsi_set_sense_information); | 295 | EXPORT_SYMBOL(scsi_set_sense_information); |
296 | |||
297 | /** | ||
298 | * scsi_set_sense_field_pointer - set the field pointer sense key | ||
299 | * specific information in a formatted sense data buffer | ||
300 | * @buf: Where to build sense data | ||
301 | * @buf_len: buffer length | ||
302 | * @fp: field pointer to be set | ||
303 | * @bp: bit pointer to be set | ||
304 | * @cd: command/data bit | ||
305 | * | ||
306 | * Return value: | ||
307 | * 0 on success or EINVAL for invalid sense buffer length | ||
308 | */ | ||
309 | int scsi_set_sense_field_pointer(u8 *buf, int buf_len, u16 fp, u8 bp, bool cd) | ||
310 | { | ||
311 | u8 *ucp, len; | ||
312 | |||
313 | if ((buf[0] & 0x7f) == 0x72) { | ||
314 | len = buf[7]; | ||
315 | ucp = (char *)scsi_sense_desc_find(buf, len + 8, 2); | ||
316 | if (!ucp) { | ||
317 | buf[7] = len + 8; | ||
318 | ucp = buf + 8 + len; | ||
319 | } | ||
320 | |||
321 | if (buf_len < len + 8) | ||
322 | /* Not enough room for info */ | ||
323 | return -EINVAL; | ||
324 | |||
325 | ucp[0] = 2; | ||
326 | ucp[1] = 6; | ||
327 | ucp[4] = 0x80; /* Valid bit */ | ||
328 | if (cd) | ||
329 | ucp[4] |= 0x40; | ||
330 | if (bp < 0x8) | ||
331 | ucp[4] |= 0x8 | bp; | ||
332 | put_unaligned_be16(fp, &ucp[5]); | ||
333 | } else if ((buf[0] & 0x7f) == 0x70) { | ||
334 | len = buf[7]; | ||
335 | if (len < 18) | ||
336 | buf[7] = 18; | ||
337 | |||
338 | buf[15] = 0x80; | ||
339 | if (cd) | ||
340 | buf[15] |= 0x40; | ||
341 | if (bp < 0x8) | ||
342 | buf[15] |= 0x8 | bp; | ||
343 | put_unaligned_be16(fp, &buf[16]); | ||
344 | } | ||
345 | |||
346 | return 0; | ||
347 | } | ||
348 | EXPORT_SYMBOL(scsi_set_sense_field_pointer); | ||
diff --git a/include/scsi/scsi_common.h b/include/scsi/scsi_common.h index 11571b2a831e..20bf7eaef05a 100644 --- a/include/scsi/scsi_common.h +++ b/include/scsi/scsi_common.h | |||
@@ -63,6 +63,7 @@ extern bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len, | |||
63 | 63 | ||
64 | extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq); | 64 | extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq); |
65 | int scsi_set_sense_information(u8 *buf, int buf_len, u64 info); | 65 | int scsi_set_sense_information(u8 *buf, int buf_len, u64 info); |
66 | int scsi_set_sense_field_pointer(u8 *buf, int buf_len, u16 fp, u8 bp, bool cd); | ||
66 | extern const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len, | 67 | extern const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len, |
67 | int desc_type); | 68 | int desc_type); |
68 | 69 | ||