diff options
author | James Smart <james.smart@emulex.com> | 2011-02-16 12:40:06 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2011-02-18 16:36:33 -0500 |
commit | 2a622bfbe1d95664ecd4bc1cfe6dacf4788dfc10 (patch) | |
tree | 25d1bb419a3036612fe4967309804a2ec4c6a195 /drivers/scsi/lpfc | |
parent | ab56dc2e1d32556971e0729b3a6c37e0ff3104a6 (diff) |
[SCSI] lpfc 8.3.21: Debugfs additions
- Add the driver debugfs framework for supporting debugfs read and write
operations, and iDiag command structure.
- Add read and write to SLI4 device PCI config space registers.
- Add the driver support of debugfs PCI config space register bits set/clear
methods to the provided bitmask.
- Add iDiag driver support for SLI4 device queue diagnostic.
Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 6 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.c | 954 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.h | 60 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 5 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli4.h | 2 |
5 files changed, 972 insertions, 55 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index f41722e8652a..b64c6da870d3 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2010 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2011 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -799,6 +799,10 @@ struct lpfc_hba { | |||
799 | struct dentry *debug_slow_ring_trc; | 799 | struct dentry *debug_slow_ring_trc; |
800 | struct lpfc_debugfs_trc *slow_ring_trc; | 800 | struct lpfc_debugfs_trc *slow_ring_trc; |
801 | atomic_t slow_ring_trc_cnt; | 801 | atomic_t slow_ring_trc_cnt; |
802 | /* iDiag debugfs sub-directory */ | ||
803 | struct dentry *idiag_root; | ||
804 | struct dentry *idiag_pci_cfg; | ||
805 | struct dentry *idiag_que_info; | ||
802 | #endif | 806 | #endif |
803 | 807 | ||
804 | /* Used for deferred freeing of ELS data buffers */ | 808 | /* Used for deferred freeing of ELS data buffers */ |
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 3c8c91a7609c..a753581509d6 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2007-2009 Emulex. All rights reserved. * | 4 | * Copyright (C) 2007-2011 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -57,8 +57,8 @@ | |||
57 | * # mount -t debugfs none /sys/kernel/debug | 57 | * # mount -t debugfs none /sys/kernel/debug |
58 | * | 58 | * |
59 | * The lpfc debugfs directory hierarchy is: | 59 | * The lpfc debugfs directory hierarchy is: |
60 | * lpfc/lpfcX/vportY | 60 | * /sys/kernel/debug/lpfc/fnX/vportY |
61 | * where X is the lpfc hba unique_id | 61 | * where X is the lpfc hba function unique_id |
62 | * where Y is the vport VPI on that hba | 62 | * where Y is the vport VPI on that hba |
63 | * | 63 | * |
64 | * Debugging services available per vport: | 64 | * Debugging services available per vport: |
@@ -104,30 +104,12 @@ MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc, | |||
104 | 104 | ||
105 | #include <linux/debugfs.h> | 105 | #include <linux/debugfs.h> |
106 | 106 | ||
107 | /* size of output line, for discovery_trace and slow_ring_trace */ | ||
108 | #define LPFC_DEBUG_TRC_ENTRY_SIZE 100 | ||
109 | |||
110 | /* nodelist output buffer size */ | ||
111 | #define LPFC_NODELIST_SIZE 8192 | ||
112 | #define LPFC_NODELIST_ENTRY_SIZE 120 | ||
113 | |||
114 | /* dumpHBASlim output buffer size */ | ||
115 | #define LPFC_DUMPHBASLIM_SIZE 4096 | ||
116 | |||
117 | /* dumpHostSlim output buffer size */ | ||
118 | #define LPFC_DUMPHOSTSLIM_SIZE 4096 | ||
119 | |||
120 | /* hbqinfo output buffer size */ | ||
121 | #define LPFC_HBQINFO_SIZE 8192 | ||
122 | |||
123 | struct lpfc_debug { | ||
124 | char *buffer; | ||
125 | int len; | ||
126 | }; | ||
127 | |||
128 | static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0); | 107 | static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0); |
129 | static unsigned long lpfc_debugfs_start_time = 0L; | 108 | static unsigned long lpfc_debugfs_start_time = 0L; |
130 | 109 | ||
110 | /* iDiag */ | ||
111 | static struct lpfc_idiag idiag; | ||
112 | |||
131 | /** | 113 | /** |
132 | * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer | 114 | * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer |
133 | * @vport: The vport to gather the log info from. | 115 | * @vport: The vport to gather the log info from. |
@@ -996,8 +978,6 @@ lpfc_debugfs_dumpDataDif_write(struct file *file, const char __user *buf, | |||
996 | return nbytes; | 978 | return nbytes; |
997 | } | 979 | } |
998 | 980 | ||
999 | |||
1000 | |||
1001 | /** | 981 | /** |
1002 | * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file | 982 | * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file |
1003 | * @inode: The inode pointer that contains a vport pointer. | 983 | * @inode: The inode pointer that contains a vport pointer. |
@@ -1099,6 +1079,7 @@ lpfc_debugfs_read(struct file *file, char __user *buf, | |||
1099 | size_t nbytes, loff_t *ppos) | 1079 | size_t nbytes, loff_t *ppos) |
1100 | { | 1080 | { |
1101 | struct lpfc_debug *debug = file->private_data; | 1081 | struct lpfc_debug *debug = file->private_data; |
1082 | |||
1102 | return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer, | 1083 | return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer, |
1103 | debug->len); | 1084 | debug->len); |
1104 | } | 1085 | } |
@@ -1137,6 +1118,776 @@ lpfc_debugfs_dumpDataDif_release(struct inode *inode, struct file *file) | |||
1137 | return 0; | 1118 | return 0; |
1138 | } | 1119 | } |
1139 | 1120 | ||
1121 | /* | ||
1122 | * iDiag debugfs file access methods | ||
1123 | */ | ||
1124 | |||
1125 | /* | ||
1126 | * iDiag PCI config space register access methods: | ||
1127 | * | ||
1128 | * The PCI config space register accessees of read, write, read-modify-write | ||
1129 | * for set bits, and read-modify-write for clear bits to SLI4 PCI functions | ||
1130 | * are provided. In the proper SLI4 PCI function's debugfs iDiag directory, | ||
1131 | * | ||
1132 | * /sys/kernel/debug/lpfc/fn<#>/iDiag | ||
1133 | * | ||
1134 | * the access is through the debugfs entry pciCfg: | ||
1135 | * | ||
1136 | * 1. For PCI config space register read access, there are two read methods: | ||
1137 | * A) read a single PCI config space register in the size of a byte | ||
1138 | * (8 bits), a word (16 bits), or a dword (32 bits); or B) browse through | ||
1139 | * the 4K extended PCI config space. | ||
1140 | * | ||
1141 | * A) Read a single PCI config space register consists of two steps: | ||
1142 | * | ||
1143 | * Step-1: Set up PCI config space register read command, the command | ||
1144 | * syntax is, | ||
1145 | * | ||
1146 | * echo 1 <where> <count> > pciCfg | ||
1147 | * | ||
1148 | * where, 1 is the iDiag command for PCI config space read, <where> is the | ||
1149 | * offset from the beginning of the device's PCI config space to read from, | ||
1150 | * and <count> is the size of PCI config space register data to read back, | ||
1151 | * it will be 1 for reading a byte (8 bits), 2 for reading a word (16 bits | ||
1152 | * or 2 bytes), or 4 for reading a dword (32 bits or 4 bytes). | ||
1153 | * | ||
1154 | * Setp-2: Perform the debugfs read operation to execute the idiag command | ||
1155 | * set up in Step-1, | ||
1156 | * | ||
1157 | * cat pciCfg | ||
1158 | * | ||
1159 | * Examples: | ||
1160 | * To read PCI device's vendor-id and device-id from PCI config space, | ||
1161 | * | ||
1162 | * echo 1 0 4 > pciCfg | ||
1163 | * cat pciCfg | ||
1164 | * | ||
1165 | * To read PCI device's currnt command from config space, | ||
1166 | * | ||
1167 | * echo 1 4 2 > pciCfg | ||
1168 | * cat pciCfg | ||
1169 | * | ||
1170 | * B) Browse through the entire 4K extended PCI config space also consists | ||
1171 | * of two steps: | ||
1172 | * | ||
1173 | * Step-1: Set up PCI config space register browsing command, the command | ||
1174 | * syntax is, | ||
1175 | * | ||
1176 | * echo 1 0 4096 > pciCfg | ||
1177 | * | ||
1178 | * where, 1 is the iDiag command for PCI config space read, 0 must be used | ||
1179 | * as the offset for PCI config space register browse, and 4096 must be | ||
1180 | * used as the count for PCI config space register browse. | ||
1181 | * | ||
1182 | * Step-2: Repeately issue the debugfs read operation to browse through | ||
1183 | * the entire PCI config space registers: | ||
1184 | * | ||
1185 | * cat pciCfg | ||
1186 | * cat pciCfg | ||
1187 | * cat pciCfg | ||
1188 | * ... | ||
1189 | * | ||
1190 | * When browsing to the end of the 4K PCI config space, the browse method | ||
1191 | * shall wrap around to start reading from beginning again, and again... | ||
1192 | * | ||
1193 | * 2. For PCI config space register write access, it supports a single PCI | ||
1194 | * config space register write in the size of a byte (8 bits), a word | ||
1195 | * (16 bits), or a dword (32 bits). The command syntax is, | ||
1196 | * | ||
1197 | * echo 2 <where> <count> <value> > pciCfg | ||
1198 | * | ||
1199 | * where, 2 is the iDiag command for PCI config space write, <where> is | ||
1200 | * the offset from the beginning of the device's PCI config space to write | ||
1201 | * into, <count> is the size of data to write into the PCI config space, | ||
1202 | * it will be 1 for writing a byte (8 bits), 2 for writing a word (16 bits | ||
1203 | * or 2 bytes), or 4 for writing a dword (32 bits or 4 bytes), and <value> | ||
1204 | * is the data to be written into the PCI config space register at the | ||
1205 | * offset. | ||
1206 | * | ||
1207 | * Examples: | ||
1208 | * To disable PCI device's interrupt assertion, | ||
1209 | * | ||
1210 | * 1) Read in device's PCI config space register command field <cmd>: | ||
1211 | * | ||
1212 | * echo 1 4 2 > pciCfg | ||
1213 | * cat pciCfg | ||
1214 | * | ||
1215 | * 2) Set bit 10 (Interrupt Disable bit) in the <cmd>: | ||
1216 | * | ||
1217 | * <cmd> = <cmd> | (1 < 10) | ||
1218 | * | ||
1219 | * 3) Write the modified command back: | ||
1220 | * | ||
1221 | * echo 2 4 2 <cmd> > pciCfg | ||
1222 | * | ||
1223 | * 3. For PCI config space register set bits access, it supports a single PCI | ||
1224 | * config space register set bits in the size of a byte (8 bits), a word | ||
1225 | * (16 bits), or a dword (32 bits). The command syntax is, | ||
1226 | * | ||
1227 | * echo 3 <where> <count> <bitmask> > pciCfg | ||
1228 | * | ||
1229 | * where, 3 is the iDiag command for PCI config space set bits, <where> is | ||
1230 | * the offset from the beginning of the device's PCI config space to set | ||
1231 | * bits into, <count> is the size of the bitmask to set into the PCI config | ||
1232 | * space, it will be 1 for setting a byte (8 bits), 2 for setting a word | ||
1233 | * (16 bits or 2 bytes), or 4 for setting a dword (32 bits or 4 bytes), and | ||
1234 | * <bitmask> is the bitmask, indicating the bits to be set into the PCI | ||
1235 | * config space register at the offset. The logic performed to the content | ||
1236 | * of the PCI config space register, regval, is, | ||
1237 | * | ||
1238 | * regval |= <bitmask> | ||
1239 | * | ||
1240 | * 4. For PCI config space register clear bits access, it supports a single | ||
1241 | * PCI config space register clear bits in the size of a byte (8 bits), | ||
1242 | * a word (16 bits), or a dword (32 bits). The command syntax is, | ||
1243 | * | ||
1244 | * echo 4 <where> <count> <bitmask> > pciCfg | ||
1245 | * | ||
1246 | * where, 4 is the iDiag command for PCI config space clear bits, <where> | ||
1247 | * is the offset from the beginning of the device's PCI config space to | ||
1248 | * clear bits from, <count> is the size of the bitmask to set into the PCI | ||
1249 | * config space, it will be 1 for setting a byte (8 bits), 2 for setting | ||
1250 | * a word(16 bits or 2 bytes), or 4 for setting a dword (32 bits or 4 | ||
1251 | * bytes), and <bitmask> is the bitmask, indicating the bits to be cleared | ||
1252 | * from the PCI config space register at the offset. the logic performed | ||
1253 | * to the content of the PCI config space register, regval, is, | ||
1254 | * | ||
1255 | * regval &= ~<bitmask> | ||
1256 | * | ||
1257 | * Note, for all single register read, write, set bits, or clear bits access, | ||
1258 | * the offset (<where>) must be aligned with the size of the data: | ||
1259 | * | ||
1260 | * For data size of byte (8 bits), the offset must be aligned to the byte | ||
1261 | * boundary; for data size of word (16 bits), the offset must be aligned | ||
1262 | * to the word boundary; while for data size of dword (32 bits), the offset | ||
1263 | * must be aligned to the dword boundary. Otherwise, the interface will | ||
1264 | * return the error: | ||
1265 | * | ||
1266 | * "-bash: echo: write error: Invalid argument". | ||
1267 | * | ||
1268 | * For example: | ||
1269 | * | ||
1270 | * echo 1 2 4 > pciCfg | ||
1271 | * -bash: echo: write error: Invalid argument | ||
1272 | * | ||
1273 | * Note also, all of the numbers in the command fields for all read, write, | ||
1274 | * set bits, and clear bits PCI config space register command fields can be | ||
1275 | * either decimal or hex. | ||
1276 | * | ||
1277 | * For example, | ||
1278 | * echo 1 0 4096 > pciCfg | ||
1279 | * | ||
1280 | * will be the same as | ||
1281 | * echo 1 0 0x1000 > pciCfg | ||
1282 | * | ||
1283 | * And, | ||
1284 | * echo 2 155 1 10 > pciCfg | ||
1285 | * | ||
1286 | * will be | ||
1287 | * echo 2 0x9b 1 0xa > pciCfg | ||
1288 | */ | ||
1289 | |||
1290 | /** | ||
1291 | * lpfc_idiag_cmd_get - Get and parse idiag debugfs comands from user space | ||
1292 | * @buf: The pointer to the user space buffer. | ||
1293 | * @nbytes: The number of bytes in the user space buffer. | ||
1294 | * @idiag_cmd: pointer to the idiag command struct. | ||
1295 | * | ||
1296 | * This routine reads data from debugfs user space buffer and parses the | ||
1297 | * buffer for getting the idiag command and arguments. The while space in | ||
1298 | * between the set of data is used as the parsing separator. | ||
1299 | * | ||
1300 | * This routine returns 0 when successful, it returns proper error code | ||
1301 | * back to the user space in error conditions. | ||
1302 | */ | ||
1303 | static int lpfc_idiag_cmd_get(const char __user *buf, size_t nbytes, | ||
1304 | struct lpfc_idiag_cmd *idiag_cmd) | ||
1305 | { | ||
1306 | char mybuf[64]; | ||
1307 | char *pbuf, *step_str; | ||
1308 | int bsize, i; | ||
1309 | |||
1310 | /* Protect copy from user */ | ||
1311 | if (!access_ok(VERIFY_READ, buf, nbytes)) | ||
1312 | return -EFAULT; | ||
1313 | |||
1314 | memset(mybuf, 0, sizeof(mybuf)); | ||
1315 | memset(idiag_cmd, 0, sizeof(*idiag_cmd)); | ||
1316 | bsize = min(nbytes, (sizeof(mybuf)-1)); | ||
1317 | |||
1318 | if (copy_from_user(mybuf, buf, bsize)) | ||
1319 | return -EFAULT; | ||
1320 | pbuf = &mybuf[0]; | ||
1321 | step_str = strsep(&pbuf, "\t "); | ||
1322 | |||
1323 | /* The opcode must present */ | ||
1324 | if (!step_str) | ||
1325 | return -EINVAL; | ||
1326 | |||
1327 | idiag_cmd->opcode = simple_strtol(step_str, NULL, 0); | ||
1328 | if (idiag_cmd->opcode == 0) | ||
1329 | return -EINVAL; | ||
1330 | |||
1331 | for (i = 0; i < LPFC_IDIAG_CMD_DATA_SIZE; i++) { | ||
1332 | step_str = strsep(&pbuf, "\t "); | ||
1333 | if (!step_str) | ||
1334 | return 0; | ||
1335 | idiag_cmd->data[i] = simple_strtol(step_str, NULL, 0); | ||
1336 | } | ||
1337 | return 0; | ||
1338 | } | ||
1339 | |||
1340 | /** | ||
1341 | * lpfc_idiag_open - idiag open debugfs | ||
1342 | * @inode: The inode pointer that contains a pointer to phba. | ||
1343 | * @file: The file pointer to attach the file operation. | ||
1344 | * | ||
1345 | * Description: | ||
1346 | * This routine is the entry point for the debugfs open file operation. It | ||
1347 | * gets the reference to phba from the i_private field in @inode, it then | ||
1348 | * allocates buffer for the file operation, performs the necessary PCI config | ||
1349 | * space read into the allocated buffer according to the idiag user command | ||
1350 | * setup, and then returns a pointer to buffer in the private_data field in | ||
1351 | * @file. | ||
1352 | * | ||
1353 | * Returns: | ||
1354 | * This function returns zero if successful. On error it will return an | ||
1355 | * negative error value. | ||
1356 | **/ | ||
1357 | static int | ||
1358 | lpfc_idiag_open(struct inode *inode, struct file *file) | ||
1359 | { | ||
1360 | struct lpfc_debug *debug; | ||
1361 | |||
1362 | debug = kmalloc(sizeof(*debug), GFP_KERNEL); | ||
1363 | if (!debug) | ||
1364 | return -ENOMEM; | ||
1365 | |||
1366 | debug->i_private = inode->i_private; | ||
1367 | debug->buffer = NULL; | ||
1368 | file->private_data = debug; | ||
1369 | |||
1370 | return 0; | ||
1371 | } | ||
1372 | |||
1373 | /** | ||
1374 | * lpfc_idiag_release - Release idiag access file operation | ||
1375 | * @inode: The inode pointer that contains a vport pointer. (unused) | ||
1376 | * @file: The file pointer that contains the buffer to release. | ||
1377 | * | ||
1378 | * Description: | ||
1379 | * This routine is the generic release routine for the idiag access file | ||
1380 | * operation, it frees the buffer that was allocated when the debugfs file | ||
1381 | * was opened. | ||
1382 | * | ||
1383 | * Returns: | ||
1384 | * This function returns zero. | ||
1385 | **/ | ||
1386 | static int | ||
1387 | lpfc_idiag_release(struct inode *inode, struct file *file) | ||
1388 | { | ||
1389 | struct lpfc_debug *debug = file->private_data; | ||
1390 | |||
1391 | /* Free the buffers to the file operation */ | ||
1392 | kfree(debug->buffer); | ||
1393 | kfree(debug); | ||
1394 | |||
1395 | return 0; | ||
1396 | } | ||
1397 | |||
1398 | /** | ||
1399 | * lpfc_idiag_cmd_release - Release idiag cmd access file operation | ||
1400 | * @inode: The inode pointer that contains a vport pointer. (unused) | ||
1401 | * @file: The file pointer that contains the buffer to release. | ||
1402 | * | ||
1403 | * Description: | ||
1404 | * This routine frees the buffer that was allocated when the debugfs file | ||
1405 | * was opened. It also reset the fields in the idiag command struct in the | ||
1406 | * case the command is not continuous browsing of the data structure. | ||
1407 | * | ||
1408 | * Returns: | ||
1409 | * This function returns zero. | ||
1410 | **/ | ||
1411 | static int | ||
1412 | lpfc_idiag_cmd_release(struct inode *inode, struct file *file) | ||
1413 | { | ||
1414 | struct lpfc_debug *debug = file->private_data; | ||
1415 | |||
1416 | /* Read PCI config register, if not read all, clear command fields */ | ||
1417 | if ((debug->op == LPFC_IDIAG_OP_RD) && | ||
1418 | (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD)) | ||
1419 | if ((idiag.cmd.data[1] == sizeof(uint8_t)) || | ||
1420 | (idiag.cmd.data[1] == sizeof(uint16_t)) || | ||
1421 | (idiag.cmd.data[1] == sizeof(uint32_t))) | ||
1422 | memset(&idiag, 0, sizeof(idiag)); | ||
1423 | |||
1424 | /* Write PCI config register, clear command fields */ | ||
1425 | if ((debug->op == LPFC_IDIAG_OP_WR) && | ||
1426 | (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)) | ||
1427 | memset(&idiag, 0, sizeof(idiag)); | ||
1428 | |||
1429 | /* Free the buffers to the file operation */ | ||
1430 | kfree(debug->buffer); | ||
1431 | kfree(debug); | ||
1432 | |||
1433 | return 0; | ||
1434 | } | ||
1435 | |||
1436 | /** | ||
1437 | * lpfc_idiag_pcicfg_read - idiag debugfs read pcicfg | ||
1438 | * @file: The file pointer to read from. | ||
1439 | * @buf: The buffer to copy the data to. | ||
1440 | * @nbytes: The number of bytes to read. | ||
1441 | * @ppos: The position in the file to start reading from. | ||
1442 | * | ||
1443 | * Description: | ||
1444 | * This routine reads data from the @phba pci config space according to the | ||
1445 | * idiag command, and copies to user @buf. Depending on the PCI config space | ||
1446 | * read command setup, it does either a single register read of a byte | ||
1447 | * (8 bits), a word (16 bits), or a dword (32 bits) or browsing through all | ||
1448 | * registers from the 4K extended PCI config space. | ||
1449 | * | ||
1450 | * Returns: | ||
1451 | * This function returns the amount of data that was read (this could be less | ||
1452 | * than @nbytes if the end of the file was reached) or a negative error value. | ||
1453 | **/ | ||
1454 | static ssize_t | ||
1455 | lpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes, | ||
1456 | loff_t *ppos) | ||
1457 | { | ||
1458 | struct lpfc_debug *debug = file->private_data; | ||
1459 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | ||
1460 | int offset_label, offset, len = 0, index = LPFC_PCI_CFG_RD_SIZE; | ||
1461 | int where, count; | ||
1462 | char *pbuffer; | ||
1463 | struct pci_dev *pdev; | ||
1464 | uint32_t u32val; | ||
1465 | uint16_t u16val; | ||
1466 | uint8_t u8val; | ||
1467 | |||
1468 | pdev = phba->pcidev; | ||
1469 | if (!pdev) | ||
1470 | return 0; | ||
1471 | |||
1472 | /* This is a user read operation */ | ||
1473 | debug->op = LPFC_IDIAG_OP_RD; | ||
1474 | |||
1475 | if (!debug->buffer) | ||
1476 | debug->buffer = kmalloc(LPFC_PCI_CFG_SIZE, GFP_KERNEL); | ||
1477 | if (!debug->buffer) | ||
1478 | return 0; | ||
1479 | pbuffer = debug->buffer; | ||
1480 | |||
1481 | if (*ppos) | ||
1482 | return 0; | ||
1483 | |||
1484 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) { | ||
1485 | where = idiag.cmd.data[0]; | ||
1486 | count = idiag.cmd.data[1]; | ||
1487 | } else | ||
1488 | return 0; | ||
1489 | |||
1490 | /* Read single PCI config space register */ | ||
1491 | switch (count) { | ||
1492 | case SIZE_U8: /* byte (8 bits) */ | ||
1493 | pci_read_config_byte(pdev, where, &u8val); | ||
1494 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | ||
1495 | "%03x: %02x\n", where, u8val); | ||
1496 | break; | ||
1497 | case SIZE_U16: /* word (16 bits) */ | ||
1498 | pci_read_config_word(pdev, where, &u16val); | ||
1499 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | ||
1500 | "%03x: %04x\n", where, u16val); | ||
1501 | break; | ||
1502 | case SIZE_U32: /* double word (32 bits) */ | ||
1503 | pci_read_config_dword(pdev, where, &u32val); | ||
1504 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | ||
1505 | "%03x: %08x\n", where, u32val); | ||
1506 | break; | ||
1507 | case LPFC_PCI_CFG_SIZE: /* browse all */ | ||
1508 | goto pcicfg_browse; | ||
1509 | break; | ||
1510 | default: | ||
1511 | /* illegal count */ | ||
1512 | len = 0; | ||
1513 | break; | ||
1514 | } | ||
1515 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | ||
1516 | |||
1517 | pcicfg_browse: | ||
1518 | |||
1519 | /* Browse all PCI config space registers */ | ||
1520 | offset_label = idiag.offset.last_rd; | ||
1521 | offset = offset_label; | ||
1522 | |||
1523 | /* Read PCI config space */ | ||
1524 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | ||
1525 | "%03x: ", offset_label); | ||
1526 | while (index > 0) { | ||
1527 | pci_read_config_dword(pdev, offset, &u32val); | ||
1528 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | ||
1529 | "%08x ", u32val); | ||
1530 | offset += sizeof(uint32_t); | ||
1531 | index -= sizeof(uint32_t); | ||
1532 | if (!index) | ||
1533 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | ||
1534 | "\n"); | ||
1535 | else if (!(index % (8 * sizeof(uint32_t)))) { | ||
1536 | offset_label += (8 * sizeof(uint32_t)); | ||
1537 | len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, | ||
1538 | "\n%03x: ", offset_label); | ||
1539 | } | ||
1540 | } | ||
1541 | |||
1542 | /* Set up the offset for next portion of pci cfg read */ | ||
1543 | idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE; | ||
1544 | if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE) | ||
1545 | idiag.offset.last_rd = 0; | ||
1546 | |||
1547 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | ||
1548 | } | ||
1549 | |||
1550 | /** | ||
1551 | * lpfc_idiag_pcicfg_write - Syntax check and set up idiag pcicfg commands | ||
1552 | * @file: The file pointer to read from. | ||
1553 | * @buf: The buffer to copy the user data from. | ||
1554 | * @nbytes: The number of bytes to get. | ||
1555 | * @ppos: The position in the file to start reading from. | ||
1556 | * | ||
1557 | * This routine get the debugfs idiag command struct from user space and | ||
1558 | * then perform the syntax check for PCI config space read or write command | ||
1559 | * accordingly. In the case of PCI config space read command, it sets up | ||
1560 | * the command in the idiag command struct for the debugfs read operation. | ||
1561 | * In the case of PCI config space write operation, it executes the write | ||
1562 | * operation into the PCI config space accordingly. | ||
1563 | * | ||
1564 | * It returns the @nbytges passing in from debugfs user space when successful. | ||
1565 | * In case of error conditions, it returns proper error code back to the user | ||
1566 | * space. | ||
1567 | */ | ||
1568 | static ssize_t | ||
1569 | lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf, | ||
1570 | size_t nbytes, loff_t *ppos) | ||
1571 | { | ||
1572 | struct lpfc_debug *debug = file->private_data; | ||
1573 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | ||
1574 | uint32_t where, value, count; | ||
1575 | uint32_t u32val; | ||
1576 | uint16_t u16val; | ||
1577 | uint8_t u8val; | ||
1578 | struct pci_dev *pdev; | ||
1579 | int rc; | ||
1580 | |||
1581 | pdev = phba->pcidev; | ||
1582 | if (!pdev) | ||
1583 | return -EFAULT; | ||
1584 | |||
1585 | /* This is a user write operation */ | ||
1586 | debug->op = LPFC_IDIAG_OP_WR; | ||
1587 | |||
1588 | rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); | ||
1589 | if (rc) | ||
1590 | return rc; | ||
1591 | |||
1592 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) { | ||
1593 | /* Read command from PCI config space, set up command fields */ | ||
1594 | where = idiag.cmd.data[0]; | ||
1595 | count = idiag.cmd.data[1]; | ||
1596 | if (count == LPFC_PCI_CFG_SIZE) { | ||
1597 | if (where != 0) | ||
1598 | goto error_out; | ||
1599 | } else if ((count != sizeof(uint8_t)) && | ||
1600 | (count != sizeof(uint16_t)) && | ||
1601 | (count != sizeof(uint32_t))) | ||
1602 | goto error_out; | ||
1603 | if (count == sizeof(uint8_t)) { | ||
1604 | if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t)) | ||
1605 | goto error_out; | ||
1606 | if (where % sizeof(uint8_t)) | ||
1607 | goto error_out; | ||
1608 | } | ||
1609 | if (count == sizeof(uint16_t)) { | ||
1610 | if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t)) | ||
1611 | goto error_out; | ||
1612 | if (where % sizeof(uint16_t)) | ||
1613 | goto error_out; | ||
1614 | } | ||
1615 | if (count == sizeof(uint32_t)) { | ||
1616 | if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t)) | ||
1617 | goto error_out; | ||
1618 | if (where % sizeof(uint32_t)) | ||
1619 | goto error_out; | ||
1620 | } | ||
1621 | } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR || | ||
1622 | idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST || | ||
1623 | idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) { | ||
1624 | /* Write command to PCI config space, read-modify-write */ | ||
1625 | where = idiag.cmd.data[0]; | ||
1626 | count = idiag.cmd.data[1]; | ||
1627 | value = idiag.cmd.data[2]; | ||
1628 | /* Sanity checks */ | ||
1629 | if ((count != sizeof(uint8_t)) && | ||
1630 | (count != sizeof(uint16_t)) && | ||
1631 | (count != sizeof(uint32_t))) | ||
1632 | goto error_out; | ||
1633 | if (count == sizeof(uint8_t)) { | ||
1634 | if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t)) | ||
1635 | goto error_out; | ||
1636 | if (where % sizeof(uint8_t)) | ||
1637 | goto error_out; | ||
1638 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR) | ||
1639 | pci_write_config_byte(pdev, where, | ||
1640 | (uint8_t)value); | ||
1641 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) { | ||
1642 | rc = pci_read_config_byte(pdev, where, &u8val); | ||
1643 | if (!rc) { | ||
1644 | u8val |= (uint8_t)value; | ||
1645 | pci_write_config_byte(pdev, where, | ||
1646 | u8val); | ||
1647 | } | ||
1648 | } | ||
1649 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) { | ||
1650 | rc = pci_read_config_byte(pdev, where, &u8val); | ||
1651 | if (!rc) { | ||
1652 | u8val &= (uint8_t)(~value); | ||
1653 | pci_write_config_byte(pdev, where, | ||
1654 | u8val); | ||
1655 | } | ||
1656 | } | ||
1657 | } | ||
1658 | if (count == sizeof(uint16_t)) { | ||
1659 | if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t)) | ||
1660 | goto error_out; | ||
1661 | if (where % sizeof(uint16_t)) | ||
1662 | goto error_out; | ||
1663 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR) | ||
1664 | pci_write_config_word(pdev, where, | ||
1665 | (uint16_t)value); | ||
1666 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) { | ||
1667 | rc = pci_read_config_word(pdev, where, &u16val); | ||
1668 | if (!rc) { | ||
1669 | u16val |= (uint16_t)value; | ||
1670 | pci_write_config_word(pdev, where, | ||
1671 | u16val); | ||
1672 | } | ||
1673 | } | ||
1674 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) { | ||
1675 | rc = pci_read_config_word(pdev, where, &u16val); | ||
1676 | if (!rc) { | ||
1677 | u16val &= (uint16_t)(~value); | ||
1678 | pci_write_config_word(pdev, where, | ||
1679 | u16val); | ||
1680 | } | ||
1681 | } | ||
1682 | } | ||
1683 | if (count == sizeof(uint32_t)) { | ||
1684 | if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t)) | ||
1685 | goto error_out; | ||
1686 | if (where % sizeof(uint32_t)) | ||
1687 | goto error_out; | ||
1688 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR) | ||
1689 | pci_write_config_dword(pdev, where, value); | ||
1690 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) { | ||
1691 | rc = pci_read_config_dword(pdev, where, | ||
1692 | &u32val); | ||
1693 | if (!rc) { | ||
1694 | u32val |= value; | ||
1695 | pci_write_config_dword(pdev, where, | ||
1696 | u32val); | ||
1697 | } | ||
1698 | } | ||
1699 | if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) { | ||
1700 | rc = pci_read_config_dword(pdev, where, | ||
1701 | &u32val); | ||
1702 | if (!rc) { | ||
1703 | u32val &= ~value; | ||
1704 | pci_write_config_dword(pdev, where, | ||
1705 | u32val); | ||
1706 | } | ||
1707 | } | ||
1708 | } | ||
1709 | } else | ||
1710 | /* All other opecodes are illegal for now */ | ||
1711 | goto error_out; | ||
1712 | |||
1713 | return nbytes; | ||
1714 | error_out: | ||
1715 | memset(&idiag, 0, sizeof(idiag)); | ||
1716 | return -EINVAL; | ||
1717 | } | ||
1718 | |||
1719 | /** | ||
1720 | * lpfc_idiag_queinfo_read - idiag debugfs read queue information | ||
1721 | * @file: The file pointer to read from. | ||
1722 | * @buf: The buffer to copy the data to. | ||
1723 | * @nbytes: The number of bytes to read. | ||
1724 | * @ppos: The position in the file to start reading from. | ||
1725 | * | ||
1726 | * Description: | ||
1727 | * This routine reads data from the @phba SLI4 PCI function queue information, | ||
1728 | * and copies to user @buf. | ||
1729 | * | ||
1730 | * Returns: | ||
1731 | * This function returns the amount of data that was read (this could be less | ||
1732 | * than @nbytes if the end of the file was reached) or a negative error value. | ||
1733 | **/ | ||
1734 | static ssize_t | ||
1735 | lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes, | ||
1736 | loff_t *ppos) | ||
1737 | { | ||
1738 | struct lpfc_debug *debug = file->private_data; | ||
1739 | struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private; | ||
1740 | int len = 0, fcp_qidx; | ||
1741 | char *pbuffer; | ||
1742 | |||
1743 | if (!debug->buffer) | ||
1744 | debug->buffer = kmalloc(LPFC_QUE_INFO_GET_BUF_SIZE, GFP_KERNEL); | ||
1745 | if (!debug->buffer) | ||
1746 | return 0; | ||
1747 | pbuffer = debug->buffer; | ||
1748 | |||
1749 | if (*ppos) | ||
1750 | return 0; | ||
1751 | |||
1752 | /* Get slow-path event queue information */ | ||
1753 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1754 | "Slow-path EQ information:\n"); | ||
1755 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1756 | "\tID [%02d], EQE-COUNT [%04d], " | ||
1757 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", | ||
1758 | phba->sli4_hba.sp_eq->queue_id, | ||
1759 | phba->sli4_hba.sp_eq->entry_count, | ||
1760 | phba->sli4_hba.sp_eq->host_index, | ||
1761 | phba->sli4_hba.sp_eq->hba_index); | ||
1762 | |||
1763 | /* Get fast-path event queue information */ | ||
1764 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1765 | "Fast-path EQ information:\n"); | ||
1766 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) { | ||
1767 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1768 | "\tID [%02d], EQE-COUNT [%04d], " | ||
1769 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", | ||
1770 | phba->sli4_hba.fp_eq[fcp_qidx]->queue_id, | ||
1771 | phba->sli4_hba.fp_eq[fcp_qidx]->entry_count, | ||
1772 | phba->sli4_hba.fp_eq[fcp_qidx]->host_index, | ||
1773 | phba->sli4_hba.fp_eq[fcp_qidx]->hba_index); | ||
1774 | } | ||
1775 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); | ||
1776 | |||
1777 | /* Get mailbox complete queue information */ | ||
1778 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1779 | "Mailbox CQ information:\n"); | ||
1780 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1781 | "\t\tAssociated EQ-ID [%02d]:\n", | ||
1782 | phba->sli4_hba.mbx_cq->assoc_qid); | ||
1783 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1784 | "\tID [%02d], CQE-COUNT [%04d], " | ||
1785 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", | ||
1786 | phba->sli4_hba.mbx_cq->queue_id, | ||
1787 | phba->sli4_hba.mbx_cq->entry_count, | ||
1788 | phba->sli4_hba.mbx_cq->host_index, | ||
1789 | phba->sli4_hba.mbx_cq->hba_index); | ||
1790 | |||
1791 | /* Get slow-path complete queue information */ | ||
1792 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1793 | "Slow-path CQ information:\n"); | ||
1794 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1795 | "\t\tAssociated EQ-ID [%02d]:\n", | ||
1796 | phba->sli4_hba.els_cq->assoc_qid); | ||
1797 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1798 | "\tID [%02d], CQE-COUNT [%04d], " | ||
1799 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", | ||
1800 | phba->sli4_hba.els_cq->queue_id, | ||
1801 | phba->sli4_hba.els_cq->entry_count, | ||
1802 | phba->sli4_hba.els_cq->host_index, | ||
1803 | phba->sli4_hba.els_cq->hba_index); | ||
1804 | |||
1805 | /* Get fast-path complete queue information */ | ||
1806 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1807 | "Fast-path CQ information:\n"); | ||
1808 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) { | ||
1809 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1810 | "\t\tAssociated EQ-ID [%02d]:\n", | ||
1811 | phba->sli4_hba.fcp_cq[fcp_qidx]->assoc_qid); | ||
1812 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1813 | "\tID [%02d], EQE-COUNT [%04d], " | ||
1814 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", | ||
1815 | phba->sli4_hba.fcp_cq[fcp_qidx]->queue_id, | ||
1816 | phba->sli4_hba.fcp_cq[fcp_qidx]->entry_count, | ||
1817 | phba->sli4_hba.fcp_cq[fcp_qidx]->host_index, | ||
1818 | phba->sli4_hba.fcp_cq[fcp_qidx]->hba_index); | ||
1819 | } | ||
1820 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); | ||
1821 | |||
1822 | /* Get mailbox queue information */ | ||
1823 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1824 | "Mailbox MQ information:\n"); | ||
1825 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1826 | "\t\tAssociated CQ-ID [%02d]:\n", | ||
1827 | phba->sli4_hba.mbx_wq->assoc_qid); | ||
1828 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1829 | "\tID [%02d], MQE-COUNT [%04d], " | ||
1830 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", | ||
1831 | phba->sli4_hba.mbx_wq->queue_id, | ||
1832 | phba->sli4_hba.mbx_wq->entry_count, | ||
1833 | phba->sli4_hba.mbx_wq->host_index, | ||
1834 | phba->sli4_hba.mbx_wq->hba_index); | ||
1835 | |||
1836 | /* Get slow-path work queue information */ | ||
1837 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1838 | "Slow-path WQ information:\n"); | ||
1839 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1840 | "\t\tAssociated CQ-ID [%02d]:\n", | ||
1841 | phba->sli4_hba.els_wq->assoc_qid); | ||
1842 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1843 | "\tID [%02d], WQE-COUNT [%04d], " | ||
1844 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", | ||
1845 | phba->sli4_hba.els_wq->queue_id, | ||
1846 | phba->sli4_hba.els_wq->entry_count, | ||
1847 | phba->sli4_hba.els_wq->host_index, | ||
1848 | phba->sli4_hba.els_wq->hba_index); | ||
1849 | |||
1850 | /* Get fast-path work queue information */ | ||
1851 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1852 | "Fast-path WQ information:\n"); | ||
1853 | for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_wq_count; fcp_qidx++) { | ||
1854 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1855 | "\t\tAssociated CQ-ID [%02d]:\n", | ||
1856 | phba->sli4_hba.fcp_wq[fcp_qidx]->assoc_qid); | ||
1857 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1858 | "\tID [%02d], WQE-COUNT [%04d], " | ||
1859 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", | ||
1860 | phba->sli4_hba.fcp_wq[fcp_qidx]->queue_id, | ||
1861 | phba->sli4_hba.fcp_wq[fcp_qidx]->entry_count, | ||
1862 | phba->sli4_hba.fcp_wq[fcp_qidx]->host_index, | ||
1863 | phba->sli4_hba.fcp_wq[fcp_qidx]->hba_index); | ||
1864 | } | ||
1865 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); | ||
1866 | |||
1867 | /* Get receive queue information */ | ||
1868 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1869 | "Slow-path RQ information:\n"); | ||
1870 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1871 | "\t\tAssociated CQ-ID [%02d]:\n", | ||
1872 | phba->sli4_hba.hdr_rq->assoc_qid); | ||
1873 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1874 | "\tID [%02d], RHQE-COUNT [%04d], " | ||
1875 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", | ||
1876 | phba->sli4_hba.hdr_rq->queue_id, | ||
1877 | phba->sli4_hba.hdr_rq->entry_count, | ||
1878 | phba->sli4_hba.hdr_rq->host_index, | ||
1879 | phba->sli4_hba.hdr_rq->hba_index); | ||
1880 | len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, | ||
1881 | "\tID [%02d], RDQE-COUNT [%04d], " | ||
1882 | "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", | ||
1883 | phba->sli4_hba.dat_rq->queue_id, | ||
1884 | phba->sli4_hba.dat_rq->entry_count, | ||
1885 | phba->sli4_hba.dat_rq->host_index, | ||
1886 | phba->sli4_hba.dat_rq->hba_index); | ||
1887 | |||
1888 | return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); | ||
1889 | } | ||
1890 | |||
1140 | #undef lpfc_debugfs_op_disc_trc | 1891 | #undef lpfc_debugfs_op_disc_trc |
1141 | static const struct file_operations lpfc_debugfs_op_disc_trc = { | 1892 | static const struct file_operations lpfc_debugfs_op_disc_trc = { |
1142 | .owner = THIS_MODULE, | 1893 | .owner = THIS_MODULE, |
@@ -1213,6 +1964,28 @@ static const struct file_operations lpfc_debugfs_op_slow_ring_trc = { | |||
1213 | 1964 | ||
1214 | static struct dentry *lpfc_debugfs_root = NULL; | 1965 | static struct dentry *lpfc_debugfs_root = NULL; |
1215 | static atomic_t lpfc_debugfs_hba_count; | 1966 | static atomic_t lpfc_debugfs_hba_count; |
1967 | |||
1968 | /* | ||
1969 | * File operations for the iDiag debugfs | ||
1970 | */ | ||
1971 | #undef lpfc_idiag_op_pciCfg | ||
1972 | static const struct file_operations lpfc_idiag_op_pciCfg = { | ||
1973 | .owner = THIS_MODULE, | ||
1974 | .open = lpfc_idiag_open, | ||
1975 | .llseek = lpfc_debugfs_lseek, | ||
1976 | .read = lpfc_idiag_pcicfg_read, | ||
1977 | .write = lpfc_idiag_pcicfg_write, | ||
1978 | .release = lpfc_idiag_cmd_release, | ||
1979 | }; | ||
1980 | |||
1981 | #undef lpfc_idiag_op_queInfo | ||
1982 | static const struct file_operations lpfc_idiag_op_queInfo = { | ||
1983 | .owner = THIS_MODULE, | ||
1984 | .open = lpfc_idiag_open, | ||
1985 | .read = lpfc_idiag_queinfo_read, | ||
1986 | .release = lpfc_idiag_release, | ||
1987 | }; | ||
1988 | |||
1216 | #endif | 1989 | #endif |
1217 | 1990 | ||
1218 | /** | 1991 | /** |
@@ -1249,8 +2022,8 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) | |||
1249 | if (!lpfc_debugfs_start_time) | 2022 | if (!lpfc_debugfs_start_time) |
1250 | lpfc_debugfs_start_time = jiffies; | 2023 | lpfc_debugfs_start_time = jiffies; |
1251 | 2024 | ||
1252 | /* Setup lpfcX directory for specific HBA */ | 2025 | /* Setup funcX directory for specific HBA PCI function */ |
1253 | snprintf(name, sizeof(name), "lpfc%d", phba->brd_no); | 2026 | snprintf(name, sizeof(name), "fn%d", phba->brd_no); |
1254 | if (!phba->hba_debugfs_root) { | 2027 | if (!phba->hba_debugfs_root) { |
1255 | phba->hba_debugfs_root = | 2028 | phba->hba_debugfs_root = |
1256 | debugfs_create_dir(name, lpfc_debugfs_root); | 2029 | debugfs_create_dir(name, lpfc_debugfs_root); |
@@ -1275,28 +2048,38 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) | |||
1275 | } | 2048 | } |
1276 | 2049 | ||
1277 | /* Setup dumpHBASlim */ | 2050 | /* Setup dumpHBASlim */ |
1278 | snprintf(name, sizeof(name), "dumpHBASlim"); | 2051 | if (phba->sli_rev < LPFC_SLI_REV4) { |
1279 | phba->debug_dumpHBASlim = | 2052 | snprintf(name, sizeof(name), "dumpHBASlim"); |
1280 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | 2053 | phba->debug_dumpHBASlim = |
1281 | phba->hba_debugfs_root, | 2054 | debugfs_create_file(name, |
1282 | phba, &lpfc_debugfs_op_dumpHBASlim); | 2055 | S_IFREG|S_IRUGO|S_IWUSR, |
1283 | if (!phba->debug_dumpHBASlim) { | 2056 | phba->hba_debugfs_root, |
1284 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | 2057 | phba, &lpfc_debugfs_op_dumpHBASlim); |
1285 | "0413 Cannot create debugfs dumpHBASlim\n"); | 2058 | if (!phba->debug_dumpHBASlim) { |
1286 | goto debug_failed; | 2059 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, |
1287 | } | 2060 | "0413 Cannot create debugfs " |
2061 | "dumpHBASlim\n"); | ||
2062 | goto debug_failed; | ||
2063 | } | ||
2064 | } else | ||
2065 | phba->debug_dumpHBASlim = NULL; | ||
1288 | 2066 | ||
1289 | /* Setup dumpHostSlim */ | 2067 | /* Setup dumpHostSlim */ |
1290 | snprintf(name, sizeof(name), "dumpHostSlim"); | 2068 | if (phba->sli_rev < LPFC_SLI_REV4) { |
1291 | phba->debug_dumpHostSlim = | 2069 | snprintf(name, sizeof(name), "dumpHostSlim"); |
1292 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | 2070 | phba->debug_dumpHostSlim = |
1293 | phba->hba_debugfs_root, | 2071 | debugfs_create_file(name, |
1294 | phba, &lpfc_debugfs_op_dumpHostSlim); | 2072 | S_IFREG|S_IRUGO|S_IWUSR, |
1295 | if (!phba->debug_dumpHostSlim) { | 2073 | phba->hba_debugfs_root, |
1296 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | 2074 | phba, &lpfc_debugfs_op_dumpHostSlim); |
1297 | "0414 Cannot create debugfs dumpHostSlim\n"); | 2075 | if (!phba->debug_dumpHostSlim) { |
1298 | goto debug_failed; | 2076 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, |
1299 | } | 2077 | "0414 Cannot create debugfs " |
2078 | "dumpHostSlim\n"); | ||
2079 | goto debug_failed; | ||
2080 | } | ||
2081 | } else | ||
2082 | phba->debug_dumpHBASlim = NULL; | ||
1300 | 2083 | ||
1301 | /* Setup dumpData */ | 2084 | /* Setup dumpData */ |
1302 | snprintf(name, sizeof(name), "dumpData"); | 2085 | snprintf(name, sizeof(name), "dumpData"); |
@@ -1322,8 +2105,6 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) | |||
1322 | goto debug_failed; | 2105 | goto debug_failed; |
1323 | } | 2106 | } |
1324 | 2107 | ||
1325 | |||
1326 | |||
1327 | /* Setup slow ring trace */ | 2108 | /* Setup slow ring trace */ |
1328 | if (lpfc_debugfs_max_slow_ring_trc) { | 2109 | if (lpfc_debugfs_max_slow_ring_trc) { |
1329 | num = lpfc_debugfs_max_slow_ring_trc - 1; | 2110 | num = lpfc_debugfs_max_slow_ring_trc - 1; |
@@ -1342,7 +2123,6 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) | |||
1342 | } | 2123 | } |
1343 | } | 2124 | } |
1344 | 2125 | ||
1345 | |||
1346 | snprintf(name, sizeof(name), "slow_ring_trace"); | 2126 | snprintf(name, sizeof(name), "slow_ring_trace"); |
1347 | phba->debug_slow_ring_trc = | 2127 | phba->debug_slow_ring_trc = |
1348 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | 2128 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, |
@@ -1434,6 +2214,53 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) | |||
1434 | "0409 Cant create debugfs nodelist\n"); | 2214 | "0409 Cant create debugfs nodelist\n"); |
1435 | goto debug_failed; | 2215 | goto debug_failed; |
1436 | } | 2216 | } |
2217 | |||
2218 | /* | ||
2219 | * iDiag debugfs root entry points for SLI4 device only | ||
2220 | */ | ||
2221 | if (phba->sli_rev < LPFC_SLI_REV4) | ||
2222 | goto debug_failed; | ||
2223 | |||
2224 | snprintf(name, sizeof(name), "iDiag"); | ||
2225 | if (!phba->idiag_root) { | ||
2226 | phba->idiag_root = | ||
2227 | debugfs_create_dir(name, phba->hba_debugfs_root); | ||
2228 | if (!phba->idiag_root) { | ||
2229 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | ||
2230 | "2922 Can't create idiag debugfs\n"); | ||
2231 | goto debug_failed; | ||
2232 | } | ||
2233 | /* Initialize iDiag data structure */ | ||
2234 | memset(&idiag, 0, sizeof(idiag)); | ||
2235 | } | ||
2236 | |||
2237 | /* iDiag read PCI config space */ | ||
2238 | snprintf(name, sizeof(name), "pciCfg"); | ||
2239 | if (!phba->idiag_pci_cfg) { | ||
2240 | phba->idiag_pci_cfg = | ||
2241 | debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR, | ||
2242 | phba->idiag_root, phba, &lpfc_idiag_op_pciCfg); | ||
2243 | if (!phba->idiag_pci_cfg) { | ||
2244 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | ||
2245 | "2923 Can't create idiag debugfs\n"); | ||
2246 | goto debug_failed; | ||
2247 | } | ||
2248 | idiag.offset.last_rd = 0; | ||
2249 | } | ||
2250 | |||
2251 | /* iDiag get PCI function queue information */ | ||
2252 | snprintf(name, sizeof(name), "queInfo"); | ||
2253 | if (!phba->idiag_que_info) { | ||
2254 | phba->idiag_que_info = | ||
2255 | debugfs_create_file(name, S_IFREG|S_IRUGO, | ||
2256 | phba->idiag_root, phba, &lpfc_idiag_op_queInfo); | ||
2257 | if (!phba->idiag_que_info) { | ||
2258 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | ||
2259 | "2924 Can't create idiag debugfs\n"); | ||
2260 | goto debug_failed; | ||
2261 | } | ||
2262 | } | ||
2263 | |||
1437 | debug_failed: | 2264 | debug_failed: |
1438 | return; | 2265 | return; |
1439 | #endif | 2266 | #endif |
@@ -1508,8 +2335,31 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport) | |||
1508 | phba->debug_slow_ring_trc = NULL; | 2335 | phba->debug_slow_ring_trc = NULL; |
1509 | } | 2336 | } |
1510 | 2337 | ||
2338 | /* | ||
2339 | * iDiag release | ||
2340 | */ | ||
2341 | if (phba->sli_rev == LPFC_SLI_REV4) { | ||
2342 | if (phba->idiag_que_info) { | ||
2343 | /* iDiag queInfo */ | ||
2344 | debugfs_remove(phba->idiag_que_info); | ||
2345 | phba->idiag_que_info = NULL; | ||
2346 | } | ||
2347 | if (phba->idiag_pci_cfg) { | ||
2348 | /* iDiag pciCfg */ | ||
2349 | debugfs_remove(phba->idiag_pci_cfg); | ||
2350 | phba->idiag_pci_cfg = NULL; | ||
2351 | } | ||
2352 | |||
2353 | /* Finally remove the iDiag debugfs root */ | ||
2354 | if (phba->idiag_root) { | ||
2355 | /* iDiag root */ | ||
2356 | debugfs_remove(phba->idiag_root); | ||
2357 | phba->idiag_root = NULL; | ||
2358 | } | ||
2359 | } | ||
2360 | |||
1511 | if (phba->hba_debugfs_root) { | 2361 | if (phba->hba_debugfs_root) { |
1512 | debugfs_remove(phba->hba_debugfs_root); /* lpfcX */ | 2362 | debugfs_remove(phba->hba_debugfs_root); /* fnX */ |
1513 | phba->hba_debugfs_root = NULL; | 2363 | phba->hba_debugfs_root = NULL; |
1514 | atomic_dec(&lpfc_debugfs_hba_count); | 2364 | atomic_dec(&lpfc_debugfs_hba_count); |
1515 | } | 2365 | } |
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h index 03c7313a1012..91b9a9427cda 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.h +++ b/drivers/scsi/lpfc/lpfc_debugfs.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2007 Emulex. All rights reserved. * | 4 | * Copyright (C) 2007-2011 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -22,6 +22,44 @@ | |||
22 | #define _H_LPFC_DEBUG_FS | 22 | #define _H_LPFC_DEBUG_FS |
23 | 23 | ||
24 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS | 24 | #ifdef CONFIG_SCSI_LPFC_DEBUG_FS |
25 | |||
26 | /* size of output line, for discovery_trace and slow_ring_trace */ | ||
27 | #define LPFC_DEBUG_TRC_ENTRY_SIZE 100 | ||
28 | |||
29 | /* nodelist output buffer size */ | ||
30 | #define LPFC_NODELIST_SIZE 8192 | ||
31 | #define LPFC_NODELIST_ENTRY_SIZE 120 | ||
32 | |||
33 | /* dumpHBASlim output buffer size */ | ||
34 | #define LPFC_DUMPHBASLIM_SIZE 4096 | ||
35 | |||
36 | /* dumpHostSlim output buffer size */ | ||
37 | #define LPFC_DUMPHOSTSLIM_SIZE 4096 | ||
38 | |||
39 | /* hbqinfo output buffer size */ | ||
40 | #define LPFC_HBQINFO_SIZE 8192 | ||
41 | |||
42 | /* rdPciConf output buffer size */ | ||
43 | #define LPFC_PCI_CFG_SIZE 4096 | ||
44 | #define LPFC_PCI_CFG_RD_BUF_SIZE (LPFC_PCI_CFG_SIZE/2) | ||
45 | #define LPFC_PCI_CFG_RD_SIZE (LPFC_PCI_CFG_SIZE/4) | ||
46 | |||
47 | /* queue info output buffer size */ | ||
48 | #define LPFC_QUE_INFO_GET_BUF_SIZE 2048 | ||
49 | |||
50 | #define SIZE_U8 sizeof(uint8_t) | ||
51 | #define SIZE_U16 sizeof(uint16_t) | ||
52 | #define SIZE_U32 sizeof(uint32_t) | ||
53 | |||
54 | struct lpfc_debug { | ||
55 | char *i_private; | ||
56 | char op; | ||
57 | #define LPFC_IDIAG_OP_RD 1 | ||
58 | #define LPFC_IDIAG_OP_WR 2 | ||
59 | char *buffer; | ||
60 | int len; | ||
61 | }; | ||
62 | |||
25 | struct lpfc_debugfs_trc { | 63 | struct lpfc_debugfs_trc { |
26 | char *fmt; | 64 | char *fmt; |
27 | uint32_t data1; | 65 | uint32_t data1; |
@@ -30,6 +68,26 @@ struct lpfc_debugfs_trc { | |||
30 | uint32_t seq_cnt; | 68 | uint32_t seq_cnt; |
31 | unsigned long jif; | 69 | unsigned long jif; |
32 | }; | 70 | }; |
71 | |||
72 | struct lpfc_idiag_offset { | ||
73 | uint32_t last_rd; | ||
74 | }; | ||
75 | |||
76 | #define LPFC_IDIAG_CMD_DATA_SIZE 4 | ||
77 | struct lpfc_idiag_cmd { | ||
78 | uint32_t opcode; | ||
79 | #define LPFC_IDIAG_CMD_PCICFG_RD 0x00000001 | ||
80 | #define LPFC_IDIAG_CMD_PCICFG_WR 0x00000002 | ||
81 | #define LPFC_IDIAG_CMD_PCICFG_ST 0x00000003 | ||
82 | #define LPFC_IDIAG_CMD_PCICFG_CL 0x00000004 | ||
83 | uint32_t data[LPFC_IDIAG_CMD_DATA_SIZE]; | ||
84 | }; | ||
85 | |||
86 | struct lpfc_idiag { | ||
87 | uint32_t active; | ||
88 | struct lpfc_idiag_cmd cmd; | ||
89 | struct lpfc_idiag_offset offset; | ||
90 | }; | ||
33 | #endif | 91 | #endif |
34 | 92 | ||
35 | /* Mask for discovery_trace */ | 93 | /* Mask for discovery_trace */ |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index b85c40e3bf55..2ee0374a9908 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -10471,6 +10471,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, | |||
10471 | cq->type = type; | 10471 | cq->type = type; |
10472 | cq->subtype = subtype; | 10472 | cq->subtype = subtype; |
10473 | cq->queue_id = bf_get(lpfc_mbx_cq_create_q_id, &cq_create->u.response); | 10473 | cq->queue_id = bf_get(lpfc_mbx_cq_create_q_id, &cq_create->u.response); |
10474 | cq->assoc_qid = eq->queue_id; | ||
10474 | cq->host_index = 0; | 10475 | cq->host_index = 0; |
10475 | cq->hba_index = 0; | 10476 | cq->hba_index = 0; |
10476 | 10477 | ||
@@ -10665,6 +10666,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq, | |||
10665 | goto out; | 10666 | goto out; |
10666 | } | 10667 | } |
10667 | mq->type = LPFC_MQ; | 10668 | mq->type = LPFC_MQ; |
10669 | mq->assoc_qid = cq->queue_id; | ||
10668 | mq->subtype = subtype; | 10670 | mq->subtype = subtype; |
10669 | mq->host_index = 0; | 10671 | mq->host_index = 0; |
10670 | mq->hba_index = 0; | 10672 | mq->hba_index = 0; |
@@ -10752,6 +10754,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, | |||
10752 | goto out; | 10754 | goto out; |
10753 | } | 10755 | } |
10754 | wq->type = LPFC_WQ; | 10756 | wq->type = LPFC_WQ; |
10757 | wq->assoc_qid = cq->queue_id; | ||
10755 | wq->subtype = subtype; | 10758 | wq->subtype = subtype; |
10756 | wq->host_index = 0; | 10759 | wq->host_index = 0; |
10757 | wq->hba_index = 0; | 10760 | wq->hba_index = 0; |
@@ -10869,6 +10872,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, | |||
10869 | goto out; | 10872 | goto out; |
10870 | } | 10873 | } |
10871 | hrq->type = LPFC_HRQ; | 10874 | hrq->type = LPFC_HRQ; |
10875 | hrq->assoc_qid = cq->queue_id; | ||
10872 | hrq->subtype = subtype; | 10876 | hrq->subtype = subtype; |
10873 | hrq->host_index = 0; | 10877 | hrq->host_index = 0; |
10874 | hrq->hba_index = 0; | 10878 | hrq->hba_index = 0; |
@@ -10929,6 +10933,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, | |||
10929 | goto out; | 10933 | goto out; |
10930 | } | 10934 | } |
10931 | drq->type = LPFC_DRQ; | 10935 | drq->type = LPFC_DRQ; |
10936 | drq->assoc_qid = cq->queue_id; | ||
10932 | drq->subtype = subtype; | 10937 | drq->subtype = subtype; |
10933 | drq->host_index = 0; | 10938 | drq->host_index = 0; |
10934 | drq->hba_index = 0; | 10939 | drq->hba_index = 0; |
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 435a09d331ee..595056b89608 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
@@ -125,9 +125,9 @@ struct lpfc_queue { | |||
125 | uint32_t entry_count; /* Number of entries to support on the queue */ | 125 | uint32_t entry_count; /* Number of entries to support on the queue */ |
126 | uint32_t entry_size; /* Size of each queue entry. */ | 126 | uint32_t entry_size; /* Size of each queue entry. */ |
127 | uint32_t queue_id; /* Queue ID assigned by the hardware */ | 127 | uint32_t queue_id; /* Queue ID assigned by the hardware */ |
128 | uint32_t assoc_qid; /* Queue ID associated with, for CQ/WQ/MQ */ | ||
128 | struct list_head page_list; | 129 | struct list_head page_list; |
129 | uint32_t page_count; /* Number of pages allocated for this queue */ | 130 | uint32_t page_count; /* Number of pages allocated for this queue */ |
130 | |||
131 | uint32_t host_index; /* The host's index for putting or getting */ | 131 | uint32_t host_index; /* The host's index for putting or getting */ |
132 | uint32_t hba_index; /* The last known hba index for get or put */ | 132 | uint32_t hba_index; /* The last known hba index for get or put */ |
133 | union sli4_qe qe[1]; /* array to index entries (must be last) */ | 133 | union sli4_qe qe[1]; /* array to index entries (must be last) */ |