diff options
Diffstat (limited to 'drivers/scsi/ipr.c')
-rw-r--r-- | drivers/scsi/ipr.c | 322 |
1 files changed, 266 insertions, 56 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 2dde821025f3..ccd4dafce8e2 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -79,7 +79,6 @@ | |||
79 | #include <scsi/scsi_tcq.h> | 79 | #include <scsi/scsi_tcq.h> |
80 | #include <scsi/scsi_eh.h> | 80 | #include <scsi/scsi_eh.h> |
81 | #include <scsi/scsi_cmnd.h> | 81 | #include <scsi/scsi_cmnd.h> |
82 | #include <scsi/scsi_transport.h> | ||
83 | #include "ipr.h" | 82 | #include "ipr.h" |
84 | 83 | ||
85 | /* | 84 | /* |
@@ -98,7 +97,7 @@ static DEFINE_SPINLOCK(ipr_driver_lock); | |||
98 | 97 | ||
99 | /* This table describes the differences between DMA controller chips */ | 98 | /* This table describes the differences between DMA controller chips */ |
100 | static const struct ipr_chip_cfg_t ipr_chip_cfg[] = { | 99 | static const struct ipr_chip_cfg_t ipr_chip_cfg[] = { |
101 | { /* Gemstone, Citrine, and Obsidian */ | 100 | { /* Gemstone, Citrine, Obsidian, and Obsidian-E */ |
102 | .mailbox = 0x0042C, | 101 | .mailbox = 0x0042C, |
103 | .cache_line_size = 0x20, | 102 | .cache_line_size = 0x20, |
104 | { | 103 | { |
@@ -135,6 +134,7 @@ static const struct ipr_chip_t ipr_chip[] = { | |||
135 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, &ipr_chip_cfg[0] }, | 134 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, &ipr_chip_cfg[0] }, |
136 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, &ipr_chip_cfg[0] }, | 135 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, &ipr_chip_cfg[0] }, |
137 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, &ipr_chip_cfg[0] }, | 136 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, &ipr_chip_cfg[0] }, |
137 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, &ipr_chip_cfg[0] }, | ||
138 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, &ipr_chip_cfg[1] }, | 138 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, &ipr_chip_cfg[1] }, |
139 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, &ipr_chip_cfg[1] } | 139 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, &ipr_chip_cfg[1] } |
140 | }; | 140 | }; |
@@ -1249,19 +1249,23 @@ static void ipr_log_array_error(struct ipr_ioa_cfg *ioa_cfg, | |||
1249 | 1249 | ||
1250 | /** | 1250 | /** |
1251 | * ipr_log_hex_data - Log additional hex IOA error data. | 1251 | * ipr_log_hex_data - Log additional hex IOA error data. |
1252 | * @ioa_cfg: ioa config struct | ||
1252 | * @data: IOA error data | 1253 | * @data: IOA error data |
1253 | * @len: data length | 1254 | * @len: data length |
1254 | * | 1255 | * |
1255 | * Return value: | 1256 | * Return value: |
1256 | * none | 1257 | * none |
1257 | **/ | 1258 | **/ |
1258 | static void ipr_log_hex_data(u32 *data, int len) | 1259 | static void ipr_log_hex_data(struct ipr_ioa_cfg *ioa_cfg, u32 *data, int len) |
1259 | { | 1260 | { |
1260 | int i; | 1261 | int i; |
1261 | 1262 | ||
1262 | if (len == 0) | 1263 | if (len == 0) |
1263 | return; | 1264 | return; |
1264 | 1265 | ||
1266 | if (ioa_cfg->log_level <= IPR_DEFAULT_LOG_LEVEL) | ||
1267 | len = min_t(int, len, IPR_DEFAULT_MAX_ERROR_DUMP); | ||
1268 | |||
1265 | for (i = 0; i < len / 4; i += 4) { | 1269 | for (i = 0; i < len / 4; i += 4) { |
1266 | ipr_err("%08X: %08X %08X %08X %08X\n", i*4, | 1270 | ipr_err("%08X: %08X %08X %08X %08X\n", i*4, |
1267 | be32_to_cpu(data[i]), | 1271 | be32_to_cpu(data[i]), |
@@ -1290,7 +1294,7 @@ static void ipr_log_enhanced_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, | |||
1290 | ipr_err("%s\n", error->failure_reason); | 1294 | ipr_err("%s\n", error->failure_reason); |
1291 | ipr_err("Remote Adapter VPD:\n"); | 1295 | ipr_err("Remote Adapter VPD:\n"); |
1292 | ipr_log_ext_vpd(&error->vpd); | 1296 | ipr_log_ext_vpd(&error->vpd); |
1293 | ipr_log_hex_data(error->data, | 1297 | ipr_log_hex_data(ioa_cfg, error->data, |
1294 | be32_to_cpu(hostrcb->hcam.length) - | 1298 | be32_to_cpu(hostrcb->hcam.length) - |
1295 | (offsetof(struct ipr_hostrcb_error, u) + | 1299 | (offsetof(struct ipr_hostrcb_error, u) + |
1296 | offsetof(struct ipr_hostrcb_type_17_error, data))); | 1300 | offsetof(struct ipr_hostrcb_type_17_error, data))); |
@@ -1315,12 +1319,225 @@ static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, | |||
1315 | ipr_err("%s\n", error->failure_reason); | 1319 | ipr_err("%s\n", error->failure_reason); |
1316 | ipr_err("Remote Adapter VPD:\n"); | 1320 | ipr_err("Remote Adapter VPD:\n"); |
1317 | ipr_log_vpd(&error->vpd); | 1321 | ipr_log_vpd(&error->vpd); |
1318 | ipr_log_hex_data(error->data, | 1322 | ipr_log_hex_data(ioa_cfg, error->data, |
1319 | be32_to_cpu(hostrcb->hcam.length) - | 1323 | be32_to_cpu(hostrcb->hcam.length) - |
1320 | (offsetof(struct ipr_hostrcb_error, u) + | 1324 | (offsetof(struct ipr_hostrcb_error, u) + |
1321 | offsetof(struct ipr_hostrcb_type_07_error, data))); | 1325 | offsetof(struct ipr_hostrcb_type_07_error, data))); |
1322 | } | 1326 | } |
1323 | 1327 | ||
1328 | static const struct { | ||
1329 | u8 active; | ||
1330 | char *desc; | ||
1331 | } path_active_desc[] = { | ||
1332 | { IPR_PATH_NO_INFO, "Path" }, | ||
1333 | { IPR_PATH_ACTIVE, "Active path" }, | ||
1334 | { IPR_PATH_NOT_ACTIVE, "Inactive path" } | ||
1335 | }; | ||
1336 | |||
1337 | static const struct { | ||
1338 | u8 state; | ||
1339 | char *desc; | ||
1340 | } path_state_desc[] = { | ||
1341 | { IPR_PATH_STATE_NO_INFO, "has no path state information available" }, | ||
1342 | { IPR_PATH_HEALTHY, "is healthy" }, | ||
1343 | { IPR_PATH_DEGRADED, "is degraded" }, | ||
1344 | { IPR_PATH_FAILED, "is failed" } | ||
1345 | }; | ||
1346 | |||
1347 | /** | ||
1348 | * ipr_log_fabric_path - Log a fabric path error | ||
1349 | * @hostrcb: hostrcb struct | ||
1350 | * @fabric: fabric descriptor | ||
1351 | * | ||
1352 | * Return value: | ||
1353 | * none | ||
1354 | **/ | ||
1355 | static void ipr_log_fabric_path(struct ipr_hostrcb *hostrcb, | ||
1356 | struct ipr_hostrcb_fabric_desc *fabric) | ||
1357 | { | ||
1358 | int i, j; | ||
1359 | u8 path_state = fabric->path_state; | ||
1360 | u8 active = path_state & IPR_PATH_ACTIVE_MASK; | ||
1361 | u8 state = path_state & IPR_PATH_STATE_MASK; | ||
1362 | |||
1363 | for (i = 0; i < ARRAY_SIZE(path_active_desc); i++) { | ||
1364 | if (path_active_desc[i].active != active) | ||
1365 | continue; | ||
1366 | |||
1367 | for (j = 0; j < ARRAY_SIZE(path_state_desc); j++) { | ||
1368 | if (path_state_desc[j].state != state) | ||
1369 | continue; | ||
1370 | |||
1371 | if (fabric->cascaded_expander == 0xff && fabric->phy == 0xff) { | ||
1372 | ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d\n", | ||
1373 | path_active_desc[i].desc, path_state_desc[j].desc, | ||
1374 | fabric->ioa_port); | ||
1375 | } else if (fabric->cascaded_expander == 0xff) { | ||
1376 | ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Phy=%d\n", | ||
1377 | path_active_desc[i].desc, path_state_desc[j].desc, | ||
1378 | fabric->ioa_port, fabric->phy); | ||
1379 | } else if (fabric->phy == 0xff) { | ||
1380 | ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d\n", | ||
1381 | path_active_desc[i].desc, path_state_desc[j].desc, | ||
1382 | fabric->ioa_port, fabric->cascaded_expander); | ||
1383 | } else { | ||
1384 | ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d, Phy=%d\n", | ||
1385 | path_active_desc[i].desc, path_state_desc[j].desc, | ||
1386 | fabric->ioa_port, fabric->cascaded_expander, fabric->phy); | ||
1387 | } | ||
1388 | return; | ||
1389 | } | ||
1390 | } | ||
1391 | |||
1392 | ipr_err("Path state=%02X IOA Port=%d Cascade=%d Phy=%d\n", path_state, | ||
1393 | fabric->ioa_port, fabric->cascaded_expander, fabric->phy); | ||
1394 | } | ||
1395 | |||
1396 | static const struct { | ||
1397 | u8 type; | ||
1398 | char *desc; | ||
1399 | } path_type_desc[] = { | ||
1400 | { IPR_PATH_CFG_IOA_PORT, "IOA port" }, | ||
1401 | { IPR_PATH_CFG_EXP_PORT, "Expander port" }, | ||
1402 | { IPR_PATH_CFG_DEVICE_PORT, "Device port" }, | ||
1403 | { IPR_PATH_CFG_DEVICE_LUN, "Device LUN" } | ||
1404 | }; | ||
1405 | |||
1406 | static const struct { | ||
1407 | u8 status; | ||
1408 | char *desc; | ||
1409 | } path_status_desc[] = { | ||
1410 | { IPR_PATH_CFG_NO_PROB, "Functional" }, | ||
1411 | { IPR_PATH_CFG_DEGRADED, "Degraded" }, | ||
1412 | { IPR_PATH_CFG_FAILED, "Failed" }, | ||
1413 | { IPR_PATH_CFG_SUSPECT, "Suspect" }, | ||
1414 | { IPR_PATH_NOT_DETECTED, "Missing" }, | ||
1415 | { IPR_PATH_INCORRECT_CONN, "Incorrectly connected" } | ||
1416 | }; | ||
1417 | |||
1418 | static const char *link_rate[] = { | ||
1419 | "unknown", | ||
1420 | "disabled", | ||
1421 | "phy reset problem", | ||
1422 | "spinup hold", | ||
1423 | "port selector", | ||
1424 | "unknown", | ||
1425 | "unknown", | ||
1426 | "unknown", | ||
1427 | "1.5Gbps", | ||
1428 | "3.0Gbps", | ||
1429 | "unknown", | ||
1430 | "unknown", | ||
1431 | "unknown", | ||
1432 | "unknown", | ||
1433 | "unknown", | ||
1434 | "unknown" | ||
1435 | }; | ||
1436 | |||
1437 | /** | ||
1438 | * ipr_log_path_elem - Log a fabric path element. | ||
1439 | * @hostrcb: hostrcb struct | ||
1440 | * @cfg: fabric path element struct | ||
1441 | * | ||
1442 | * Return value: | ||
1443 | * none | ||
1444 | **/ | ||
1445 | static void ipr_log_path_elem(struct ipr_hostrcb *hostrcb, | ||
1446 | struct ipr_hostrcb_config_element *cfg) | ||
1447 | { | ||
1448 | int i, j; | ||
1449 | u8 type = cfg->type_status & IPR_PATH_CFG_TYPE_MASK; | ||
1450 | u8 status = cfg->type_status & IPR_PATH_CFG_STATUS_MASK; | ||
1451 | |||
1452 | if (type == IPR_PATH_CFG_NOT_EXIST) | ||
1453 | return; | ||
1454 | |||
1455 | for (i = 0; i < ARRAY_SIZE(path_type_desc); i++) { | ||
1456 | if (path_type_desc[i].type != type) | ||
1457 | continue; | ||
1458 | |||
1459 | for (j = 0; j < ARRAY_SIZE(path_status_desc); j++) { | ||
1460 | if (path_status_desc[j].status != status) | ||
1461 | continue; | ||
1462 | |||
1463 | if (type == IPR_PATH_CFG_IOA_PORT) { | ||
1464 | ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, WWN=%08X%08X\n", | ||
1465 | path_status_desc[j].desc, path_type_desc[i].desc, | ||
1466 | cfg->phy, link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], | ||
1467 | be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); | ||
1468 | } else { | ||
1469 | if (cfg->cascaded_expander == 0xff && cfg->phy == 0xff) { | ||
1470 | ipr_hcam_err(hostrcb, "%s %s: Link rate=%s, WWN=%08X%08X\n", | ||
1471 | path_status_desc[j].desc, path_type_desc[i].desc, | ||
1472 | link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], | ||
1473 | be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); | ||
1474 | } else if (cfg->cascaded_expander == 0xff) { | ||
1475 | ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, " | ||
1476 | "WWN=%08X%08X\n", path_status_desc[j].desc, | ||
1477 | path_type_desc[i].desc, cfg->phy, | ||
1478 | link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], | ||
1479 | be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); | ||
1480 | } else if (cfg->phy == 0xff) { | ||
1481 | ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Link rate=%s, " | ||
1482 | "WWN=%08X%08X\n", path_status_desc[j].desc, | ||
1483 | path_type_desc[i].desc, cfg->cascaded_expander, | ||
1484 | link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], | ||
1485 | be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); | ||
1486 | } else { | ||
1487 | ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Phy=%d, Link rate=%s " | ||
1488 | "WWN=%08X%08X\n", path_status_desc[j].desc, | ||
1489 | path_type_desc[i].desc, cfg->cascaded_expander, cfg->phy, | ||
1490 | link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], | ||
1491 | be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); | ||
1492 | } | ||
1493 | } | ||
1494 | return; | ||
1495 | } | ||
1496 | } | ||
1497 | |||
1498 | ipr_hcam_err(hostrcb, "Path element=%02X: Cascade=%d Phy=%d Link rate=%s " | ||
1499 | "WWN=%08X%08X\n", cfg->type_status, cfg->cascaded_expander, cfg->phy, | ||
1500 | link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], | ||
1501 | be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); | ||
1502 | } | ||
1503 | |||
1504 | /** | ||
1505 | * ipr_log_fabric_error - Log a fabric error. | ||
1506 | * @ioa_cfg: ioa config struct | ||
1507 | * @hostrcb: hostrcb struct | ||
1508 | * | ||
1509 | * Return value: | ||
1510 | * none | ||
1511 | **/ | ||
1512 | static void ipr_log_fabric_error(struct ipr_ioa_cfg *ioa_cfg, | ||
1513 | struct ipr_hostrcb *hostrcb) | ||
1514 | { | ||
1515 | struct ipr_hostrcb_type_20_error *error; | ||
1516 | struct ipr_hostrcb_fabric_desc *fabric; | ||
1517 | struct ipr_hostrcb_config_element *cfg; | ||
1518 | int i, add_len; | ||
1519 | |||
1520 | error = &hostrcb->hcam.u.error.u.type_20_error; | ||
1521 | error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; | ||
1522 | ipr_hcam_err(hostrcb, "%s\n", error->failure_reason); | ||
1523 | |||
1524 | add_len = be32_to_cpu(hostrcb->hcam.length) - | ||
1525 | (offsetof(struct ipr_hostrcb_error, u) + | ||
1526 | offsetof(struct ipr_hostrcb_type_20_error, desc)); | ||
1527 | |||
1528 | for (i = 0, fabric = error->desc; i < error->num_entries; i++) { | ||
1529 | ipr_log_fabric_path(hostrcb, fabric); | ||
1530 | for_each_fabric_cfg(fabric, cfg) | ||
1531 | ipr_log_path_elem(hostrcb, cfg); | ||
1532 | |||
1533 | add_len -= be16_to_cpu(fabric->length); | ||
1534 | fabric = (struct ipr_hostrcb_fabric_desc *) | ||
1535 | ((unsigned long)fabric + be16_to_cpu(fabric->length)); | ||
1536 | } | ||
1537 | |||
1538 | ipr_log_hex_data(ioa_cfg, (u32 *)fabric, add_len); | ||
1539 | } | ||
1540 | |||
1324 | /** | 1541 | /** |
1325 | * ipr_log_generic_error - Log an adapter error. | 1542 | * ipr_log_generic_error - Log an adapter error. |
1326 | * @ioa_cfg: ioa config struct | 1543 | * @ioa_cfg: ioa config struct |
@@ -1332,7 +1549,7 @@ static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, | |||
1332 | static void ipr_log_generic_error(struct ipr_ioa_cfg *ioa_cfg, | 1549 | static void ipr_log_generic_error(struct ipr_ioa_cfg *ioa_cfg, |
1333 | struct ipr_hostrcb *hostrcb) | 1550 | struct ipr_hostrcb *hostrcb) |
1334 | { | 1551 | { |
1335 | ipr_log_hex_data(hostrcb->hcam.u.raw.data, | 1552 | ipr_log_hex_data(ioa_cfg, hostrcb->hcam.u.raw.data, |
1336 | be32_to_cpu(hostrcb->hcam.length)); | 1553 | be32_to_cpu(hostrcb->hcam.length)); |
1337 | } | 1554 | } |
1338 | 1555 | ||
@@ -1394,13 +1611,7 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, | |||
1394 | if (!ipr_error_table[error_index].log_hcam) | 1611 | if (!ipr_error_table[error_index].log_hcam) |
1395 | return; | 1612 | return; |
1396 | 1613 | ||
1397 | if (ipr_is_device(&hostrcb->hcam.u.error.failing_dev_res_addr)) { | 1614 | ipr_hcam_err(hostrcb, "%s\n", ipr_error_table[error_index].error); |
1398 | ipr_ra_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr, | ||
1399 | "%s\n", ipr_error_table[error_index].error); | ||
1400 | } else { | ||
1401 | dev_err(&ioa_cfg->pdev->dev, "%s\n", | ||
1402 | ipr_error_table[error_index].error); | ||
1403 | } | ||
1404 | 1615 | ||
1405 | /* Set indication we have logged an error */ | 1616 | /* Set indication we have logged an error */ |
1406 | ioa_cfg->errors_logged++; | 1617 | ioa_cfg->errors_logged++; |
@@ -1437,6 +1648,9 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, | |||
1437 | case IPR_HOST_RCB_OVERLAY_ID_17: | 1648 | case IPR_HOST_RCB_OVERLAY_ID_17: |
1438 | ipr_log_enhanced_dual_ioa_error(ioa_cfg, hostrcb); | 1649 | ipr_log_enhanced_dual_ioa_error(ioa_cfg, hostrcb); |
1439 | break; | 1650 | break; |
1651 | case IPR_HOST_RCB_OVERLAY_ID_20: | ||
1652 | ipr_log_fabric_error(ioa_cfg, hostrcb); | ||
1653 | break; | ||
1440 | case IPR_HOST_RCB_OVERLAY_ID_1: | 1654 | case IPR_HOST_RCB_OVERLAY_ID_1: |
1441 | case IPR_HOST_RCB_OVERLAY_ID_DEFAULT: | 1655 | case IPR_HOST_RCB_OVERLAY_ID_DEFAULT: |
1442 | default: | 1656 | default: |
@@ -2093,7 +2307,7 @@ static void ipr_release_dump(struct kref *kref) | |||
2093 | 2307 | ||
2094 | /** | 2308 | /** |
2095 | * ipr_worker_thread - Worker thread | 2309 | * ipr_worker_thread - Worker thread |
2096 | * @data: ioa config struct | 2310 | * @work: ioa config struct |
2097 | * | 2311 | * |
2098 | * Called at task level from a work thread. This function takes care | 2312 | * Called at task level from a work thread. This function takes care |
2099 | * of adding and removing device from the mid-layer as configuration | 2313 | * of adding and removing device from the mid-layer as configuration |
@@ -2102,13 +2316,14 @@ static void ipr_release_dump(struct kref *kref) | |||
2102 | * Return value: | 2316 | * Return value: |
2103 | * nothing | 2317 | * nothing |
2104 | **/ | 2318 | **/ |
2105 | static void ipr_worker_thread(void *data) | 2319 | static void ipr_worker_thread(struct work_struct *work) |
2106 | { | 2320 | { |
2107 | unsigned long lock_flags; | 2321 | unsigned long lock_flags; |
2108 | struct ipr_resource_entry *res; | 2322 | struct ipr_resource_entry *res; |
2109 | struct scsi_device *sdev; | 2323 | struct scsi_device *sdev; |
2110 | struct ipr_dump *dump; | 2324 | struct ipr_dump *dump; |
2111 | struct ipr_ioa_cfg *ioa_cfg = data; | 2325 | struct ipr_ioa_cfg *ioa_cfg = |
2326 | container_of(work, struct ipr_ioa_cfg, work_q); | ||
2112 | u8 bus, target, lun; | 2327 | u8 bus, target, lun; |
2113 | int did_work; | 2328 | int did_work; |
2114 | 2329 | ||
@@ -2969,7 +3184,6 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg) | |||
2969 | struct ipr_dump *dump; | 3184 | struct ipr_dump *dump; |
2970 | unsigned long lock_flags = 0; | 3185 | unsigned long lock_flags = 0; |
2971 | 3186 | ||
2972 | ENTER; | ||
2973 | dump = kzalloc(sizeof(struct ipr_dump), GFP_KERNEL); | 3187 | dump = kzalloc(sizeof(struct ipr_dump), GFP_KERNEL); |
2974 | 3188 | ||
2975 | if (!dump) { | 3189 | if (!dump) { |
@@ -2996,7 +3210,6 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg) | |||
2996 | } | 3210 | } |
2997 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | 3211 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); |
2998 | 3212 | ||
2999 | LEAVE; | ||
3000 | return 0; | 3213 | return 0; |
3001 | } | 3214 | } |
3002 | 3215 | ||
@@ -3573,6 +3786,12 @@ static int ipr_sata_reset(struct ata_port *ap, unsigned int *classes) | |||
3573 | 3786 | ||
3574 | ENTER; | 3787 | ENTER; |
3575 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | 3788 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); |
3789 | while(ioa_cfg->in_reset_reload) { | ||
3790 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
3791 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); | ||
3792 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | ||
3793 | } | ||
3794 | |||
3576 | res = sata_port->res; | 3795 | res = sata_port->res; |
3577 | if (res) { | 3796 | if (res) { |
3578 | rc = ipr_device_reset(ioa_cfg, res); | 3797 | rc = ipr_device_reset(ioa_cfg, res); |
@@ -3636,6 +3855,10 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd) | |||
3636 | if (ipr_cmd->ioarcb.res_handle == res->cfgte.res_handle) { | 3855 | if (ipr_cmd->ioarcb.res_handle == res->cfgte.res_handle) { |
3637 | if (ipr_cmd->scsi_cmd) | 3856 | if (ipr_cmd->scsi_cmd) |
3638 | ipr_cmd->done = ipr_scsi_eh_done; | 3857 | ipr_cmd->done = ipr_scsi_eh_done; |
3858 | if (ipr_cmd->qc && !(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) { | ||
3859 | ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT; | ||
3860 | ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED; | ||
3861 | } | ||
3639 | } | 3862 | } |
3640 | } | 3863 | } |
3641 | 3864 | ||
@@ -3770,7 +3993,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd) | |||
3770 | */ | 3993 | */ |
3771 | if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead) | 3994 | if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead) |
3772 | return FAILED; | 3995 | return FAILED; |
3773 | if (!res || (!ipr_is_gscsi(res) && !ipr_is_vset_device(res))) | 3996 | if (!res || !ipr_is_gscsi(res)) |
3774 | return FAILED; | 3997 | return FAILED; |
3775 | 3998 | ||
3776 | list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { | 3999 | list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { |
@@ -4615,7 +4838,7 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd, | |||
4615 | * Return value: | 4838 | * Return value: |
4616 | * 0 on success / other on failure | 4839 | * 0 on success / other on failure |
4617 | **/ | 4840 | **/ |
4618 | int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) | 4841 | static int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) |
4619 | { | 4842 | { |
4620 | struct ipr_resource_entry *res; | 4843 | struct ipr_resource_entry *res; |
4621 | 4844 | ||
@@ -4648,40 +4871,6 @@ static const char * ipr_ioa_info(struct Scsi_Host *host) | |||
4648 | return buffer; | 4871 | return buffer; |
4649 | } | 4872 | } |
4650 | 4873 | ||
4651 | /** | ||
4652 | * ipr_scsi_timed_out - Handle scsi command timeout | ||
4653 | * @scsi_cmd: scsi command struct | ||
4654 | * | ||
4655 | * Return value: | ||
4656 | * EH_NOT_HANDLED | ||
4657 | **/ | ||
4658 | enum scsi_eh_timer_return ipr_scsi_timed_out(struct scsi_cmnd *scsi_cmd) | ||
4659 | { | ||
4660 | struct ipr_ioa_cfg *ioa_cfg; | ||
4661 | struct ipr_cmnd *ipr_cmd; | ||
4662 | unsigned long flags; | ||
4663 | |||
4664 | ENTER; | ||
4665 | spin_lock_irqsave(scsi_cmd->device->host->host_lock, flags); | ||
4666 | ioa_cfg = (struct ipr_ioa_cfg *)scsi_cmd->device->host->hostdata; | ||
4667 | |||
4668 | list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { | ||
4669 | if (ipr_cmd->qc && ipr_cmd->qc->scsicmd == scsi_cmd) { | ||
4670 | ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT; | ||
4671 | ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED; | ||
4672 | break; | ||
4673 | } | ||
4674 | } | ||
4675 | |||
4676 | spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, flags); | ||
4677 | LEAVE; | ||
4678 | return EH_NOT_HANDLED; | ||
4679 | } | ||
4680 | |||
4681 | static struct scsi_transport_template ipr_transport_template = { | ||
4682 | .eh_timed_out = ipr_scsi_timed_out | ||
4683 | }; | ||
4684 | |||
4685 | static struct scsi_host_template driver_template = { | 4874 | static struct scsi_host_template driver_template = { |
4686 | .module = THIS_MODULE, | 4875 | .module = THIS_MODULE, |
4687 | .name = "IPR", | 4876 | .name = "IPR", |
@@ -4776,6 +4965,12 @@ static void ipr_ata_post_internal(struct ata_queued_cmd *qc) | |||
4776 | unsigned long flags; | 4965 | unsigned long flags; |
4777 | 4966 | ||
4778 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); | 4967 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); |
4968 | while(ioa_cfg->in_reset_reload) { | ||
4969 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); | ||
4970 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); | ||
4971 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); | ||
4972 | } | ||
4973 | |||
4779 | list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { | 4974 | list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { |
4780 | if (ipr_cmd->qc == qc) { | 4975 | if (ipr_cmd->qc == qc) { |
4781 | ipr_device_reset(ioa_cfg, sata_port->res); | 4976 | ipr_device_reset(ioa_cfg, sata_port->res); |
@@ -6832,6 +7027,7 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg) | |||
6832 | 7027 | ||
6833 | ioa_cfg->hostrcb[i]->hostrcb_dma = | 7028 | ioa_cfg->hostrcb[i]->hostrcb_dma = |
6834 | ioa_cfg->hostrcb_dma[i] + offsetof(struct ipr_hostrcb, hcam); | 7029 | ioa_cfg->hostrcb_dma[i] + offsetof(struct ipr_hostrcb, hcam); |
7030 | ioa_cfg->hostrcb[i]->ioa_cfg = ioa_cfg; | ||
6835 | list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q); | 7031 | list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q); |
6836 | } | 7032 | } |
6837 | 7033 | ||
@@ -6926,7 +7122,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, | |||
6926 | INIT_LIST_HEAD(&ioa_cfg->hostrcb_pending_q); | 7122 | INIT_LIST_HEAD(&ioa_cfg->hostrcb_pending_q); |
6927 | INIT_LIST_HEAD(&ioa_cfg->free_res_q); | 7123 | INIT_LIST_HEAD(&ioa_cfg->free_res_q); |
6928 | INIT_LIST_HEAD(&ioa_cfg->used_res_q); | 7124 | INIT_LIST_HEAD(&ioa_cfg->used_res_q); |
6929 | INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread, ioa_cfg); | 7125 | INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread); |
6930 | init_waitqueue_head(&ioa_cfg->reset_wait_q); | 7126 | init_waitqueue_head(&ioa_cfg->reset_wait_q); |
6931 | ioa_cfg->sdt_state = INACTIVE; | 7127 | ioa_cfg->sdt_state = INACTIVE; |
6932 | if (ipr_enable_cache) | 7128 | if (ipr_enable_cache) |
@@ -7017,7 +7213,6 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, | |||
7017 | 7213 | ||
7018 | ioa_cfg = (struct ipr_ioa_cfg *)host->hostdata; | 7214 | ioa_cfg = (struct ipr_ioa_cfg *)host->hostdata; |
7019 | memset(ioa_cfg, 0, sizeof(struct ipr_ioa_cfg)); | 7215 | memset(ioa_cfg, 0, sizeof(struct ipr_ioa_cfg)); |
7020 | host->transportt = &ipr_transport_template; | ||
7021 | ata_host_init(&ioa_cfg->ata_host, &pdev->dev, | 7216 | ata_host_init(&ioa_cfg->ata_host, &pdev->dev, |
7022 | sata_port_info.flags, &ipr_sata_ops); | 7217 | sata_port_info.flags, &ipr_sata_ops); |
7023 | 7218 | ||
@@ -7351,12 +7546,24 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { | |||
7351 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, | 7546 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, |
7352 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, | 7547 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, |
7353 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | 7548 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, |
7549 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, | ||
7550 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, | ||
7551 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | ||
7354 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, | 7552 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, |
7355 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, | 7553 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, |
7356 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | 7554 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, |
7357 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, | 7555 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, |
7358 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, | 7556 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, |
7359 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | 7557 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, |
7558 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, | ||
7559 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, | ||
7560 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | ||
7561 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, | ||
7562 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B8, | ||
7563 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | ||
7564 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, | ||
7565 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, | ||
7566 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | ||
7360 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, | 7567 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, |
7361 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, | 7568 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, |
7362 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, | 7569 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, |
@@ -7366,6 +7573,9 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { | |||
7366 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, | 7573 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, |
7367 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, | 7574 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, |
7368 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, | 7575 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, |
7576 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, | ||
7577 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, | ||
7578 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, | ||
7369 | { } | 7579 | { } |
7370 | }; | 7580 | }; |
7371 | MODULE_DEVICE_TABLE(pci, ipr_pci_table); | 7581 | MODULE_DEVICE_TABLE(pci, ipr_pci_table); |