aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShahed Shaikh <shahed.shaikh@qlogic.com>2013-08-30 13:51:19 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-31 22:34:43 -0400
commit890b6e023bd7ff9b5fc89750d9ab2cd414fa302e (patch)
tree13a33a89110cc81c7b5c3c3796679cdac65c8dd5
parent7010bb65ce01278abe6709fe90407183abc6cbef (diff)
qlcnic: Store firmware dump state in CAMRAM register
-Use CAMRAM register to store firmware dump state in adapter instead of maintaining it in each function driver separately. -Return appropriate error code on failure Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h4
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h1
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c152
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c2
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c8
5 files changed, 135 insertions, 32 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index 4e74376fdd9b..f9cd2744b2a0 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -392,7 +392,7 @@ struct qlcnic_dump_template_hdr {
392 392
393struct qlcnic_fw_dump { 393struct qlcnic_fw_dump {
394 u8 clr; /* flag to indicate if dump is cleared */ 394 u8 clr; /* flag to indicate if dump is cleared */
395 u8 enable; /* enable/disable dump */ 395 bool enable; /* enable/disable dump */
396 u32 size; /* total size of the dump */ 396 u32 size; /* total size of the dump */
397 void *data; /* dump data area */ 397 void *data; /* dump data area */
398 struct qlcnic_dump_template_hdr *tmpl_hdr; 398 struct qlcnic_dump_template_hdr *tmpl_hdr;
@@ -1477,6 +1477,8 @@ int qlcnic_wol_supported(struct qlcnic_adapter *adapter);
1477void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter); 1477void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter);
1478void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter); 1478void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter);
1479int qlcnic_dump_fw(struct qlcnic_adapter *); 1479int qlcnic_dump_fw(struct qlcnic_adapter *);
1480int qlcnic_enable_fw_dump_state(struct qlcnic_adapter *);
1481bool qlcnic_check_fw_dump_state(struct qlcnic_adapter *);
1480 1482
1481/* Functions from qlcnic_init.c */ 1483/* Functions from qlcnic_init.c */
1482void qlcnic_schedule_work(struct qlcnic_adapter *, work_func_t, int); 1484void qlcnic_schedule_work(struct qlcnic_adapter *, work_func_t, int);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
index 0fc56160d584..053a3a1770bb 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -297,6 +297,7 @@ struct qlc_83xx_reset {
297 297
298#define QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY 0x1 298#define QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY 0x1
299#define QLC_83XX_IDC_GRACEFULL_RESET 0x2 299#define QLC_83XX_IDC_GRACEFULL_RESET 0x2
300#define QLC_83XX_IDC_DISABLE_FW_DUMP 0x4
300#define QLC_83XX_IDC_TIMESTAMP 0 301#define QLC_83XX_IDC_TIMESTAMP 0
301#define QLC_83XX_IDC_DURATION 1 302#define QLC_83XX_IDC_DURATION 1
302#define QLC_83XX_IDC_INIT_TIMEOUT_SECS 30 303#define QLC_83XX_IDC_INIT_TIMEOUT_SECS 30
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index 7b0c90efb365..332aa71798f6 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -1509,6 +1509,68 @@ static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
1509 adapter->ahw->msg_enable = msglvl; 1509 adapter->ahw->msg_enable = msglvl;
1510} 1510}
1511 1511
1512int qlcnic_enable_fw_dump_state(struct qlcnic_adapter *adapter)
1513{
1514 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1515 u32 val;
1516
1517 if (qlcnic_84xx_check(adapter)) {
1518 if (qlcnic_83xx_lock_driver(adapter))
1519 return -EBUSY;
1520
1521 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
1522 val &= ~QLC_83XX_IDC_DISABLE_FW_DUMP;
1523 QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
1524
1525 qlcnic_83xx_unlock_driver(adapter);
1526 } else {
1527 fw_dump->enable = true;
1528 }
1529
1530 dev_info(&adapter->pdev->dev, "FW dump enabled\n");
1531
1532 return 0;
1533}
1534
1535static int qlcnic_disable_fw_dump_state(struct qlcnic_adapter *adapter)
1536{
1537 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1538 u32 val;
1539
1540 if (qlcnic_84xx_check(adapter)) {
1541 if (qlcnic_83xx_lock_driver(adapter))
1542 return -EBUSY;
1543
1544 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
1545 val |= QLC_83XX_IDC_DISABLE_FW_DUMP;
1546 QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
1547
1548 qlcnic_83xx_unlock_driver(adapter);
1549 } else {
1550 fw_dump->enable = false;
1551 }
1552
1553 dev_info(&adapter->pdev->dev, "FW dump disabled\n");
1554
1555 return 0;
1556}
1557
1558bool qlcnic_check_fw_dump_state(struct qlcnic_adapter *adapter)
1559{
1560 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1561 bool state;
1562 u32 val;
1563
1564 if (qlcnic_84xx_check(adapter)) {
1565 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
1566 state = (val & QLC_83XX_IDC_DISABLE_FW_DUMP) ? false : true;
1567 } else {
1568 state = fw_dump->enable;
1569 }
1570
1571 return state;
1572}
1573
1512static int 1574static int
1513qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) 1575qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
1514{ 1576{
@@ -1525,7 +1587,7 @@ qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
1525 else 1587 else
1526 dump->len = 0; 1588 dump->len = 0;
1527 1589
1528 if (!fw_dump->enable) 1590 if (!qlcnic_check_fw_dump_state(adapter))
1529 dump->flag = ETH_FW_DUMP_DISABLE; 1591 dump->flag = ETH_FW_DUMP_DISABLE;
1530 else 1592 else
1531 dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; 1593 dump->flag = fw_dump->tmpl_hdr->drv_cap_mask;
@@ -1573,77 +1635,111 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
1573 return 0; 1635 return 0;
1574} 1636}
1575 1637
1638static int qlcnic_set_dump_mask(struct qlcnic_adapter *adapter, u32 mask)
1639{
1640 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1641 struct net_device *netdev = adapter->netdev;
1642
1643 if (!qlcnic_check_fw_dump_state(adapter)) {
1644 netdev_info(netdev,
1645 "Can not change driver mask to 0x%x. FW dump not enabled\n",
1646 mask);
1647 return -EOPNOTSUPP;
1648 }
1649
1650 fw_dump->tmpl_hdr->drv_cap_mask = mask;
1651 netdev_info(netdev, "Driver mask changed to: 0x%x\n", mask);
1652 return 0;
1653}
1654
1576static int 1655static int
1577qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) 1656qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
1578{ 1657{
1579 int i;
1580 struct qlcnic_adapter *adapter = netdev_priv(netdev); 1658 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1581 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; 1659 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1660 bool valid_mask = false;
1661 int i, ret = 0;
1582 u32 state; 1662 u32 state;
1583 1663
1584 switch (val->flag) { 1664 switch (val->flag) {
1585 case QLCNIC_FORCE_FW_DUMP_KEY: 1665 case QLCNIC_FORCE_FW_DUMP_KEY:
1586 if (!fw_dump->tmpl_hdr) { 1666 if (!fw_dump->tmpl_hdr) {
1587 netdev_err(netdev, "FW dump not supported\n"); 1667 netdev_err(netdev, "FW dump not supported\n");
1588 return -ENOTSUPP; 1668 ret = -EOPNOTSUPP;
1669 break;
1589 } 1670 }
1590 if (!fw_dump->enable) { 1671
1672 if (!qlcnic_check_fw_dump_state(adapter)) {
1591 netdev_info(netdev, "FW dump not enabled\n"); 1673 netdev_info(netdev, "FW dump not enabled\n");
1592 return 0; 1674 ret = -EOPNOTSUPP;
1675 break;
1593 } 1676 }
1677
1594 if (fw_dump->clr) { 1678 if (fw_dump->clr) {
1595 netdev_info(netdev, 1679 netdev_info(netdev,
1596 "Previous dump not cleared, not forcing dump\n"); 1680 "Previous dump not cleared, not forcing dump\n");
1597 return 0; 1681 break;
1598 } 1682 }
1683
1599 netdev_info(netdev, "Forcing a FW dump\n"); 1684 netdev_info(netdev, "Forcing a FW dump\n");
1600 qlcnic_dev_request_reset(adapter, val->flag); 1685 qlcnic_dev_request_reset(adapter, val->flag);
1601 break; 1686 break;
1602 case QLCNIC_DISABLE_FW_DUMP: 1687 case QLCNIC_DISABLE_FW_DUMP:
1603 if (fw_dump->enable && fw_dump->tmpl_hdr) { 1688 if (!fw_dump->tmpl_hdr) {
1604 netdev_info(netdev, "Disabling FW dump\n"); 1689 netdev_err(netdev, "FW dump not supported\n");
1605 fw_dump->enable = 0; 1690 ret = -EOPNOTSUPP;
1691 break;
1606 } 1692 }
1607 return 0; 1693
1694 ret = qlcnic_disable_fw_dump_state(adapter);
1695 break;
1696
1608 case QLCNIC_ENABLE_FW_DUMP: 1697 case QLCNIC_ENABLE_FW_DUMP:
1609 if (!fw_dump->tmpl_hdr) { 1698 if (!fw_dump->tmpl_hdr) {
1610 netdev_err(netdev, "FW dump not supported\n"); 1699 netdev_err(netdev, "FW dump not supported\n");
1611 return -ENOTSUPP; 1700 ret = -EOPNOTSUPP;
1612 } 1701 break;
1613 if (!fw_dump->enable) {
1614 netdev_info(netdev, "Enabling FW dump\n");
1615 fw_dump->enable = 1;
1616 } 1702 }
1617 return 0; 1703
1704 ret = qlcnic_enable_fw_dump_state(adapter);
1705 break;
1706
1618 case QLCNIC_FORCE_FW_RESET: 1707 case QLCNIC_FORCE_FW_RESET:
1619 netdev_info(netdev, "Forcing a FW reset\n"); 1708 netdev_info(netdev, "Forcing a FW reset\n");
1620 qlcnic_dev_request_reset(adapter, val->flag); 1709 qlcnic_dev_request_reset(adapter, val->flag);
1621 adapter->flags &= ~QLCNIC_FW_RESET_OWNER; 1710 adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
1622 return 0; 1711 break;
1712;
1623 case QLCNIC_SET_QUIESCENT: 1713 case QLCNIC_SET_QUIESCENT:
1624 case QLCNIC_RESET_QUIESCENT: 1714 case QLCNIC_RESET_QUIESCENT:
1625 state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); 1715 state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
1626 if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) 1716 if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
1627 netdev_info(netdev, "Device in FAILED state\n"); 1717 netdev_info(netdev, "Device in FAILED state\n");
1628 return 0; 1718 break;
1719
1629 default: 1720 default:
1630 if (!fw_dump->tmpl_hdr) { 1721 if (!fw_dump->tmpl_hdr) {
1631 netdev_err(netdev, "FW dump not supported\n"); 1722 netdev_err(netdev, "FW dump not supported\n");
1632 return -ENOTSUPP; 1723 ret = -EOPNOTSUPP;
1724 break;
1633 } 1725 }
1726
1634 for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) { 1727 for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) {
1635 if (val->flag == qlcnic_fw_dump_level[i]) { 1728 if (val->flag == qlcnic_fw_dump_level[i]) {
1636 fw_dump->tmpl_hdr->drv_cap_mask = 1729 valid_mask = true;
1637 val->flag; 1730 break;
1638 netdev_info(netdev, "Driver mask changed to: 0x%x\n",
1639 fw_dump->tmpl_hdr->drv_cap_mask);
1640 return 0;
1641 } 1731 }
1642 } 1732 }
1643 netdev_info(netdev, "Invalid dump level: 0x%x\n", val->flag); 1733
1644 return -EINVAL; 1734 if (valid_mask) {
1735 ret = qlcnic_set_dump_mask(adapter, val->flag);
1736 } else {
1737 netdev_info(netdev, "Invalid dump level: 0x%x\n",
1738 val->flag);
1739 ret = -EINVAL;
1740 }
1645 } 1741 }
1646 return 0; 1742 return ret;
1647} 1743}
1648 1744
1649const struct ethtool_ops qlcnic_ethtool_ops = { 1745const struct ethtool_ops qlcnic_ethtool_ops = {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index d1ed4e351ab1..e380f0398165 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -3045,7 +3045,7 @@ skip_ack_check:
3045 qlcnic_api_unlock(adapter); 3045 qlcnic_api_unlock(adapter);
3046 3046
3047 rtnl_lock(); 3047 rtnl_lock();
3048 if (adapter->ahw->fw_dump.enable && 3048 if (qlcnic_check_fw_dump_state(adapter) &&
3049 (adapter->flags & QLCNIC_FW_RESET_OWNER)) { 3049 (adapter->flags & QLCNIC_FW_RESET_OWNER)) {
3050 QLCDB(adapter, DRV, "Take FW dump\n"); 3050 QLCDB(adapter, DRV, "Take FW dump\n");
3051 qlcnic_dump_fw(adapter); 3051 qlcnic_dump_fw(adapter);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
index b7871fe99162..15513608d480 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
@@ -1092,7 +1092,7 @@ flash_temp:
1092 else 1092 else
1093 ahw->fw_dump.use_pex_dma = false; 1093 ahw->fw_dump.use_pex_dma = false;
1094 1094
1095 ahw->fw_dump.enable = 1; 1095 qlcnic_enable_fw_dump_state(adapter);
1096 1096
1097 return 0; 1097 return 0;
1098} 1098}
@@ -1115,7 +1115,11 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
1115 1115
1116 ahw = adapter->ahw; 1116 ahw = adapter->ahw;
1117 1117
1118 if (!fw_dump->enable) { 1118 /* Return if we don't have firmware dump template header */
1119 if (!tmpl_hdr)
1120 return -EIO;
1121
1122 if (!qlcnic_check_fw_dump_state(adapter)) {
1119 dev_info(&adapter->pdev->dev, "Dump not enabled\n"); 1123 dev_info(&adapter->pdev->dev, "Dump not enabled\n");
1120 return -EIO; 1124 return -EIO;
1121 } 1125 }