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

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>

authored by

Hannes Reinecke and committed by
Tejun Heo
78db6e30 06dbde5f

+54
+53
drivers/scsi/scsi_common.c
··· 293 293 return 0; 294 294 } 295 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);
+1
include/scsi/scsi_common.h
··· 63 63 64 64 extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq); 65 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 67 extern const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len, 67 68 int desc_type); 68 69