xref: /openbmc/linux/drivers/scsi/scsi_logging.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
155716d26SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2ded85c19SHannes Reinecke /*
3ded85c19SHannes Reinecke  * scsi_logging.c
4ded85c19SHannes Reinecke  *
5ded85c19SHannes Reinecke  * Copyright (C) 2014 SUSE Linux Products GmbH
6ded85c19SHannes Reinecke  * Copyright (C) 2014 Hannes Reinecke <hare@suse.de>
7ded85c19SHannes Reinecke  */
8ded85c19SHannes Reinecke 
9ded85c19SHannes Reinecke #include <linux/kernel.h>
10ded85c19SHannes Reinecke #include <linux/atomic.h>
11ded85c19SHannes Reinecke 
12ded85c19SHannes Reinecke #include <scsi/scsi.h>
13ded85c19SHannes Reinecke #include <scsi/scsi_cmnd.h>
14ded85c19SHannes Reinecke #include <scsi/scsi_device.h>
159e5ed2a5SHannes Reinecke #include <scsi/scsi_eh.h>
16ded85c19SHannes Reinecke #include <scsi/scsi_dbg.h>
17ded85c19SHannes Reinecke 
scsi_log_reserve_buffer(size_t * len)18ded85c19SHannes Reinecke static char *scsi_log_reserve_buffer(size_t *len)
19ded85c19SHannes Reinecke {
20dccc96abSBart Van Assche 	*len = 128;
21dccc96abSBart Van Assche 	return kmalloc(*len, GFP_ATOMIC);
22ded85c19SHannes Reinecke }
23ded85c19SHannes Reinecke 
scsi_log_release_buffer(char * bufptr)24ded85c19SHannes Reinecke static void scsi_log_release_buffer(char *bufptr)
25ded85c19SHannes Reinecke {
26dccc96abSBart Van Assche 	kfree(bufptr);
27ded85c19SHannes Reinecke }
28ded85c19SHannes Reinecke 
scmd_name(const struct scsi_cmnd * scmd)2921045519SHannes Reinecke static inline const char *scmd_name(const struct scsi_cmnd *scmd)
3021045519SHannes Reinecke {
31aa8e25e5SBart Van Assche 	struct request *rq = scsi_cmd_to_rq((struct scsi_cmnd *)scmd);
32aa8e25e5SBart Van Assche 
33*f06aa52cSTomas Henzl 	if (!rq->q || !rq->q->disk)
34f3fa33acSChristoph Hellwig 		return NULL;
35f3fa33acSChristoph Hellwig 	return rq->q->disk->disk_name;
3621045519SHannes Reinecke }
3721045519SHannes Reinecke 
sdev_format_header(char * logbuf,size_t logbuf_len,const char * name,int tag)3821045519SHannes Reinecke static size_t sdev_format_header(char *logbuf, size_t logbuf_len,
3921045519SHannes Reinecke 				 const char *name, int tag)
409e5ed2a5SHannes Reinecke {
419e5ed2a5SHannes Reinecke 	size_t off = 0;
429e5ed2a5SHannes Reinecke 
4321045519SHannes Reinecke 	if (name)
449e5ed2a5SHannes Reinecke 		off += scnprintf(logbuf + off, logbuf_len - off,
4521045519SHannes Reinecke 				 "[%s] ", name);
469e5ed2a5SHannes Reinecke 
479e5ed2a5SHannes Reinecke 	if (WARN_ON(off >= logbuf_len))
489e5ed2a5SHannes Reinecke 		return off;
499e5ed2a5SHannes Reinecke 
509e5ed2a5SHannes Reinecke 	if (tag >= 0)
519e5ed2a5SHannes Reinecke 		off += scnprintf(logbuf + off, logbuf_len - off,
529e5ed2a5SHannes Reinecke 				 "tag#%d ", tag);
539e5ed2a5SHannes Reinecke 	return off;
549e5ed2a5SHannes Reinecke }
559e5ed2a5SHannes Reinecke 
sdev_prefix_printk(const char * level,const struct scsi_device * sdev,const char * name,const char * fmt,...)569c4a6b1eSHannes Reinecke void sdev_prefix_printk(const char *level, const struct scsi_device *sdev,
57ded85c19SHannes Reinecke 			const char *name, const char *fmt, ...)
58ded85c19SHannes Reinecke {
59ded85c19SHannes Reinecke 	va_list args;
60ded85c19SHannes Reinecke 	char *logbuf;
61ded85c19SHannes Reinecke 	size_t off = 0, logbuf_len;
62ded85c19SHannes Reinecke 
63ded85c19SHannes Reinecke 	if (!sdev)
649c4a6b1eSHannes Reinecke 		return;
65ded85c19SHannes Reinecke 
66ded85c19SHannes Reinecke 	logbuf = scsi_log_reserve_buffer(&logbuf_len);
67ded85c19SHannes Reinecke 	if (!logbuf)
689c4a6b1eSHannes Reinecke 		return;
69ded85c19SHannes Reinecke 
70ded85c19SHannes Reinecke 	if (name)
71ded85c19SHannes Reinecke 		off += scnprintf(logbuf + off, logbuf_len - off,
72ded85c19SHannes Reinecke 				 "[%s] ", name);
739e5ed2a5SHannes Reinecke 	if (!WARN_ON(off >= logbuf_len)) {
74ded85c19SHannes Reinecke 		va_start(args, fmt);
75ded85c19SHannes Reinecke 		off += vscnprintf(logbuf + off, logbuf_len - off, fmt, args);
76ded85c19SHannes Reinecke 		va_end(args);
779e5ed2a5SHannes Reinecke 	}
789c4a6b1eSHannes Reinecke 	dev_printk(level, &sdev->sdev_gendev, "%s", logbuf);
79ded85c19SHannes Reinecke 	scsi_log_release_buffer(logbuf);
80ded85c19SHannes Reinecke }
81ded85c19SHannes Reinecke EXPORT_SYMBOL(sdev_prefix_printk);
82ded85c19SHannes Reinecke 
scmd_printk(const char * level,const struct scsi_cmnd * scmd,const char * fmt,...)839c4a6b1eSHannes Reinecke void scmd_printk(const char *level, const struct scsi_cmnd *scmd,
84ded85c19SHannes Reinecke 		const char *fmt, ...)
85ded85c19SHannes Reinecke {
86ded85c19SHannes Reinecke 	va_list args;
87ded85c19SHannes Reinecke 	char *logbuf;
88ded85c19SHannes Reinecke 	size_t off = 0, logbuf_len;
89ded85c19SHannes Reinecke 
90ce70fd9aSChristoph Hellwig 	if (!scmd)
919c4a6b1eSHannes Reinecke 		return;
92ded85c19SHannes Reinecke 
93ded85c19SHannes Reinecke 	logbuf = scsi_log_reserve_buffer(&logbuf_len);
94ded85c19SHannes Reinecke 	if (!logbuf)
959c4a6b1eSHannes Reinecke 		return;
9621045519SHannes Reinecke 	off = sdev_format_header(logbuf, logbuf_len, scmd_name(scmd),
97aa8e25e5SBart Van Assche 				 scsi_cmd_to_rq((struct scsi_cmnd *)scmd)->tag);
989e5ed2a5SHannes Reinecke 	if (off < logbuf_len) {
99ded85c19SHannes Reinecke 		va_start(args, fmt);
100ded85c19SHannes Reinecke 		off += vscnprintf(logbuf + off, logbuf_len - off, fmt, args);
101ded85c19SHannes Reinecke 		va_end(args);
1029e5ed2a5SHannes Reinecke 	}
1039c4a6b1eSHannes Reinecke 	dev_printk(level, &scmd->device->sdev_gendev, "%s", logbuf);
104ded85c19SHannes Reinecke 	scsi_log_release_buffer(logbuf);
105ded85c19SHannes Reinecke }
106ded85c19SHannes Reinecke EXPORT_SYMBOL(scmd_printk);
1079e5ed2a5SHannes Reinecke 
scsi_format_opcode_name(char * buffer,size_t buf_len,const unsigned char * cdbp)1089e5ed2a5SHannes Reinecke static size_t scsi_format_opcode_name(char *buffer, size_t buf_len,
1099e5ed2a5SHannes Reinecke 				      const unsigned char *cdbp)
1109e5ed2a5SHannes Reinecke {
1119e5ed2a5SHannes Reinecke 	int sa, cdb0;
1129e5ed2a5SHannes Reinecke 	const char *cdb_name = NULL, *sa_name = NULL;
1139e5ed2a5SHannes Reinecke 	size_t off;
1149e5ed2a5SHannes Reinecke 
1159e5ed2a5SHannes Reinecke 	cdb0 = cdbp[0];
1169e5ed2a5SHannes Reinecke 	if (cdb0 == VARIABLE_LENGTH_CMD) {
1179e5ed2a5SHannes Reinecke 		int len = scsi_varlen_cdb_length(cdbp);
1189e5ed2a5SHannes Reinecke 
1199e5ed2a5SHannes Reinecke 		if (len < 10) {
1209e5ed2a5SHannes Reinecke 			off = scnprintf(buffer, buf_len,
1219e5ed2a5SHannes Reinecke 					"short variable length command, len=%d",
1229e5ed2a5SHannes Reinecke 					len);
1239e5ed2a5SHannes Reinecke 			return off;
1249e5ed2a5SHannes Reinecke 		}
1259e5ed2a5SHannes Reinecke 		sa = (cdbp[8] << 8) + cdbp[9];
1269e5ed2a5SHannes Reinecke 	} else
1279e5ed2a5SHannes Reinecke 		sa = cdbp[1] & 0x1f;
1289e5ed2a5SHannes Reinecke 
1299e5ed2a5SHannes Reinecke 	if (!scsi_opcode_sa_name(cdb0, sa, &cdb_name, &sa_name)) {
1309e5ed2a5SHannes Reinecke 		if (cdb_name)
1319e5ed2a5SHannes Reinecke 			off = scnprintf(buffer, buf_len, "%s", cdb_name);
1329e5ed2a5SHannes Reinecke 		else {
1339e5ed2a5SHannes Reinecke 			off = scnprintf(buffer, buf_len, "opcode=0x%x", cdb0);
1349e5ed2a5SHannes Reinecke 			if (WARN_ON(off >= buf_len))
1359e5ed2a5SHannes Reinecke 				return off;
1369e5ed2a5SHannes Reinecke 			if (cdb0 >= VENDOR_SPECIFIC_CDB)
1379e5ed2a5SHannes Reinecke 				off += scnprintf(buffer + off, buf_len - off,
1389e5ed2a5SHannes Reinecke 						 " (vendor)");
1399e5ed2a5SHannes Reinecke 			else if (cdb0 >= 0x60 && cdb0 < 0x7e)
1409e5ed2a5SHannes Reinecke 				off += scnprintf(buffer + off, buf_len - off,
1419e5ed2a5SHannes Reinecke 						 " (reserved)");
1429e5ed2a5SHannes Reinecke 		}
1439e5ed2a5SHannes Reinecke 	} else {
1449e5ed2a5SHannes Reinecke 		if (sa_name)
1459e5ed2a5SHannes Reinecke 			off = scnprintf(buffer, buf_len, "%s", sa_name);
1469e5ed2a5SHannes Reinecke 		else if (cdb_name)
1479e5ed2a5SHannes Reinecke 			off = scnprintf(buffer, buf_len, "%s, sa=0x%x",
1489e5ed2a5SHannes Reinecke 					cdb_name, sa);
1499e5ed2a5SHannes Reinecke 		else
1509e5ed2a5SHannes Reinecke 			off = scnprintf(buffer, buf_len,
1519e5ed2a5SHannes Reinecke 					"opcode=0x%x, sa=0x%x", cdb0, sa);
1529e5ed2a5SHannes Reinecke 	}
1539e5ed2a5SHannes Reinecke 	WARN_ON(off >= buf_len);
1549e5ed2a5SHannes Reinecke 	return off;
1559e5ed2a5SHannes Reinecke }
1569e5ed2a5SHannes Reinecke 
__scsi_format_command(char * logbuf,size_t logbuf_len,const unsigned char * cdb,size_t cdb_len)1579e5ed2a5SHannes Reinecke size_t __scsi_format_command(char *logbuf, size_t logbuf_len,
1589e5ed2a5SHannes Reinecke 			     const unsigned char *cdb, size_t cdb_len)
1599e5ed2a5SHannes Reinecke {
1609e5ed2a5SHannes Reinecke 	int len, k;
1619e5ed2a5SHannes Reinecke 	size_t off;
1629e5ed2a5SHannes Reinecke 
1639e5ed2a5SHannes Reinecke 	off = scsi_format_opcode_name(logbuf, logbuf_len, cdb);
1649e5ed2a5SHannes Reinecke 	if (off >= logbuf_len)
1659e5ed2a5SHannes Reinecke 		return off;
1669e5ed2a5SHannes Reinecke 	len = scsi_command_size(cdb);
1679e5ed2a5SHannes Reinecke 	if (cdb_len < len)
1689e5ed2a5SHannes Reinecke 		len = cdb_len;
1699e5ed2a5SHannes Reinecke 	/* print out all bytes in cdb */
1709e5ed2a5SHannes Reinecke 	for (k = 0; k < len; ++k) {
1719e5ed2a5SHannes Reinecke 		if (off > logbuf_len - 3)
1729e5ed2a5SHannes Reinecke 			break;
1739e5ed2a5SHannes Reinecke 		off += scnprintf(logbuf + off, logbuf_len - off,
1749e5ed2a5SHannes Reinecke 				 " %02x", cdb[k]);
1759e5ed2a5SHannes Reinecke 	}
1769e5ed2a5SHannes Reinecke 	return off;
1779e5ed2a5SHannes Reinecke }
1789e5ed2a5SHannes Reinecke EXPORT_SYMBOL(__scsi_format_command);
1799e5ed2a5SHannes Reinecke 
scsi_print_command(struct scsi_cmnd * cmd)1809e5ed2a5SHannes Reinecke void scsi_print_command(struct scsi_cmnd *cmd)
1819e5ed2a5SHannes Reinecke {
1829e5ed2a5SHannes Reinecke 	int k;
1839e5ed2a5SHannes Reinecke 	char *logbuf;
1849e5ed2a5SHannes Reinecke 	size_t off, logbuf_len;
1859e5ed2a5SHannes Reinecke 
1869e5ed2a5SHannes Reinecke 	logbuf = scsi_log_reserve_buffer(&logbuf_len);
1879e5ed2a5SHannes Reinecke 	if (!logbuf)
1889e5ed2a5SHannes Reinecke 		return;
1899e5ed2a5SHannes Reinecke 
19021045519SHannes Reinecke 	off = sdev_format_header(logbuf, logbuf_len,
191aa8e25e5SBart Van Assche 				 scmd_name(cmd), scsi_cmd_to_rq(cmd)->tag);
1929e5ed2a5SHannes Reinecke 	if (off >= logbuf_len)
1939e5ed2a5SHannes Reinecke 		goto out_printk;
1949e5ed2a5SHannes Reinecke 	off += scnprintf(logbuf + off, logbuf_len - off, "CDB: ");
1959e5ed2a5SHannes Reinecke 	if (WARN_ON(off >= logbuf_len))
1969e5ed2a5SHannes Reinecke 		goto out_printk;
1979e5ed2a5SHannes Reinecke 
1989e5ed2a5SHannes Reinecke 	off += scsi_format_opcode_name(logbuf + off, logbuf_len - off,
1999e5ed2a5SHannes Reinecke 				       cmd->cmnd);
2009e5ed2a5SHannes Reinecke 	if (off >= logbuf_len)
2019e5ed2a5SHannes Reinecke 		goto out_printk;
2029e5ed2a5SHannes Reinecke 
2039e5ed2a5SHannes Reinecke 	/* print out all bytes in cdb */
2049e5ed2a5SHannes Reinecke 	if (cmd->cmd_len > 16) {
2059e5ed2a5SHannes Reinecke 		/* Print opcode in one line and use separate lines for CDB */
2069e5ed2a5SHannes Reinecke 		off += scnprintf(logbuf + off, logbuf_len - off, "\n");
2072fc583c4SChristoph Hellwig 		dev_printk(KERN_INFO, &cmd->device->sdev_gendev, "%s", logbuf);
2089e5ed2a5SHannes Reinecke 		for (k = 0; k < cmd->cmd_len; k += 16) {
2099e5ed2a5SHannes Reinecke 			size_t linelen = min(cmd->cmd_len - k, 16);
2109e5ed2a5SHannes Reinecke 
21121045519SHannes Reinecke 			off = sdev_format_header(logbuf, logbuf_len,
21221045519SHannes Reinecke 						 scmd_name(cmd),
213aa8e25e5SBart Van Assche 						 scsi_cmd_to_rq(cmd)->tag);
2149e5ed2a5SHannes Reinecke 			if (!WARN_ON(off > logbuf_len - 58)) {
2159e5ed2a5SHannes Reinecke 				off += scnprintf(logbuf + off, logbuf_len - off,
2169e5ed2a5SHannes Reinecke 						 "CDB[%02x]: ", k);
2179e5ed2a5SHannes Reinecke 				hex_dump_to_buffer(&cmd->cmnd[k], linelen,
2189e5ed2a5SHannes Reinecke 						   16, 1, logbuf + off,
2199e5ed2a5SHannes Reinecke 						   logbuf_len - off, false);
2209e5ed2a5SHannes Reinecke 			}
2212fc583c4SChristoph Hellwig 			dev_printk(KERN_INFO, &cmd->device->sdev_gendev, "%s",
2229e5ed2a5SHannes Reinecke 				   logbuf);
2239e5ed2a5SHannes Reinecke 		}
224811f3947SYe Bin 		goto out;
2259e5ed2a5SHannes Reinecke 	}
2269e5ed2a5SHannes Reinecke 	if (!WARN_ON(off > logbuf_len - 49)) {
2279e5ed2a5SHannes Reinecke 		off += scnprintf(logbuf + off, logbuf_len - off, " ");
2289e5ed2a5SHannes Reinecke 		hex_dump_to_buffer(cmd->cmnd, cmd->cmd_len, 16, 1,
2299e5ed2a5SHannes Reinecke 				   logbuf + off, logbuf_len - off,
2309e5ed2a5SHannes Reinecke 				   false);
2319e5ed2a5SHannes Reinecke 	}
2329e5ed2a5SHannes Reinecke out_printk:
2332fc583c4SChristoph Hellwig 	dev_printk(KERN_INFO, &cmd->device->sdev_gendev, "%s", logbuf);
234811f3947SYe Bin out:
2359e5ed2a5SHannes Reinecke 	scsi_log_release_buffer(logbuf);
2369e5ed2a5SHannes Reinecke }
2379e5ed2a5SHannes Reinecke EXPORT_SYMBOL(scsi_print_command);
23821045519SHannes Reinecke 
23921045519SHannes Reinecke static size_t
scsi_format_extd_sense(char * buffer,size_t buf_len,unsigned char asc,unsigned char ascq)24021045519SHannes Reinecke scsi_format_extd_sense(char *buffer, size_t buf_len,
24121045519SHannes Reinecke 		       unsigned char asc, unsigned char ascq)
24221045519SHannes Reinecke {
24321045519SHannes Reinecke 	size_t off = 0;
24421045519SHannes Reinecke 	const char *extd_sense_fmt = NULL;
24521045519SHannes Reinecke 	const char *extd_sense_str = scsi_extd_sense_format(asc, ascq,
24621045519SHannes Reinecke 							    &extd_sense_fmt);
24721045519SHannes Reinecke 
24821045519SHannes Reinecke 	if (extd_sense_str) {
24921045519SHannes Reinecke 		off = scnprintf(buffer, buf_len, "Add. Sense: %s",
25021045519SHannes Reinecke 				extd_sense_str);
25121045519SHannes Reinecke 		if (extd_sense_fmt)
25221045519SHannes Reinecke 			off += scnprintf(buffer + off, buf_len - off,
25321045519SHannes Reinecke 					 "(%s%x)", extd_sense_fmt, ascq);
25421045519SHannes Reinecke 	} else {
25521045519SHannes Reinecke 		if (asc >= 0x80)
25621045519SHannes Reinecke 			off = scnprintf(buffer, buf_len, "<<vendor>>");
25721045519SHannes Reinecke 		off += scnprintf(buffer + off, buf_len - off,
25821045519SHannes Reinecke 				 "ASC=0x%x ", asc);
25921045519SHannes Reinecke 		if (ascq >= 0x80)
26021045519SHannes Reinecke 			off += scnprintf(buffer + off, buf_len - off,
26121045519SHannes Reinecke 					 "<<vendor>>");
26221045519SHannes Reinecke 		off += scnprintf(buffer + off, buf_len - off,
26321045519SHannes Reinecke 				 "ASCQ=0x%x ", ascq);
26421045519SHannes Reinecke 	}
26521045519SHannes Reinecke 	return off;
26621045519SHannes Reinecke }
26721045519SHannes Reinecke 
26821045519SHannes Reinecke static size_t
scsi_format_sense_hdr(char * buffer,size_t buf_len,const struct scsi_sense_hdr * sshdr)26921045519SHannes Reinecke scsi_format_sense_hdr(char *buffer, size_t buf_len,
27021045519SHannes Reinecke 		      const struct scsi_sense_hdr *sshdr)
27121045519SHannes Reinecke {
27221045519SHannes Reinecke 	const char *sense_txt;
27321045519SHannes Reinecke 	size_t off;
27421045519SHannes Reinecke 
27521045519SHannes Reinecke 	off = scnprintf(buffer, buf_len, "Sense Key : ");
27621045519SHannes Reinecke 	sense_txt = scsi_sense_key_string(sshdr->sense_key);
27721045519SHannes Reinecke 	if (sense_txt)
27821045519SHannes Reinecke 		off += scnprintf(buffer + off, buf_len - off,
27921045519SHannes Reinecke 				 "%s ", sense_txt);
28021045519SHannes Reinecke 	else
28121045519SHannes Reinecke 		off += scnprintf(buffer + off, buf_len - off,
28221045519SHannes Reinecke 				 "0x%x ", sshdr->sense_key);
28321045519SHannes Reinecke 	off += scnprintf(buffer + off, buf_len - off,
28421045519SHannes Reinecke 		scsi_sense_is_deferred(sshdr) ? "[deferred] " : "[current] ");
28521045519SHannes Reinecke 
28621045519SHannes Reinecke 	if (sshdr->response_code >= 0x72)
28721045519SHannes Reinecke 		off += scnprintf(buffer + off, buf_len - off, "[descriptor] ");
28821045519SHannes Reinecke 	return off;
28921045519SHannes Reinecke }
29021045519SHannes Reinecke 
29121045519SHannes Reinecke static void
scsi_log_dump_sense(const struct scsi_device * sdev,const char * name,int tag,const unsigned char * sense_buffer,int sense_len)29221045519SHannes Reinecke scsi_log_dump_sense(const struct scsi_device *sdev, const char *name, int tag,
29321045519SHannes Reinecke 		    const unsigned char *sense_buffer, int sense_len)
29421045519SHannes Reinecke {
29521045519SHannes Reinecke 	char *logbuf;
29621045519SHannes Reinecke 	size_t logbuf_len;
29721045519SHannes Reinecke 	int i;
29821045519SHannes Reinecke 
29921045519SHannes Reinecke 	logbuf = scsi_log_reserve_buffer(&logbuf_len);
30021045519SHannes Reinecke 	if (!logbuf)
30121045519SHannes Reinecke 		return;
30221045519SHannes Reinecke 
30321045519SHannes Reinecke 	for (i = 0; i < sense_len; i += 16) {
30421045519SHannes Reinecke 		int len = min(sense_len - i, 16);
30521045519SHannes Reinecke 		size_t off;
30621045519SHannes Reinecke 
30721045519SHannes Reinecke 		off = sdev_format_header(logbuf, logbuf_len,
30821045519SHannes Reinecke 					 name, tag);
30921045519SHannes Reinecke 		hex_dump_to_buffer(&sense_buffer[i], len, 16, 1,
31021045519SHannes Reinecke 				   logbuf + off, logbuf_len - off,
31121045519SHannes Reinecke 				   false);
3122fc583c4SChristoph Hellwig 		dev_printk(KERN_INFO, &sdev->sdev_gendev, "%s", logbuf);
31321045519SHannes Reinecke 	}
31421045519SHannes Reinecke 	scsi_log_release_buffer(logbuf);
31521045519SHannes Reinecke }
31621045519SHannes Reinecke 
31721045519SHannes Reinecke static void
scsi_log_print_sense_hdr(const struct scsi_device * sdev,const char * name,int tag,const struct scsi_sense_hdr * sshdr)31821045519SHannes Reinecke scsi_log_print_sense_hdr(const struct scsi_device *sdev, const char *name,
31921045519SHannes Reinecke 			 int tag, const struct scsi_sense_hdr *sshdr)
32021045519SHannes Reinecke {
32121045519SHannes Reinecke 	char *logbuf;
32221045519SHannes Reinecke 	size_t off, logbuf_len;
32321045519SHannes Reinecke 
32421045519SHannes Reinecke 	logbuf = scsi_log_reserve_buffer(&logbuf_len);
32521045519SHannes Reinecke 	if (!logbuf)
32621045519SHannes Reinecke 		return;
32721045519SHannes Reinecke 	off = sdev_format_header(logbuf, logbuf_len, name, tag);
32821045519SHannes Reinecke 	off += scsi_format_sense_hdr(logbuf + off, logbuf_len - off, sshdr);
3292fc583c4SChristoph Hellwig 	dev_printk(KERN_INFO, &sdev->sdev_gendev, "%s", logbuf);
33021045519SHannes Reinecke 	scsi_log_release_buffer(logbuf);
33121045519SHannes Reinecke 
33221045519SHannes Reinecke 	logbuf = scsi_log_reserve_buffer(&logbuf_len);
33321045519SHannes Reinecke 	if (!logbuf)
33421045519SHannes Reinecke 		return;
33521045519SHannes Reinecke 	off = sdev_format_header(logbuf, logbuf_len, name, tag);
33621045519SHannes Reinecke 	off += scsi_format_extd_sense(logbuf + off, logbuf_len - off,
33721045519SHannes Reinecke 				      sshdr->asc, sshdr->ascq);
3382fc583c4SChristoph Hellwig 	dev_printk(KERN_INFO, &sdev->sdev_gendev, "%s", logbuf);
33921045519SHannes Reinecke 	scsi_log_release_buffer(logbuf);
34021045519SHannes Reinecke }
34121045519SHannes Reinecke 
34221045519SHannes Reinecke static void
scsi_log_print_sense(const struct scsi_device * sdev,const char * name,int tag,const unsigned char * sense_buffer,int sense_len)34321045519SHannes Reinecke scsi_log_print_sense(const struct scsi_device *sdev, const char *name, int tag,
34421045519SHannes Reinecke 		     const unsigned char *sense_buffer, int sense_len)
34521045519SHannes Reinecke {
34621045519SHannes Reinecke 	struct scsi_sense_hdr sshdr;
34721045519SHannes Reinecke 
34821045519SHannes Reinecke 	if (scsi_normalize_sense(sense_buffer, sense_len, &sshdr))
34921045519SHannes Reinecke 		scsi_log_print_sense_hdr(sdev, name, tag, &sshdr);
35021045519SHannes Reinecke 	else
35121045519SHannes Reinecke 		scsi_log_dump_sense(sdev, name, tag, sense_buffer, sense_len);
35221045519SHannes Reinecke }
35321045519SHannes Reinecke 
35421045519SHannes Reinecke /*
35521045519SHannes Reinecke  * Print normalized SCSI sense header with a prefix.
35621045519SHannes Reinecke  */
35721045519SHannes Reinecke void
scsi_print_sense_hdr(const struct scsi_device * sdev,const char * name,const struct scsi_sense_hdr * sshdr)35821045519SHannes Reinecke scsi_print_sense_hdr(const struct scsi_device *sdev, const char *name,
35921045519SHannes Reinecke 		     const struct scsi_sense_hdr *sshdr)
36021045519SHannes Reinecke {
36121045519SHannes Reinecke 	scsi_log_print_sense_hdr(sdev, name, -1, sshdr);
36221045519SHannes Reinecke }
36321045519SHannes Reinecke EXPORT_SYMBOL(scsi_print_sense_hdr);
36421045519SHannes Reinecke 
36521045519SHannes Reinecke /* Normalize and print sense buffer with name prefix */
__scsi_print_sense(const struct scsi_device * sdev,const char * name,const unsigned char * sense_buffer,int sense_len)36621045519SHannes Reinecke void __scsi_print_sense(const struct scsi_device *sdev, const char *name,
36721045519SHannes Reinecke 			const unsigned char *sense_buffer, int sense_len)
36821045519SHannes Reinecke {
36921045519SHannes Reinecke 	scsi_log_print_sense(sdev, name, -1, sense_buffer, sense_len);
37021045519SHannes Reinecke }
37121045519SHannes Reinecke EXPORT_SYMBOL(__scsi_print_sense);
37221045519SHannes Reinecke 
37321045519SHannes Reinecke /* Normalize and print sense buffer in SCSI command */
scsi_print_sense(const struct scsi_cmnd * cmd)37421045519SHannes Reinecke void scsi_print_sense(const struct scsi_cmnd *cmd)
37521045519SHannes Reinecke {
376aa8e25e5SBart Van Assche 	scsi_log_print_sense(cmd->device, scmd_name(cmd),
377aa8e25e5SBart Van Assche 			     scsi_cmd_to_rq((struct scsi_cmnd *)cmd)->tag,
37821045519SHannes Reinecke 			     cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
37921045519SHannes Reinecke }
38021045519SHannes Reinecke EXPORT_SYMBOL(scsi_print_sense);
381026f8da8SHannes Reinecke 
scsi_print_result(const struct scsi_cmnd * cmd,const char * msg,int disposition)382026f8da8SHannes Reinecke void scsi_print_result(const struct scsi_cmnd *cmd, const char *msg,
383026f8da8SHannes Reinecke 		       int disposition)
384026f8da8SHannes Reinecke {
385026f8da8SHannes Reinecke 	char *logbuf;
386026f8da8SHannes Reinecke 	size_t off, logbuf_len;
387026f8da8SHannes Reinecke 	const char *mlret_string = scsi_mlreturn_string(disposition);
388026f8da8SHannes Reinecke 	const char *hb_string = scsi_hostbyte_string(cmd->result);
3898ee132b3SMilan P. Gandhi 	unsigned long cmd_age = (jiffies - cmd->jiffies_at_alloc) / HZ;
390026f8da8SHannes Reinecke 
391026f8da8SHannes Reinecke 	logbuf = scsi_log_reserve_buffer(&logbuf_len);
392026f8da8SHannes Reinecke 	if (!logbuf)
393026f8da8SHannes Reinecke 		return;
394026f8da8SHannes Reinecke 
395aa8e25e5SBart Van Assche 	off = sdev_format_header(logbuf, logbuf_len, scmd_name(cmd),
396aa8e25e5SBart Van Assche 				 scsi_cmd_to_rq((struct scsi_cmnd *)cmd)->tag);
397026f8da8SHannes Reinecke 
398026f8da8SHannes Reinecke 	if (off >= logbuf_len)
399026f8da8SHannes Reinecke 		goto out_printk;
400026f8da8SHannes Reinecke 
401026f8da8SHannes Reinecke 	if (msg) {
402026f8da8SHannes Reinecke 		off += scnprintf(logbuf + off, logbuf_len - off,
403026f8da8SHannes Reinecke 				 "%s: ", msg);
404026f8da8SHannes Reinecke 		if (WARN_ON(off >= logbuf_len))
405026f8da8SHannes Reinecke 			goto out_printk;
406026f8da8SHannes Reinecke 	}
407026f8da8SHannes Reinecke 	if (mlret_string)
408026f8da8SHannes Reinecke 		off += scnprintf(logbuf + off, logbuf_len - off,
409026f8da8SHannes Reinecke 				 "%s ", mlret_string);
410026f8da8SHannes Reinecke 	else
411026f8da8SHannes Reinecke 		off += scnprintf(logbuf + off, logbuf_len - off,
412026f8da8SHannes Reinecke 				 "UNKNOWN(0x%02x) ", disposition);
413026f8da8SHannes Reinecke 	if (WARN_ON(off >= logbuf_len))
414026f8da8SHannes Reinecke 		goto out_printk;
415026f8da8SHannes Reinecke 
416026f8da8SHannes Reinecke 	off += scnprintf(logbuf + off, logbuf_len - off, "Result: ");
417026f8da8SHannes Reinecke 	if (WARN_ON(off >= logbuf_len))
418026f8da8SHannes Reinecke 		goto out_printk;
419026f8da8SHannes Reinecke 
420026f8da8SHannes Reinecke 	if (hb_string)
421026f8da8SHannes Reinecke 		off += scnprintf(logbuf + off, logbuf_len - off,
422026f8da8SHannes Reinecke 				 "hostbyte=%s ", hb_string);
423026f8da8SHannes Reinecke 	else
424026f8da8SHannes Reinecke 		off += scnprintf(logbuf + off, logbuf_len - off,
425026f8da8SHannes Reinecke 				 "hostbyte=0x%02x ", host_byte(cmd->result));
426026f8da8SHannes Reinecke 	if (WARN_ON(off >= logbuf_len))
427026f8da8SHannes Reinecke 		goto out_printk;
428026f8da8SHannes Reinecke 
429026f8da8SHannes Reinecke 	off += scnprintf(logbuf + off, logbuf_len - off,
43054c29086SHannes Reinecke 			 "driverbyte=DRIVER_OK ");
4318ee132b3SMilan P. Gandhi 
4328ee132b3SMilan P. Gandhi 	off += scnprintf(logbuf + off, logbuf_len - off,
4338ee132b3SMilan P. Gandhi 			 "cmd_age=%lus", cmd_age);
4348ee132b3SMilan P. Gandhi 
435026f8da8SHannes Reinecke out_printk:
4362fc583c4SChristoph Hellwig 	dev_printk(KERN_INFO, &cmd->device->sdev_gendev, "%s", logbuf);
437026f8da8SHannes Reinecke 	scsi_log_release_buffer(logbuf);
438026f8da8SHannes Reinecke }
439026f8da8SHannes Reinecke EXPORT_SYMBOL(scsi_print_result);
440