summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMitko Haralanov <mitko.haralanov@intel.com>2018-05-02 09:43:24 -0400
committerDoug Ledford <dledford@redhat.com>2018-05-09 15:53:30 -0400
commita74d5307caba42fe9bbc180feb03003f14f9f45c (patch)
treea1bac0b78d9931dc5efde4f30e7a4acb1ff32f7c
parent8d3e71136a080d007620472f50c7b3e63ba0f5cf (diff)
IB/hfi1: Rework fault injection machinery
The packet fault injection code present in the HFI1 driver had some issues which not only fragment the code but also created user confusion. Furthermore, it suffered from the following issues: 1. The fault_packet method only worked for received packets. This meant that the only fault injection mode available for sent packets is fault_opcode, which did not allow for random packet drops on all egressing packets. 2. The mask available for the fault_opcode mode did not really work due to the fact that the opcode values are not bits in a bitmask but rather sequential integer values. Creating a opcode/mask pair that would successfully capture a set of packets was nearly impossible. 3. The code was fragmented and used too many debugfs entries to operate and control. This was confusing to users. 4. It did not allow filtering fault injection on a per direction basis - egress vs. ingress. In order to improve or fix the above issues, the following changes have been made: 1. The fault injection methods have been combined into a single fault injection facility. As such, the fault injection has been plugged into both the send and receive code paths. Regardless of method used the fault injection will operate on both egress and ingress packets. 2. The type of fault injection - by packet or by opcode - is now controlled by changing the boolean value of the file "opcode_mode". When the value is set to True, fault injection is done by opcode. Otherwise, by packet. 2. The masking ability has been removed in favor of a bitmap that holds opcodes of interest (one bit per opcode, a total of 256 bits). This works in tandem with the "opcode_mode" value. When the value of "opcode_mode" is False, this bitmap is ignored. When the value is True, the bitmap lists all opcodes to be considered for fault injection. By default, the bitmap is empty. When the user wants to filter by opcode, the user sets the corresponding bit in the bitmap by echo'ing the bit position into the 'opcodes' file. This gets around the issue that the set of opcodes does not lend itself to effective masks and allow for extremely fine-grained filtering by opcode. 4. fault_packet and fault_opcode methods have been combined. Hence, there is only one debugfs directory controlling the entire operation of the fault injection machinery. This reduces the number of debugfs entries and provides a more unified user experience. 5. A new control files - "direction" - is provided to allow the user to control the direction of packets, which are subject to fault injection. 6. A new control file - "skip_usec" - is added that would allow the user to specify a "timeout" during which no fault injection will occur. In addition, the following bug fixes have been applied: 1. The fault injection code has been split into its own header and source files. This was done to better organize the code and support conditional compilation without littering the code with #ifdef's. 2. The method by which the TX PIO packets were being marked for drop conflicted with the way send contexts were being setup. As a result, the send context was repeatedly being reset. 3. The fault injection only makes sense when the user can control it through the debugfs entries. However, a kernel configuration can enable fault injection but keep fault injection debugfs entries disabled. Therefore, it makes sense that the HFI fault injection code depends on both. 4. Error suppression did not take into account the method by which PIO packets were being dropped. Therefore, even with error suppression turned on, errors would still be displayed to the screen. A larger enough packet drop percentage would case the kernel to crash because the driver would be stuck printing errors. Reviewed-by: Dennis Dalessandro <dennis.dalessandro@intel.com> Reviewed-by: Don Hiatt <don.hiatt@intel.com> Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com> Signed-off-by: Mitko Haralanov <mitko.haralanov@intel.com> Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/hw/hfi1/Makefile10
-rw-r--r--drivers/infiniband/hw/hfi1/chip.c3
-rw-r--r--drivers/infiniband/hw/hfi1/debugfs.c296
-rw-r--r--drivers/infiniband/hw/hfi1/debugfs.h93
-rw-r--r--drivers/infiniband/hw/hfi1/driver.c20
-rw-r--r--drivers/infiniband/hw/hfi1/fault.c375
-rw-r--r--drivers/infiniband/hw/hfi1/fault.h109
-rw-r--r--drivers/infiniband/hw/hfi1/hfi.h10
-rw-r--r--drivers/infiniband/hw/hfi1/verbs.c13
-rw-r--r--drivers/infiniband/hw/hfi1/verbs.h6
10 files changed, 577 insertions, 358 deletions
diff --git a/drivers/infiniband/hw/hfi1/Makefile b/drivers/infiniband/hw/hfi1/Makefile
index ce4010bad982..f451ba912f47 100644
--- a/drivers/infiniband/hw/hfi1/Makefile
+++ b/drivers/infiniband/hw/hfi1/Makefile
@@ -14,7 +14,15 @@ hfi1-y := affinity.o chip.o device.o driver.o efivar.o \
14 qp.o qsfp.o rc.o ruc.o sdma.o sysfs.o trace.o \ 14 qp.o qsfp.o rc.o ruc.o sdma.o sysfs.o trace.o \
15 uc.o ud.o user_exp_rcv.o user_pages.o user_sdma.o verbs.o \ 15 uc.o ud.o user_exp_rcv.o user_pages.o user_sdma.o verbs.o \
16 verbs_txreq.o vnic_main.o vnic_sdma.o 16 verbs_txreq.o vnic_main.o vnic_sdma.o
17hfi1-$(CONFIG_DEBUG_FS) += debugfs.o 17
18ifdef CONFIG_DEBUG_FS
19hfi1-y += debugfs.o
20ifdef CONFIG_FAULT_INJECTION
21ifdef CONFIG_FAULT_INJECTION_DEBUG_FS
22hfi1-y += fault.o
23endif
24endif
25endif
18 26
19CFLAGS_trace.o = -I$(src) 27CFLAGS_trace.o = -I$(src)
20ifdef MVERSION 28ifdef MVERSION
diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c
index 4cd422ff92f8..582cf7eb779f 100644
--- a/drivers/infiniband/hw/hfi1/chip.c
+++ b/drivers/infiniband/hw/hfi1/chip.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright(c) 2015 - 2017 Intel Corporation. 2 * Copyright(c) 2015 - 2018 Intel Corporation.
3 * 3 *
4 * This file is provided under a dual BSD/GPLv2 license. When using or 4 * This file is provided under a dual BSD/GPLv2 license. When using or
5 * redistributing this file, you may do so under either license. 5 * redistributing this file, you may do so under either license.
@@ -65,6 +65,7 @@
65#include "aspm.h" 65#include "aspm.h"
66#include "affinity.h" 66#include "affinity.h"
67#include "debugfs.h" 67#include "debugfs.h"
68#include "fault.h"
68 69
69#define NUM_IB_PORTS 1 70#define NUM_IB_PORTS 1
70 71
diff --git a/drivers/infiniband/hw/hfi1/debugfs.c b/drivers/infiniband/hw/hfi1/debugfs.c
index 5343960610fe..9f992ae36c89 100644
--- a/drivers/infiniband/hw/hfi1/debugfs.c
+++ b/drivers/infiniband/hw/hfi1/debugfs.c
@@ -60,15 +60,13 @@
60#include "device.h" 60#include "device.h"
61#include "qp.h" 61#include "qp.h"
62#include "sdma.h" 62#include "sdma.h"
63#include "fault.h"
63 64
64static struct dentry *hfi1_dbg_root; 65static struct dentry *hfi1_dbg_root;
65 66
66/* wrappers to enforce srcu in seq file */ 67/* wrappers to enforce srcu in seq file */
67static ssize_t hfi1_seq_read( 68ssize_t hfi1_seq_read(struct file *file, char __user *buf, size_t size,
68 struct file *file, 69 loff_t *ppos)
69 char __user *buf,
70 size_t size,
71 loff_t *ppos)
72{ 70{
73 struct dentry *d = file->f_path.dentry; 71 struct dentry *d = file->f_path.dentry;
74 ssize_t r; 72 ssize_t r;
@@ -81,10 +79,7 @@ static ssize_t hfi1_seq_read(
81 return r; 79 return r;
82} 80}
83 81
84static loff_t hfi1_seq_lseek( 82loff_t hfi1_seq_lseek(struct file *file, loff_t offset, int whence)
85 struct file *file,
86 loff_t offset,
87 int whence)
88{ 83{
89 struct dentry *d = file->f_path.dentry; 84 struct dentry *d = file->f_path.dentry;
90 loff_t r; 85 loff_t r;
@@ -100,48 +95,6 @@ static loff_t hfi1_seq_lseek(
100#define private2dd(file) (file_inode(file)->i_private) 95#define private2dd(file) (file_inode(file)->i_private)
101#define private2ppd(file) (file_inode(file)->i_private) 96#define private2ppd(file) (file_inode(file)->i_private)
102 97
103#define DEBUGFS_SEQ_FILE_OPS(name) \
104static const struct seq_operations _##name##_seq_ops = { \
105 .start = _##name##_seq_start, \
106 .next = _##name##_seq_next, \
107 .stop = _##name##_seq_stop, \
108 .show = _##name##_seq_show \
109}
110
111#define DEBUGFS_SEQ_FILE_OPEN(name) \
112static int _##name##_open(struct inode *inode, struct file *s) \
113{ \
114 struct seq_file *seq; \
115 int ret; \
116 ret = seq_open(s, &_##name##_seq_ops); \
117 if (ret) \
118 return ret; \
119 seq = s->private_data; \
120 seq->private = inode->i_private; \
121 return 0; \
122}
123
124#define DEBUGFS_FILE_OPS(name) \
125static const struct file_operations _##name##_file_ops = { \
126 .owner = THIS_MODULE, \
127 .open = _##name##_open, \
128 .read = hfi1_seq_read, \
129 .llseek = hfi1_seq_lseek, \
130 .release = seq_release \
131}
132
133#define DEBUGFS_FILE_CREATE(name, parent, data, ops, mode) \
134do { \
135 struct dentry *ent; \
136 ent = debugfs_create_file(name, mode, parent, \
137 data, ops); \
138 if (!ent) \
139 pr_warn("create of %s failed\n", name); \
140} while (0)
141
142#define DEBUGFS_SEQ_FILE_CREATE(name, parent, data) \
143 DEBUGFS_FILE_CREATE(#name, parent, data, &_##name##_file_ops, S_IRUGO)
144
145static void *_opcode_stats_seq_start(struct seq_file *s, loff_t *pos) 98static void *_opcode_stats_seq_start(struct seq_file *s, loff_t *pos)
146{ 99{
147 struct hfi1_opcode_stats_perctx *opstats; 100 struct hfi1_opcode_stats_perctx *opstats;
@@ -1160,236 +1113,6 @@ DEBUGFS_SEQ_FILE_OPS(sdma_cpu_list);
1160DEBUGFS_SEQ_FILE_OPEN(sdma_cpu_list) 1113DEBUGFS_SEQ_FILE_OPEN(sdma_cpu_list)
1161DEBUGFS_FILE_OPS(sdma_cpu_list); 1114DEBUGFS_FILE_OPS(sdma_cpu_list);
1162 1115
1163#ifdef CONFIG_FAULT_INJECTION
1164static void *_fault_stats_seq_start(struct seq_file *s, loff_t *pos)
1165{
1166 struct hfi1_opcode_stats_perctx *opstats;
1167
1168 if (*pos >= ARRAY_SIZE(opstats->stats))
1169 return NULL;
1170 return pos;
1171}
1172
1173static void *_fault_stats_seq_next(struct seq_file *s, void *v, loff_t *pos)
1174{
1175 struct hfi1_opcode_stats_perctx *opstats;
1176
1177 ++*pos;
1178 if (*pos >= ARRAY_SIZE(opstats->stats))
1179 return NULL;
1180 return pos;
1181}
1182
1183static void _fault_stats_seq_stop(struct seq_file *s, void *v)
1184{
1185}
1186
1187static int _fault_stats_seq_show(struct seq_file *s, void *v)
1188{
1189 loff_t *spos = v;
1190 loff_t i = *spos, j;
1191 u64 n_packets = 0, n_bytes = 0;
1192 struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
1193 struct hfi1_devdata *dd = dd_from_dev(ibd);
1194 struct hfi1_ctxtdata *rcd;
1195
1196 for (j = 0; j < dd->first_dyn_alloc_ctxt; j++) {
1197 rcd = hfi1_rcd_get_by_index(dd, j);
1198 if (rcd) {
1199 n_packets += rcd->opstats->stats[i].n_packets;
1200 n_bytes += rcd->opstats->stats[i].n_bytes;
1201 }
1202 hfi1_rcd_put(rcd);
1203 }
1204 for_each_possible_cpu(j) {
1205 struct hfi1_opcode_stats_perctx *sp =
1206 per_cpu_ptr(dd->tx_opstats, j);
1207
1208 n_packets += sp->stats[i].n_packets;
1209 n_bytes += sp->stats[i].n_bytes;
1210 }
1211 if (!n_packets && !n_bytes)
1212 return SEQ_SKIP;
1213 if (!ibd->fault_opcode->n_rxfaults[i] &&
1214 !ibd->fault_opcode->n_txfaults[i])
1215 return SEQ_SKIP;
1216 seq_printf(s, "%02llx %llu/%llu (faults rx:%llu faults: tx:%llu)\n", i,
1217 (unsigned long long)n_packets,
1218 (unsigned long long)n_bytes,
1219 (unsigned long long)ibd->fault_opcode->n_rxfaults[i],
1220 (unsigned long long)ibd->fault_opcode->n_txfaults[i]);
1221 return 0;
1222}
1223
1224DEBUGFS_SEQ_FILE_OPS(fault_stats);
1225DEBUGFS_SEQ_FILE_OPEN(fault_stats);
1226DEBUGFS_FILE_OPS(fault_stats);
1227
1228static void fault_exit_opcode_debugfs(struct hfi1_ibdev *ibd)
1229{
1230 if (ibd->fault_opcode)
1231 debugfs_remove_recursive(ibd->fault_opcode->dir);
1232 kfree(ibd->fault_opcode);
1233 ibd->fault_opcode = NULL;
1234}
1235
1236static int fault_init_opcode_debugfs(struct hfi1_ibdev *ibd)
1237{
1238 struct dentry *parent = ibd->hfi1_ibdev_dbg;
1239
1240 ibd->fault_opcode = kzalloc(sizeof(*ibd->fault_opcode), GFP_KERNEL);
1241 if (!ibd->fault_opcode)
1242 return -ENOMEM;
1243
1244 ibd->fault_opcode->attr.interval = 1;
1245 ibd->fault_opcode->attr.require_end = ULONG_MAX;
1246 ibd->fault_opcode->attr.stacktrace_depth = 32;
1247 ibd->fault_opcode->attr.dname = NULL;
1248 ibd->fault_opcode->attr.verbose = 0;
1249 ibd->fault_opcode->fault_by_opcode = false;
1250 ibd->fault_opcode->opcode = 0;
1251 ibd->fault_opcode->mask = 0xff;
1252
1253 ibd->fault_opcode->dir =
1254 fault_create_debugfs_attr("fault_opcode",
1255 parent,
1256 &ibd->fault_opcode->attr);
1257 if (IS_ERR(ibd->fault_opcode->dir)) {
1258 kfree(ibd->fault_opcode);
1259 ibd->fault_opcode = NULL;
1260 return -ENOENT;
1261 }
1262
1263 DEBUGFS_SEQ_FILE_CREATE(fault_stats, ibd->fault_opcode->dir, ibd);
1264 if (!debugfs_create_bool("fault_by_opcode", 0600,
1265 ibd->fault_opcode->dir,
1266 &ibd->fault_opcode->fault_by_opcode))
1267 goto fail;
1268 if (!debugfs_create_x8("opcode", 0600, ibd->fault_opcode->dir,
1269 &ibd->fault_opcode->opcode))
1270 goto fail;
1271 if (!debugfs_create_x8("mask", 0600, ibd->fault_opcode->dir,
1272 &ibd->fault_opcode->mask))
1273 goto fail;
1274
1275 return 0;
1276fail:
1277 fault_exit_opcode_debugfs(ibd);
1278 return -ENOMEM;
1279}
1280
1281static void fault_exit_packet_debugfs(struct hfi1_ibdev *ibd)
1282{
1283 if (ibd->fault_packet)
1284 debugfs_remove_recursive(ibd->fault_packet->dir);
1285 kfree(ibd->fault_packet);
1286 ibd->fault_packet = NULL;
1287}
1288
1289static int fault_init_packet_debugfs(struct hfi1_ibdev *ibd)
1290{
1291 struct dentry *parent = ibd->hfi1_ibdev_dbg;
1292
1293 ibd->fault_packet = kzalloc(sizeof(*ibd->fault_packet), GFP_KERNEL);
1294 if (!ibd->fault_packet)
1295 return -ENOMEM;
1296
1297 ibd->fault_packet->attr.interval = 1;
1298 ibd->fault_packet->attr.require_end = ULONG_MAX;
1299 ibd->fault_packet->attr.stacktrace_depth = 32;
1300 ibd->fault_packet->attr.dname = NULL;
1301 ibd->fault_packet->attr.verbose = 0;
1302 ibd->fault_packet->fault_by_packet = false;
1303
1304 ibd->fault_packet->dir =
1305 fault_create_debugfs_attr("fault_packet",
1306 parent,
1307 &ibd->fault_opcode->attr);
1308 if (IS_ERR(ibd->fault_packet->dir)) {
1309 kfree(ibd->fault_packet);
1310 ibd->fault_packet = NULL;
1311 return -ENOENT;
1312 }
1313
1314 if (!debugfs_create_bool("fault_by_packet", 0600,
1315 ibd->fault_packet->dir,
1316 &ibd->fault_packet->fault_by_packet))
1317 goto fail;
1318 if (!debugfs_create_u64("fault_stats", 0400,
1319 ibd->fault_packet->dir,
1320 &ibd->fault_packet->n_faults))
1321 goto fail;
1322
1323 return 0;
1324fail:
1325 fault_exit_packet_debugfs(ibd);
1326 return -ENOMEM;
1327}
1328
1329static void fault_exit_debugfs(struct hfi1_ibdev *ibd)
1330{
1331 fault_exit_opcode_debugfs(ibd);
1332 fault_exit_packet_debugfs(ibd);
1333}
1334
1335static int fault_init_debugfs(struct hfi1_ibdev *ibd)
1336{
1337 int ret = 0;
1338
1339 ret = fault_init_opcode_debugfs(ibd);
1340 if (ret)
1341 return ret;
1342
1343 ret = fault_init_packet_debugfs(ibd);
1344 if (ret)
1345 fault_exit_opcode_debugfs(ibd);
1346
1347 return ret;
1348}
1349
1350bool hfi1_dbg_fault_suppress_err(struct hfi1_ibdev *ibd)
1351{
1352 return ibd->fault_suppress_err;
1353}
1354
1355bool hfi1_dbg_fault_opcode(struct rvt_qp *qp, u32 opcode, bool rx)
1356{
1357 bool ret = false;
1358 struct hfi1_ibdev *ibd = to_idev(qp->ibqp.device);
1359
1360 if (!ibd->fault_opcode || !ibd->fault_opcode->fault_by_opcode)
1361 return false;
1362 if (ibd->fault_opcode->opcode != (opcode & ibd->fault_opcode->mask))
1363 return false;
1364 ret = should_fail(&ibd->fault_opcode->attr, 1);
1365 if (ret) {
1366 trace_hfi1_fault_opcode(qp, opcode);
1367 if (rx)
1368 ibd->fault_opcode->n_rxfaults[opcode]++;
1369 else
1370 ibd->fault_opcode->n_txfaults[opcode]++;
1371 }
1372 return ret;
1373}
1374
1375bool hfi1_dbg_fault_packet(struct hfi1_packet *packet)
1376{
1377 struct rvt_dev_info *rdi = &packet->rcd->ppd->dd->verbs_dev.rdi;
1378 struct hfi1_ibdev *ibd = dev_from_rdi(rdi);
1379 bool ret = false;
1380
1381 if (!ibd->fault_packet || !ibd->fault_packet->fault_by_packet)
1382 return false;
1383
1384 ret = should_fail(&ibd->fault_packet->attr, 1);
1385 if (ret) {
1386 ++ibd->fault_packet->n_faults;
1387 trace_hfi1_fault_packet(packet);
1388 }
1389 return ret;
1390}
1391#endif
1392
1393void hfi1_dbg_ibdev_init(struct hfi1_ibdev *ibd) 1116void hfi1_dbg_ibdev_init(struct hfi1_ibdev *ibd)
1394{ 1117{
1395 char name[sizeof("port0counters") + 1]; 1118 char name[sizeof("port0counters") + 1];
@@ -1442,21 +1165,14 @@ void hfi1_dbg_ibdev_init(struct hfi1_ibdev *ibd)
1442 S_IRUGO : S_IRUGO | S_IWUSR); 1165 S_IRUGO : S_IRUGO | S_IWUSR);
1443 } 1166 }
1444 1167
1445#ifdef CONFIG_FAULT_INJECTION 1168 hfi1_fault_init_debugfs(ibd);
1446 debugfs_create_bool("fault_suppress_err", 0600,
1447 ibd->hfi1_ibdev_dbg,
1448 &ibd->fault_suppress_err);
1449 fault_init_debugfs(ibd);
1450#endif
1451} 1169}
1452 1170
1453void hfi1_dbg_ibdev_exit(struct hfi1_ibdev *ibd) 1171void hfi1_dbg_ibdev_exit(struct hfi1_ibdev *ibd)
1454{ 1172{
1455 if (!hfi1_dbg_root) 1173 if (!hfi1_dbg_root)
1456 goto out; 1174 goto out;
1457#ifdef CONFIG_FAULT_INJECTION 1175 hfi1_fault_exit_debugfs(ibd);
1458 fault_exit_debugfs(ibd);
1459#endif
1460 debugfs_remove(ibd->hfi1_ibdev_link); 1176 debugfs_remove(ibd->hfi1_ibdev_link);
1461 debugfs_remove_recursive(ibd->hfi1_ibdev_dbg); 1177 debugfs_remove_recursive(ibd->hfi1_ibdev_dbg);
1462out: 1178out:
diff --git a/drivers/infiniband/hw/hfi1/debugfs.h b/drivers/infiniband/hw/hfi1/debugfs.h
index 38c38a98156d..1c91461b108f 100644
--- a/drivers/infiniband/hw/hfi1/debugfs.h
+++ b/drivers/infiniband/hw/hfi1/debugfs.h
@@ -1,7 +1,7 @@
1#ifndef _HFI1_DEBUGFS_H 1#ifndef _HFI1_DEBUGFS_H
2#define _HFI1_DEBUGFS_H 2#define _HFI1_DEBUGFS_H
3/* 3/*
4 * Copyright(c) 2015, 2016 Intel Corporation. 4 * Copyright(c) 2015, 2016, 2018 Intel Corporation.
5 * 5 *
6 * This file is provided under a dual BSD/GPLv2 license. When using or 6 * This file is provided under a dual BSD/GPLv2 license. When using or
7 * redistributing this file, you may do so under either license. 7 * redistributing this file, you may do so under either license.
@@ -48,51 +48,59 @@
48 */ 48 */
49 49
50struct hfi1_ibdev; 50struct hfi1_ibdev;
51#ifdef CONFIG_DEBUG_FS
52void hfi1_dbg_ibdev_init(struct hfi1_ibdev *ibd);
53void hfi1_dbg_ibdev_exit(struct hfi1_ibdev *ibd);
54void hfi1_dbg_init(void);
55void hfi1_dbg_exit(void);
56 51
57#ifdef CONFIG_FAULT_INJECTION 52#define DEBUGFS_FILE_CREATE(name, parent, data, ops, mode) \
58#include <linux/fault-inject.h> 53do { \
59struct fault_opcode { 54 struct dentry *ent; \
60 struct fault_attr attr; 55 const char *__name = name; \
61 struct dentry *dir; 56 ent = debugfs_create_file(__name, mode, parent, \
62 bool fault_by_opcode; 57 data, ops); \
63 u64 n_rxfaults[256]; 58 if (!ent) \
64 u64 n_txfaults[256]; 59 pr_warn("create of %s failed\n", __name); \
65 u8 opcode; 60} while (0)
66 u8 mask; 61
67}; 62#define DEBUGFS_SEQ_FILE_OPS(name) \
68 63static const struct seq_operations _##name##_seq_ops = { \
69struct fault_packet { 64 .start = _##name##_seq_start, \
70 struct fault_attr attr; 65 .next = _##name##_seq_next, \
71 struct dentry *dir; 66 .stop = _##name##_seq_stop, \
72 bool fault_by_packet; 67 .show = _##name##_seq_show \
73 u64 n_faults;
74};
75
76bool hfi1_dbg_fault_opcode(struct rvt_qp *qp, u32 opcode, bool rx);
77bool hfi1_dbg_fault_packet(struct hfi1_packet *packet);
78bool hfi1_dbg_fault_suppress_err(struct hfi1_ibdev *ibd);
79#else
80static inline bool hfi1_dbg_fault_packet(struct hfi1_packet *packet)
81{
82 return false;
83} 68}
84 69
85static inline bool hfi1_dbg_fault_opcode(struct rvt_qp *qp, 70#define DEBUGFS_SEQ_FILE_OPEN(name) \
86 u32 opcode, bool rx) 71static int _##name##_open(struct inode *inode, struct file *s) \
87{ 72{ \
88 return false; 73 struct seq_file *seq; \
74 int ret; \
75 ret = seq_open(s, &_##name##_seq_ops); \
76 if (ret) \
77 return ret; \
78 seq = s->private_data; \
79 seq->private = inode->i_private; \
80 return 0; \
89} 81}
90 82
91static inline bool hfi1_dbg_fault_suppress_err(struct hfi1_ibdev *ibd) 83#define DEBUGFS_FILE_OPS(name) \
92{ 84static const struct file_operations _##name##_file_ops = { \
93 return false; 85 .owner = THIS_MODULE, \
86 .open = _##name##_open, \
87 .read = hfi1_seq_read, \
88 .llseek = hfi1_seq_lseek, \
89 .release = seq_release \
94} 90}
95#endif 91
92#define DEBUGFS_SEQ_FILE_CREATE(name, parent, data) \
93 DEBUGFS_FILE_CREATE(#name, parent, data, &_##name##_file_ops, 0444)
94
95ssize_t hfi1_seq_read(struct file *file, char __user *buf, size_t size,
96 loff_t *ppos);
97loff_t hfi1_seq_lseek(struct file *file, loff_t offset, int whence);
98
99#ifdef CONFIG_DEBUG_FS
100void hfi1_dbg_ibdev_init(struct hfi1_ibdev *ibd);
101void hfi1_dbg_ibdev_exit(struct hfi1_ibdev *ibd);
102void hfi1_dbg_init(void);
103void hfi1_dbg_exit(void);
96 104
97#else 105#else
98static inline void hfi1_dbg_ibdev_init(struct hfi1_ibdev *ibd) 106static inline void hfi1_dbg_ibdev_init(struct hfi1_ibdev *ibd)
@@ -111,13 +119,12 @@ static inline void hfi1_dbg_exit(void)
111{ 119{
112} 120}
113 121
114static inline bool hfi1_dbg_fault_packet(struct hfi1_packet *packet) 122static inline bool hfi1_dbg_should_fault_rx(struct hfi1_packet *packet)
115{ 123{
116 return false; 124 return false;
117} 125}
118 126
119static inline bool hfi1_dbg_fault_opcode(struct rvt_qp *qp, 127static inline bool hfi1_dbg_should_fault_tx(struct rvt_qp *qp, u32 opcode)
120 u32 opcode, bool rx)
121{ 128{
122 return false; 129 return false;
123} 130}
diff --git a/drivers/infiniband/hw/hfi1/driver.c b/drivers/infiniband/hw/hfi1/driver.c
index bd837a048bf4..e5a57ebd8da4 100644
--- a/drivers/infiniband/hw/hfi1/driver.c
+++ b/drivers/infiniband/hw/hfi1/driver.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright(c) 2015-2017 Intel Corporation. 2 * Copyright(c) 2015-2018 Intel Corporation.
3 * 3 *
4 * This file is provided under a dual BSD/GPLv2 license. When using or 4 * This file is provided under a dual BSD/GPLv2 license. When using or
5 * redistributing this file, you may do so under either license. 5 * redistributing this file, you may do so under either license.
@@ -61,6 +61,7 @@
61#include "sdma.h" 61#include "sdma.h"
62#include "debugfs.h" 62#include "debugfs.h"
63#include "vnic.h" 63#include "vnic.h"
64#include "fault.h"
64 65
65#undef pr_fmt 66#undef pr_fmt
66#define pr_fmt(fmt) DRIVER_NAME ": " fmt 67#define pr_fmt(fmt) DRIVER_NAME ": " fmt
@@ -1565,10 +1566,10 @@ void handle_eflags(struct hfi1_packet *packet)
1565 */ 1566 */
1566int process_receive_ib(struct hfi1_packet *packet) 1567int process_receive_ib(struct hfi1_packet *packet)
1567{ 1568{
1568 if (unlikely(hfi1_dbg_fault_packet(packet))) 1569 if (hfi1_setup_9B_packet(packet))
1569 return RHF_RCV_CONTINUE; 1570 return RHF_RCV_CONTINUE;
1570 1571
1571 if (hfi1_setup_9B_packet(packet)) 1572 if (unlikely(hfi1_dbg_should_fault_rx(packet)))
1572 return RHF_RCV_CONTINUE; 1573 return RHF_RCV_CONTINUE;
1573 1574
1574 trace_hfi1_rcvhdr(packet); 1575 trace_hfi1_rcvhdr(packet);
@@ -1642,7 +1643,8 @@ int process_receive_error(struct hfi1_packet *packet)
1642 /* KHdrHCRCErr -- KDETH packet with a bad HCRC */ 1643 /* KHdrHCRCErr -- KDETH packet with a bad HCRC */
1643 if (unlikely( 1644 if (unlikely(
1644 hfi1_dbg_fault_suppress_err(&packet->rcd->dd->verbs_dev) && 1645 hfi1_dbg_fault_suppress_err(&packet->rcd->dd->verbs_dev) &&
1645 rhf_rcv_type_err(packet->rhf) == 3)) 1646 (rhf_rcv_type_err(packet->rhf) == RHF_RCV_TYPE_ERROR ||
1647 packet->rhf & RHF_DC_ERR)))
1646 return RHF_RCV_CONTINUE; 1648 return RHF_RCV_CONTINUE;
1647 1649
1648 hfi1_setup_ib_header(packet); 1650 hfi1_setup_ib_header(packet);
@@ -1657,10 +1659,10 @@ int process_receive_error(struct hfi1_packet *packet)
1657 1659
1658int kdeth_process_expected(struct hfi1_packet *packet) 1660int kdeth_process_expected(struct hfi1_packet *packet)
1659{ 1661{
1660 if (unlikely(hfi1_dbg_fault_packet(packet))) 1662 hfi1_setup_9B_packet(packet);
1663 if (unlikely(hfi1_dbg_should_fault_rx(packet)))
1661 return RHF_RCV_CONTINUE; 1664 return RHF_RCV_CONTINUE;
1662 1665
1663 hfi1_setup_ib_header(packet);
1664 if (unlikely(rhf_err_flags(packet->rhf))) 1666 if (unlikely(rhf_err_flags(packet->rhf)))
1665 handle_eflags(packet); 1667 handle_eflags(packet);
1666 1668
@@ -1671,11 +1673,11 @@ int kdeth_process_expected(struct hfi1_packet *packet)
1671 1673
1672int kdeth_process_eager(struct hfi1_packet *packet) 1674int kdeth_process_eager(struct hfi1_packet *packet)
1673{ 1675{
1674 hfi1_setup_ib_header(packet); 1676 hfi1_setup_9B_packet(packet);
1677 if (unlikely(hfi1_dbg_should_fault_rx(packet)))
1678 return RHF_RCV_CONTINUE;
1675 if (unlikely(rhf_err_flags(packet->rhf))) 1679 if (unlikely(rhf_err_flags(packet->rhf)))
1676 handle_eflags(packet); 1680 handle_eflags(packet);
1677 if (unlikely(hfi1_dbg_fault_packet(packet)))
1678 return RHF_RCV_CONTINUE;
1679 1681
1680 dd_dev_err(packet->rcd->dd, 1682 dd_dev_err(packet->rcd->dd,
1681 "Unhandled eager packet received. Dropping.\n"); 1683 "Unhandled eager packet received. Dropping.\n");
diff --git a/drivers/infiniband/hw/hfi1/fault.c b/drivers/infiniband/hw/hfi1/fault.c
new file mode 100644
index 000000000000..e2290f32c8d9
--- /dev/null
+++ b/drivers/infiniband/hw/hfi1/fault.c
@@ -0,0 +1,375 @@
1/*
2 * Copyright(c) 2018 Intel Corporation.
3 *
4 * This file is provided under a dual BSD/GPLv2 license. When using or
5 * redistributing this file, you may do so under either license.
6 *
7 * GPL LICENSE SUMMARY
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * BSD LICENSE
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 *
24 * - Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 * - Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in
28 * the documentation and/or other materials provided with the
29 * distribution.
30 * - Neither the name of Intel Corporation nor the names of its
31 * contributors may be used to endorse or promote products derived
32 * from this software without specific prior written permission.
33 *
34 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
35 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
36 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
37 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
38 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
41 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
42 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
44 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 *
46 */
47#include <linux/debugfs.h>
48#include <linux/seq_file.h>
49#include <linux/kernel.h>
50#include <linux/module.h>
51#include <linux/types.h>
52#include <linux/bitmap.h>
53
54#include "debugfs.h"
55#include "fault.h"
56#include "trace.h"
57
58#define HFI1_FAULT_DIR_TX BIT(0)
59#define HFI1_FAULT_DIR_RX BIT(1)
60#define HFI1_FAULT_DIR_TXRX (HFI1_FAULT_DIR_TX | HFI1_FAULT_DIR_RX)
61
62static void *_fault_stats_seq_start(struct seq_file *s, loff_t *pos)
63{
64 struct hfi1_opcode_stats_perctx *opstats;
65
66 if (*pos >= ARRAY_SIZE(opstats->stats))
67 return NULL;
68 return pos;
69}
70
71static void *_fault_stats_seq_next(struct seq_file *s, void *v, loff_t *pos)
72{
73 struct hfi1_opcode_stats_perctx *opstats;
74
75 ++*pos;
76 if (*pos >= ARRAY_SIZE(opstats->stats))
77 return NULL;
78 return pos;
79}
80
81static void _fault_stats_seq_stop(struct seq_file *s, void *v)
82{
83}
84
85static int _fault_stats_seq_show(struct seq_file *s, void *v)
86{
87 loff_t *spos = v;
88 loff_t i = *spos, j;
89 u64 n_packets = 0, n_bytes = 0;
90 struct hfi1_ibdev *ibd = (struct hfi1_ibdev *)s->private;
91 struct hfi1_devdata *dd = dd_from_dev(ibd);
92 struct hfi1_ctxtdata *rcd;
93
94 for (j = 0; j < dd->first_dyn_alloc_ctxt; j++) {
95 rcd = hfi1_rcd_get_by_index(dd, j);
96 if (rcd) {
97 n_packets += rcd->opstats->stats[i].n_packets;
98 n_bytes += rcd->opstats->stats[i].n_bytes;
99 }
100 hfi1_rcd_put(rcd);
101 }
102 for_each_possible_cpu(j) {
103 struct hfi1_opcode_stats_perctx *sp =
104 per_cpu_ptr(dd->tx_opstats, j);
105
106 n_packets += sp->stats[i].n_packets;
107 n_bytes += sp->stats[i].n_bytes;
108 }
109 if (!n_packets && !n_bytes)
110 return SEQ_SKIP;
111 if (!ibd->fault->n_rxfaults[i] && !ibd->fault->n_txfaults[i])
112 return SEQ_SKIP;
113 seq_printf(s, "%02llx %llu/%llu (faults rx:%llu faults: tx:%llu)\n", i,
114 (unsigned long long)n_packets,
115 (unsigned long long)n_bytes,
116 (unsigned long long)ibd->fault->n_rxfaults[i],
117 (unsigned long long)ibd->fault->n_txfaults[i]);
118 return 0;
119}
120
121DEBUGFS_SEQ_FILE_OPS(fault_stats);
122DEBUGFS_SEQ_FILE_OPEN(fault_stats);
123DEBUGFS_FILE_OPS(fault_stats);
124
125static int fault_opcodes_open(struct inode *inode, struct file *file)
126{
127 file->private_data = inode->i_private;
128 return nonseekable_open(inode, file);
129}
130
131static ssize_t fault_opcodes_write(struct file *file, const char __user *buf,
132 size_t len, loff_t *pos)
133{
134 ssize_t ret = 0;
135 /* 1280 = 256 opcodes * 4 chars/opcode + 255 commas + NULL */
136 size_t copy, datalen = 1280;
137 char *data, *token, *ptr, *end;
138 struct fault *fault = file->private_data;
139
140 data = kcalloc(datalen, sizeof(*data), GFP_KERNEL);
141 if (!data)
142 return -ENOMEM;
143 copy = min(len, datalen - 1);
144 if (copy_from_user(data, buf, copy))
145 return -EFAULT;
146
147 ret = debugfs_file_get(file->f_path.dentry);
148 if (unlikely(ret))
149 return ret;
150 ptr = data;
151 token = ptr;
152 for (ptr = data; *ptr; ptr = end + 1, token = ptr) {
153 char *dash;
154 unsigned long range_start, range_end, i;
155 bool remove = false;
156
157 end = strchr(ptr, ',');
158 if (end)
159 *end = '\0';
160 if (token[0] == '-') {
161 remove = true;
162 token++;
163 }
164 dash = strchr(token, '-');
165 if (dash)
166 *dash = '\0';
167 if (kstrtoul(token, 0, &range_start))
168 break;
169 if (dash) {
170 token = dash + 1;
171 if (kstrtoul(token, 0, &range_end))
172 break;
173 } else {
174 range_end = range_start;
175 }
176 if (range_start == range_end && range_start == -1UL) {
177 bitmap_zero(fault->opcodes, sizeof(fault->opcodes) *
178 BITS_PER_BYTE);
179 break;
180 }
181 for (i = range_start; i <= range_end; i++) {
182 if (remove)
183 clear_bit(i, fault->opcodes);
184 else
185 set_bit(i, fault->opcodes);
186 }
187 if (!end)
188 break;
189 }
190 ret = len;
191
192 debugfs_file_put(file->f_path.dentry);
193 kfree(data);
194 return ret;
195}
196
197static ssize_t fault_opcodes_read(struct file *file, char __user *buf,
198 size_t len, loff_t *pos)
199{
200 ssize_t ret = 0;
201 char *data;
202 size_t datalen = 1280, size = 0; /* see fault_opcodes_write() */
203 unsigned long bit = 0, zero = 0;
204 struct fault *fault = file->private_data;
205 size_t bitsize = sizeof(fault->opcodes) * BITS_PER_BYTE;
206
207 data = kcalloc(datalen, sizeof(*data), GFP_KERNEL);
208 if (!data)
209 return -ENOMEM;
210 ret = debugfs_file_get(file->f_path.dentry);
211 if (unlikely(ret))
212 return ret;
213 bit = find_first_bit(fault->opcodes, bitsize);
214 while (bit < bitsize) {
215 zero = find_next_zero_bit(fault->opcodes, bitsize, bit);
216 if (zero - 1 != bit)
217 size += snprintf(data + size,
218 datalen - size - 1,
219 "0x%lx-0x%lx,", bit, zero - 1);
220 else
221 size += snprintf(data + size,
222 datalen - size - 1, "0x%lx,",
223 bit);
224 bit = find_next_bit(fault->opcodes, bitsize, zero);
225 }
226 debugfs_file_put(file->f_path.dentry);
227 data[size - 1] = '\n';
228 data[size] = '\0';
229 ret = simple_read_from_buffer(buf, len, pos, data, size);
230 kfree(data);
231 return ret;
232}
233
234static const struct file_operations __fault_opcodes_fops = {
235 .owner = THIS_MODULE,
236 .open = fault_opcodes_open,
237 .read = fault_opcodes_read,
238 .write = fault_opcodes_write,
239 .llseek = no_llseek
240};
241
242void hfi1_fault_exit_debugfs(struct hfi1_ibdev *ibd)
243{
244 if (ibd->fault)
245 debugfs_remove_recursive(ibd->fault->dir);
246 kfree(ibd->fault);
247 ibd->fault = NULL;
248}
249
250int hfi1_fault_init_debugfs(struct hfi1_ibdev *ibd)
251{
252 struct dentry *parent = ibd->hfi1_ibdev_dbg;
253
254 ibd->fault = kzalloc(sizeof(*ibd->fault), GFP_KERNEL);
255 if (!ibd->fault)
256 return -ENOMEM;
257
258 ibd->fault->attr.interval = 1;
259 ibd->fault->attr.require_end = ULONG_MAX;
260 ibd->fault->attr.stacktrace_depth = 32;
261 ibd->fault->attr.dname = NULL;
262 ibd->fault->attr.verbose = 0;
263 ibd->fault->enable = false;
264 ibd->fault->opcode = false;
265 ibd->fault->fault_skip = 0;
266 ibd->fault->skip = 0;
267 ibd->fault->direction = HFI1_FAULT_DIR_TXRX;
268 ibd->fault->suppress_err = false;
269 bitmap_zero(ibd->fault->opcodes,
270 sizeof(ibd->fault->opcodes) * BITS_PER_BYTE);
271
272 ibd->fault->dir =
273 fault_create_debugfs_attr("fault", parent,
274 &ibd->fault->attr);
275 if (IS_ERR(ibd->fault->dir)) {
276 kfree(ibd->fault);
277 ibd->fault = NULL;
278 return -ENOENT;
279 }
280
281 DEBUGFS_SEQ_FILE_CREATE(fault_stats, ibd->fault->dir, ibd);
282 if (!debugfs_create_bool("enable", 0600, ibd->fault->dir,
283 &ibd->fault->enable))
284 goto fail;
285 if (!debugfs_create_bool("suppress_err", 0600,
286 ibd->fault->dir,
287 &ibd->fault->suppress_err))
288 goto fail;
289 if (!debugfs_create_bool("opcode_mode", 0600, ibd->fault->dir,
290 &ibd->fault->opcode))
291 goto fail;
292 if (!debugfs_create_file("opcodes", 0600, ibd->fault->dir,
293 ibd->fault, &__fault_opcodes_fops))
294 goto fail;
295 if (!debugfs_create_u64("skip_pkts", 0600,
296 ibd->fault->dir,
297 &ibd->fault->fault_skip))
298 goto fail;
299 if (!debugfs_create_u64("skip_usec", 0600,
300 ibd->fault->dir,
301 &ibd->fault->fault_skip_usec))
302 goto fail;
303 if (!debugfs_create_u8("direction", 0600, ibd->fault->dir,
304 &ibd->fault->direction))
305 goto fail;
306
307 return 0;
308fail:
309 hfi1_fault_exit_debugfs(ibd);
310 return -ENOMEM;
311}
312
313bool hfi1_dbg_fault_suppress_err(struct hfi1_ibdev *ibd)
314{
315 if (ibd->fault)
316 return ibd->fault->suppress_err;
317 return false;
318}
319
320static bool __hfi1_should_fault(struct hfi1_ibdev *ibd, u32 opcode,
321 u8 direction)
322{
323 bool ret = false;
324
325 if (!ibd->fault || !ibd->fault->enable)
326 return false;
327 if (!(ibd->fault->direction & direction))
328 return false;
329 if (ibd->fault->opcode) {
330 if (bitmap_empty(ibd->fault->opcodes,
331 (sizeof(ibd->fault->opcodes) *
332 BITS_PER_BYTE)))
333 return false;
334 if (!(test_bit(opcode, ibd->fault->opcodes)))
335 return false;
336 }
337 if (ibd->fault->fault_skip_usec &&
338 time_before(jiffies, ibd->fault->skip_usec))
339 return false;
340 if (ibd->fault->fault_skip && ibd->fault->skip) {
341 ibd->fault->skip--;
342 return false;
343 }
344 ret = should_fail(&ibd->fault->attr, 1);
345 if (ret) {
346 ibd->fault->skip = ibd->fault->fault_skip;
347 ibd->fault->skip_usec = jiffies +
348 usecs_to_jiffies(ibd->fault->fault_skip_usec);
349 }
350 return ret;
351}
352
353bool hfi1_dbg_should_fault_tx(struct rvt_qp *qp, u32 opcode)
354{
355 struct hfi1_ibdev *ibd = to_idev(qp->ibqp.device);
356
357 if (__hfi1_should_fault(ibd, opcode, HFI1_FAULT_DIR_TX)) {
358 trace_hfi1_fault_opcode(qp, opcode);
359 ibd->fault->n_txfaults[opcode]++;
360 return true;
361 }
362 return false;
363}
364
365bool hfi1_dbg_should_fault_rx(struct hfi1_packet *packet)
366{
367 struct hfi1_ibdev *ibd = &packet->rcd->dd->verbs_dev;
368
369 if (__hfi1_should_fault(ibd, packet->opcode, HFI1_FAULT_DIR_RX)) {
370 trace_hfi1_fault_packet(packet);
371 ibd->fault->n_rxfaults[packet->opcode]++;
372 return true;
373 }
374 return false;
375}
diff --git a/drivers/infiniband/hw/hfi1/fault.h b/drivers/infiniband/hw/hfi1/fault.h
new file mode 100644
index 000000000000..a83382700a7c
--- /dev/null
+++ b/drivers/infiniband/hw/hfi1/fault.h
@@ -0,0 +1,109 @@
1#ifndef _HFI1_FAULT_H
2#define _HFI1_FAULT_H
3/*
4 * Copyright(c) 2018 Intel Corporation.
5 *
6 * This file is provided under a dual BSD/GPLv2 license. When using or
7 * redistributing this file, you may do so under either license.
8 *
9 * GPL LICENSE SUMMARY
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of version 2 of the GNU General Public License as
13 * published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * BSD LICENSE
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 *
26 * - Redistributions of source code must retain the above copyright
27 * notice, this list of conditions and the following disclaimer.
28 * - Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in
30 * the documentation and/or other materials provided with the
31 * distribution.
32 * - Neither the name of Intel Corporation nor the names of its
33 * contributors may be used to endorse or promote products derived
34 * from this software without specific prior written permission.
35 *
36 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
39 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
40 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 *
48 */
49#include <linux/fault-inject.h>
50#include <linux/dcache.h>
51#include <linux/bitops.h>
52#include <linux/kernel.h>
53#include <rdma/rdma_vt.h>
54
55#include "hfi.h"
56
57struct hfi1_ibdev;
58
59#if defined(CONFIG_FAULT_INJECTION) && defined(CONFIG_FAULT_INJECTION_DEBUG_FS)
60struct fault {
61 struct fault_attr attr;
62 struct dentry *dir;
63 u64 n_rxfaults[(1U << BITS_PER_BYTE)];
64 u64 n_txfaults[(1U << BITS_PER_BYTE)];
65 u64 fault_skip;
66 u64 skip;
67 u64 fault_skip_usec;
68 unsigned long skip_usec;
69 unsigned long opcodes[(1U << BITS_PER_BYTE) / BITS_PER_LONG];
70 bool enable;
71 bool suppress_err;
72 bool opcode;
73 u8 direction;
74};
75
76int hfi1_fault_init_debugfs(struct hfi1_ibdev *ibd);
77bool hfi1_dbg_should_fault_tx(struct rvt_qp *qp, u32 opcode);
78bool hfi1_dbg_should_fault_rx(struct hfi1_packet *packet);
79bool hfi1_dbg_fault_suppress_err(struct hfi1_ibdev *ibd);
80void hfi1_fault_exit_debugfs(struct hfi1_ibdev *ibd);
81
82#else
83
84static inline int hfi1_fault_init_debugfs(struct hfi1_ibdev *ibd)
85{
86 return 0;
87}
88
89static inline bool hfi1_dbg_should_fault_rx(struct hfi1_packet *packet)
90{
91 return false;
92}
93
94static inline bool hfi1_dbg_should_fault_tx(struct rvt_qp *qp,
95 u32 opcode)
96{
97 return false;
98}
99
100static inline bool hfi1_dbg_fault_suppress_err(struct hfi1_ibdev *ibd)
101{
102 return false;
103}
104
105static inline void hfi1_fault_exit_debugfs(struct hfi1_ibdev *ibd)
106{
107}
108#endif
109#endif /* _HFI1_FAULT_H */
diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h
index 9c97c180c35e..9cd758ce7764 100644
--- a/drivers/infiniband/hw/hfi1/hfi.h
+++ b/drivers/infiniband/hw/hfi1/hfi.h
@@ -1,7 +1,7 @@
1#ifndef _HFI1_KERNEL_H 1#ifndef _HFI1_KERNEL_H
2#define _HFI1_KERNEL_H 2#define _HFI1_KERNEL_H
3/* 3/*
4 * Copyright(c) 2015-2017 Intel Corporation. 4 * Copyright(c) 2015-2018 Intel Corporation.
5 * 5 *
6 * This file is provided under a dual BSD/GPLv2 license. When using or 6 * This file is provided under a dual BSD/GPLv2 license. When using or
7 * redistributing this file, you may do so under either license. 7 * redistributing this file, you may do so under either license.
@@ -2049,7 +2049,9 @@ static inline u64 hfi1_pkt_default_send_ctxt_mask(struct hfi1_devdata *dd,
2049 | SEND_CTXT_CHECK_ENABLE_DISALLOW_TOO_LONG_BYPASS_PACKETS_SMASK 2049 | SEND_CTXT_CHECK_ENABLE_DISALLOW_TOO_LONG_BYPASS_PACKETS_SMASK
2050 | SEND_CTXT_CHECK_ENABLE_DISALLOW_TOO_LONG_IB_PACKETS_SMASK 2050 | SEND_CTXT_CHECK_ENABLE_DISALLOW_TOO_LONG_IB_PACKETS_SMASK
2051 | SEND_CTXT_CHECK_ENABLE_DISALLOW_BAD_PKT_LEN_SMASK 2051 | SEND_CTXT_CHECK_ENABLE_DISALLOW_BAD_PKT_LEN_SMASK
2052#ifndef CONFIG_FAULT_INJECTION
2052 | SEND_CTXT_CHECK_ENABLE_DISALLOW_PBC_TEST_SMASK 2053 | SEND_CTXT_CHECK_ENABLE_DISALLOW_PBC_TEST_SMASK
2054#endif
2053 | SEND_CTXT_CHECK_ENABLE_DISALLOW_TOO_SMALL_BYPASS_PACKETS_SMASK 2055 | SEND_CTXT_CHECK_ENABLE_DISALLOW_TOO_SMALL_BYPASS_PACKETS_SMASK
2054 | SEND_CTXT_CHECK_ENABLE_DISALLOW_TOO_SMALL_IB_PACKETS_SMASK 2056 | SEND_CTXT_CHECK_ENABLE_DISALLOW_TOO_SMALL_IB_PACKETS_SMASK
2055 | SEND_CTXT_CHECK_ENABLE_DISALLOW_RAW_IPV6_SMASK 2057 | SEND_CTXT_CHECK_ENABLE_DISALLOW_RAW_IPV6_SMASK
@@ -2062,7 +2064,11 @@ static inline u64 hfi1_pkt_default_send_ctxt_mask(struct hfi1_devdata *dd,
2062 | SEND_CTXT_CHECK_ENABLE_CHECK_ENABLE_SMASK; 2064 | SEND_CTXT_CHECK_ENABLE_CHECK_ENABLE_SMASK;
2063 2065
2064 if (ctxt_type == SC_USER) 2066 if (ctxt_type == SC_USER)
2065 base_sc_integrity |= HFI1_PKT_USER_SC_INTEGRITY; 2067 base_sc_integrity |=
2068#ifndef CONFIG_FAULT_INJECTION
2069 SEND_CTXT_CHECK_ENABLE_DISALLOW_PBC_TEST_SMASK |
2070#endif
2071 HFI1_PKT_USER_SC_INTEGRITY;
2066 else 2072 else
2067 base_sc_integrity |= HFI1_PKT_KERNEL_SC_INTEGRITY; 2073 base_sc_integrity |= HFI1_PKT_KERNEL_SC_INTEGRITY;
2068 2074
diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c
index c8cf4d4984d3..9554e912af98 100644
--- a/drivers/infiniband/hw/hfi1/verbs.c
+++ b/drivers/infiniband/hw/hfi1/verbs.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright(c) 2015 - 2017 Intel Corporation. 2 * Copyright(c) 2015 - 2018 Intel Corporation.
3 * 3 *
4 * This file is provided under a dual BSD/GPLv2 license. When using or 4 * This file is provided under a dual BSD/GPLv2 license. When using or
5 * redistributing this file, you may do so under either license. 5 * redistributing this file, you may do so under either license.
@@ -63,6 +63,7 @@
63#include "verbs_txreq.h" 63#include "verbs_txreq.h"
64#include "debugfs.h" 64#include "debugfs.h"
65#include "vnic.h" 65#include "vnic.h"
66#include "fault.h"
66 67
67static unsigned int hfi1_lkey_table_size = 16; 68static unsigned int hfi1_lkey_table_size = 16;
68module_param_named(lkey_table_size, hfi1_lkey_table_size, uint, 69module_param_named(lkey_table_size, hfi1_lkey_table_size, uint,
@@ -624,10 +625,6 @@ static inline void hfi1_handle_packet(struct hfi1_packet *packet,
624 if (hfi1_do_pkey_check(packet)) 625 if (hfi1_do_pkey_check(packet))
625 goto unlock_drop; 626 goto unlock_drop;
626 627
627 if (unlikely(hfi1_dbg_fault_opcode(packet->qp, packet->opcode,
628 true)))
629 goto unlock_drop;
630
631 spin_lock_irqsave(&packet->qp->r_lock, flags); 628 spin_lock_irqsave(&packet->qp->r_lock, flags);
632 packet_handler = qp_ok(packet); 629 packet_handler = qp_ok(packet);
633 if (likely(packet_handler)) 630 if (likely(packet_handler))
@@ -934,8 +931,7 @@ int hfi1_verbs_send_dma(struct rvt_qp *qp, struct hfi1_pkt_state *ps,
934 else 931 else
935 pbc |= (ib_is_sc5(sc5) << PBC_DC_INFO_SHIFT); 932 pbc |= (ib_is_sc5(sc5) << PBC_DC_INFO_SHIFT);
936 933
937 if (unlikely(hfi1_dbg_fault_opcode(qp, ps->opcode, 934 if (unlikely(hfi1_dbg_should_fault_tx(qp, ps->opcode)))
938 false)))
939 pbc = hfi1_fault_tx(qp, ps->opcode, pbc); 935 pbc = hfi1_fault_tx(qp, ps->opcode, pbc);
940 pbc = create_pbc(ppd, 936 pbc = create_pbc(ppd,
941 pbc, 937 pbc,
@@ -1088,7 +1084,8 @@ int hfi1_verbs_send_pio(struct rvt_qp *qp, struct hfi1_pkt_state *ps,
1088 pbc |= PBC_PACKET_BYPASS | PBC_INSERT_BYPASS_ICRC; 1084 pbc |= PBC_PACKET_BYPASS | PBC_INSERT_BYPASS_ICRC;
1089 else 1085 else
1090 pbc |= (ib_is_sc5(sc5) << PBC_DC_INFO_SHIFT); 1086 pbc |= (ib_is_sc5(sc5) << PBC_DC_INFO_SHIFT);
1091 if (unlikely(hfi1_dbg_fault_opcode(qp, ps->opcode, false))) 1087
1088 if (unlikely(hfi1_dbg_should_fault_tx(qp, ps->opcode)))
1092 pbc = hfi1_fault_tx(qp, ps->opcode, pbc); 1089 pbc = hfi1_fault_tx(qp, ps->opcode, pbc);
1093 pbc = create_pbc(ppd, pbc, qp->srate_mbps, vl, plen); 1090 pbc = create_pbc(ppd, pbc, qp->srate_mbps, vl, plen);
1094 } 1091 }
diff --git a/drivers/infiniband/hw/hfi1/verbs.h b/drivers/infiniband/hw/hfi1/verbs.h
index 2d787b8346ca..081ca52e6621 100644
--- a/drivers/infiniband/hw/hfi1/verbs.h
+++ b/drivers/infiniband/hw/hfi1/verbs.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright(c) 2015 - 2017 Intel Corporation. 2 * Copyright(c) 2015 - 2018 Intel Corporation.
3 * 3 *
4 * This file is provided under a dual BSD/GPLv2 license. When using or 4 * This file is provided under a dual BSD/GPLv2 license. When using or
5 * redistributing this file, you may do so under either license. 5 * redistributing this file, you may do so under either license.
@@ -227,9 +227,7 @@ struct hfi1_ibdev {
227 /* per HFI symlinks to above */ 227 /* per HFI symlinks to above */
228 struct dentry *hfi1_ibdev_link; 228 struct dentry *hfi1_ibdev_link;
229#ifdef CONFIG_FAULT_INJECTION 229#ifdef CONFIG_FAULT_INJECTION
230 struct fault_opcode *fault_opcode; 230 struct fault *fault;
231 struct fault_packet *fault_packet;
232 bool fault_suppress_err;
233#endif 231#endif
234#endif 232#endif
235}; 233};