aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c931
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.h48
3 files changed, 759 insertions, 222 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 60e98a62f308..02d53d89534f 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -805,6 +805,8 @@ struct lpfc_hba {
805 struct dentry *idiag_root; 805 struct dentry *idiag_root;
806 struct dentry *idiag_pci_cfg; 806 struct dentry *idiag_pci_cfg;
807 struct dentry *idiag_que_info; 807 struct dentry *idiag_que_info;
808 struct dentry *idiag_que_acc;
809 struct dentry *idiag_drb_acc;
808#endif 810#endif
809 811
810 /* Used for deferred freeing of ELS data buffers */ 812 /* 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 3d967741c708..c93fca058603 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -1119,172 +1119,14 @@ lpfc_debugfs_dumpDataDif_release(struct inode *inode, struct file *file)
1119} 1119}
1120 1120
1121/* 1121/*
1122 * ---------------------------------
1122 * iDiag debugfs file access methods 1123 * iDiag debugfs file access methods
1123 */ 1124 * ---------------------------------
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 * 1125 *
1266 * "-bash: echo: write error: Invalid argument". 1126 * All access methods are through the proper SLI4 PCI function's debugfs
1127 * iDiag directory:
1267 * 1128 *
1268 * For example: 1129 * /sys/kernel/debug/lpfc/fn<#>/iDiag
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 */ 1130 */
1289 1131
1290/** 1132/**
@@ -1331,10 +1173,10 @@ static int lpfc_idiag_cmd_get(const char __user *buf, size_t nbytes,
1331 for (i = 0; i < LPFC_IDIAG_CMD_DATA_SIZE; i++) { 1173 for (i = 0; i < LPFC_IDIAG_CMD_DATA_SIZE; i++) {
1332 step_str = strsep(&pbuf, "\t "); 1174 step_str = strsep(&pbuf, "\t ");
1333 if (!step_str) 1175 if (!step_str)
1334 return 0; 1176 return i;
1335 idiag_cmd->data[i] = simple_strtol(step_str, NULL, 0); 1177 idiag_cmd->data[i] = simple_strtol(step_str, NULL, 0);
1336 } 1178 }
1337 return 0; 1179 return i;
1338} 1180}
1339 1181
1340/** 1182/**
@@ -1403,7 +1245,7 @@ lpfc_idiag_release(struct inode *inode, struct file *file)
1403 * Description: 1245 * Description:
1404 * This routine frees the buffer that was allocated when the debugfs file 1246 * 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 1247 * 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. 1248 * case of command for write operation.
1407 * 1249 *
1408 * Returns: 1250 * Returns:
1409 * This function returns zero. 1251 * This function returns zero.
@@ -1413,18 +1255,20 @@ lpfc_idiag_cmd_release(struct inode *inode, struct file *file)
1413{ 1255{
1414 struct lpfc_debug *debug = file->private_data; 1256 struct lpfc_debug *debug = file->private_data;
1415 1257
1416 /* Read PCI config register, if not read all, clear command fields */ 1258 if (debug->op == LPFC_IDIAG_OP_WR) {
1417 if ((debug->op == LPFC_IDIAG_OP_RD) && 1259 switch (idiag.cmd.opcode) {
1418 (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD)) 1260 case LPFC_IDIAG_CMD_PCICFG_WR:
1419 if ((idiag.cmd.data[1] == sizeof(uint8_t)) || 1261 case LPFC_IDIAG_CMD_PCICFG_ST:
1420 (idiag.cmd.data[1] == sizeof(uint16_t)) || 1262 case LPFC_IDIAG_CMD_PCICFG_CL:
1421 (idiag.cmd.data[1] == sizeof(uint32_t))) 1263 case LPFC_IDIAG_CMD_QUEACC_WR:
1264 case LPFC_IDIAG_CMD_QUEACC_ST:
1265 case LPFC_IDIAG_CMD_QUEACC_CL:
1422 memset(&idiag, 0, sizeof(idiag)); 1266 memset(&idiag, 0, sizeof(idiag));
1423 1267 break;
1424 /* Write PCI config register, clear command fields */ 1268 default:
1425 if ((debug->op == LPFC_IDIAG_OP_WR) && 1269 break;
1426 (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)) 1270 }
1427 memset(&idiag, 0, sizeof(idiag)); 1271 }
1428 1272
1429 /* Free the buffers to the file operation */ 1273 /* Free the buffers to the file operation */
1430 kfree(debug->buffer); 1274 kfree(debug->buffer);
@@ -1504,7 +1348,7 @@ lpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes,
1504 len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len, 1348 len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
1505 "%03x: %08x\n", where, u32val); 1349 "%03x: %08x\n", where, u32val);
1506 break; 1350 break;
1507 case LPFC_PCI_CFG_SIZE: /* browse all */ 1351 case LPFC_PCI_CFG_BROWSE: /* browse all */
1508 goto pcicfg_browse; 1352 goto pcicfg_browse;
1509 break; 1353 break;
1510 default: 1354 default:
@@ -1586,16 +1430,21 @@ lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf,
1586 debug->op = LPFC_IDIAG_OP_WR; 1430 debug->op = LPFC_IDIAG_OP_WR;
1587 1431
1588 rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd); 1432 rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
1589 if (rc) 1433 if (rc < 0)
1590 return rc; 1434 return rc;
1591 1435
1592 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) { 1436 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) {
1437 /* Sanity check on PCI config read command line arguments */
1438 if (rc != LPFC_PCI_CFG_RD_CMD_ARG)
1439 goto error_out;
1593 /* Read command from PCI config space, set up command fields */ 1440 /* Read command from PCI config space, set up command fields */
1594 where = idiag.cmd.data[0]; 1441 where = idiag.cmd.data[0];
1595 count = idiag.cmd.data[1]; 1442 count = idiag.cmd.data[1];
1596 if (count == LPFC_PCI_CFG_SIZE) { 1443 if (count == LPFC_PCI_CFG_BROWSE) {
1597 if (where != 0) 1444 if (where % sizeof(uint32_t))
1598 goto error_out; 1445 goto error_out;
1446 /* Starting offset to browse */
1447 idiag.offset.last_rd = where;
1599 } else if ((count != sizeof(uint8_t)) && 1448 } else if ((count != sizeof(uint8_t)) &&
1600 (count != sizeof(uint16_t)) && 1449 (count != sizeof(uint16_t)) &&
1601 (count != sizeof(uint32_t))) 1450 (count != sizeof(uint32_t)))
@@ -1621,6 +1470,9 @@ lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf,
1621 } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR || 1470 } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR ||
1622 idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST || 1471 idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST ||
1623 idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) { 1472 idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
1473 /* Sanity check on PCI config write command line arguments */
1474 if (rc != LPFC_PCI_CFG_WR_CMD_ARG)
1475 goto error_out;
1624 /* Write command to PCI config space, read-modify-write */ 1476 /* Write command to PCI config space, read-modify-write */
1625 where = idiag.cmd.data[0]; 1477 where = idiag.cmd.data[0];
1626 count = idiag.cmd.data[1]; 1478 count = idiag.cmd.data[1];
@@ -1753,10 +1605,12 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
1753 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1605 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1754 "Slow-path EQ information:\n"); 1606 "Slow-path EQ information:\n");
1755 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1607 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1756 "\tID [%02d], EQE-COUNT [%04d], " 1608 "\tEQID[%02d], "
1757 "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", 1609 "QE-COUNT[%04d], QE-SIZE[%04d], "
1610 "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n",
1758 phba->sli4_hba.sp_eq->queue_id, 1611 phba->sli4_hba.sp_eq->queue_id,
1759 phba->sli4_hba.sp_eq->entry_count, 1612 phba->sli4_hba.sp_eq->entry_count,
1613 phba->sli4_hba.sp_eq->entry_size,
1760 phba->sli4_hba.sp_eq->host_index, 1614 phba->sli4_hba.sp_eq->host_index,
1761 phba->sli4_hba.sp_eq->hba_index); 1615 phba->sli4_hba.sp_eq->hba_index);
1762 1616
@@ -1765,10 +1619,12 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
1765 "Fast-path EQ information:\n"); 1619 "Fast-path EQ information:\n");
1766 for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) { 1620 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, 1621 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1768 "\tID [%02d], EQE-COUNT [%04d], " 1622 "\tEQID[%02d], "
1769 "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", 1623 "QE-COUNT[%04d], QE-SIZE[%04d], "
1624 "HOST-INDEX[%04d], PORT-INDEX[%04d]\n",
1770 phba->sli4_hba.fp_eq[fcp_qidx]->queue_id, 1625 phba->sli4_hba.fp_eq[fcp_qidx]->queue_id,
1771 phba->sli4_hba.fp_eq[fcp_qidx]->entry_count, 1626 phba->sli4_hba.fp_eq[fcp_qidx]->entry_count,
1627 phba->sli4_hba.fp_eq[fcp_qidx]->entry_size,
1772 phba->sli4_hba.fp_eq[fcp_qidx]->host_index, 1628 phba->sli4_hba.fp_eq[fcp_qidx]->host_index,
1773 phba->sli4_hba.fp_eq[fcp_qidx]->hba_index); 1629 phba->sli4_hba.fp_eq[fcp_qidx]->hba_index);
1774 } 1630 }
@@ -1776,89 +1632,101 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
1776 1632
1777 /* Get mailbox complete queue information */ 1633 /* Get mailbox complete queue information */
1778 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1634 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1779 "Mailbox CQ information:\n"); 1635 "Slow-path MBX CQ information:\n");
1780 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1636 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1781 "\t\tAssociated EQ-ID [%02d]:\n", 1637 "Associated EQID[%02d]:\n",
1782 phba->sli4_hba.mbx_cq->assoc_qid); 1638 phba->sli4_hba.mbx_cq->assoc_qid);
1783 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1639 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1784 "\tID [%02d], CQE-COUNT [%04d], " 1640 "\tCQID[%02d], "
1785 "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", 1641 "QE-COUNT[%04d], QE-SIZE[%04d], "
1642 "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n",
1786 phba->sli4_hba.mbx_cq->queue_id, 1643 phba->sli4_hba.mbx_cq->queue_id,
1787 phba->sli4_hba.mbx_cq->entry_count, 1644 phba->sli4_hba.mbx_cq->entry_count,
1645 phba->sli4_hba.mbx_cq->entry_size,
1788 phba->sli4_hba.mbx_cq->host_index, 1646 phba->sli4_hba.mbx_cq->host_index,
1789 phba->sli4_hba.mbx_cq->hba_index); 1647 phba->sli4_hba.mbx_cq->hba_index);
1790 1648
1791 /* Get slow-path complete queue information */ 1649 /* Get slow-path complete queue information */
1792 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1650 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1793 "Slow-path CQ information:\n"); 1651 "Slow-path ELS CQ information:\n");
1794 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1652 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1795 "\t\tAssociated EQ-ID [%02d]:\n", 1653 "Associated EQID[%02d]:\n",
1796 phba->sli4_hba.els_cq->assoc_qid); 1654 phba->sli4_hba.els_cq->assoc_qid);
1797 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1655 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1798 "\tID [%02d], CQE-COUNT [%04d], " 1656 "\tCQID [%02d], "
1799 "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", 1657 "QE-COUNT[%04d], QE-SIZE[%04d], "
1658 "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n",
1800 phba->sli4_hba.els_cq->queue_id, 1659 phba->sli4_hba.els_cq->queue_id,
1801 phba->sli4_hba.els_cq->entry_count, 1660 phba->sli4_hba.els_cq->entry_count,
1661 phba->sli4_hba.els_cq->entry_size,
1802 phba->sli4_hba.els_cq->host_index, 1662 phba->sli4_hba.els_cq->host_index,
1803 phba->sli4_hba.els_cq->hba_index); 1663 phba->sli4_hba.els_cq->hba_index);
1804 1664
1805 /* Get fast-path complete queue information */ 1665 /* Get fast-path complete queue information */
1806 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1666 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1807 "Fast-path CQ information:\n"); 1667 "Fast-path FCP CQ information:\n");
1808 for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) { 1668 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, 1669 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1810 "\t\tAssociated EQ-ID [%02d]:\n", 1670 "Associated EQID[%02d]:\n",
1811 phba->sli4_hba.fcp_cq[fcp_qidx]->assoc_qid); 1671 phba->sli4_hba.fcp_cq[fcp_qidx]->assoc_qid);
1812 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1672 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1813 "\tID [%02d], EQE-COUNT [%04d], " 1673 "\tCQID[%02d], "
1814 "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", 1674 "QE-COUNT[%04d], QE-SIZE[%04d], "
1815 phba->sli4_hba.fcp_cq[fcp_qidx]->queue_id, 1675 "HOST-INDEX[%04d], PORT-INDEX[%04d]\n",
1816 phba->sli4_hba.fcp_cq[fcp_qidx]->entry_count, 1676 phba->sli4_hba.fcp_cq[fcp_qidx]->queue_id,
1817 phba->sli4_hba.fcp_cq[fcp_qidx]->host_index, 1677 phba->sli4_hba.fcp_cq[fcp_qidx]->entry_count,
1818 phba->sli4_hba.fcp_cq[fcp_qidx]->hba_index); 1678 phba->sli4_hba.fcp_cq[fcp_qidx]->entry_size,
1679 phba->sli4_hba.fcp_cq[fcp_qidx]->host_index,
1680 phba->sli4_hba.fcp_cq[fcp_qidx]->hba_index);
1819 } 1681 }
1820 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n"); 1682 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n");
1821 1683
1822 /* Get mailbox queue information */ 1684 /* Get mailbox queue information */
1823 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1685 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1824 "Mailbox MQ information:\n"); 1686 "Slow-path MBX MQ information:\n");
1825 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1687 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1826 "\t\tAssociated CQ-ID [%02d]:\n", 1688 "Associated CQID[%02d]:\n",
1827 phba->sli4_hba.mbx_wq->assoc_qid); 1689 phba->sli4_hba.mbx_wq->assoc_qid);
1828 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1690 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1829 "\tID [%02d], MQE-COUNT [%04d], " 1691 "\tWQID[%02d], "
1830 "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", 1692 "QE-COUNT[%04d], QE-SIZE[%04d], "
1693 "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n",
1831 phba->sli4_hba.mbx_wq->queue_id, 1694 phba->sli4_hba.mbx_wq->queue_id,
1832 phba->sli4_hba.mbx_wq->entry_count, 1695 phba->sli4_hba.mbx_wq->entry_count,
1696 phba->sli4_hba.mbx_wq->entry_size,
1833 phba->sli4_hba.mbx_wq->host_index, 1697 phba->sli4_hba.mbx_wq->host_index,
1834 phba->sli4_hba.mbx_wq->hba_index); 1698 phba->sli4_hba.mbx_wq->hba_index);
1835 1699
1836 /* Get slow-path work queue information */ 1700 /* Get slow-path work queue information */
1837 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1701 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1838 "Slow-path WQ information:\n"); 1702 "Slow-path ELS WQ information:\n");
1839 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1703 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1840 "\t\tAssociated CQ-ID [%02d]:\n", 1704 "Associated CQID[%02d]:\n",
1841 phba->sli4_hba.els_wq->assoc_qid); 1705 phba->sli4_hba.els_wq->assoc_qid);
1842 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1706 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1843 "\tID [%02d], WQE-COUNT [%04d], " 1707 "\tWQID[%02d], "
1844 "HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n", 1708 "QE-COUNT[%04d], QE-SIZE[%04d], "
1709 "HOST-INDEX[%04d], PORT-INDEX[%04d]\n\n",
1845 phba->sli4_hba.els_wq->queue_id, 1710 phba->sli4_hba.els_wq->queue_id,
1846 phba->sli4_hba.els_wq->entry_count, 1711 phba->sli4_hba.els_wq->entry_count,
1712 phba->sli4_hba.els_wq->entry_size,
1847 phba->sli4_hba.els_wq->host_index, 1713 phba->sli4_hba.els_wq->host_index,
1848 phba->sli4_hba.els_wq->hba_index); 1714 phba->sli4_hba.els_wq->hba_index);
1849 1715
1850 /* Get fast-path work queue information */ 1716 /* Get fast-path work queue information */
1851 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1717 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1852 "Fast-path WQ information:\n"); 1718 "Fast-path FCP WQ information:\n");
1853 for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_wq_count; fcp_qidx++) { 1719 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, 1720 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1855 "\t\tAssociated CQ-ID [%02d]:\n", 1721 "Associated CQID[%02d]:\n",
1856 phba->sli4_hba.fcp_wq[fcp_qidx]->assoc_qid); 1722 phba->sli4_hba.fcp_wq[fcp_qidx]->assoc_qid);
1857 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1723 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1858 "\tID [%02d], WQE-COUNT [%04d], " 1724 "\tWQID[%02d], "
1859 "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", 1725 "QE-COUNT[%04d], WQE-SIZE[%04d], "
1726 "HOST-INDEX[%04d], PORT-INDEX[%04d]\n",
1860 phba->sli4_hba.fcp_wq[fcp_qidx]->queue_id, 1727 phba->sli4_hba.fcp_wq[fcp_qidx]->queue_id,
1861 phba->sli4_hba.fcp_wq[fcp_qidx]->entry_count, 1728 phba->sli4_hba.fcp_wq[fcp_qidx]->entry_count,
1729 phba->sli4_hba.fcp_wq[fcp_qidx]->entry_size,
1862 phba->sli4_hba.fcp_wq[fcp_qidx]->host_index, 1730 phba->sli4_hba.fcp_wq[fcp_qidx]->host_index,
1863 phba->sli4_hba.fcp_wq[fcp_qidx]->hba_index); 1731 phba->sli4_hba.fcp_wq[fcp_qidx]->hba_index);
1864 } 1732 }
@@ -1868,26 +1736,597 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
1868 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1736 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1869 "Slow-path RQ information:\n"); 1737 "Slow-path RQ information:\n");
1870 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1738 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1871 "\t\tAssociated CQ-ID [%02d]:\n", 1739 "Associated CQID[%02d]:\n",
1872 phba->sli4_hba.hdr_rq->assoc_qid); 1740 phba->sli4_hba.hdr_rq->assoc_qid);
1873 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1741 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1874 "\tID [%02d], RHQE-COUNT [%04d], " 1742 "\tHQID[%02d], "
1875 "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", 1743 "QE-COUNT[%04d], QE-SIZE[%04d], "
1744 "HOST-INDEX[%04d], PORT-INDEX[%04d]\n",
1876 phba->sli4_hba.hdr_rq->queue_id, 1745 phba->sli4_hba.hdr_rq->queue_id,
1877 phba->sli4_hba.hdr_rq->entry_count, 1746 phba->sli4_hba.hdr_rq->entry_count,
1747 phba->sli4_hba.hdr_rq->entry_size,
1878 phba->sli4_hba.hdr_rq->host_index, 1748 phba->sli4_hba.hdr_rq->host_index,
1879 phba->sli4_hba.hdr_rq->hba_index); 1749 phba->sli4_hba.hdr_rq->hba_index);
1880 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, 1750 len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
1881 "\tID [%02d], RDQE-COUNT [%04d], " 1751 "\tDQID[%02d], "
1882 "HOST-INDEX [%04x], PORT-INDEX [%04x]\n", 1752 "QE-COUNT[%04d], QE-SIZE[%04d], "
1753 "HOST-INDEX[%04d], PORT-INDEX[%04d]\n",
1883 phba->sli4_hba.dat_rq->queue_id, 1754 phba->sli4_hba.dat_rq->queue_id,
1884 phba->sli4_hba.dat_rq->entry_count, 1755 phba->sli4_hba.dat_rq->entry_count,
1756 phba->sli4_hba.dat_rq->entry_size,
1885 phba->sli4_hba.dat_rq->host_index, 1757 phba->sli4_hba.dat_rq->host_index,
1886 phba->sli4_hba.dat_rq->hba_index); 1758 phba->sli4_hba.dat_rq->hba_index);
1887 1759
1888 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len); 1760 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
1889} 1761}
1890 1762
1763/**
1764 * lpfc_idiag_que_param_check - queue access command parameter sanity check
1765 * @q: The pointer to queue structure.
1766 * @index: The index into a queue entry.
1767 * @count: The number of queue entries to access.
1768 *
1769 * Description:
1770 * The routine performs sanity check on device queue access method commands.
1771 *
1772 * Returns:
1773 * This function returns -EINVAL when fails the sanity check, otherwise, it
1774 * returns 0.
1775 **/
1776static int
1777lpfc_idiag_que_param_check(struct lpfc_queue *q, int index, int count)
1778{
1779 /* Only support single entry read or browsing */
1780 if ((count != 1) && (count != LPFC_QUE_ACC_BROWSE))
1781 return -EINVAL;
1782 if (index > q->entry_count - 1)
1783 return -EINVAL;
1784 return 0;
1785}
1786
1787/**
1788 * lpfc_idiag_queacc_read_qe - read a single entry from the given queue index
1789 * @pbuffer: The pointer to buffer to copy the read data into.
1790 * @pque: The pointer to the queue to be read.
1791 * @index: The index into the queue entry.
1792 *
1793 * Description:
1794 * This routine reads out a single entry from the given queue's index location
1795 * and copies it into the buffer provided.
1796 *
1797 * Returns:
1798 * This function returns 0 when it fails, otherwise, it returns the length of
1799 * the data read into the buffer provided.
1800 **/
1801static int
1802lpfc_idiag_queacc_read_qe(char *pbuffer, int len, struct lpfc_queue *pque,
1803 uint32_t index)
1804{
1805 int offset, esize;
1806 uint32_t *pentry;
1807
1808 if (!pbuffer || !pque)
1809 return 0;
1810
1811 esize = pque->entry_size;
1812 len += snprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len,
1813 "QE-INDEX[%04d]:\n", index);
1814
1815 offset = 0;
1816 pentry = pque->qe[index].address;
1817 while (esize > 0) {
1818 len += snprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len,
1819 "%08x ", *pentry);
1820 pentry++;
1821 offset += sizeof(uint32_t);
1822 esize -= sizeof(uint32_t);
1823 if (esize > 0 && !(offset % (4 * sizeof(uint32_t))))
1824 len += snprintf(pbuffer+len,
1825 LPFC_QUE_ACC_BUF_SIZE-len, "\n");
1826 }
1827 len += snprintf(pbuffer+len, LPFC_QUE_ACC_BUF_SIZE-len, "\n");
1828
1829 return len;
1830}
1831
1832/**
1833 * lpfc_idiag_queacc_read - idiag debugfs read port queue
1834 * @file: The file pointer to read from.
1835 * @buf: The buffer to copy the data to.
1836 * @nbytes: The number of bytes to read.
1837 * @ppos: The position in the file to start reading from.
1838 *
1839 * Description:
1840 * This routine reads data from the @phba device queue memory according to the
1841 * idiag command, and copies to user @buf. Depending on the queue dump read
1842 * command setup, it does either a single queue entry read or browing through
1843 * all entries of the queue.
1844 *
1845 * Returns:
1846 * This function returns the amount of data that was read (this could be less
1847 * than @nbytes if the end of the file was reached) or a negative error value.
1848 **/
1849static ssize_t
1850lpfc_idiag_queacc_read(struct file *file, char __user *buf, size_t nbytes,
1851 loff_t *ppos)
1852{
1853 struct lpfc_debug *debug = file->private_data;
1854 uint32_t last_index, index, count;
1855 struct lpfc_queue *pque = NULL;
1856 char *pbuffer;
1857 int len = 0;
1858
1859 /* This is a user read operation */
1860 debug->op = LPFC_IDIAG_OP_RD;
1861
1862 if (!debug->buffer)
1863 debug->buffer = kmalloc(LPFC_QUE_ACC_BUF_SIZE, GFP_KERNEL);
1864 if (!debug->buffer)
1865 return 0;
1866 pbuffer = debug->buffer;
1867
1868 if (*ppos)
1869 return 0;
1870
1871 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) {
1872 index = idiag.cmd.data[2];
1873 count = idiag.cmd.data[3];
1874 pque = (struct lpfc_queue *)idiag.ptr_private;
1875 } else
1876 return 0;
1877
1878 /* Browse the queue starting from index */
1879 if (count == LPFC_QUE_ACC_BROWSE)
1880 goto que_browse;
1881
1882 /* Read a single entry from the queue */
1883 len = lpfc_idiag_queacc_read_qe(pbuffer, len, pque, index);
1884
1885 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
1886
1887que_browse:
1888
1889 /* Browse all entries from the queue */
1890 last_index = idiag.offset.last_rd;
1891 index = last_index;
1892
1893 while (len < LPFC_QUE_ACC_SIZE - pque->entry_size) {
1894 len = lpfc_idiag_queacc_read_qe(pbuffer, len, pque, index);
1895 index++;
1896 if (index > pque->entry_count - 1)
1897 break;
1898 }
1899
1900 /* Set up the offset for next portion of pci cfg read */
1901 if (index > pque->entry_count - 1)
1902 index = 0;
1903 idiag.offset.last_rd = index;
1904
1905 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
1906}
1907
1908/**
1909 * lpfc_idiag_queacc_write - Syntax check and set up idiag queacc commands
1910 * @file: The file pointer to read from.
1911 * @buf: The buffer to copy the user data from.
1912 * @nbytes: The number of bytes to get.
1913 * @ppos: The position in the file to start reading from.
1914 *
1915 * This routine get the debugfs idiag command struct from user space and then
1916 * perform the syntax check for port queue read (dump) or write (set) command
1917 * accordingly. In the case of port queue read command, it sets up the command
1918 * in the idiag command struct for the following debugfs read operation. In
1919 * the case of port queue write operation, it executes the write operation
1920 * into the port queue entry accordingly.
1921 *
1922 * It returns the @nbytges passing in from debugfs user space when successful.
1923 * In case of error conditions, it returns proper error code back to the user
1924 * space.
1925 **/
1926static ssize_t
1927lpfc_idiag_queacc_write(struct file *file, const char __user *buf,
1928 size_t nbytes, loff_t *ppos)
1929{
1930 struct lpfc_debug *debug = file->private_data;
1931 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
1932 uint32_t qidx, quetp, queid, index, count, offset, value;
1933 uint32_t *pentry;
1934 struct lpfc_queue *pque;
1935 int rc;
1936
1937 /* This is a user write operation */
1938 debug->op = LPFC_IDIAG_OP_WR;
1939
1940 rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
1941 if (rc < 0)
1942 return rc;
1943
1944 /* Get and sanity check on command feilds */
1945 quetp = idiag.cmd.data[0];
1946 queid = idiag.cmd.data[1];
1947 index = idiag.cmd.data[2];
1948 count = idiag.cmd.data[3];
1949 offset = idiag.cmd.data[4];
1950 value = idiag.cmd.data[5];
1951
1952 /* Sanity check on command line arguments */
1953 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR ||
1954 idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST ||
1955 idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL) {
1956 if (rc != LPFC_QUE_ACC_WR_CMD_ARG)
1957 goto error_out;
1958 if (count != 1)
1959 goto error_out;
1960 } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) {
1961 if (rc != LPFC_QUE_ACC_RD_CMD_ARG)
1962 goto error_out;
1963 } else
1964 goto error_out;
1965
1966 switch (quetp) {
1967 case LPFC_IDIAG_EQ:
1968 /* Slow-path event queue */
1969 if (phba->sli4_hba.sp_eq->queue_id == queid) {
1970 /* Sanity check */
1971 rc = lpfc_idiag_que_param_check(
1972 phba->sli4_hba.sp_eq, index, count);
1973 if (rc)
1974 goto error_out;
1975 idiag.ptr_private = phba->sli4_hba.sp_eq;
1976 goto pass_check;
1977 }
1978 /* Fast-path event queue */
1979 for (qidx = 0; qidx < phba->cfg_fcp_eq_count; qidx++) {
1980 if (phba->sli4_hba.fp_eq[qidx]->queue_id == queid) {
1981 /* Sanity check */
1982 rc = lpfc_idiag_que_param_check(
1983 phba->sli4_hba.fp_eq[qidx],
1984 index, count);
1985 if (rc)
1986 goto error_out;
1987 idiag.ptr_private = phba->sli4_hba.fp_eq[qidx];
1988 goto pass_check;
1989 }
1990 }
1991 goto error_out;
1992 break;
1993 case LPFC_IDIAG_CQ:
1994 /* MBX complete queue */
1995 if (phba->sli4_hba.mbx_cq->queue_id == queid) {
1996 /* Sanity check */
1997 rc = lpfc_idiag_que_param_check(
1998 phba->sli4_hba.mbx_cq, index, count);
1999 if (rc)
2000 goto error_out;
2001 idiag.ptr_private = phba->sli4_hba.mbx_cq;
2002 goto pass_check;
2003 }
2004 /* ELS complete queue */
2005 if (phba->sli4_hba.els_cq->queue_id == queid) {
2006 /* Sanity check */
2007 rc = lpfc_idiag_que_param_check(
2008 phba->sli4_hba.els_cq, index, count);
2009 if (rc)
2010 goto error_out;
2011 idiag.ptr_private = phba->sli4_hba.els_cq;
2012 goto pass_check;
2013 }
2014 /* FCP complete queue */
2015 for (qidx = 0; qidx < phba->cfg_fcp_eq_count; qidx++) {
2016 if (phba->sli4_hba.fcp_cq[qidx]->queue_id == queid) {
2017 /* Sanity check */
2018 rc = lpfc_idiag_que_param_check(
2019 phba->sli4_hba.fcp_cq[qidx],
2020 index, count);
2021 if (rc)
2022 goto error_out;
2023 idiag.ptr_private =
2024 phba->sli4_hba.fcp_cq[qidx];
2025 goto pass_check;
2026 }
2027 }
2028 goto error_out;
2029 break;
2030 case LPFC_IDIAG_MQ:
2031 /* MBX work queue */
2032 if (phba->sli4_hba.mbx_wq->queue_id == queid) {
2033 /* Sanity check */
2034 rc = lpfc_idiag_que_param_check(
2035 phba->sli4_hba.mbx_wq, index, count);
2036 if (rc)
2037 goto error_out;
2038 idiag.ptr_private = phba->sli4_hba.mbx_wq;
2039 goto pass_check;
2040 }
2041 break;
2042 case LPFC_IDIAG_WQ:
2043 /* ELS work queue */
2044 if (phba->sli4_hba.els_wq->queue_id == queid) {
2045 /* Sanity check */
2046 rc = lpfc_idiag_que_param_check(
2047 phba->sli4_hba.els_wq, index, count);
2048 if (rc)
2049 goto error_out;
2050 idiag.ptr_private = phba->sli4_hba.els_wq;
2051 goto pass_check;
2052 }
2053 /* FCP work queue */
2054 for (qidx = 0; qidx < phba->cfg_fcp_wq_count; qidx++) {
2055 if (phba->sli4_hba.fcp_wq[qidx]->queue_id == queid) {
2056 /* Sanity check */
2057 rc = lpfc_idiag_que_param_check(
2058 phba->sli4_hba.fcp_wq[qidx],
2059 index, count);
2060 if (rc)
2061 goto error_out;
2062 idiag.ptr_private =
2063 phba->sli4_hba.fcp_wq[qidx];
2064 goto pass_check;
2065 }
2066 }
2067 goto error_out;
2068 break;
2069 case LPFC_IDIAG_RQ:
2070 /* HDR queue */
2071 if (phba->sli4_hba.hdr_rq->queue_id == queid) {
2072 /* Sanity check */
2073 rc = lpfc_idiag_que_param_check(
2074 phba->sli4_hba.hdr_rq, index, count);
2075 if (rc)
2076 goto error_out;
2077 idiag.ptr_private = phba->sli4_hba.hdr_rq;
2078 goto pass_check;
2079 }
2080 /* DAT queue */
2081 if (phba->sli4_hba.dat_rq->queue_id == queid) {
2082 /* Sanity check */
2083 rc = lpfc_idiag_que_param_check(
2084 phba->sli4_hba.dat_rq, index, count);
2085 if (rc)
2086 goto error_out;
2087 idiag.ptr_private = phba->sli4_hba.dat_rq;
2088 goto pass_check;
2089 }
2090 goto error_out;
2091 break;
2092 default:
2093 goto error_out;
2094 break;
2095 }
2096
2097pass_check:
2098
2099 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_RD) {
2100 if (count == LPFC_QUE_ACC_BROWSE)
2101 idiag.offset.last_rd = index;
2102 }
2103
2104 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR ||
2105 idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST ||
2106 idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL) {
2107 /* Additional sanity checks on write operation */
2108 pque = (struct lpfc_queue *)idiag.ptr_private;
2109 if (offset > pque->entry_size/sizeof(uint32_t) - 1)
2110 goto error_out;
2111 pentry = pque->qe[index].address;
2112 pentry += offset;
2113 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_WR)
2114 *pentry = value;
2115 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_ST)
2116 *pentry |= value;
2117 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_QUEACC_CL)
2118 *pentry &= ~value;
2119 }
2120 return nbytes;
2121
2122error_out:
2123 /* Clean out command structure on command error out */
2124 memset(&idiag, 0, sizeof(idiag));
2125 return -EINVAL;
2126}
2127
2128/**
2129 * lpfc_idiag_drbacc_read_reg - idiag debugfs read a doorbell register
2130 * @phba: The pointer to hba structure.
2131 * @pbuffer: The pointer to the buffer to copy the data to.
2132 * @len: The lenght of bytes to copied.
2133 * @drbregid: The id to doorbell registers.
2134 *
2135 * Description:
2136 * This routine reads a doorbell register and copies its content to the
2137 * user buffer pointed to by @pbuffer.
2138 *
2139 * Returns:
2140 * This function returns the amount of data that was copied into @pbuffer.
2141 **/
2142static int
2143lpfc_idiag_drbacc_read_reg(struct lpfc_hba *phba, char *pbuffer,
2144 int len, uint32_t drbregid)
2145{
2146
2147 if (!pbuffer)
2148 return 0;
2149
2150 switch (drbregid) {
2151 case LPFC_DRB_EQCQ:
2152 len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
2153 "EQCQ-DRB-REG: 0x%08x\n",
2154 readl(phba->sli4_hba.EQCQDBregaddr));
2155 break;
2156 case LPFC_DRB_MQ:
2157 len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
2158 "MQ-DRB-REG: 0x%08x\n",
2159 readl(phba->sli4_hba.MQDBregaddr));
2160 break;
2161 case LPFC_DRB_WQ:
2162 len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
2163 "WQ-DRB-REG: 0x%08x\n",
2164 readl(phba->sli4_hba.WQDBregaddr));
2165 break;
2166 case LPFC_DRB_RQ:
2167 len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
2168 "RQ-DRB-REG: 0x%08x\n",
2169 readl(phba->sli4_hba.RQDBregaddr));
2170 break;
2171 default:
2172 break;
2173 }
2174
2175 return len;
2176}
2177
2178/**
2179 * lpfc_idiag_drbacc_read - idiag debugfs read port doorbell
2180 * @file: The file pointer to read from.
2181 * @buf: The buffer to copy the data to.
2182 * @nbytes: The number of bytes to read.
2183 * @ppos: The position in the file to start reading from.
2184 *
2185 * Description:
2186 * This routine reads data from the @phba device doorbell register according
2187 * to the idiag command, and copies to user @buf. Depending on the doorbell
2188 * register read command setup, it does either a single doorbell register
2189 * read or dump all doorbell registers.
2190 *
2191 * Returns:
2192 * This function returns the amount of data that was read (this could be less
2193 * than @nbytes if the end of the file was reached) or a negative error value.
2194 **/
2195static ssize_t
2196lpfc_idiag_drbacc_read(struct file *file, char __user *buf, size_t nbytes,
2197 loff_t *ppos)
2198{
2199 struct lpfc_debug *debug = file->private_data;
2200 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
2201 uint32_t drb_reg_id, i;
2202 char *pbuffer;
2203 int len = 0;
2204
2205 /* This is a user read operation */
2206 debug->op = LPFC_IDIAG_OP_RD;
2207
2208 if (!debug->buffer)
2209 debug->buffer = kmalloc(LPFC_DRB_ACC_BUF_SIZE, GFP_KERNEL);
2210 if (!debug->buffer)
2211 return 0;
2212 pbuffer = debug->buffer;
2213
2214 if (*ppos)
2215 return 0;
2216
2217 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD)
2218 drb_reg_id = idiag.cmd.data[0];
2219 else
2220 return 0;
2221
2222 if (drb_reg_id == LPFC_DRB_ACC_ALL)
2223 for (i = 1; i <= LPFC_DRB_MAX; i++)
2224 len = lpfc_idiag_drbacc_read_reg(phba,
2225 pbuffer, len, i);
2226 else
2227 len = lpfc_idiag_drbacc_read_reg(phba,
2228 pbuffer, len, drb_reg_id);
2229
2230 return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
2231}
2232
2233/**
2234 * lpfc_idiag_drbacc_write - Syntax check and set up idiag drbacc commands
2235 * @file: The file pointer to read from.
2236 * @buf: The buffer to copy the user data from.
2237 * @nbytes: The number of bytes to get.
2238 * @ppos: The position in the file to start reading from.
2239 *
2240 * This routine get the debugfs idiag command struct from user space and then
2241 * perform the syntax check for port doorbell register read (dump) or write
2242 * (set) command accordingly. In the case of port queue read command, it sets
2243 * up the command in the idiag command struct for the following debugfs read
2244 * operation. In the case of port doorbell register write operation, it
2245 * executes the write operation into the port doorbell register accordingly.
2246 *
2247 * It returns the @nbytges passing in from debugfs user space when successful.
2248 * In case of error conditions, it returns proper error code back to the user
2249 * space.
2250 **/
2251static ssize_t
2252lpfc_idiag_drbacc_write(struct file *file, const char __user *buf,
2253 size_t nbytes, loff_t *ppos)
2254{
2255 struct lpfc_debug *debug = file->private_data;
2256 struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
2257 uint32_t drb_reg_id, value, reg_val;
2258 void __iomem *drb_reg;
2259 int rc;
2260
2261 /* This is a user write operation */
2262 debug->op = LPFC_IDIAG_OP_WR;
2263
2264 rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
2265 if (rc < 0)
2266 return rc;
2267
2268 /* Sanity check on command line arguments */
2269 drb_reg_id = idiag.cmd.data[0];
2270 value = idiag.cmd.data[1];
2271
2272 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR ||
2273 idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST ||
2274 idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) {
2275 if (rc != LPFC_DRB_ACC_WR_CMD_ARG)
2276 goto error_out;
2277 if (drb_reg_id > LPFC_DRB_MAX)
2278 goto error_out;
2279 } else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_RD) {
2280 if (rc != LPFC_DRB_ACC_RD_CMD_ARG)
2281 goto error_out;
2282 if ((drb_reg_id > LPFC_DRB_MAX) &&
2283 (drb_reg_id != LPFC_DRB_ACC_ALL))
2284 goto error_out;
2285 } else
2286 goto error_out;
2287
2288 /* Perform the write access operation */
2289 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR ||
2290 idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST ||
2291 idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) {
2292 switch (drb_reg_id) {
2293 case LPFC_DRB_EQCQ:
2294 drb_reg = phba->sli4_hba.EQCQDBregaddr;
2295 break;
2296 case LPFC_DRB_MQ:
2297 drb_reg = phba->sli4_hba.MQDBregaddr;
2298 break;
2299 case LPFC_DRB_WQ:
2300 drb_reg = phba->sli4_hba.WQDBregaddr;
2301 break;
2302 case LPFC_DRB_RQ:
2303 drb_reg = phba->sli4_hba.RQDBregaddr;
2304 break;
2305 default:
2306 goto error_out;
2307 }
2308
2309 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_WR)
2310 reg_val = value;
2311 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST) {
2312 reg_val = readl(drb_reg);
2313 reg_val |= value;
2314 }
2315 if (idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) {
2316 reg_val = readl(drb_reg);
2317 reg_val &= ~value;
2318 }
2319 writel(reg_val, drb_reg);
2320 readl(drb_reg); /* flush */
2321 }
2322 return nbytes;
2323
2324error_out:
2325 /* Clean out command structure on command error out */
2326 memset(&idiag, 0, sizeof(idiag));
2327 return -EINVAL;
2328}
2329
1891#undef lpfc_debugfs_op_disc_trc 2330#undef lpfc_debugfs_op_disc_trc
1892static const struct file_operations lpfc_debugfs_op_disc_trc = { 2331static const struct file_operations lpfc_debugfs_op_disc_trc = {
1893 .owner = THIS_MODULE, 2332 .owner = THIS_MODULE,
@@ -1986,6 +2425,26 @@ static const struct file_operations lpfc_idiag_op_queInfo = {
1986 .release = lpfc_idiag_release, 2425 .release = lpfc_idiag_release,
1987}; 2426};
1988 2427
2428#undef lpfc_idiag_op_queacc
2429static const struct file_operations lpfc_idiag_op_queAcc = {
2430 .owner = THIS_MODULE,
2431 .open = lpfc_idiag_open,
2432 .llseek = lpfc_debugfs_lseek,
2433 .read = lpfc_idiag_queacc_read,
2434 .write = lpfc_idiag_queacc_write,
2435 .release = lpfc_idiag_cmd_release,
2436};
2437
2438#undef lpfc_idiag_op_drbacc
2439static const struct file_operations lpfc_idiag_op_drbAcc = {
2440 .owner = THIS_MODULE,
2441 .open = lpfc_idiag_open,
2442 .llseek = lpfc_debugfs_lseek,
2443 .read = lpfc_idiag_drbacc_read,
2444 .write = lpfc_idiag_drbacc_write,
2445 .release = lpfc_idiag_cmd_release,
2446};
2447
1989#endif 2448#endif
1990 2449
1991/** 2450/**
@@ -2261,6 +2720,32 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
2261 } 2720 }
2262 } 2721 }
2263 2722
2723 /* iDiag access PCI function queue */
2724 snprintf(name, sizeof(name), "queAcc");
2725 if (!phba->idiag_que_acc) {
2726 phba->idiag_que_acc =
2727 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
2728 phba->idiag_root, phba, &lpfc_idiag_op_queAcc);
2729 if (!phba->idiag_que_acc) {
2730 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
2731 "2926 Can't create idiag debugfs\n");
2732 goto debug_failed;
2733 }
2734 }
2735
2736 /* iDiag access PCI function doorbell registers */
2737 snprintf(name, sizeof(name), "drbAcc");
2738 if (!phba->idiag_drb_acc) {
2739 phba->idiag_drb_acc =
2740 debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
2741 phba->idiag_root, phba, &lpfc_idiag_op_drbAcc);
2742 if (!phba->idiag_drb_acc) {
2743 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
2744 "2927 Can't create idiag debugfs\n");
2745 goto debug_failed;
2746 }
2747 }
2748
2264debug_failed: 2749debug_failed:
2265 return; 2750 return;
2266#endif 2751#endif
@@ -2339,6 +2824,16 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
2339 * iDiag release 2824 * iDiag release
2340 */ 2825 */
2341 if (phba->sli_rev == LPFC_SLI_REV4) { 2826 if (phba->sli_rev == LPFC_SLI_REV4) {
2827 if (phba->idiag_drb_acc) {
2828 /* iDiag drbAcc */
2829 debugfs_remove(phba->idiag_drb_acc);
2830 phba->idiag_drb_acc = NULL;
2831 }
2832 if (phba->idiag_que_acc) {
2833 /* iDiag queAcc */
2834 debugfs_remove(phba->idiag_que_acc);
2835 phba->idiag_que_acc = NULL;
2836 }
2342 if (phba->idiag_que_info) { 2837 if (phba->idiag_que_info) {
2343 /* iDiag queInfo */ 2838 /* iDiag queInfo */
2344 debugfs_remove(phba->idiag_que_info); 2839 debugfs_remove(phba->idiag_que_info);
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h
index 91b9a9427cda..6525a5e62d27 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.h
+++ b/drivers/scsi/lpfc/lpfc_debugfs.h
@@ -39,13 +39,42 @@
39/* hbqinfo output buffer size */ 39/* hbqinfo output buffer size */
40#define LPFC_HBQINFO_SIZE 8192 40#define LPFC_HBQINFO_SIZE 8192
41 41
42/* rdPciConf output buffer size */ 42/* pciConf */
43#define LPFC_PCI_CFG_BROWSE 0xffff
44#define LPFC_PCI_CFG_RD_CMD_ARG 2
45#define LPFC_PCI_CFG_WR_CMD_ARG 3
43#define LPFC_PCI_CFG_SIZE 4096 46#define LPFC_PCI_CFG_SIZE 4096
44#define LPFC_PCI_CFG_RD_BUF_SIZE (LPFC_PCI_CFG_SIZE/2) 47#define LPFC_PCI_CFG_RD_BUF_SIZE (LPFC_PCI_CFG_SIZE/2)
45#define LPFC_PCI_CFG_RD_SIZE (LPFC_PCI_CFG_SIZE/4) 48#define LPFC_PCI_CFG_RD_SIZE (LPFC_PCI_CFG_SIZE/4)
46 49
47/* queue info output buffer size */ 50/* queue info */
48#define LPFC_QUE_INFO_GET_BUF_SIZE 2048 51#define LPFC_QUE_INFO_GET_BUF_SIZE 4096
52
53/* queue acc */
54#define LPFC_QUE_ACC_BROWSE 0xffff
55#define LPFC_QUE_ACC_RD_CMD_ARG 4
56#define LPFC_QUE_ACC_WR_CMD_ARG 6
57#define LPFC_QUE_ACC_BUF_SIZE 4096
58#define LPFC_QUE_ACC_SIZE (LPFC_QUE_ACC_BUF_SIZE/2)
59
60#define LPFC_IDIAG_EQ 1
61#define LPFC_IDIAG_CQ 2
62#define LPFC_IDIAG_MQ 3
63#define LPFC_IDIAG_WQ 4
64#define LPFC_IDIAG_RQ 5
65
66/* doorbell acc */
67#define LPFC_DRB_ACC_ALL 0xffff
68#define LPFC_DRB_ACC_RD_CMD_ARG 1
69#define LPFC_DRB_ACC_WR_CMD_ARG 2
70#define LPFC_DRB_ACC_BUF_SIZE 256
71
72#define LPFC_DRB_EQCQ 1
73#define LPFC_DRB_MQ 2
74#define LPFC_DRB_WQ 3
75#define LPFC_DRB_RQ 4
76
77#define LPFC_DRB_MAX 4
49 78
50#define SIZE_U8 sizeof(uint8_t) 79#define SIZE_U8 sizeof(uint8_t)
51#define SIZE_U16 sizeof(uint16_t) 80#define SIZE_U16 sizeof(uint16_t)
@@ -73,13 +102,23 @@ struct lpfc_idiag_offset {
73 uint32_t last_rd; 102 uint32_t last_rd;
74}; 103};
75 104
76#define LPFC_IDIAG_CMD_DATA_SIZE 4 105#define LPFC_IDIAG_CMD_DATA_SIZE 8
77struct lpfc_idiag_cmd { 106struct lpfc_idiag_cmd {
78 uint32_t opcode; 107 uint32_t opcode;
79#define LPFC_IDIAG_CMD_PCICFG_RD 0x00000001 108#define LPFC_IDIAG_CMD_PCICFG_RD 0x00000001
80#define LPFC_IDIAG_CMD_PCICFG_WR 0x00000002 109#define LPFC_IDIAG_CMD_PCICFG_WR 0x00000002
81#define LPFC_IDIAG_CMD_PCICFG_ST 0x00000003 110#define LPFC_IDIAG_CMD_PCICFG_ST 0x00000003
82#define LPFC_IDIAG_CMD_PCICFG_CL 0x00000004 111#define LPFC_IDIAG_CMD_PCICFG_CL 0x00000004
112
113#define LPFC_IDIAG_CMD_QUEACC_RD 0x00000011
114#define LPFC_IDIAG_CMD_QUEACC_WR 0x00000012
115#define LPFC_IDIAG_CMD_QUEACC_ST 0x00000013
116#define LPFC_IDIAG_CMD_QUEACC_CL 0x00000014
117
118#define LPFC_IDIAG_CMD_DRBACC_RD 0x00000021
119#define LPFC_IDIAG_CMD_DRBACC_WR 0x00000022
120#define LPFC_IDIAG_CMD_DRBACC_ST 0x00000023
121#define LPFC_IDIAG_CMD_DRBACC_CL 0x00000024
83 uint32_t data[LPFC_IDIAG_CMD_DATA_SIZE]; 122 uint32_t data[LPFC_IDIAG_CMD_DATA_SIZE];
84}; 123};
85 124
@@ -87,6 +126,7 @@ struct lpfc_idiag {
87 uint32_t active; 126 uint32_t active;
88 struct lpfc_idiag_cmd cmd; 127 struct lpfc_idiag_cmd cmd;
89 struct lpfc_idiag_offset offset; 128 struct lpfc_idiag_offset offset;
129 void *ptr_private;
90}; 130};
91#endif 131#endif
92 132