···293293 return 0;294294}295295EXPORT_SYMBOL(scsi_set_sense_information);296296+297297+/**298298+ * scsi_set_sense_field_pointer - set the field pointer sense key299299+ * specific information in a formatted sense data buffer300300+ * @buf: Where to build sense data301301+ * @buf_len: buffer length302302+ * @fp: field pointer to be set303303+ * @bp: bit pointer to be set304304+ * @cd: command/data bit305305+ *306306+ * Return value:307307+ * 0 on success or EINVAL for invalid sense buffer length308308+ */309309+int scsi_set_sense_field_pointer(u8 *buf, int buf_len, u16 fp, u8 bp, bool cd)310310+{311311+ u8 *ucp, len;312312+313313+ if ((buf[0] & 0x7f) == 0x72) {314314+ len = buf[7];315315+ ucp = (char *)scsi_sense_desc_find(buf, len + 8, 2);316316+ if (!ucp) {317317+ buf[7] = len + 8;318318+ ucp = buf + 8 + len;319319+ }320320+321321+ if (buf_len < len + 8)322322+ /* Not enough room for info */323323+ return -EINVAL;324324+325325+ ucp[0] = 2;326326+ ucp[1] = 6;327327+ ucp[4] = 0x80; /* Valid bit */328328+ if (cd)329329+ ucp[4] |= 0x40;330330+ if (bp < 0x8)331331+ ucp[4] |= 0x8 | bp;332332+ put_unaligned_be16(fp, &ucp[5]);333333+ } else if ((buf[0] & 0x7f) == 0x70) {334334+ len = buf[7];335335+ if (len < 18)336336+ buf[7] = 18;337337+338338+ buf[15] = 0x80;339339+ if (cd)340340+ buf[15] |= 0x40;341341+ if (bp < 0x8)342342+ buf[15] |= 0x8 | bp;343343+ put_unaligned_be16(fp, &buf[16]);344344+ }345345+346346+ return 0;347347+}348348+EXPORT_SYMBOL(scsi_set_sense_field_pointer);
+1
include/scsi/scsi_common.h
···63636464extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq);6565int scsi_set_sense_information(u8 *buf, int buf_len, u64 info);6666+int scsi_set_sense_field_pointer(u8 *buf, int buf_len, u16 fp, u8 bp, bool cd);6667extern const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,6768 int desc_type);6869