diff options
Diffstat (limited to 'drivers/net/ethernet/qlogic/netxen')
-rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic.h | 421 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c | 143 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c | 104 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c | 629 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 102 |
6 files changed, 1380 insertions, 22 deletions
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h index 1b09ba172310..8a35430b2f8b 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h | |||
@@ -1154,6 +1154,7 @@ typedef struct { | |||
1154 | #define NETXEN_NIC_LRO_DISABLED 0x00 | 1154 | #define NETXEN_NIC_LRO_DISABLED 0x00 |
1155 | #define NETXEN_NIC_BRIDGE_ENABLED 0X10 | 1155 | #define NETXEN_NIC_BRIDGE_ENABLED 0X10 |
1156 | #define NETXEN_NIC_DIAG_ENABLED 0x20 | 1156 | #define NETXEN_NIC_DIAG_ENABLED 0x20 |
1157 | #define NETXEN_FW_RESET_OWNER 0x40 | ||
1157 | #define NETXEN_IS_MSI_FAMILY(adapter) \ | 1158 | #define NETXEN_IS_MSI_FAMILY(adapter) \ |
1158 | ((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED)) | 1159 | ((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED)) |
1159 | 1160 | ||
@@ -1171,6 +1172,419 @@ typedef struct { | |||
1171 | #define __NX_DEV_UP 1 | 1172 | #define __NX_DEV_UP 1 |
1172 | #define __NX_RESETTING 2 | 1173 | #define __NX_RESETTING 2 |
1173 | 1174 | ||
1175 | /* Mini Coredump FW supported version */ | ||
1176 | #define NX_MD_SUPPORT_MAJOR 4 | ||
1177 | #define NX_MD_SUPPORT_MINOR 0 | ||
1178 | #define NX_MD_SUPPORT_SUBVERSION 579 | ||
1179 | |||
1180 | #define LSW(x) ((uint16_t)(x)) | ||
1181 | #define LSD(x) ((uint32_t)((uint64_t)(x))) | ||
1182 | #define MSD(x) ((uint32_t)((((uint64_t)(x)) >> 16) >> 16)) | ||
1183 | |||
1184 | /* Mini Coredump mask level */ | ||
1185 | #define NX_DUMP_MASK_MIN 0x03 | ||
1186 | #define NX_DUMP_MASK_DEF 0x1f | ||
1187 | #define NX_DUMP_MASK_MAX 0xff | ||
1188 | |||
1189 | /* Mini Coredump CDRP commands */ | ||
1190 | #define NX_CDRP_CMD_TEMP_SIZE 0x0000002f | ||
1191 | #define NX_CDRP_CMD_GET_TEMP_HDR 0x00000030 | ||
1192 | |||
1193 | |||
1194 | #define NX_DUMP_STATE_ARRAY_LEN 16 | ||
1195 | #define NX_DUMP_CAP_SIZE_ARRAY_LEN 8 | ||
1196 | |||
1197 | /* Mini Coredump sysfs entries flags*/ | ||
1198 | #define NX_FORCE_FW_DUMP_KEY 0xdeadfeed | ||
1199 | #define NX_ENABLE_FW_DUMP 0xaddfeed | ||
1200 | #define NX_DISABLE_FW_DUMP 0xbadfeed | ||
1201 | #define NX_FORCE_FW_RESET 0xdeaddead | ||
1202 | |||
1203 | |||
1204 | /* Flash read/write address */ | ||
1205 | #define NX_FW_DUMP_REG1 0x00130060 | ||
1206 | #define NX_FW_DUMP_REG2 0x001e0000 | ||
1207 | #define NX_FLASH_SEM2_LK 0x0013C010 | ||
1208 | #define NX_FLASH_SEM2_ULK 0x0013C014 | ||
1209 | #define NX_FLASH_LOCK_ID 0x001B2100 | ||
1210 | #define FLASH_ROM_WINDOW 0x42110030 | ||
1211 | #define FLASH_ROM_DATA 0x42150000 | ||
1212 | |||
1213 | /* Mini Coredump register read/write routine */ | ||
1214 | #define NX_RD_DUMP_REG(addr, bar0, data) do { \ | ||
1215 | writel((addr & 0xFFFF0000), (void __iomem *) (bar0 + \ | ||
1216 | NX_FW_DUMP_REG1)); \ | ||
1217 | readl((void __iomem *) (bar0 + NX_FW_DUMP_REG1)); \ | ||
1218 | *data = readl((void __iomem *) (bar0 + NX_FW_DUMP_REG2 + \ | ||
1219 | LSW(addr))); \ | ||
1220 | } while (0) | ||
1221 | |||
1222 | #define NX_WR_DUMP_REG(addr, bar0, data) do { \ | ||
1223 | writel((addr & 0xFFFF0000), (void __iomem *) (bar0 + \ | ||
1224 | NX_FW_DUMP_REG1)); \ | ||
1225 | readl((void __iomem *) (bar0 + NX_FW_DUMP_REG1)); \ | ||
1226 | writel(data, (void __iomem *) (bar0 + NX_FW_DUMP_REG2 + LSW(addr)));\ | ||
1227 | readl((void __iomem *) (bar0 + NX_FW_DUMP_REG2 + LSW(addr))); \ | ||
1228 | } while (0) | ||
1229 | |||
1230 | |||
1231 | /* | ||
1232 | Entry Type Defines | ||
1233 | */ | ||
1234 | |||
1235 | #define RDNOP 0 | ||
1236 | #define RDCRB 1 | ||
1237 | #define RDMUX 2 | ||
1238 | #define QUEUE 3 | ||
1239 | #define BOARD 4 | ||
1240 | #define RDSRE 5 | ||
1241 | #define RDOCM 6 | ||
1242 | #define PREGS 7 | ||
1243 | #define L1DTG 8 | ||
1244 | #define L1ITG 9 | ||
1245 | #define CACHE 10 | ||
1246 | |||
1247 | #define L1DAT 11 | ||
1248 | #define L1INS 12 | ||
1249 | #define RDSTK 13 | ||
1250 | #define RDCON 14 | ||
1251 | |||
1252 | #define L2DTG 21 | ||
1253 | #define L2ITG 22 | ||
1254 | #define L2DAT 23 | ||
1255 | #define L2INS 24 | ||
1256 | #define RDOC3 25 | ||
1257 | |||
1258 | #define MEMBK 32 | ||
1259 | |||
1260 | #define RDROM 71 | ||
1261 | #define RDMEM 72 | ||
1262 | #define RDMN 73 | ||
1263 | |||
1264 | #define INFOR 81 | ||
1265 | #define CNTRL 98 | ||
1266 | |||
1267 | #define TLHDR 99 | ||
1268 | #define RDEND 255 | ||
1269 | |||
1270 | #define PRIMQ 103 | ||
1271 | #define SQG2Q 104 | ||
1272 | #define SQG3Q 105 | ||
1273 | |||
1274 | /* | ||
1275 | * Opcodes for Control Entries. | ||
1276 | * These Flags are bit fields. | ||
1277 | */ | ||
1278 | #define NX_DUMP_WCRB 0x01 | ||
1279 | #define NX_DUMP_RWCRB 0x02 | ||
1280 | #define NX_DUMP_ANDCRB 0x04 | ||
1281 | #define NX_DUMP_ORCRB 0x08 | ||
1282 | #define NX_DUMP_POLLCRB 0x10 | ||
1283 | #define NX_DUMP_RD_SAVE 0x20 | ||
1284 | #define NX_DUMP_WRT_SAVED 0x40 | ||
1285 | #define NX_DUMP_MOD_SAVE_ST 0x80 | ||
1286 | |||
1287 | /* Driver Flags */ | ||
1288 | #define NX_DUMP_SKIP 0x80 /* driver skipped this entry */ | ||
1289 | #define NX_DUMP_SIZE_ERR 0x40 /*entry size vs capture size mismatch*/ | ||
1290 | |||
1291 | #define NX_PCI_READ_32(ADDR) readl((ADDR)) | ||
1292 | #define NX_PCI_WRITE_32(DATA, ADDR) writel(DATA, (ADDR)) | ||
1293 | |||
1294 | |||
1295 | |||
1296 | struct netxen_minidump { | ||
1297 | u32 pos; /* position in the dump buffer */ | ||
1298 | u8 fw_supports_md; /* FW supports Mini cordump */ | ||
1299 | u8 has_valid_dump; /* indicates valid dump */ | ||
1300 | u8 md_capture_mask; /* driver capture mask */ | ||
1301 | u8 md_enabled; /* Turn Mini Coredump on/off */ | ||
1302 | u32 md_dump_size; /* Total FW Mini Coredump size */ | ||
1303 | u32 md_capture_size; /* FW dump capture size */ | ||
1304 | u32 md_template_size; /* FW template size */ | ||
1305 | u32 md_template_ver; /* FW template version */ | ||
1306 | u64 md_timestamp; /* FW Mini dump timestamp */ | ||
1307 | void *md_template; /* FW template will be stored */ | ||
1308 | void *md_capture_buff; /* FW dump will be stored */ | ||
1309 | }; | ||
1310 | |||
1311 | |||
1312 | |||
1313 | struct netxen_minidump_template_hdr { | ||
1314 | u32 entry_type; | ||
1315 | u32 first_entry_offset; | ||
1316 | u32 size_of_template; | ||
1317 | u32 capture_mask; | ||
1318 | u32 num_of_entries; | ||
1319 | u32 version; | ||
1320 | u32 driver_timestamp; | ||
1321 | u32 checksum; | ||
1322 | u32 driver_capture_mask; | ||
1323 | u32 driver_info_word2; | ||
1324 | u32 driver_info_word3; | ||
1325 | u32 driver_info_word4; | ||
1326 | u32 saved_state_array[NX_DUMP_STATE_ARRAY_LEN]; | ||
1327 | u32 capture_size_array[NX_DUMP_CAP_SIZE_ARRAY_LEN]; | ||
1328 | u32 rsvd[0]; | ||
1329 | }; | ||
1330 | |||
1331 | /* Common Entry Header: Common to All Entry Types */ | ||
1332 | /* | ||
1333 | * Driver Code is for driver to write some info about the entry. | ||
1334 | * Currently not used. | ||
1335 | */ | ||
1336 | |||
1337 | struct netxen_common_entry_hdr { | ||
1338 | u32 entry_type; | ||
1339 | u32 entry_size; | ||
1340 | u32 entry_capture_size; | ||
1341 | union { | ||
1342 | struct { | ||
1343 | u8 entry_capture_mask; | ||
1344 | u8 entry_code; | ||
1345 | u8 driver_code; | ||
1346 | u8 driver_flags; | ||
1347 | }; | ||
1348 | u32 entry_ctrl_word; | ||
1349 | }; | ||
1350 | }; | ||
1351 | |||
1352 | |||
1353 | /* Generic Entry Including Header */ | ||
1354 | struct netxen_minidump_entry { | ||
1355 | struct netxen_common_entry_hdr hdr; | ||
1356 | u32 entry_data00; | ||
1357 | u32 entry_data01; | ||
1358 | u32 entry_data02; | ||
1359 | u32 entry_data03; | ||
1360 | u32 entry_data04; | ||
1361 | u32 entry_data05; | ||
1362 | u32 entry_data06; | ||
1363 | u32 entry_data07; | ||
1364 | }; | ||
1365 | |||
1366 | /* Read ROM Header */ | ||
1367 | struct netxen_minidump_entry_rdrom { | ||
1368 | struct netxen_common_entry_hdr h; | ||
1369 | union { | ||
1370 | struct { | ||
1371 | u32 select_addr_reg; | ||
1372 | }; | ||
1373 | u32 rsvd_0; | ||
1374 | }; | ||
1375 | union { | ||
1376 | struct { | ||
1377 | u8 addr_stride; | ||
1378 | u8 addr_cnt; | ||
1379 | u16 data_size; | ||
1380 | }; | ||
1381 | u32 rsvd_1; | ||
1382 | }; | ||
1383 | union { | ||
1384 | struct { | ||
1385 | u32 op_count; | ||
1386 | }; | ||
1387 | u32 rsvd_2; | ||
1388 | }; | ||
1389 | union { | ||
1390 | struct { | ||
1391 | u32 read_addr_reg; | ||
1392 | }; | ||
1393 | u32 rsvd_3; | ||
1394 | }; | ||
1395 | union { | ||
1396 | struct { | ||
1397 | u32 write_mask; | ||
1398 | }; | ||
1399 | u32 rsvd_4; | ||
1400 | }; | ||
1401 | union { | ||
1402 | struct { | ||
1403 | u32 read_mask; | ||
1404 | }; | ||
1405 | u32 rsvd_5; | ||
1406 | }; | ||
1407 | u32 read_addr; | ||
1408 | u32 read_data_size; | ||
1409 | }; | ||
1410 | |||
1411 | |||
1412 | /* Read CRB and Control Entry Header */ | ||
1413 | struct netxen_minidump_entry_crb { | ||
1414 | struct netxen_common_entry_hdr h; | ||
1415 | u32 addr; | ||
1416 | union { | ||
1417 | struct { | ||
1418 | u8 addr_stride; | ||
1419 | u8 state_index_a; | ||
1420 | u16 poll_timeout; | ||
1421 | }; | ||
1422 | u32 addr_cntrl; | ||
1423 | }; | ||
1424 | u32 data_size; | ||
1425 | u32 op_count; | ||
1426 | union { | ||
1427 | struct { | ||
1428 | u8 opcode; | ||
1429 | u8 state_index_v; | ||
1430 | u8 shl; | ||
1431 | u8 shr; | ||
1432 | }; | ||
1433 | u32 control_value; | ||
1434 | }; | ||
1435 | u32 value_1; | ||
1436 | u32 value_2; | ||
1437 | u32 value_3; | ||
1438 | }; | ||
1439 | |||
1440 | /* Read Memory and MN Header */ | ||
1441 | struct netxen_minidump_entry_rdmem { | ||
1442 | struct netxen_common_entry_hdr h; | ||
1443 | union { | ||
1444 | struct { | ||
1445 | u32 select_addr_reg; | ||
1446 | }; | ||
1447 | u32 rsvd_0; | ||
1448 | }; | ||
1449 | union { | ||
1450 | struct { | ||
1451 | u8 addr_stride; | ||
1452 | u8 addr_cnt; | ||
1453 | u16 data_size; | ||
1454 | }; | ||
1455 | u32 rsvd_1; | ||
1456 | }; | ||
1457 | union { | ||
1458 | struct { | ||
1459 | u32 op_count; | ||
1460 | }; | ||
1461 | u32 rsvd_2; | ||
1462 | }; | ||
1463 | union { | ||
1464 | struct { | ||
1465 | u32 read_addr_reg; | ||
1466 | }; | ||
1467 | u32 rsvd_3; | ||
1468 | }; | ||
1469 | union { | ||
1470 | struct { | ||
1471 | u32 cntrl_addr_reg; | ||
1472 | }; | ||
1473 | u32 rsvd_4; | ||
1474 | }; | ||
1475 | union { | ||
1476 | struct { | ||
1477 | u8 wr_byte0; | ||
1478 | u8 wr_byte1; | ||
1479 | u8 poll_mask; | ||
1480 | u8 poll_cnt; | ||
1481 | }; | ||
1482 | u32 rsvd_5; | ||
1483 | }; | ||
1484 | u32 read_addr; | ||
1485 | u32 read_data_size; | ||
1486 | }; | ||
1487 | |||
1488 | /* Read Cache L1 and L2 Header */ | ||
1489 | struct netxen_minidump_entry_cache { | ||
1490 | struct netxen_common_entry_hdr h; | ||
1491 | u32 tag_reg_addr; | ||
1492 | union { | ||
1493 | struct { | ||
1494 | u16 tag_value_stride; | ||
1495 | u16 init_tag_value; | ||
1496 | }; | ||
1497 | u32 select_addr_cntrl; | ||
1498 | }; | ||
1499 | u32 data_size; | ||
1500 | u32 op_count; | ||
1501 | u32 control_addr; | ||
1502 | union { | ||
1503 | struct { | ||
1504 | u16 write_value; | ||
1505 | u8 poll_mask; | ||
1506 | u8 poll_wait; | ||
1507 | }; | ||
1508 | u32 control_value; | ||
1509 | }; | ||
1510 | u32 read_addr; | ||
1511 | union { | ||
1512 | struct { | ||
1513 | u8 read_addr_stride; | ||
1514 | u8 read_addr_cnt; | ||
1515 | u16 rsvd_1; | ||
1516 | }; | ||
1517 | u32 read_addr_cntrl; | ||
1518 | }; | ||
1519 | }; | ||
1520 | |||
1521 | /* Read OCM Header */ | ||
1522 | struct netxen_minidump_entry_rdocm { | ||
1523 | struct netxen_common_entry_hdr h; | ||
1524 | u32 rsvd_0; | ||
1525 | union { | ||
1526 | struct { | ||
1527 | u32 rsvd_1; | ||
1528 | }; | ||
1529 | u32 select_addr_cntrl; | ||
1530 | }; | ||
1531 | u32 data_size; | ||
1532 | u32 op_count; | ||
1533 | u32 rsvd_2; | ||
1534 | u32 rsvd_3; | ||
1535 | u32 read_addr; | ||
1536 | union { | ||
1537 | struct { | ||
1538 | u32 read_addr_stride; | ||
1539 | }; | ||
1540 | u32 read_addr_cntrl; | ||
1541 | }; | ||
1542 | }; | ||
1543 | |||
1544 | /* Read MUX Header */ | ||
1545 | struct netxen_minidump_entry_mux { | ||
1546 | struct netxen_common_entry_hdr h; | ||
1547 | u32 select_addr; | ||
1548 | union { | ||
1549 | struct { | ||
1550 | u32 rsvd_0; | ||
1551 | }; | ||
1552 | u32 select_addr_cntrl; | ||
1553 | }; | ||
1554 | u32 data_size; | ||
1555 | u32 op_count; | ||
1556 | u32 select_value; | ||
1557 | u32 select_value_stride; | ||
1558 | u32 read_addr; | ||
1559 | u32 rsvd_1; | ||
1560 | }; | ||
1561 | |||
1562 | /* Read Queue Header */ | ||
1563 | struct netxen_minidump_entry_queue { | ||
1564 | struct netxen_common_entry_hdr h; | ||
1565 | u32 select_addr; | ||
1566 | union { | ||
1567 | struct { | ||
1568 | u16 queue_id_stride; | ||
1569 | u16 rsvd_0; | ||
1570 | }; | ||
1571 | u32 select_addr_cntrl; | ||
1572 | }; | ||
1573 | u32 data_size; | ||
1574 | u32 op_count; | ||
1575 | u32 rsvd_1; | ||
1576 | u32 rsvd_2; | ||
1577 | u32 read_addr; | ||
1578 | union { | ||
1579 | struct { | ||
1580 | u8 read_addr_stride; | ||
1581 | u8 read_addr_cnt; | ||
1582 | u16 rsvd_3; | ||
1583 | }; | ||
1584 | u32 read_addr_cntrl; | ||
1585 | }; | ||
1586 | }; | ||
1587 | |||
1174 | struct netxen_dummy_dma { | 1588 | struct netxen_dummy_dma { |
1175 | void *addr; | 1589 | void *addr; |
1176 | dma_addr_t phys_addr; | 1590 | dma_addr_t phys_addr; |
@@ -1275,6 +1689,8 @@ struct netxen_adapter { | |||
1275 | __le32 file_prd_off; /*File fw product offset*/ | 1689 | __le32 file_prd_off; /*File fw product offset*/ |
1276 | u32 fw_version; | 1690 | u32 fw_version; |
1277 | const struct firmware *fw; | 1691 | const struct firmware *fw; |
1692 | struct netxen_minidump mdump; /* mdump ptr */ | ||
1693 | int fw_mdump_rdy; /* for mdump ready */ | ||
1278 | }; | 1694 | }; |
1279 | 1695 | ||
1280 | int nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val); | 1696 | int nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val); |
@@ -1377,13 +1793,16 @@ int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); | |||
1377 | int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable); | 1793 | int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable); |
1378 | int netxen_config_bridged_mode(struct netxen_adapter *adapter, int enable); | 1794 | int netxen_config_bridged_mode(struct netxen_adapter *adapter, int enable); |
1379 | int netxen_send_lro_cleanup(struct netxen_adapter *adapter); | 1795 | int netxen_send_lro_cleanup(struct netxen_adapter *adapter); |
1380 | 1796 | int netxen_setup_minidump(struct netxen_adapter *adapter); | |
1797 | void netxen_dump_fw(struct netxen_adapter *adapter); | ||
1381 | void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, | 1798 | void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, |
1382 | struct nx_host_tx_ring *tx_ring); | 1799 | struct nx_host_tx_ring *tx_ring); |
1383 | 1800 | ||
1384 | /* Functions from netxen_nic_main.c */ | 1801 | /* Functions from netxen_nic_main.c */ |
1385 | int netxen_nic_reset_context(struct netxen_adapter *); | 1802 | int netxen_nic_reset_context(struct netxen_adapter *); |
1386 | 1803 | ||
1804 | int nx_dev_request_reset(struct netxen_adapter *adapter); | ||
1805 | |||
1387 | /* | 1806 | /* |
1388 | * NetXen Board information | 1807 | * NetXen Board information |
1389 | */ | 1808 | */ |
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c index d46e8cb394eb..8f89c05e0c70 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c | |||
@@ -83,6 +83,7 @@ netxen_issue_cmd(struct netxen_adapter *adapter, struct netxen_cmd_args *cmd) | |||
83 | printk(KERN_ERR "%s: failed card response code:0x%x\n", | 83 | printk(KERN_ERR "%s: failed card response code:0x%x\n", |
84 | netxen_nic_driver_name, rcode); | 84 | netxen_nic_driver_name, rcode); |
85 | } else if (rsp == NX_CDRP_RSP_OK) { | 85 | } else if (rsp == NX_CDRP_RSP_OK) { |
86 | cmd->rsp.cmd = NX_RCODE_SUCCESS; | ||
86 | if (cmd->rsp.arg2) | 87 | if (cmd->rsp.arg2) |
87 | cmd->rsp.arg2 = NXRD32(adapter, NX_ARG2_CRB_OFFSET); | 88 | cmd->rsp.arg2 = NXRD32(adapter, NX_ARG2_CRB_OFFSET); |
88 | if (cmd->rsp.arg3) | 89 | if (cmd->rsp.arg3) |
@@ -97,6 +98,148 @@ netxen_issue_cmd(struct netxen_adapter *adapter, struct netxen_cmd_args *cmd) | |||
97 | return rcode; | 98 | return rcode; |
98 | } | 99 | } |
99 | 100 | ||
101 | static int | ||
102 | netxen_get_minidump_template_size(struct netxen_adapter *adapter) | ||
103 | { | ||
104 | struct netxen_cmd_args cmd; | ||
105 | memset(&cmd, 0, sizeof(cmd)); | ||
106 | cmd.req.cmd = NX_CDRP_CMD_TEMP_SIZE; | ||
107 | memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd)); | ||
108 | netxen_issue_cmd(adapter, &cmd); | ||
109 | if (cmd.rsp.cmd != NX_RCODE_SUCCESS) { | ||
110 | dev_info(&adapter->pdev->dev, | ||
111 | "Can't get template size %d\n", cmd.rsp.cmd); | ||
112 | return -EIO; | ||
113 | } | ||
114 | adapter->mdump.md_template_size = cmd.rsp.arg2; | ||
115 | adapter->mdump.md_template_ver = cmd.rsp.arg3; | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static int | ||
120 | netxen_get_minidump_template(struct netxen_adapter *adapter) | ||
121 | { | ||
122 | dma_addr_t md_template_addr; | ||
123 | void *addr; | ||
124 | u32 size; | ||
125 | struct netxen_cmd_args cmd; | ||
126 | size = adapter->mdump.md_template_size; | ||
127 | |||
128 | if (size == 0) { | ||
129 | dev_err(&adapter->pdev->dev, "Can not capture Minidump " | ||
130 | "template. Invalid template size.\n"); | ||
131 | return NX_RCODE_INVALID_ARGS; | ||
132 | } | ||
133 | |||
134 | addr = pci_alloc_consistent(adapter->pdev, size, &md_template_addr); | ||
135 | |||
136 | if (!addr) { | ||
137 | dev_err(&adapter->pdev->dev, "Unable to allocate dmable memory for template.\n"); | ||
138 | return -ENOMEM; | ||
139 | } | ||
140 | |||
141 | memset(addr, 0, size); | ||
142 | memset(&cmd, 0, sizeof(cmd)); | ||
143 | memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd)); | ||
144 | cmd.req.cmd = NX_CDRP_CMD_GET_TEMP_HDR; | ||
145 | cmd.req.arg1 = LSD(md_template_addr); | ||
146 | cmd.req.arg2 = MSD(md_template_addr); | ||
147 | cmd.req.arg3 |= size; | ||
148 | netxen_issue_cmd(adapter, &cmd); | ||
149 | |||
150 | if ((cmd.rsp.cmd == NX_RCODE_SUCCESS) && (size == cmd.rsp.arg2)) { | ||
151 | memcpy(adapter->mdump.md_template, addr, size); | ||
152 | } else { | ||
153 | dev_err(&adapter->pdev->dev, "Failed to get minidump template, " | ||
154 | "err_code : %d, requested_size : %d, actual_size : %d\n ", | ||
155 | cmd.rsp.cmd, size, cmd.rsp.arg2); | ||
156 | } | ||
157 | pci_free_consistent(adapter->pdev, size, addr, md_template_addr); | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static u32 | ||
162 | netxen_check_template_checksum(struct netxen_adapter *adapter) | ||
163 | { | ||
164 | u64 sum = 0 ; | ||
165 | u32 *buff = adapter->mdump.md_template; | ||
166 | int count = adapter->mdump.md_template_size/sizeof(uint32_t) ; | ||
167 | |||
168 | while (count-- > 0) | ||
169 | sum += *buff++ ; | ||
170 | while (sum >> 32) | ||
171 | sum = (sum & 0xFFFFFFFF) + (sum >> 32) ; | ||
172 | |||
173 | return ~sum; | ||
174 | } | ||
175 | |||
176 | int | ||
177 | netxen_setup_minidump(struct netxen_adapter *adapter) | ||
178 | { | ||
179 | int err = 0, i; | ||
180 | u32 *template, *tmp_buf; | ||
181 | struct netxen_minidump_template_hdr *hdr; | ||
182 | err = netxen_get_minidump_template_size(adapter); | ||
183 | if (err) { | ||
184 | adapter->mdump.fw_supports_md = 0; | ||
185 | if ((err == NX_RCODE_CMD_INVALID) || | ||
186 | (err == NX_RCODE_CMD_NOT_IMPL)) { | ||
187 | dev_info(&adapter->pdev->dev, | ||
188 | "Flashed firmware version does not support minidump, " | ||
189 | "minimum version required is [ %u.%u.%u ].\n ", | ||
190 | NX_MD_SUPPORT_MAJOR, NX_MD_SUPPORT_MINOR, | ||
191 | NX_MD_SUPPORT_SUBVERSION); | ||
192 | } | ||
193 | return err; | ||
194 | } | ||
195 | |||
196 | if (!adapter->mdump.md_template_size) { | ||
197 | dev_err(&adapter->pdev->dev, "Error : Invalid template size " | ||
198 | ",should be non-zero.\n"); | ||
199 | return -EIO; | ||
200 | } | ||
201 | adapter->mdump.md_template = | ||
202 | kmalloc(adapter->mdump.md_template_size, GFP_KERNEL); | ||
203 | |||
204 | if (!adapter->mdump.md_template) { | ||
205 | dev_err(&adapter->pdev->dev, "Unable to allocate memory " | ||
206 | "for minidump template.\n"); | ||
207 | return -ENOMEM; | ||
208 | } | ||
209 | |||
210 | err = netxen_get_minidump_template(adapter); | ||
211 | if (err) { | ||
212 | if (err == NX_RCODE_CMD_NOT_IMPL) | ||
213 | adapter->mdump.fw_supports_md = 0; | ||
214 | goto free_template; | ||
215 | } | ||
216 | |||
217 | if (netxen_check_template_checksum(adapter)) { | ||
218 | dev_err(&adapter->pdev->dev, "Minidump template checksum Error\n"); | ||
219 | err = -EIO; | ||
220 | goto free_template; | ||
221 | } | ||
222 | |||
223 | adapter->mdump.md_capture_mask = NX_DUMP_MASK_DEF; | ||
224 | tmp_buf = (u32 *) adapter->mdump.md_template; | ||
225 | template = (u32 *) adapter->mdump.md_template; | ||
226 | for (i = 0; i < adapter->mdump.md_template_size/sizeof(u32); i++) | ||
227 | *template++ = __le32_to_cpu(*tmp_buf++); | ||
228 | hdr = (struct netxen_minidump_template_hdr *) | ||
229 | adapter->mdump.md_template; | ||
230 | adapter->mdump.md_capture_buff = NULL; | ||
231 | adapter->mdump.fw_supports_md = 1; | ||
232 | adapter->mdump.md_enabled = 1; | ||
233 | |||
234 | return err; | ||
235 | |||
236 | free_template: | ||
237 | kfree(adapter->mdump.md_template); | ||
238 | adapter->mdump.md_template = NULL; | ||
239 | return err; | ||
240 | } | ||
241 | |||
242 | |||
100 | int | 243 | int |
101 | nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu) | 244 | nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu) |
102 | { | 245 | { |
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c index 8a371985319f..3e73d35cceaa 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c | |||
@@ -812,6 +812,107 @@ static int netxen_get_intr_coalesce(struct net_device *netdev, | |||
812 | return 0; | 812 | return 0; |
813 | } | 813 | } |
814 | 814 | ||
815 | static int | ||
816 | netxen_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) | ||
817 | { | ||
818 | struct netxen_adapter *adapter = netdev_priv(netdev); | ||
819 | struct netxen_minidump *mdump = &adapter->mdump; | ||
820 | if (adapter->fw_mdump_rdy) | ||
821 | dump->len = mdump->md_dump_size; | ||
822 | else | ||
823 | dump->len = 0; | ||
824 | dump->flag = mdump->md_capture_mask; | ||
825 | dump->version = adapter->fw_version; | ||
826 | return 0; | ||
827 | } | ||
828 | |||
829 | static int | ||
830 | netxen_set_dump(struct net_device *netdev, struct ethtool_dump *val) | ||
831 | { | ||
832 | int ret = 0; | ||
833 | struct netxen_adapter *adapter = netdev_priv(netdev); | ||
834 | struct netxen_minidump *mdump = &adapter->mdump; | ||
835 | |||
836 | switch (val->flag) { | ||
837 | case NX_FORCE_FW_DUMP_KEY: | ||
838 | if (!mdump->md_enabled) | ||
839 | mdump->md_enabled = 1; | ||
840 | if (adapter->fw_mdump_rdy) { | ||
841 | netdev_info(netdev, "Previous dump not cleared, not forcing dump\n"); | ||
842 | return ret; | ||
843 | } | ||
844 | netdev_info(netdev, "Forcing a fw dump\n"); | ||
845 | nx_dev_request_reset(adapter); | ||
846 | break; | ||
847 | case NX_DISABLE_FW_DUMP: | ||
848 | if (mdump->md_enabled) { | ||
849 | netdev_info(netdev, "Disabling FW Dump\n"); | ||
850 | mdump->md_enabled = 0; | ||
851 | } | ||
852 | break; | ||
853 | case NX_ENABLE_FW_DUMP: | ||
854 | if (!mdump->md_enabled) { | ||
855 | netdev_info(netdev, "Enabling FW dump\n"); | ||
856 | mdump->md_enabled = 1; | ||
857 | } | ||
858 | break; | ||
859 | case NX_FORCE_FW_RESET: | ||
860 | netdev_info(netdev, "Forcing FW reset\n"); | ||
861 | nx_dev_request_reset(adapter); | ||
862 | adapter->flags &= ~NETXEN_FW_RESET_OWNER; | ||
863 | break; | ||
864 | default: | ||
865 | if (val->flag <= NX_DUMP_MASK_MAX && | ||
866 | val->flag >= NX_DUMP_MASK_MIN) { | ||
867 | mdump->md_capture_mask = val->flag & 0xff; | ||
868 | netdev_info(netdev, "Driver mask changed to: 0x%x\n", | ||
869 | mdump->md_capture_mask); | ||
870 | break; | ||
871 | } | ||
872 | netdev_info(netdev, | ||
873 | "Invalid dump level: 0x%x\n", val->flag); | ||
874 | return -EINVAL; | ||
875 | } | ||
876 | |||
877 | return ret; | ||
878 | } | ||
879 | |||
880 | static int | ||
881 | netxen_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, | ||
882 | void *buffer) | ||
883 | { | ||
884 | int i, copy_sz; | ||
885 | u32 *hdr_ptr, *data; | ||
886 | struct netxen_adapter *adapter = netdev_priv(netdev); | ||
887 | struct netxen_minidump *mdump = &adapter->mdump; | ||
888 | |||
889 | |||
890 | if (!adapter->fw_mdump_rdy) { | ||
891 | netdev_info(netdev, "Dump not available\n"); | ||
892 | return -EINVAL; | ||
893 | } | ||
894 | /* Copy template header first */ | ||
895 | copy_sz = mdump->md_template_size; | ||
896 | hdr_ptr = (u32 *) mdump->md_template; | ||
897 | data = buffer; | ||
898 | for (i = 0; i < copy_sz/sizeof(u32); i++) | ||
899 | *data++ = cpu_to_le32(*hdr_ptr++); | ||
900 | |||
901 | /* Copy captured dump data */ | ||
902 | memcpy(buffer + copy_sz, | ||
903 | mdump->md_capture_buff + mdump->md_template_size, | ||
904 | mdump->md_capture_size); | ||
905 | dump->len = copy_sz + mdump->md_capture_size; | ||
906 | dump->flag = mdump->md_capture_mask; | ||
907 | |||
908 | /* Free dump area once data has been captured */ | ||
909 | vfree(mdump->md_capture_buff); | ||
910 | mdump->md_capture_buff = NULL; | ||
911 | adapter->fw_mdump_rdy = 0; | ||
912 | netdev_info(netdev, "extracted the fw dump Successfully\n"); | ||
913 | return 0; | ||
914 | } | ||
915 | |||
815 | const struct ethtool_ops netxen_nic_ethtool_ops = { | 916 | const struct ethtool_ops netxen_nic_ethtool_ops = { |
816 | .get_settings = netxen_nic_get_settings, | 917 | .get_settings = netxen_nic_get_settings, |
817 | .set_settings = netxen_nic_set_settings, | 918 | .set_settings = netxen_nic_set_settings, |
@@ -833,4 +934,7 @@ const struct ethtool_ops netxen_nic_ethtool_ops = { | |||
833 | .get_sset_count = netxen_get_sset_count, | 934 | .get_sset_count = netxen_get_sset_count, |
834 | .get_coalesce = netxen_get_intr_coalesce, | 935 | .get_coalesce = netxen_get_intr_coalesce, |
835 | .set_coalesce = netxen_set_intr_coalesce, | 936 | .set_coalesce = netxen_set_intr_coalesce, |
937 | .get_dump_flag = netxen_get_dump_flag, | ||
938 | .get_dump_data = netxen_get_dump_data, | ||
939 | .set_dump = netxen_set_dump, | ||
836 | }; | 940 | }; |
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c index 3f89e57cae50..0a8122851025 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c | |||
@@ -46,7 +46,6 @@ static void netxen_nic_io_write_128M(struct netxen_adapter *adapter, | |||
46 | void __iomem *addr, u32 data); | 46 | void __iomem *addr, u32 data); |
47 | static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter, | 47 | static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter, |
48 | void __iomem *addr); | 48 | void __iomem *addr); |
49 | |||
50 | #ifndef readq | 49 | #ifndef readq |
51 | static inline u64 readq(void __iomem *addr) | 50 | static inline u64 readq(void __iomem *addr) |
52 | { | 51 | { |
@@ -1974,3 +1973,631 @@ netxen_nic_wol_supported(struct netxen_adapter *adapter) | |||
1974 | 1973 | ||
1975 | return 0; | 1974 | return 0; |
1976 | } | 1975 | } |
1976 | |||
1977 | static u32 netxen_md_cntrl(struct netxen_adapter *adapter, | ||
1978 | struct netxen_minidump_template_hdr *template_hdr, | ||
1979 | struct netxen_minidump_entry_crb *crtEntry) | ||
1980 | { | ||
1981 | int loop_cnt, i, rv = 0, timeout_flag; | ||
1982 | u32 op_count, stride; | ||
1983 | u32 opcode, read_value, addr; | ||
1984 | unsigned long timeout, timeout_jiffies; | ||
1985 | addr = crtEntry->addr; | ||
1986 | op_count = crtEntry->op_count; | ||
1987 | stride = crtEntry->addr_stride; | ||
1988 | |||
1989 | for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) { | ||
1990 | for (i = 0; i < sizeof(crtEntry->opcode) * 8; i++) { | ||
1991 | opcode = (crtEntry->opcode & (0x1 << i)); | ||
1992 | if (opcode) { | ||
1993 | switch (opcode) { | ||
1994 | case NX_DUMP_WCRB: | ||
1995 | NX_WR_DUMP_REG(addr, | ||
1996 | adapter->ahw.pci_base0, | ||
1997 | crtEntry->value_1); | ||
1998 | break; | ||
1999 | case NX_DUMP_RWCRB: | ||
2000 | NX_RD_DUMP_REG(addr, | ||
2001 | adapter->ahw.pci_base0, | ||
2002 | &read_value); | ||
2003 | NX_WR_DUMP_REG(addr, | ||
2004 | adapter->ahw.pci_base0, | ||
2005 | read_value); | ||
2006 | break; | ||
2007 | case NX_DUMP_ANDCRB: | ||
2008 | NX_RD_DUMP_REG(addr, | ||
2009 | adapter->ahw.pci_base0, | ||
2010 | &read_value); | ||
2011 | read_value &= crtEntry->value_2; | ||
2012 | NX_WR_DUMP_REG(addr, | ||
2013 | adapter->ahw.pci_base0, | ||
2014 | read_value); | ||
2015 | break; | ||
2016 | case NX_DUMP_ORCRB: | ||
2017 | NX_RD_DUMP_REG(addr, | ||
2018 | adapter->ahw.pci_base0, | ||
2019 | &read_value); | ||
2020 | read_value |= crtEntry->value_3; | ||
2021 | NX_WR_DUMP_REG(addr, | ||
2022 | adapter->ahw.pci_base0, | ||
2023 | read_value); | ||
2024 | break; | ||
2025 | case NX_DUMP_POLLCRB: | ||
2026 | timeout = crtEntry->poll_timeout; | ||
2027 | NX_RD_DUMP_REG(addr, | ||
2028 | adapter->ahw.pci_base0, | ||
2029 | &read_value); | ||
2030 | timeout_jiffies = | ||
2031 | msecs_to_jiffies(timeout) + jiffies; | ||
2032 | for (timeout_flag = 0; | ||
2033 | !timeout_flag | ||
2034 | && ((read_value & crtEntry->value_2) | ||
2035 | != crtEntry->value_1);) { | ||
2036 | if (time_after(jiffies, | ||
2037 | timeout_jiffies)) | ||
2038 | timeout_flag = 1; | ||
2039 | NX_RD_DUMP_REG(addr, | ||
2040 | adapter->ahw.pci_base0, | ||
2041 | &read_value); | ||
2042 | } | ||
2043 | |||
2044 | if (timeout_flag) { | ||
2045 | dev_err(&adapter->pdev->dev, "%s : " | ||
2046 | "Timeout in poll_crb control operation.\n" | ||
2047 | , __func__); | ||
2048 | return -1; | ||
2049 | } | ||
2050 | break; | ||
2051 | case NX_DUMP_RD_SAVE: | ||
2052 | /* Decide which address to use */ | ||
2053 | if (crtEntry->state_index_a) | ||
2054 | addr = | ||
2055 | template_hdr->saved_state_array | ||
2056 | [crtEntry->state_index_a]; | ||
2057 | NX_RD_DUMP_REG(addr, | ||
2058 | adapter->ahw.pci_base0, | ||
2059 | &read_value); | ||
2060 | template_hdr->saved_state_array | ||
2061 | [crtEntry->state_index_v] | ||
2062 | = read_value; | ||
2063 | break; | ||
2064 | case NX_DUMP_WRT_SAVED: | ||
2065 | /* Decide which value to use */ | ||
2066 | if (crtEntry->state_index_v) | ||
2067 | read_value = | ||
2068 | template_hdr->saved_state_array | ||
2069 | [crtEntry->state_index_v]; | ||
2070 | else | ||
2071 | read_value = crtEntry->value_1; | ||
2072 | |||
2073 | /* Decide which address to use */ | ||
2074 | if (crtEntry->state_index_a) | ||
2075 | addr = | ||
2076 | template_hdr->saved_state_array | ||
2077 | [crtEntry->state_index_a]; | ||
2078 | |||
2079 | NX_WR_DUMP_REG(addr, | ||
2080 | adapter->ahw.pci_base0, | ||
2081 | read_value); | ||
2082 | break; | ||
2083 | case NX_DUMP_MOD_SAVE_ST: | ||
2084 | read_value = | ||
2085 | template_hdr->saved_state_array | ||
2086 | [crtEntry->state_index_v]; | ||
2087 | read_value <<= crtEntry->shl; | ||
2088 | read_value >>= crtEntry->shr; | ||
2089 | if (crtEntry->value_2) | ||
2090 | read_value &= | ||
2091 | crtEntry->value_2; | ||
2092 | read_value |= crtEntry->value_3; | ||
2093 | read_value += crtEntry->value_1; | ||
2094 | /* Write value back to state area.*/ | ||
2095 | template_hdr->saved_state_array | ||
2096 | [crtEntry->state_index_v] | ||
2097 | = read_value; | ||
2098 | break; | ||
2099 | default: | ||
2100 | rv = 1; | ||
2101 | break; | ||
2102 | } | ||
2103 | } | ||
2104 | } | ||
2105 | addr = addr + stride; | ||
2106 | } | ||
2107 | return rv; | ||
2108 | } | ||
2109 | |||
2110 | /* Read memory or MN */ | ||
2111 | static u32 | ||
2112 | netxen_md_rdmem(struct netxen_adapter *adapter, | ||
2113 | struct netxen_minidump_entry_rdmem | ||
2114 | *memEntry, u64 *data_buff) | ||
2115 | { | ||
2116 | u64 addr, value = 0; | ||
2117 | int i = 0, loop_cnt; | ||
2118 | |||
2119 | addr = (u64)memEntry->read_addr; | ||
2120 | loop_cnt = memEntry->read_data_size; /* This is size in bytes */ | ||
2121 | loop_cnt /= sizeof(value); | ||
2122 | |||
2123 | for (i = 0; i < loop_cnt; i++) { | ||
2124 | if (netxen_nic_pci_mem_read_2M(adapter, addr, &value)) | ||
2125 | goto out; | ||
2126 | *data_buff++ = value; | ||
2127 | addr += sizeof(value); | ||
2128 | } | ||
2129 | out: | ||
2130 | return i * sizeof(value); | ||
2131 | } | ||
2132 | |||
2133 | /* Read CRB operation */ | ||
2134 | static u32 netxen_md_rd_crb(struct netxen_adapter *adapter, | ||
2135 | struct netxen_minidump_entry_crb | ||
2136 | *crbEntry, u32 *data_buff) | ||
2137 | { | ||
2138 | int loop_cnt; | ||
2139 | u32 op_count, addr, stride, value; | ||
2140 | |||
2141 | addr = crbEntry->addr; | ||
2142 | op_count = crbEntry->op_count; | ||
2143 | stride = crbEntry->addr_stride; | ||
2144 | |||
2145 | for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) { | ||
2146 | NX_RD_DUMP_REG(addr, adapter->ahw.pci_base0, &value); | ||
2147 | *data_buff++ = addr; | ||
2148 | *data_buff++ = value; | ||
2149 | addr = addr + stride; | ||
2150 | } | ||
2151 | return loop_cnt * (2 * sizeof(u32)); | ||
2152 | } | ||
2153 | |||
2154 | /* Read ROM */ | ||
2155 | static u32 | ||
2156 | netxen_md_rdrom(struct netxen_adapter *adapter, | ||
2157 | struct netxen_minidump_entry_rdrom | ||
2158 | *romEntry, u32 *data_buff) | ||
2159 | { | ||
2160 | int i, count = 0; | ||
2161 | u32 size, lck_val; | ||
2162 | u32 val; | ||
2163 | u32 fl_addr, waddr, raddr; | ||
2164 | fl_addr = romEntry->read_addr; | ||
2165 | size = romEntry->read_data_size/4; | ||
2166 | lock_try: | ||
2167 | lck_val = readl((void __iomem *)(adapter->ahw.pci_base0 + | ||
2168 | NX_FLASH_SEM2_LK)); | ||
2169 | if (!lck_val && count < MAX_CTL_CHECK) { | ||
2170 | msleep(20); | ||
2171 | count++; | ||
2172 | goto lock_try; | ||
2173 | } | ||
2174 | writel(adapter->ahw.pci_func, (void __iomem *)(adapter->ahw.pci_base0 + | ||
2175 | NX_FLASH_LOCK_ID)); | ||
2176 | for (i = 0; i < size; i++) { | ||
2177 | waddr = fl_addr & 0xFFFF0000; | ||
2178 | NX_WR_DUMP_REG(FLASH_ROM_WINDOW, adapter->ahw.pci_base0, waddr); | ||
2179 | raddr = FLASH_ROM_DATA + (fl_addr & 0x0000FFFF); | ||
2180 | NX_RD_DUMP_REG(raddr, adapter->ahw.pci_base0, &val); | ||
2181 | *data_buff++ = cpu_to_le32(val); | ||
2182 | fl_addr += sizeof(val); | ||
2183 | } | ||
2184 | readl((void __iomem *)(adapter->ahw.pci_base0 + NX_FLASH_SEM2_ULK)); | ||
2185 | return romEntry->read_data_size; | ||
2186 | } | ||
2187 | |||
2188 | /* Handle L2 Cache */ | ||
2189 | static u32 | ||
2190 | netxen_md_L2Cache(struct netxen_adapter *adapter, | ||
2191 | struct netxen_minidump_entry_cache | ||
2192 | *cacheEntry, u32 *data_buff) | ||
2193 | { | ||
2194 | int loop_cnt, i, k, timeout_flag = 0; | ||
2195 | u32 addr, read_addr, read_value, cntrl_addr, tag_reg_addr; | ||
2196 | u32 tag_value, read_cnt; | ||
2197 | u8 cntl_value_w, cntl_value_r; | ||
2198 | unsigned long timeout, timeout_jiffies; | ||
2199 | |||
2200 | loop_cnt = cacheEntry->op_count; | ||
2201 | read_addr = cacheEntry->read_addr; | ||
2202 | cntrl_addr = cacheEntry->control_addr; | ||
2203 | cntl_value_w = (u32) cacheEntry->write_value; | ||
2204 | tag_reg_addr = cacheEntry->tag_reg_addr; | ||
2205 | tag_value = cacheEntry->init_tag_value; | ||
2206 | read_cnt = cacheEntry->read_addr_cnt; | ||
2207 | |||
2208 | for (i = 0; i < loop_cnt; i++) { | ||
2209 | NX_WR_DUMP_REG(tag_reg_addr, adapter->ahw.pci_base0, tag_value); | ||
2210 | if (cntl_value_w) | ||
2211 | NX_WR_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0, | ||
2212 | (u32)cntl_value_w); | ||
2213 | if (cacheEntry->poll_mask) { | ||
2214 | timeout = cacheEntry->poll_wait; | ||
2215 | NX_RD_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0, | ||
2216 | &cntl_value_r); | ||
2217 | timeout_jiffies = msecs_to_jiffies(timeout) + jiffies; | ||
2218 | for (timeout_flag = 0; !timeout_flag && | ||
2219 | ((cntl_value_r & cacheEntry->poll_mask) != 0);) { | ||
2220 | if (time_after(jiffies, timeout_jiffies)) | ||
2221 | timeout_flag = 1; | ||
2222 | NX_RD_DUMP_REG(cntrl_addr, | ||
2223 | adapter->ahw.pci_base0, | ||
2224 | &cntl_value_r); | ||
2225 | } | ||
2226 | if (timeout_flag) { | ||
2227 | dev_err(&adapter->pdev->dev, | ||
2228 | "Timeout in processing L2 Tag poll.\n"); | ||
2229 | return -1; | ||
2230 | } | ||
2231 | } | ||
2232 | addr = read_addr; | ||
2233 | for (k = 0; k < read_cnt; k++) { | ||
2234 | NX_RD_DUMP_REG(addr, adapter->ahw.pci_base0, | ||
2235 | &read_value); | ||
2236 | *data_buff++ = read_value; | ||
2237 | addr += cacheEntry->read_addr_stride; | ||
2238 | } | ||
2239 | tag_value += cacheEntry->tag_value_stride; | ||
2240 | } | ||
2241 | return read_cnt * loop_cnt * sizeof(read_value); | ||
2242 | } | ||
2243 | |||
2244 | |||
2245 | /* Handle L1 Cache */ | ||
2246 | static u32 netxen_md_L1Cache(struct netxen_adapter *adapter, | ||
2247 | struct netxen_minidump_entry_cache | ||
2248 | *cacheEntry, u32 *data_buff) | ||
2249 | { | ||
2250 | int i, k, loop_cnt; | ||
2251 | u32 addr, read_addr, read_value, cntrl_addr, tag_reg_addr; | ||
2252 | u32 tag_value, read_cnt; | ||
2253 | u8 cntl_value_w; | ||
2254 | |||
2255 | loop_cnt = cacheEntry->op_count; | ||
2256 | read_addr = cacheEntry->read_addr; | ||
2257 | cntrl_addr = cacheEntry->control_addr; | ||
2258 | cntl_value_w = (u32) cacheEntry->write_value; | ||
2259 | tag_reg_addr = cacheEntry->tag_reg_addr; | ||
2260 | tag_value = cacheEntry->init_tag_value; | ||
2261 | read_cnt = cacheEntry->read_addr_cnt; | ||
2262 | |||
2263 | for (i = 0; i < loop_cnt; i++) { | ||
2264 | NX_WR_DUMP_REG(tag_reg_addr, adapter->ahw.pci_base0, tag_value); | ||
2265 | NX_WR_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0, | ||
2266 | (u32) cntl_value_w); | ||
2267 | addr = read_addr; | ||
2268 | for (k = 0; k < read_cnt; k++) { | ||
2269 | NX_RD_DUMP_REG(addr, | ||
2270 | adapter->ahw.pci_base0, | ||
2271 | &read_value); | ||
2272 | *data_buff++ = read_value; | ||
2273 | addr += cacheEntry->read_addr_stride; | ||
2274 | } | ||
2275 | tag_value += cacheEntry->tag_value_stride; | ||
2276 | } | ||
2277 | return read_cnt * loop_cnt * sizeof(read_value); | ||
2278 | } | ||
2279 | |||
2280 | /* Reading OCM memory */ | ||
2281 | static u32 | ||
2282 | netxen_md_rdocm(struct netxen_adapter *adapter, | ||
2283 | struct netxen_minidump_entry_rdocm | ||
2284 | *ocmEntry, u32 *data_buff) | ||
2285 | { | ||
2286 | int i, loop_cnt; | ||
2287 | u32 value; | ||
2288 | void __iomem *addr; | ||
2289 | addr = (ocmEntry->read_addr + adapter->ahw.pci_base0); | ||
2290 | loop_cnt = ocmEntry->op_count; | ||
2291 | |||
2292 | for (i = 0; i < loop_cnt; i++) { | ||
2293 | value = readl(addr); | ||
2294 | *data_buff++ = value; | ||
2295 | addr += ocmEntry->read_addr_stride; | ||
2296 | } | ||
2297 | return i * sizeof(u32); | ||
2298 | } | ||
2299 | |||
2300 | /* Read MUX data */ | ||
2301 | static u32 | ||
2302 | netxen_md_rdmux(struct netxen_adapter *adapter, struct netxen_minidump_entry_mux | ||
2303 | *muxEntry, u32 *data_buff) | ||
2304 | { | ||
2305 | int loop_cnt = 0; | ||
2306 | u32 read_addr, read_value, select_addr, sel_value; | ||
2307 | |||
2308 | read_addr = muxEntry->read_addr; | ||
2309 | sel_value = muxEntry->select_value; | ||
2310 | select_addr = muxEntry->select_addr; | ||
2311 | |||
2312 | for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) { | ||
2313 | NX_WR_DUMP_REG(select_addr, adapter->ahw.pci_base0, sel_value); | ||
2314 | NX_RD_DUMP_REG(read_addr, adapter->ahw.pci_base0, &read_value); | ||
2315 | *data_buff++ = sel_value; | ||
2316 | *data_buff++ = read_value; | ||
2317 | sel_value += muxEntry->select_value_stride; | ||
2318 | } | ||
2319 | return loop_cnt * (2 * sizeof(u32)); | ||
2320 | } | ||
2321 | |||
2322 | /* Handling Queue State Reads */ | ||
2323 | static u32 | ||
2324 | netxen_md_rdqueue(struct netxen_adapter *adapter, | ||
2325 | struct netxen_minidump_entry_queue | ||
2326 | *queueEntry, u32 *data_buff) | ||
2327 | { | ||
2328 | int loop_cnt, k; | ||
2329 | u32 queue_id, read_addr, read_value, read_stride, select_addr, read_cnt; | ||
2330 | |||
2331 | read_cnt = queueEntry->read_addr_cnt; | ||
2332 | read_stride = queueEntry->read_addr_stride; | ||
2333 | select_addr = queueEntry->select_addr; | ||
2334 | |||
2335 | for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count; | ||
2336 | loop_cnt++) { | ||
2337 | NX_WR_DUMP_REG(select_addr, adapter->ahw.pci_base0, queue_id); | ||
2338 | read_addr = queueEntry->read_addr; | ||
2339 | for (k = 0; k < read_cnt; k--) { | ||
2340 | NX_RD_DUMP_REG(read_addr, adapter->ahw.pci_base0, | ||
2341 | &read_value); | ||
2342 | *data_buff++ = read_value; | ||
2343 | read_addr += read_stride; | ||
2344 | } | ||
2345 | queue_id += queueEntry->queue_id_stride; | ||
2346 | } | ||
2347 | return loop_cnt * (read_cnt * sizeof(read_value)); | ||
2348 | } | ||
2349 | |||
2350 | |||
2351 | /* | ||
2352 | * We catch an error where driver does not read | ||
2353 | * as much data as we expect from the entry. | ||
2354 | */ | ||
2355 | |||
2356 | static int netxen_md_entry_err_chk(struct netxen_adapter *adapter, | ||
2357 | struct netxen_minidump_entry *entry, u32 esize) | ||
2358 | { | ||
2359 | if (esize < 0) { | ||
2360 | entry->hdr.driver_flags |= NX_DUMP_SKIP; | ||
2361 | return esize; | ||
2362 | } | ||
2363 | if (esize != entry->hdr.entry_capture_size) { | ||
2364 | entry->hdr.entry_capture_size = esize; | ||
2365 | entry->hdr.driver_flags |= NX_DUMP_SIZE_ERR; | ||
2366 | dev_info(&adapter->pdev->dev, | ||
2367 | "Invalidate dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n", | ||
2368 | entry->hdr.entry_type, entry->hdr.entry_capture_mask, | ||
2369 | esize, entry->hdr.entry_capture_size); | ||
2370 | dev_info(&adapter->pdev->dev, "Aborting further dump capture\n"); | ||
2371 | } | ||
2372 | return 0; | ||
2373 | } | ||
2374 | |||
2375 | static int netxen_parse_md_template(struct netxen_adapter *adapter) | ||
2376 | { | ||
2377 | int num_of_entries, buff_level, e_cnt, esize; | ||
2378 | int end_cnt = 0, rv = 0, sane_start = 0, sane_end = 0; | ||
2379 | char *dbuff; | ||
2380 | void *template_buff = adapter->mdump.md_template; | ||
2381 | char *dump_buff = adapter->mdump.md_capture_buff; | ||
2382 | int capture_mask = adapter->mdump.md_capture_mask; | ||
2383 | struct netxen_minidump_template_hdr *template_hdr; | ||
2384 | struct netxen_minidump_entry *entry; | ||
2385 | |||
2386 | if ((capture_mask & 0x3) != 0x3) { | ||
2387 | dev_err(&adapter->pdev->dev, "Capture mask %02x below minimum needed " | ||
2388 | "for valid firmware dump\n", capture_mask); | ||
2389 | return -EINVAL; | ||
2390 | } | ||
2391 | template_hdr = (struct netxen_minidump_template_hdr *) template_buff; | ||
2392 | num_of_entries = template_hdr->num_of_entries; | ||
2393 | entry = (struct netxen_minidump_entry *) ((char *) template_buff + | ||
2394 | template_hdr->first_entry_offset); | ||
2395 | memcpy(dump_buff, template_buff, adapter->mdump.md_template_size); | ||
2396 | dump_buff = dump_buff + adapter->mdump.md_template_size; | ||
2397 | |||
2398 | if (template_hdr->entry_type == TLHDR) | ||
2399 | sane_start = 1; | ||
2400 | |||
2401 | for (e_cnt = 0, buff_level = 0; e_cnt < num_of_entries; e_cnt++) { | ||
2402 | if (!(entry->hdr.entry_capture_mask & capture_mask)) { | ||
2403 | entry->hdr.driver_flags |= NX_DUMP_SKIP; | ||
2404 | entry = (struct netxen_minidump_entry *) | ||
2405 | ((char *) entry + entry->hdr.entry_size); | ||
2406 | continue; | ||
2407 | } | ||
2408 | switch (entry->hdr.entry_type) { | ||
2409 | case RDNOP: | ||
2410 | entry->hdr.driver_flags |= NX_DUMP_SKIP; | ||
2411 | break; | ||
2412 | case RDEND: | ||
2413 | entry->hdr.driver_flags |= NX_DUMP_SKIP; | ||
2414 | if (!sane_end) | ||
2415 | end_cnt = e_cnt; | ||
2416 | sane_end += 1; | ||
2417 | break; | ||
2418 | case CNTRL: | ||
2419 | rv = netxen_md_cntrl(adapter, | ||
2420 | template_hdr, (void *)entry); | ||
2421 | if (rv) | ||
2422 | entry->hdr.driver_flags |= NX_DUMP_SKIP; | ||
2423 | break; | ||
2424 | case RDCRB: | ||
2425 | dbuff = dump_buff + buff_level; | ||
2426 | esize = netxen_md_rd_crb(adapter, | ||
2427 | (void *) entry, (void *) dbuff); | ||
2428 | rv = netxen_md_entry_err_chk | ||
2429 | (adapter, entry, esize); | ||
2430 | if (rv < 0) | ||
2431 | break; | ||
2432 | buff_level += esize; | ||
2433 | break; | ||
2434 | case RDMN: | ||
2435 | case RDMEM: | ||
2436 | dbuff = dump_buff + buff_level; | ||
2437 | esize = netxen_md_rdmem(adapter, | ||
2438 | (void *) entry, (void *) dbuff); | ||
2439 | rv = netxen_md_entry_err_chk | ||
2440 | (adapter, entry, esize); | ||
2441 | if (rv < 0) | ||
2442 | break; | ||
2443 | buff_level += esize; | ||
2444 | break; | ||
2445 | case BOARD: | ||
2446 | case RDROM: | ||
2447 | dbuff = dump_buff + buff_level; | ||
2448 | esize = netxen_md_rdrom(adapter, | ||
2449 | (void *) entry, (void *) dbuff); | ||
2450 | rv = netxen_md_entry_err_chk | ||
2451 | (adapter, entry, esize); | ||
2452 | if (rv < 0) | ||
2453 | break; | ||
2454 | buff_level += esize; | ||
2455 | break; | ||
2456 | case L2ITG: | ||
2457 | case L2DTG: | ||
2458 | case L2DAT: | ||
2459 | case L2INS: | ||
2460 | dbuff = dump_buff + buff_level; | ||
2461 | esize = netxen_md_L2Cache(adapter, | ||
2462 | (void *) entry, (void *) dbuff); | ||
2463 | rv = netxen_md_entry_err_chk | ||
2464 | (adapter, entry, esize); | ||
2465 | if (rv < 0) | ||
2466 | break; | ||
2467 | buff_level += esize; | ||
2468 | break; | ||
2469 | case L1DAT: | ||
2470 | case L1INS: | ||
2471 | dbuff = dump_buff + buff_level; | ||
2472 | esize = netxen_md_L1Cache(adapter, | ||
2473 | (void *) entry, (void *) dbuff); | ||
2474 | rv = netxen_md_entry_err_chk | ||
2475 | (adapter, entry, esize); | ||
2476 | if (rv < 0) | ||
2477 | break; | ||
2478 | buff_level += esize; | ||
2479 | break; | ||
2480 | case RDOCM: | ||
2481 | dbuff = dump_buff + buff_level; | ||
2482 | esize = netxen_md_rdocm(adapter, | ||
2483 | (void *) entry, (void *) dbuff); | ||
2484 | rv = netxen_md_entry_err_chk | ||
2485 | (adapter, entry, esize); | ||
2486 | if (rv < 0) | ||
2487 | break; | ||
2488 | buff_level += esize; | ||
2489 | break; | ||
2490 | case RDMUX: | ||
2491 | dbuff = dump_buff + buff_level; | ||
2492 | esize = netxen_md_rdmux(adapter, | ||
2493 | (void *) entry, (void *) dbuff); | ||
2494 | rv = netxen_md_entry_err_chk | ||
2495 | (adapter, entry, esize); | ||
2496 | if (rv < 0) | ||
2497 | break; | ||
2498 | buff_level += esize; | ||
2499 | break; | ||
2500 | case QUEUE: | ||
2501 | dbuff = dump_buff + buff_level; | ||
2502 | esize = netxen_md_rdqueue(adapter, | ||
2503 | (void *) entry, (void *) dbuff); | ||
2504 | rv = netxen_md_entry_err_chk | ||
2505 | (adapter, entry, esize); | ||
2506 | if (rv < 0) | ||
2507 | break; | ||
2508 | buff_level += esize; | ||
2509 | break; | ||
2510 | default: | ||
2511 | entry->hdr.driver_flags |= NX_DUMP_SKIP; | ||
2512 | break; | ||
2513 | } | ||
2514 | /* Next entry in the template */ | ||
2515 | entry = (struct netxen_minidump_entry *) | ||
2516 | ((char *) entry + entry->hdr.entry_size); | ||
2517 | } | ||
2518 | if (!sane_start || sane_end > 1) { | ||
2519 | dev_err(&adapter->pdev->dev, | ||
2520 | "Firmware minidump template configuration error.\n"); | ||
2521 | } | ||
2522 | return 0; | ||
2523 | } | ||
2524 | |||
2525 | static int | ||
2526 | netxen_collect_minidump(struct netxen_adapter *adapter) | ||
2527 | { | ||
2528 | int ret = 0; | ||
2529 | struct netxen_minidump_template_hdr *hdr; | ||
2530 | struct timespec val; | ||
2531 | hdr = (struct netxen_minidump_template_hdr *) | ||
2532 | adapter->mdump.md_template; | ||
2533 | hdr->driver_capture_mask = adapter->mdump.md_capture_mask; | ||
2534 | jiffies_to_timespec(jiffies, &val); | ||
2535 | hdr->driver_timestamp = (u32) val.tv_sec; | ||
2536 | hdr->driver_info_word2 = adapter->fw_version; | ||
2537 | hdr->driver_info_word3 = NXRD32(adapter, CRB_DRIVER_VERSION); | ||
2538 | ret = netxen_parse_md_template(adapter); | ||
2539 | if (ret) | ||
2540 | return ret; | ||
2541 | |||
2542 | return ret; | ||
2543 | } | ||
2544 | |||
2545 | |||
2546 | void | ||
2547 | netxen_dump_fw(struct netxen_adapter *adapter) | ||
2548 | { | ||
2549 | struct netxen_minidump_template_hdr *hdr; | ||
2550 | int i, k, data_size = 0; | ||
2551 | u32 capture_mask; | ||
2552 | hdr = (struct netxen_minidump_template_hdr *) | ||
2553 | adapter->mdump.md_template; | ||
2554 | capture_mask = adapter->mdump.md_capture_mask; | ||
2555 | |||
2556 | for (i = 0x2, k = 1; (i & NX_DUMP_MASK_MAX); i <<= 1, k++) { | ||
2557 | if (i & capture_mask) | ||
2558 | data_size += hdr->capture_size_array[k]; | ||
2559 | } | ||
2560 | if (!data_size) { | ||
2561 | dev_err(&adapter->pdev->dev, | ||
2562 | "Invalid cap sizes for capture_mask=0x%x\n", | ||
2563 | adapter->mdump.md_capture_mask); | ||
2564 | return; | ||
2565 | } | ||
2566 | adapter->mdump.md_capture_size = data_size; | ||
2567 | adapter->mdump.md_dump_size = adapter->mdump.md_template_size + | ||
2568 | adapter->mdump.md_capture_size; | ||
2569 | if (!adapter->mdump.md_capture_buff) { | ||
2570 | adapter->mdump.md_capture_buff = | ||
2571 | vmalloc(adapter->mdump.md_dump_size); | ||
2572 | if (!adapter->mdump.md_capture_buff) { | ||
2573 | dev_info(&adapter->pdev->dev, | ||
2574 | "Unable to allocate memory for minidump " | ||
2575 | "capture_buffer(%d bytes).\n", | ||
2576 | adapter->mdump.md_dump_size); | ||
2577 | return; | ||
2578 | } | ||
2579 | memset(adapter->mdump.md_capture_buff, 0, | ||
2580 | adapter->mdump.md_dump_size); | ||
2581 | if (netxen_collect_minidump(adapter)) { | ||
2582 | adapter->mdump.has_valid_dump = 0; | ||
2583 | adapter->mdump.md_dump_size = 0; | ||
2584 | vfree(adapter->mdump.md_capture_buff); | ||
2585 | adapter->mdump.md_capture_buff = NULL; | ||
2586 | dev_err(&adapter->pdev->dev, | ||
2587 | "Error in collecting firmware minidump.\n"); | ||
2588 | } else { | ||
2589 | adapter->mdump.md_timestamp = jiffies; | ||
2590 | adapter->mdump.has_valid_dump = 1; | ||
2591 | adapter->fw_mdump_rdy = 1; | ||
2592 | dev_info(&adapter->pdev->dev, "%s Successfully " | ||
2593 | "collected fw dump.\n", adapter->netdev->name); | ||
2594 | } | ||
2595 | |||
2596 | } else { | ||
2597 | dev_info(&adapter->pdev->dev, | ||
2598 | "Cannot overwrite previously collected " | ||
2599 | "firmware minidump.\n"); | ||
2600 | adapter->fw_mdump_rdy = 1; | ||
2601 | return; | ||
2602 | } | ||
2603 | } | ||
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c index 094d26c51816..f69ac442c6a1 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c | |||
@@ -446,7 +446,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter) | |||
446 | 446 | ||
447 | /* resetall */ | 447 | /* resetall */ |
448 | netxen_rom_lock(adapter); | 448 | netxen_rom_lock(adapter); |
449 | NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xffffffff); | 449 | NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xfeffffff); |
450 | netxen_rom_unlock(adapter); | 450 | netxen_rom_unlock(adapter); |
451 | 451 | ||
452 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { | 452 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { |
@@ -1347,7 +1347,6 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) | |||
1347 | 1347 | ||
1348 | do { | 1348 | do { |
1349 | val = NXRD32(adapter, CRB_CMDPEG_STATE); | 1349 | val = NXRD32(adapter, CRB_CMDPEG_STATE); |
1350 | |||
1351 | switch (val) { | 1350 | switch (val) { |
1352 | case PHAN_INITIALIZE_COMPLETE: | 1351 | case PHAN_INITIALIZE_COMPLETE: |
1353 | case PHAN_INITIALIZE_ACK: | 1352 | case PHAN_INITIALIZE_ACK: |
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 64aa44d5dabb..f67655f3462c 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | |||
@@ -82,7 +82,6 @@ static void netxen_create_sysfs_entries(struct netxen_adapter *adapter); | |||
82 | static void netxen_remove_sysfs_entries(struct netxen_adapter *adapter); | 82 | static void netxen_remove_sysfs_entries(struct netxen_adapter *adapter); |
83 | static void netxen_create_diag_entries(struct netxen_adapter *adapter); | 83 | static void netxen_create_diag_entries(struct netxen_adapter *adapter); |
84 | static void netxen_remove_diag_entries(struct netxen_adapter *adapter); | 84 | static void netxen_remove_diag_entries(struct netxen_adapter *adapter); |
85 | |||
86 | static int nx_dev_request_aer(struct netxen_adapter *adapter); | 85 | static int nx_dev_request_aer(struct netxen_adapter *adapter); |
87 | static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter); | 86 | static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter); |
88 | static int netxen_can_start_firmware(struct netxen_adapter *adapter); | 87 | static int netxen_can_start_firmware(struct netxen_adapter *adapter); |
@@ -802,10 +801,10 @@ err_out: | |||
802 | static void | 801 | static void |
803 | netxen_check_options(struct netxen_adapter *adapter) | 802 | netxen_check_options(struct netxen_adapter *adapter) |
804 | { | 803 | { |
805 | u32 fw_major, fw_minor, fw_build; | 804 | u32 fw_major, fw_minor, fw_build, prev_fw_version; |
806 | char brd_name[NETXEN_MAX_SHORT_NAME]; | 805 | char brd_name[NETXEN_MAX_SHORT_NAME]; |
807 | char serial_num[32]; | 806 | char serial_num[32]; |
808 | int i, offset, val; | 807 | int i, offset, val, err; |
809 | int *ptr32; | 808 | int *ptr32; |
810 | struct pci_dev *pdev = adapter->pdev; | 809 | struct pci_dev *pdev = adapter->pdev; |
811 | 810 | ||
@@ -826,9 +825,22 @@ netxen_check_options(struct netxen_adapter *adapter) | |||
826 | fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); | 825 | fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); |
827 | fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); | 826 | fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); |
828 | fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); | 827 | fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); |
829 | 828 | prev_fw_version = adapter->fw_version; | |
830 | adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build); | 829 | adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build); |
831 | 830 | ||
831 | /* Get FW Mini Coredump template and store it */ | ||
832 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { | ||
833 | if (adapter->mdump.md_template == NULL || | ||
834 | adapter->fw_version > prev_fw_version) { | ||
835 | kfree(adapter->mdump.md_template); | ||
836 | adapter->mdump.md_template = NULL; | ||
837 | err = netxen_setup_minidump(adapter); | ||
838 | if (err) | ||
839 | dev_err(&adapter->pdev->dev, | ||
840 | "Failed to setup minidump rcode = %d\n", err); | ||
841 | } | ||
842 | } | ||
843 | |||
832 | if (adapter->portnum == 0) { | 844 | if (adapter->portnum == 0) { |
833 | get_brd_name_by_type(adapter->ahw.board_type, brd_name); | 845 | get_brd_name_by_type(adapter->ahw.board_type, brd_name); |
834 | 846 | ||
@@ -909,7 +921,12 @@ netxen_start_firmware(struct netxen_adapter *adapter) | |||
909 | if (err) | 921 | if (err) |
910 | return err; | 922 | return err; |
911 | 923 | ||
912 | if (!netxen_can_start_firmware(adapter)) | 924 | err = netxen_can_start_firmware(adapter); |
925 | |||
926 | if (err < 0) | ||
927 | return err; | ||
928 | |||
929 | if (!err) | ||
913 | goto wait_init; | 930 | goto wait_init; |
914 | 931 | ||
915 | first_boot = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc)); | 932 | first_boot = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc)); |
@@ -1528,6 +1545,18 @@ err_out_disable_pdev: | |||
1528 | return err; | 1545 | return err; |
1529 | } | 1546 | } |
1530 | 1547 | ||
1548 | static | ||
1549 | void netxen_cleanup_minidump(struct netxen_adapter *adapter) | ||
1550 | { | ||
1551 | kfree(adapter->mdump.md_template); | ||
1552 | adapter->mdump.md_template = NULL; | ||
1553 | |||
1554 | if (adapter->mdump.md_capture_buff) { | ||
1555 | vfree(adapter->mdump.md_capture_buff); | ||
1556 | adapter->mdump.md_capture_buff = NULL; | ||
1557 | } | ||
1558 | } | ||
1559 | |||
1531 | static void __devexit netxen_nic_remove(struct pci_dev *pdev) | 1560 | static void __devexit netxen_nic_remove(struct pci_dev *pdev) |
1532 | { | 1561 | { |
1533 | struct netxen_adapter *adapter; | 1562 | struct netxen_adapter *adapter; |
@@ -1563,8 +1592,10 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) | |||
1563 | 1592 | ||
1564 | netxen_release_firmware(adapter); | 1593 | netxen_release_firmware(adapter); |
1565 | 1594 | ||
1566 | if (NX_IS_REVISION_P3(pdev->revision)) | 1595 | if (NX_IS_REVISION_P3(pdev->revision)) { |
1596 | netxen_cleanup_minidump(adapter); | ||
1567 | pci_disable_pcie_error_reporting(pdev); | 1597 | pci_disable_pcie_error_reporting(pdev); |
1598 | } | ||
1568 | 1599 | ||
1569 | pci_release_regions(pdev); | 1600 | pci_release_regions(pdev); |
1570 | pci_disable_device(pdev); | 1601 | pci_disable_device(pdev); |
@@ -2316,7 +2347,7 @@ nx_incr_dev_ref_cnt(struct netxen_adapter *adapter) | |||
2316 | static int | 2347 | static int |
2317 | nx_decr_dev_ref_cnt(struct netxen_adapter *adapter) | 2348 | nx_decr_dev_ref_cnt(struct netxen_adapter *adapter) |
2318 | { | 2349 | { |
2319 | int count; | 2350 | int count, state; |
2320 | if (netxen_api_lock(adapter)) | 2351 | if (netxen_api_lock(adapter)) |
2321 | return -EIO; | 2352 | return -EIO; |
2322 | 2353 | ||
@@ -2324,8 +2355,9 @@ nx_decr_dev_ref_cnt(struct netxen_adapter *adapter) | |||
2324 | WARN_ON(count == 0); | 2355 | WARN_ON(count == 0); |
2325 | 2356 | ||
2326 | NXWR32(adapter, NX_CRB_DEV_REF_COUNT, --count); | 2357 | NXWR32(adapter, NX_CRB_DEV_REF_COUNT, --count); |
2358 | state = NXRD32(adapter, NX_CRB_DEV_STATE); | ||
2327 | 2359 | ||
2328 | if (count == 0) | 2360 | if (count == 0 && state != NX_DEV_FAILED) |
2329 | NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_COLD); | 2361 | NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_COLD); |
2330 | 2362 | ||
2331 | netxen_api_unlock(adapter); | 2363 | netxen_api_unlock(adapter); |
@@ -2354,7 +2386,7 @@ nx_dev_request_aer(struct netxen_adapter *adapter) | |||
2354 | return ret; | 2386 | return ret; |
2355 | } | 2387 | } |
2356 | 2388 | ||
2357 | static int | 2389 | int |
2358 | nx_dev_request_reset(struct netxen_adapter *adapter) | 2390 | nx_dev_request_reset(struct netxen_adapter *adapter) |
2359 | { | 2391 | { |
2360 | u32 state; | 2392 | u32 state; |
@@ -2365,10 +2397,11 @@ nx_dev_request_reset(struct netxen_adapter *adapter) | |||
2365 | 2397 | ||
2366 | state = NXRD32(adapter, NX_CRB_DEV_STATE); | 2398 | state = NXRD32(adapter, NX_CRB_DEV_STATE); |
2367 | 2399 | ||
2368 | if (state == NX_DEV_NEED_RESET) | 2400 | if (state == NX_DEV_NEED_RESET || state == NX_DEV_FAILED) |
2369 | ret = 0; | 2401 | ret = 0; |
2370 | else if (state != NX_DEV_INITALIZING && state != NX_DEV_NEED_AER) { | 2402 | else if (state != NX_DEV_INITALIZING && state != NX_DEV_NEED_AER) { |
2371 | NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_RESET); | 2403 | NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_RESET); |
2404 | adapter->flags |= NETXEN_FW_RESET_OWNER; | ||
2372 | ret = 0; | 2405 | ret = 0; |
2373 | } | 2406 | } |
2374 | 2407 | ||
@@ -2383,8 +2416,10 @@ netxen_can_start_firmware(struct netxen_adapter *adapter) | |||
2383 | int count; | 2416 | int count; |
2384 | int can_start = 0; | 2417 | int can_start = 0; |
2385 | 2418 | ||
2386 | if (netxen_api_lock(adapter)) | 2419 | if (netxen_api_lock(adapter)) { |
2387 | return 0; | 2420 | nx_incr_dev_ref_cnt(adapter); |
2421 | return -1; | ||
2422 | } | ||
2388 | 2423 | ||
2389 | count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); | 2424 | count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); |
2390 | 2425 | ||
@@ -2456,8 +2491,31 @@ netxen_fwinit_work(struct work_struct *work) | |||
2456 | struct netxen_adapter *adapter = container_of(work, | 2491 | struct netxen_adapter *adapter = container_of(work, |
2457 | struct netxen_adapter, fw_work.work); | 2492 | struct netxen_adapter, fw_work.work); |
2458 | int dev_state; | 2493 | int dev_state; |
2459 | 2494 | int count; | |
2460 | dev_state = NXRD32(adapter, NX_CRB_DEV_STATE); | 2495 | dev_state = NXRD32(adapter, NX_CRB_DEV_STATE); |
2496 | if (adapter->flags & NETXEN_FW_RESET_OWNER) { | ||
2497 | count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); | ||
2498 | WARN_ON(count == 0); | ||
2499 | if (count == 1) { | ||
2500 | if (adapter->mdump.md_enabled) { | ||
2501 | rtnl_lock(); | ||
2502 | netxen_dump_fw(adapter); | ||
2503 | rtnl_unlock(); | ||
2504 | } | ||
2505 | adapter->flags &= ~NETXEN_FW_RESET_OWNER; | ||
2506 | if (netxen_api_lock(adapter)) { | ||
2507 | clear_bit(__NX_RESETTING, &adapter->state); | ||
2508 | NXWR32(adapter, NX_CRB_DEV_STATE, | ||
2509 | NX_DEV_FAILED); | ||
2510 | return; | ||
2511 | } | ||
2512 | count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); | ||
2513 | NXWR32(adapter, NX_CRB_DEV_REF_COUNT, --count); | ||
2514 | NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_COLD); | ||
2515 | dev_state = NX_DEV_COLD; | ||
2516 | netxen_api_unlock(adapter); | ||
2517 | } | ||
2518 | } | ||
2461 | 2519 | ||
2462 | switch (dev_state) { | 2520 | switch (dev_state) { |
2463 | case NX_DEV_COLD: | 2521 | case NX_DEV_COLD: |
@@ -2470,11 +2528,9 @@ netxen_fwinit_work(struct work_struct *work) | |||
2470 | 2528 | ||
2471 | case NX_DEV_NEED_RESET: | 2529 | case NX_DEV_NEED_RESET: |
2472 | case NX_DEV_INITALIZING: | 2530 | case NX_DEV_INITALIZING: |
2473 | if (++adapter->fw_wait_cnt < FW_POLL_THRESH) { | ||
2474 | netxen_schedule_work(adapter, | 2531 | netxen_schedule_work(adapter, |
2475 | netxen_fwinit_work, 2 * FW_POLL_DELAY); | 2532 | netxen_fwinit_work, 2 * FW_POLL_DELAY); |
2476 | return; | 2533 | return; |
2477 | } | ||
2478 | 2534 | ||
2479 | case NX_DEV_FAILED: | 2535 | case NX_DEV_FAILED: |
2480 | default: | 2536 | default: |
@@ -2482,6 +2538,15 @@ netxen_fwinit_work(struct work_struct *work) | |||
2482 | break; | 2538 | break; |
2483 | } | 2539 | } |
2484 | 2540 | ||
2541 | if (netxen_api_lock(adapter)) { | ||
2542 | clear_bit(__NX_RESETTING, &adapter->state); | ||
2543 | return; | ||
2544 | } | ||
2545 | NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_FAILED); | ||
2546 | netxen_api_unlock(adapter); | ||
2547 | dev_err(&adapter->pdev->dev, "%s: Device initialization Failed\n", | ||
2548 | adapter->netdev->name); | ||
2549 | |||
2485 | clear_bit(__NX_RESETTING, &adapter->state); | 2550 | clear_bit(__NX_RESETTING, &adapter->state); |
2486 | } | 2551 | } |
2487 | 2552 | ||
@@ -2491,7 +2556,7 @@ netxen_detach_work(struct work_struct *work) | |||
2491 | struct netxen_adapter *adapter = container_of(work, | 2556 | struct netxen_adapter *adapter = container_of(work, |
2492 | struct netxen_adapter, fw_work.work); | 2557 | struct netxen_adapter, fw_work.work); |
2493 | struct net_device *netdev = adapter->netdev; | 2558 | struct net_device *netdev = adapter->netdev; |
2494 | int ref_cnt, delay; | 2559 | int ref_cnt = 0, delay; |
2495 | u32 status; | 2560 | u32 status; |
2496 | 2561 | ||
2497 | netif_device_detach(netdev); | 2562 | netif_device_detach(netdev); |
@@ -2510,7 +2575,8 @@ netxen_detach_work(struct work_struct *work) | |||
2510 | if (adapter->temp == NX_TEMP_PANIC) | 2575 | if (adapter->temp == NX_TEMP_PANIC) |
2511 | goto err_ret; | 2576 | goto err_ret; |
2512 | 2577 | ||
2513 | ref_cnt = nx_decr_dev_ref_cnt(adapter); | 2578 | if (!(adapter->flags & NETXEN_FW_RESET_OWNER)) |
2579 | ref_cnt = nx_decr_dev_ref_cnt(adapter); | ||
2514 | 2580 | ||
2515 | if (ref_cnt == -EIO) | 2581 | if (ref_cnt == -EIO) |
2516 | goto err_ret; | 2582 | goto err_ret; |
@@ -2550,7 +2616,7 @@ netxen_check_health(struct netxen_adapter *adapter) | |||
2550 | * Send request to destroy context in case of tx timeout only | 2616 | * Send request to destroy context in case of tx timeout only |
2551 | * and doesn't required in case of Fw hang | 2617 | * and doesn't required in case of Fw hang |
2552 | */ | 2618 | */ |
2553 | if (state == NX_DEV_NEED_RESET) { | 2619 | if (state == NX_DEV_NEED_RESET || state == NX_DEV_FAILED) { |
2554 | adapter->need_fw_reset = 1; | 2620 | adapter->need_fw_reset = 1; |
2555 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | 2621 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) |
2556 | goto detach; | 2622 | goto detach; |