diff options
author | Christof Schmitt <christof.schmitt@de.ibm.com> | 2008-06-10 12:20:54 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-12 09:22:25 -0400 |
commit | 24073b475d6d2bad8880434a16343ee1da816ea5 (patch) | |
tree | 27cf64817f5aa9020692b88366a46743b11db6d3 /drivers/s390/scsi/zfcp_aux.c | |
parent | 6362abd3e00d3161affad996fa53cc69a01fc6d1 (diff) |
[SCSI] zfcp: Move FC code to new file
Move all Fibre Channel related code to new file and cleanup the code
while doing so.
Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: Swen Schillig <swen@vnet.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/s390/scsi/zfcp_aux.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 518 |
1 files changed, 0 insertions, 518 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 9a3c138ec50c..9eb8827e19e2 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -43,9 +43,6 @@ static char *device; | |||
43 | /* written against the module interface */ | 43 | /* written against the module interface */ |
44 | static int __init zfcp_module_init(void); | 44 | static int __init zfcp_module_init(void); |
45 | 45 | ||
46 | /* FCP related */ | ||
47 | static void zfcp_ns_gid_pn_handler(unsigned long); | ||
48 | |||
49 | /* miscellaneous */ | 46 | /* miscellaneous */ |
50 | static int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t); | 47 | static int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t); |
51 | static void zfcp_sg_list_free(struct zfcp_sg_list *); | 48 | static void zfcp_sg_list_free(struct zfcp_sg_list *); |
@@ -1349,518 +1346,3 @@ zfcp_nameserver_enqueue(struct zfcp_adapter *adapter) | |||
1349 | } | 1346 | } |
1350 | 1347 | ||
1351 | #undef ZFCP_LOG_AREA | 1348 | #undef ZFCP_LOG_AREA |
1352 | |||
1353 | /****************************************************************/ | ||
1354 | /******* Fibre Channel Standard related Functions **************/ | ||
1355 | /****************************************************************/ | ||
1356 | |||
1357 | #define ZFCP_LOG_AREA ZFCP_LOG_AREA_FC | ||
1358 | |||
1359 | static void zfcp_fsf_incoming_els_rscn(struct zfcp_fsf_req *fsf_req) | ||
1360 | { | ||
1361 | struct fsf_status_read_buffer *status_buffer = (void*)fsf_req->data; | ||
1362 | struct zfcp_adapter *adapter = fsf_req->adapter; | ||
1363 | struct fcp_rscn_head *fcp_rscn_head; | ||
1364 | struct fcp_rscn_element *fcp_rscn_element; | ||
1365 | struct zfcp_port *port; | ||
1366 | u16 i; | ||
1367 | u16 no_entries; | ||
1368 | u32 range_mask; | ||
1369 | unsigned long flags; | ||
1370 | |||
1371 | fcp_rscn_head = (struct fcp_rscn_head *) status_buffer->payload; | ||
1372 | fcp_rscn_element = (struct fcp_rscn_element *) status_buffer->payload; | ||
1373 | |||
1374 | /* see FC-FS */ | ||
1375 | no_entries = (fcp_rscn_head->payload_len / 4); | ||
1376 | |||
1377 | for (i = 1; i < no_entries; i++) { | ||
1378 | /* skip head and start with 1st element */ | ||
1379 | fcp_rscn_element++; | ||
1380 | switch (fcp_rscn_element->addr_format) { | ||
1381 | case ZFCP_PORT_ADDRESS: | ||
1382 | range_mask = ZFCP_PORTS_RANGE_PORT; | ||
1383 | break; | ||
1384 | case ZFCP_AREA_ADDRESS: | ||
1385 | range_mask = ZFCP_PORTS_RANGE_AREA; | ||
1386 | break; | ||
1387 | case ZFCP_DOMAIN_ADDRESS: | ||
1388 | range_mask = ZFCP_PORTS_RANGE_DOMAIN; | ||
1389 | break; | ||
1390 | case ZFCP_FABRIC_ADDRESS: | ||
1391 | range_mask = ZFCP_PORTS_RANGE_FABRIC; | ||
1392 | break; | ||
1393 | default: | ||
1394 | ZFCP_LOG_INFO("incoming RSCN with unknown " | ||
1395 | "address format\n"); | ||
1396 | continue; | ||
1397 | } | ||
1398 | read_lock_irqsave(&zfcp_data.config_lock, flags); | ||
1399 | list_for_each_entry(port, &adapter->port_list_head, list) { | ||
1400 | if (atomic_test_mask | ||
1401 | (ZFCP_STATUS_PORT_WKA, &port->status)) | ||
1402 | continue; | ||
1403 | /* Do we know this port? If not skip it. */ | ||
1404 | if (!atomic_test_mask | ||
1405 | (ZFCP_STATUS_PORT_DID_DID, &port->status)) { | ||
1406 | ZFCP_LOG_INFO("incoming RSCN, trying to open " | ||
1407 | "port 0x%016Lx\n", port->wwpn); | ||
1408 | zfcp_erp_port_reopen(port, | ||
1409 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
1410 | 82, fsf_req); | ||
1411 | continue; | ||
1412 | } | ||
1413 | |||
1414 | /* | ||
1415 | * FIXME: race: d_id might being invalidated | ||
1416 | * (...DID_DID reset) | ||
1417 | */ | ||
1418 | if ((port->d_id & range_mask) | ||
1419 | == (fcp_rscn_element->nport_did & range_mask)) { | ||
1420 | ZFCP_LOG_TRACE("reopen did 0x%08x\n", | ||
1421 | fcp_rscn_element->nport_did); | ||
1422 | /* | ||
1423 | * Unfortunately, an RSCN does not specify the | ||
1424 | * type of change a target underwent. We assume | ||
1425 | * that it makes sense to reopen the link. | ||
1426 | * FIXME: Shall we try to find out more about | ||
1427 | * the target and link state before closing it? | ||
1428 | * How to accomplish this? (nameserver?) | ||
1429 | * Where would such code be put in? | ||
1430 | * (inside or outside erp) | ||
1431 | */ | ||
1432 | ZFCP_LOG_INFO("incoming RSCN, trying to open " | ||
1433 | "port 0x%016Lx\n", port->wwpn); | ||
1434 | zfcp_test_link(port); | ||
1435 | } | ||
1436 | } | ||
1437 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
1438 | } | ||
1439 | } | ||
1440 | |||
1441 | static void zfcp_fsf_incoming_els_plogi(struct zfcp_fsf_req *fsf_req) | ||
1442 | { | ||
1443 | struct fsf_status_read_buffer *status_buffer = (void*)fsf_req->data; | ||
1444 | struct zfcp_adapter *adapter = fsf_req->adapter; | ||
1445 | struct fsf_plogi *els_plogi; | ||
1446 | struct zfcp_port *port; | ||
1447 | unsigned long flags; | ||
1448 | |||
1449 | els_plogi = (struct fsf_plogi *) status_buffer->payload; | ||
1450 | read_lock_irqsave(&zfcp_data.config_lock, flags); | ||
1451 | list_for_each_entry(port, &adapter->port_list_head, list) { | ||
1452 | if (port->wwpn == (*(wwn_t *) &els_plogi->serv_param.wwpn)) | ||
1453 | break; | ||
1454 | } | ||
1455 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
1456 | |||
1457 | if (!port || (port->wwpn != (*(wwn_t *) &els_plogi->serv_param.wwpn))) { | ||
1458 | ZFCP_LOG_DEBUG("ignored incoming PLOGI for nonexisting port " | ||
1459 | "with d_id 0x%06x on adapter %s\n", | ||
1460 | status_buffer->d_id, | ||
1461 | zfcp_get_busid_by_adapter(adapter)); | ||
1462 | } else { | ||
1463 | zfcp_erp_port_forced_reopen(port, 0, 83, fsf_req); | ||
1464 | } | ||
1465 | } | ||
1466 | |||
1467 | static void zfcp_fsf_incoming_els_logo(struct zfcp_fsf_req *fsf_req) | ||
1468 | { | ||
1469 | struct fsf_status_read_buffer *status_buffer = (void*)fsf_req->data; | ||
1470 | struct zfcp_adapter *adapter = fsf_req->adapter; | ||
1471 | struct fcp_logo *els_logo = (struct fcp_logo *) status_buffer->payload; | ||
1472 | struct zfcp_port *port; | ||
1473 | unsigned long flags; | ||
1474 | |||
1475 | read_lock_irqsave(&zfcp_data.config_lock, flags); | ||
1476 | list_for_each_entry(port, &adapter->port_list_head, list) { | ||
1477 | if (port->wwpn == els_logo->nport_wwpn) | ||
1478 | break; | ||
1479 | } | ||
1480 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
1481 | |||
1482 | if (!port || (port->wwpn != els_logo->nport_wwpn)) { | ||
1483 | ZFCP_LOG_DEBUG("ignored incoming LOGO for nonexisting port " | ||
1484 | "with d_id 0x%06x on adapter %s\n", | ||
1485 | status_buffer->d_id, | ||
1486 | zfcp_get_busid_by_adapter(adapter)); | ||
1487 | } else { | ||
1488 | zfcp_erp_port_forced_reopen(port, 0, 84, fsf_req); | ||
1489 | } | ||
1490 | } | ||
1491 | |||
1492 | static void | ||
1493 | zfcp_fsf_incoming_els_unknown(struct zfcp_adapter *adapter, | ||
1494 | struct fsf_status_read_buffer *status_buffer) | ||
1495 | { | ||
1496 | ZFCP_LOG_NORMAL("warning: unknown incoming ELS 0x%08x " | ||
1497 | "for adapter %s\n", *(u32 *) (status_buffer->payload), | ||
1498 | zfcp_get_busid_by_adapter(adapter)); | ||
1499 | |||
1500 | } | ||
1501 | |||
1502 | void | ||
1503 | zfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req) | ||
1504 | { | ||
1505 | struct fsf_status_read_buffer *status_buffer; | ||
1506 | u32 els_type; | ||
1507 | struct zfcp_adapter *adapter; | ||
1508 | |||
1509 | status_buffer = (struct fsf_status_read_buffer *) fsf_req->data; | ||
1510 | els_type = *(u32 *) (status_buffer->payload); | ||
1511 | adapter = fsf_req->adapter; | ||
1512 | |||
1513 | zfcp_san_dbf_event_incoming_els(fsf_req); | ||
1514 | if (els_type == LS_PLOGI) | ||
1515 | zfcp_fsf_incoming_els_plogi(fsf_req); | ||
1516 | else if (els_type == LS_LOGO) | ||
1517 | zfcp_fsf_incoming_els_logo(fsf_req); | ||
1518 | else if ((els_type & 0xffff0000) == LS_RSCN) | ||
1519 | /* we are only concerned with the command, not the length */ | ||
1520 | zfcp_fsf_incoming_els_rscn(fsf_req); | ||
1521 | else | ||
1522 | zfcp_fsf_incoming_els_unknown(adapter, status_buffer); | ||
1523 | } | ||
1524 | |||
1525 | |||
1526 | /** | ||
1527 | * zfcp_gid_pn_buffers_alloc - allocate buffers for GID_PN nameserver request | ||
1528 | * @gid_pn: pointer to return pointer to struct zfcp_gid_pn_data | ||
1529 | * @pool: pointer to mempool_t if non-null memory pool is used for allocation | ||
1530 | */ | ||
1531 | static int | ||
1532 | zfcp_gid_pn_buffers_alloc(struct zfcp_gid_pn_data **gid_pn, mempool_t *pool) | ||
1533 | { | ||
1534 | struct zfcp_gid_pn_data *data; | ||
1535 | |||
1536 | if (pool) | ||
1537 | data = mempool_alloc(pool, GFP_ATOMIC); | ||
1538 | else | ||
1539 | data = kmem_cache_alloc(zfcp_data.gid_pn_cache, GFP_ATOMIC); | ||
1540 | |||
1541 | if (NULL == data) | ||
1542 | return -ENOMEM; | ||
1543 | |||
1544 | memset(data, 0, sizeof(*data)); | ||
1545 | data->ct.pool = pool; | ||
1546 | sg_init_table(&data->req , 1); | ||
1547 | sg_init_table(&data->resp , 1); | ||
1548 | data->ct.req = &data->req; | ||
1549 | data->ct.resp = &data->resp; | ||
1550 | data->ct.req_count = data->ct.resp_count = 1; | ||
1551 | zfcp_address_to_sg(&data->ct_iu_req, &data->req, sizeof(struct ct_iu_gid_pn_req)); | ||
1552 | zfcp_address_to_sg(&data->ct_iu_resp, &data->resp, sizeof(struct ct_iu_gid_pn_resp)); | ||
1553 | |||
1554 | *gid_pn = data; | ||
1555 | return 0; | ||
1556 | } | ||
1557 | |||
1558 | /** | ||
1559 | * zfcp_gid_pn_buffers_free - free buffers for GID_PN nameserver request | ||
1560 | * @gid_pn: pointer to struct zfcp_gid_pn_data which has to be freed | ||
1561 | */ | ||
1562 | static void zfcp_gid_pn_buffers_free(struct zfcp_gid_pn_data *gid_pn) | ||
1563 | { | ||
1564 | if (gid_pn->ct.pool) | ||
1565 | mempool_free(gid_pn, gid_pn->ct.pool); | ||
1566 | else | ||
1567 | kmem_cache_free(zfcp_data.gid_pn_cache, gid_pn); | ||
1568 | } | ||
1569 | |||
1570 | /** | ||
1571 | * zfcp_ns_gid_pn_request - initiate GID_PN nameserver request | ||
1572 | * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed | ||
1573 | */ | ||
1574 | int | ||
1575 | zfcp_ns_gid_pn_request(struct zfcp_erp_action *erp_action) | ||
1576 | { | ||
1577 | int ret; | ||
1578 | struct ct_iu_gid_pn_req *ct_iu_req; | ||
1579 | struct zfcp_gid_pn_data *gid_pn; | ||
1580 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
1581 | |||
1582 | ret = zfcp_gid_pn_buffers_alloc(&gid_pn, adapter->pool.data_gid_pn); | ||
1583 | if (ret < 0) { | ||
1584 | ZFCP_LOG_INFO("error: buffer allocation for gid_pn nameserver " | ||
1585 | "request failed for adapter %s\n", | ||
1586 | zfcp_get_busid_by_adapter(adapter)); | ||
1587 | goto out; | ||
1588 | } | ||
1589 | |||
1590 | /* setup nameserver request */ | ||
1591 | ct_iu_req = zfcp_sg_to_address(gid_pn->ct.req); | ||
1592 | ct_iu_req->header.revision = ZFCP_CT_REVISION; | ||
1593 | ct_iu_req->header.gs_type = ZFCP_CT_DIRECTORY_SERVICE; | ||
1594 | ct_iu_req->header.gs_subtype = ZFCP_CT_NAME_SERVER; | ||
1595 | ct_iu_req->header.options = ZFCP_CT_SYNCHRONOUS; | ||
1596 | ct_iu_req->header.cmd_rsp_code = ZFCP_CT_GID_PN; | ||
1597 | ct_iu_req->header.max_res_size = ZFCP_CT_MAX_SIZE; | ||
1598 | ct_iu_req->wwpn = erp_action->port->wwpn; | ||
1599 | |||
1600 | /* setup parameters for send generic command */ | ||
1601 | gid_pn->ct.port = adapter->nameserver_port; | ||
1602 | gid_pn->ct.handler = zfcp_ns_gid_pn_handler; | ||
1603 | gid_pn->ct.handler_data = (unsigned long) gid_pn; | ||
1604 | gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT; | ||
1605 | gid_pn->port = erp_action->port; | ||
1606 | |||
1607 | ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp, | ||
1608 | erp_action); | ||
1609 | if (ret) { | ||
1610 | ZFCP_LOG_INFO("error: initiation of gid_pn nameserver request " | ||
1611 | "failed for adapter %s\n", | ||
1612 | zfcp_get_busid_by_adapter(adapter)); | ||
1613 | |||
1614 | zfcp_gid_pn_buffers_free(gid_pn); | ||
1615 | } | ||
1616 | |||
1617 | out: | ||
1618 | return ret; | ||
1619 | } | ||
1620 | |||
1621 | /** | ||
1622 | * zfcp_ns_gid_pn_handler - handler for GID_PN nameserver request | ||
1623 | * @data: unsigned long, contains pointer to struct zfcp_gid_pn_data | ||
1624 | */ | ||
1625 | static void zfcp_ns_gid_pn_handler(unsigned long data) | ||
1626 | { | ||
1627 | struct zfcp_port *port; | ||
1628 | struct zfcp_send_ct *ct; | ||
1629 | struct ct_iu_gid_pn_req *ct_iu_req; | ||
1630 | struct ct_iu_gid_pn_resp *ct_iu_resp; | ||
1631 | struct zfcp_gid_pn_data *gid_pn; | ||
1632 | |||
1633 | |||
1634 | gid_pn = (struct zfcp_gid_pn_data *) data; | ||
1635 | port = gid_pn->port; | ||
1636 | ct = &gid_pn->ct; | ||
1637 | ct_iu_req = zfcp_sg_to_address(ct->req); | ||
1638 | ct_iu_resp = zfcp_sg_to_address(ct->resp); | ||
1639 | |||
1640 | if (ct->status != 0) | ||
1641 | goto failed; | ||
1642 | |||
1643 | if (zfcp_check_ct_response(&ct_iu_resp->header)) { | ||
1644 | /* FIXME: do we need some specific erp entry points */ | ||
1645 | atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status); | ||
1646 | goto failed; | ||
1647 | } | ||
1648 | /* paranoia */ | ||
1649 | if (ct_iu_req->wwpn != port->wwpn) { | ||
1650 | ZFCP_LOG_NORMAL("bug: wwpn 0x%016Lx returned by nameserver " | ||
1651 | "lookup does not match expected wwpn 0x%016Lx " | ||
1652 | "for adapter %s\n", ct_iu_req->wwpn, port->wwpn, | ||
1653 | zfcp_get_busid_by_port(port)); | ||
1654 | goto mismatch; | ||
1655 | } | ||
1656 | |||
1657 | /* looks like a valid d_id */ | ||
1658 | port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK; | ||
1659 | atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status); | ||
1660 | ZFCP_LOG_DEBUG("adapter %s: wwpn=0x%016Lx ---> d_id=0x%06x\n", | ||
1661 | zfcp_get_busid_by_port(port), port->wwpn, port->d_id); | ||
1662 | goto out; | ||
1663 | |||
1664 | mismatch: | ||
1665 | ZFCP_LOG_DEBUG("CT IUs do not match:\n"); | ||
1666 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) ct_iu_req, | ||
1667 | sizeof(struct ct_iu_gid_pn_req)); | ||
1668 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) ct_iu_resp, | ||
1669 | sizeof(struct ct_iu_gid_pn_resp)); | ||
1670 | |||
1671 | failed: | ||
1672 | ZFCP_LOG_NORMAL("warning: failed gid_pn nameserver request for wwpn " | ||
1673 | "0x%016Lx for adapter %s\n", | ||
1674 | port->wwpn, zfcp_get_busid_by_port(port)); | ||
1675 | out: | ||
1676 | zfcp_gid_pn_buffers_free(gid_pn); | ||
1677 | return; | ||
1678 | } | ||
1679 | |||
1680 | /* reject CT_IU reason codes acc. to FC-GS-4 */ | ||
1681 | static const struct zfcp_rc_entry zfcp_ct_rc[] = { | ||
1682 | {0x01, "invalid command code"}, | ||
1683 | {0x02, "invalid version level"}, | ||
1684 | {0x03, "logical error"}, | ||
1685 | {0x04, "invalid CT_IU size"}, | ||
1686 | {0x05, "logical busy"}, | ||
1687 | {0x07, "protocol error"}, | ||
1688 | {0x09, "unable to perform command request"}, | ||
1689 | {0x0b, "command not supported"}, | ||
1690 | {0x0d, "server not available"}, | ||
1691 | {0x0e, "session could not be established"}, | ||
1692 | {0xff, "vendor specific error"}, | ||
1693 | {0, NULL}, | ||
1694 | }; | ||
1695 | |||
1696 | /* LS_RJT reason codes acc. to FC-FS */ | ||
1697 | static const struct zfcp_rc_entry zfcp_ls_rjt_rc[] = { | ||
1698 | {0x01, "invalid LS_Command code"}, | ||
1699 | {0x03, "logical error"}, | ||
1700 | {0x05, "logical busy"}, | ||
1701 | {0x07, "protocol error"}, | ||
1702 | {0x09, "unable to perform command request"}, | ||
1703 | {0x0b, "command not supported"}, | ||
1704 | {0x0e, "command already in progress"}, | ||
1705 | {0xff, "vendor specific error"}, | ||
1706 | {0, NULL}, | ||
1707 | }; | ||
1708 | |||
1709 | /* reject reason codes according to FC-PH/FC-FS */ | ||
1710 | static const struct zfcp_rc_entry zfcp_p_rjt_rc[] = { | ||
1711 | {0x01, "invalid D_ID"}, | ||
1712 | {0x02, "invalid S_ID"}, | ||
1713 | {0x03, "Nx_Port not available, temporary"}, | ||
1714 | {0x04, "Nx_Port not available, permament"}, | ||
1715 | {0x05, "class not supported"}, | ||
1716 | {0x06, "delimiter usage error"}, | ||
1717 | {0x07, "TYPE not supported"}, | ||
1718 | {0x08, "invalid Link_Control"}, | ||
1719 | {0x09, "invalid R_CTL field"}, | ||
1720 | {0x0a, "invalid F_CTL field"}, | ||
1721 | {0x0b, "invalid OX_ID"}, | ||
1722 | {0x0c, "invalid RX_ID"}, | ||
1723 | {0x0d, "invalid SEQ_ID"}, | ||
1724 | {0x0e, "invalid DF_CTL"}, | ||
1725 | {0x0f, "invalid SEQ_CNT"}, | ||
1726 | {0x10, "invalid parameter field"}, | ||
1727 | {0x11, "exchange error"}, | ||
1728 | {0x12, "protocol error"}, | ||
1729 | {0x13, "incorrect length"}, | ||
1730 | {0x14, "unsupported ACK"}, | ||
1731 | {0x15, "class of service not supported by entity at FFFFFE"}, | ||
1732 | {0x16, "login required"}, | ||
1733 | {0x17, "excessive sequences attempted"}, | ||
1734 | {0x18, "unable to establish exchange"}, | ||
1735 | {0x1a, "fabric path not available"}, | ||
1736 | {0x1b, "invalid VC_ID (class 4)"}, | ||
1737 | {0x1c, "invalid CS_CTL field"}, | ||
1738 | {0x1d, "insufficient resources for VC (class 4)"}, | ||
1739 | {0x1f, "invalid class of service"}, | ||
1740 | {0x20, "preemption request rejected"}, | ||
1741 | {0x21, "preemption not enabled"}, | ||
1742 | {0x22, "multicast error"}, | ||
1743 | {0x23, "multicast error terminate"}, | ||
1744 | {0x24, "process login required"}, | ||
1745 | {0xff, "vendor specific reject"}, | ||
1746 | {0, NULL}, | ||
1747 | }; | ||
1748 | |||
1749 | /** | ||
1750 | * zfcp_rc_description - return description for given reaon code | ||
1751 | * @code: reason code | ||
1752 | * @rc_table: table of reason codes and descriptions | ||
1753 | */ | ||
1754 | static const char * | ||
1755 | zfcp_rc_description(u8 code, const struct zfcp_rc_entry *rc_table) | ||
1756 | { | ||
1757 | const char *descr = "unknown reason code"; | ||
1758 | |||
1759 | do { | ||
1760 | if (code == rc_table->code) { | ||
1761 | descr = rc_table->description; | ||
1762 | break; | ||
1763 | } | ||
1764 | rc_table++; | ||
1765 | } while (rc_table->code && rc_table->description); | ||
1766 | |||
1767 | return descr; | ||
1768 | } | ||
1769 | |||
1770 | /** | ||
1771 | * zfcp_check_ct_response - evaluate reason code for CT_IU | ||
1772 | * @rjt: response payload to an CT_IU request | ||
1773 | * Return: 0 for accept CT_IU, 1 for reject CT_IU or invlid response code | ||
1774 | */ | ||
1775 | int | ||
1776 | zfcp_check_ct_response(struct ct_hdr *rjt) | ||
1777 | { | ||
1778 | if (rjt->cmd_rsp_code == ZFCP_CT_ACCEPT) | ||
1779 | return 0; | ||
1780 | |||
1781 | if (rjt->cmd_rsp_code != ZFCP_CT_REJECT) { | ||
1782 | ZFCP_LOG_NORMAL("error: invalid Generic Service command/" | ||
1783 | "response code (0x%04hx)\n", | ||
1784 | rjt->cmd_rsp_code); | ||
1785 | return 1; | ||
1786 | } | ||
1787 | |||
1788 | ZFCP_LOG_INFO("Generic Service command rejected\n"); | ||
1789 | ZFCP_LOG_INFO("%s (0x%02x, 0x%02x, 0x%02x)\n", | ||
1790 | zfcp_rc_description(rjt->reason_code, zfcp_ct_rc), | ||
1791 | (u32) rjt->reason_code, (u32) rjt->reason_code_expl, | ||
1792 | (u32) rjt->vendor_unique); | ||
1793 | |||
1794 | return 1; | ||
1795 | } | ||
1796 | |||
1797 | /** | ||
1798 | * zfcp_print_els_rjt - print reject parameter and description for ELS reject | ||
1799 | * @rjt_par: reject parameter acc. to FC-PH/FC-FS | ||
1800 | * @rc_table: table of reason codes and descriptions | ||
1801 | */ | ||
1802 | static void | ||
1803 | zfcp_print_els_rjt(struct zfcp_ls_rjt_par *rjt_par, | ||
1804 | const struct zfcp_rc_entry *rc_table) | ||
1805 | { | ||
1806 | ZFCP_LOG_INFO("%s (%02x %02x %02x %02x)\n", | ||
1807 | zfcp_rc_description(rjt_par->reason_code, rc_table), | ||
1808 | (u32) rjt_par->action, (u32) rjt_par->reason_code, | ||
1809 | (u32) rjt_par->reason_expl, (u32) rjt_par->vendor_unique); | ||
1810 | } | ||
1811 | |||
1812 | /** | ||
1813 | * zfcp_fsf_handle_els_rjt - evaluate status qualifier/reason code on ELS reject | ||
1814 | * @sq: status qualifier word | ||
1815 | * @rjt_par: reject parameter as described in FC-PH and FC-FS | ||
1816 | * Return: -EROMTEIO for LS_RJT, -EREMCHG for invalid D_ID, -EIO else | ||
1817 | */ | ||
1818 | int | ||
1819 | zfcp_handle_els_rjt(u32 sq, struct zfcp_ls_rjt_par *rjt_par) | ||
1820 | { | ||
1821 | int ret = -EIO; | ||
1822 | |||
1823 | if (sq == FSF_IOSTAT_NPORT_RJT) { | ||
1824 | ZFCP_LOG_INFO("ELS rejected (P_RJT)\n"); | ||
1825 | zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc); | ||
1826 | /* invalid d_id */ | ||
1827 | if (rjt_par->reason_code == 0x01) | ||
1828 | ret = -EREMCHG; | ||
1829 | } else if (sq == FSF_IOSTAT_FABRIC_RJT) { | ||
1830 | ZFCP_LOG_INFO("ELS rejected (F_RJT)\n"); | ||
1831 | zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc); | ||
1832 | /* invalid d_id */ | ||
1833 | if (rjt_par->reason_code == 0x01) | ||
1834 | ret = -EREMCHG; | ||
1835 | } else if (sq == FSF_IOSTAT_LS_RJT) { | ||
1836 | ZFCP_LOG_INFO("ELS rejected (LS_RJT)\n"); | ||
1837 | zfcp_print_els_rjt(rjt_par, zfcp_ls_rjt_rc); | ||
1838 | ret = -EREMOTEIO; | ||
1839 | } else | ||
1840 | ZFCP_LOG_INFO("unexpected SQ: 0x%02x\n", sq); | ||
1841 | |||
1842 | return ret; | ||
1843 | } | ||
1844 | |||
1845 | /** | ||
1846 | * zfcp_plogi_evaluate - evaluate PLOGI playload and copy important fields | ||
1847 | * into zfcp_port structure | ||
1848 | * @port: zfcp_port structure | ||
1849 | * @plogi: plogi payload | ||
1850 | */ | ||
1851 | void | ||
1852 | zfcp_plogi_evaluate(struct zfcp_port *port, struct fsf_plogi *plogi) | ||
1853 | { | ||
1854 | port->maxframe_size = plogi->serv_param.common_serv_param[7] | | ||
1855 | ((plogi->serv_param.common_serv_param[6] & 0x0F) << 8); | ||
1856 | if (plogi->serv_param.class1_serv_param[0] & 0x80) | ||
1857 | port->supported_classes |= FC_COS_CLASS1; | ||
1858 | if (plogi->serv_param.class2_serv_param[0] & 0x80) | ||
1859 | port->supported_classes |= FC_COS_CLASS2; | ||
1860 | if (plogi->serv_param.class3_serv_param[0] & 0x80) | ||
1861 | port->supported_classes |= FC_COS_CLASS3; | ||
1862 | if (plogi->serv_param.class4_serv_param[0] & 0x80) | ||
1863 | port->supported_classes |= FC_COS_CLASS4; | ||
1864 | } | ||
1865 | |||
1866 | #undef ZFCP_LOG_AREA | ||