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