aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShmulik Ravid <shmulikr@broadcom.com>2010-12-30 01:27:03 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-31 13:50:55 -0500
commit785b9b1aebcb748fb7627ad4c12dffb7f4f91b55 (patch)
tree44d6a8d19df9fd7d4f68998ed4176ea75ad3068a
parentea45fe4e176a42d2396878f530cfdc8265bef37b (diff)
bnx2x: adding dcbnl support
Adding dcbnl implementation to bnx2x allowing users to manage the embedded DCBX engine. This patch is dependent on the following patches: [net-next-2.6 PATCH 1/3] dcbnl: add support for ieee8021Qaz attributes [net-next-2.6 PATCH 2/3] dcbnl: add appliction tlv handlers [net-next-2.6 PATCH 3/3] net_dcb: add application notifiers Signed-off-by: Shmulik Ravid <shmulikr@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/bnx2x/bnx2x.h23
-rw-r--r--drivers/net/bnx2x/bnx2x_dcb.c663
-rw-r--r--drivers/net/bnx2x/bnx2x_dcb.h9
-rw-r--r--drivers/net/bnx2x/bnx2x_main.c8
4 files changed, 677 insertions, 26 deletions
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
index f14c6ed62bbb..77d6c8d6d86b 100644
--- a/drivers/net/bnx2x/bnx2x.h
+++ b/drivers/net/bnx2x/bnx2x.h
@@ -22,15 +22,17 @@
22 * (you will need to reboot afterwards) */ 22 * (you will need to reboot afterwards) */
23/* #define BNX2X_STOP_ON_ERROR */ 23/* #define BNX2X_STOP_ON_ERROR */
24 24
25#define DRV_MODULE_VERSION "1.62.00-2" 25#define DRV_MODULE_VERSION "1.62.00-3"
26#define DRV_MODULE_RELDATE "2010/12/13" 26#define DRV_MODULE_RELDATE "2010/12/21"
27#define BNX2X_BC_VER 0x040200 27#define BNX2X_BC_VER 0x040200
28 28
29#define BNX2X_MULTI_QUEUE 29#define BNX2X_MULTI_QUEUE
30 30
31#define BNX2X_NEW_NAPI 31#define BNX2X_NEW_NAPI
32 32
33 33#if defined(CONFIG_DCB)
34#define BCM_DCB
35#endif
34#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE) 36#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
35#define BCM_CNIC 1 37#define BCM_CNIC 1
36#include "../cnic_if.h" 38#include "../cnic_if.h"
@@ -1186,7 +1188,20 @@ struct bnx2x {
1186 /* LLDP params */ 1188 /* LLDP params */
1187 struct bnx2x_config_lldp_params lldp_config_params; 1189 struct bnx2x_config_lldp_params lldp_config_params;
1188 1190
1189 /* DCBX params */ 1191 /* DCB support on/off */
1192 u16 dcb_state;
1193#define BNX2X_DCB_STATE_OFF 0
1194#define BNX2X_DCB_STATE_ON 1
1195
1196 /* DCBX engine mode */
1197 int dcbx_enabled;
1198#define BNX2X_DCBX_ENABLED_OFF 0
1199#define BNX2X_DCBX_ENABLED_ON_NEG_OFF 1
1200#define BNX2X_DCBX_ENABLED_ON_NEG_ON 2
1201#define BNX2X_DCBX_ENABLED_INVALID (-1)
1202
1203 bool dcbx_mode_uset;
1204
1190 struct bnx2x_config_dcbx_params dcbx_config_params; 1205 struct bnx2x_config_dcbx_params dcbx_config_params;
1191 1206
1192 struct bnx2x_dcbx_port_params dcbx_port_params; 1207 struct bnx2x_dcbx_port_params dcbx_port_params;
diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/bnx2x/bnx2x_dcb.c
index 0b86480379ff..fb60021f81fb 100644
--- a/drivers/net/bnx2x/bnx2x_dcb.c
+++ b/drivers/net/bnx2x/bnx2x_dcb.c
@@ -619,13 +619,10 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
619 for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++) 619 for (i = 0; i < sizeof(struct lldp_admin_mib); i += 4, buff++)
620 *buff = REG_RD(bp, (offset + i)); 620 *buff = REG_RD(bp, (offset + i));
621 621
622 622 if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON)
623 if (BNX2X_DCBX_CONFIG_INV_VALUE != dp->admin_dcbx_enable) { 623 SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
624 if (dp->admin_dcbx_enable) 624 else
625 SET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED); 625 RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
626 else
627 RESET_FLAGS(admin_mib.ver_cfg_flags, DCBX_DCBX_ENABLED);
628 }
629 626
630 if ((BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE == 627 if ((BNX2X_DCBX_OVERWRITE_SETTINGS_ENABLE ==
631 dp->overwrite_settings)) { 628 dp->overwrite_settings)) {
@@ -734,12 +731,26 @@ static void bnx2x_dcbx_admin_mib_updated_params(struct bnx2x *bp,
734 REG_WR(bp, (offset + i), *buff); 731 REG_WR(bp, (offset + i), *buff);
735} 732}
736 733
737/* default */ 734void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled)
735{
736 if (CHIP_IS_E2(bp) && !CHIP_MODE_IS_4_PORT(bp)) {
737 bp->dcb_state = dcb_on;
738 bp->dcbx_enabled = dcbx_enabled;
739 } else {
740 bp->dcb_state = false;
741 bp->dcbx_enabled = BNX2X_DCBX_ENABLED_INVALID;
742 }
743 DP(NETIF_MSG_LINK, "DCB state [%s:%s]\n",
744 dcb_on ? "ON" : "OFF",
745 dcbx_enabled == BNX2X_DCBX_ENABLED_OFF ? "user-mode" :
746 dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_OFF ? "on-chip static" :
747 dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_ON ?
748 "on-chip with negotiation" : "invalid");
749}
750
738void bnx2x_dcbx_init_params(struct bnx2x *bp) 751void bnx2x_dcbx_init_params(struct bnx2x *bp)
739{ 752{
740 bp->dcbx_config_params.admin_dcbx_version = 0x0; /* 0 - CEE; 1 - IEEE */ 753 bp->dcbx_config_params.admin_dcbx_version = 0x0; /* 0 - CEE; 1 - IEEE */
741 bp->dcbx_config_params.dcb_enable = 1;
742 bp->dcbx_config_params.admin_dcbx_enable = 1;
743 bp->dcbx_config_params.admin_ets_willing = 1; 754 bp->dcbx_config_params.admin_ets_willing = 1;
744 bp->dcbx_config_params.admin_pfc_willing = 1; 755 bp->dcbx_config_params.admin_pfc_willing = 1;
745 bp->dcbx_config_params.overwrite_settings = 1; 756 bp->dcbx_config_params.overwrite_settings = 1;
@@ -807,23 +818,27 @@ void bnx2x_dcbx_init_params(struct bnx2x *bp)
807void bnx2x_dcbx_init(struct bnx2x *bp) 818void bnx2x_dcbx_init(struct bnx2x *bp)
808{ 819{
809 u32 dcbx_lldp_params_offset = SHMEM_LLDP_DCBX_PARAMS_NONE; 820 u32 dcbx_lldp_params_offset = SHMEM_LLDP_DCBX_PARAMS_NONE;
821
822 if (bp->dcbx_enabled <= 0)
823 return;
824
810 /* validate: 825 /* validate:
811 * chip of good for dcbx version, 826 * chip of good for dcbx version,
812 * dcb is wanted 827 * dcb is wanted
813 * the function is pmf 828 * the function is pmf
814 * shmem2 contains DCBX support fields 829 * shmem2 contains DCBX support fields
815 */ 830 */
816 DP(NETIF_MSG_LINK, "dcb_enable %d bp->port.pmf %d\n", 831 DP(NETIF_MSG_LINK, "dcb_state %d bp->port.pmf %d\n",
817 bp->dcbx_config_params.dcb_enable, bp->port.pmf); 832 bp->dcb_state, bp->port.pmf);
818 833
819 if (CHIP_IS_E2(bp) && !CHIP_MODE_IS_4_PORT(bp) && 834 if (bp->dcb_state == BNX2X_DCB_STATE_ON && bp->port.pmf &&
820 bp->dcbx_config_params.dcb_enable &&
821 bp->port.pmf &&
822 SHMEM2_HAS(bp, dcbx_lldp_params_offset)) { 835 SHMEM2_HAS(bp, dcbx_lldp_params_offset)) {
823 dcbx_lldp_params_offset = SHMEM2_RD(bp, 836 dcbx_lldp_params_offset =
824 dcbx_lldp_params_offset); 837 SHMEM2_RD(bp, dcbx_lldp_params_offset);
838
825 DP(NETIF_MSG_LINK, "dcbx_lldp_params_offset 0x%x\n", 839 DP(NETIF_MSG_LINK, "dcbx_lldp_params_offset 0x%x\n",
826 dcbx_lldp_params_offset); 840 dcbx_lldp_params_offset);
841
827 if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) { 842 if (SHMEM_LLDP_DCBX_PARAMS_NONE != dcbx_lldp_params_offset) {
828 bnx2x_dcbx_lldp_updated_params(bp, 843 bnx2x_dcbx_lldp_updated_params(bp,
829 dcbx_lldp_params_offset); 844 dcbx_lldp_params_offset);
@@ -1452,7 +1467,7 @@ static void bnx2x_dcbx_get_ets_pri_pg_tbl(struct bnx2x *bp,
1452 ******************************************************************************/ 1467 ******************************************************************************/
1453static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp) 1468static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp)
1454{ 1469{
1455 struct flow_control_configuration *pfc_fw_cfg = 0; 1470 struct flow_control_configuration *pfc_fw_cfg = NULL;
1456 u16 pri_bit = 0; 1471 u16 pri_bit = 0;
1457 u8 cos = 0, pri = 0; 1472 u8 cos = 0, pri = 0;
1458 struct priority_cos *tt2cos; 1473 struct priority_cos *tt2cos;
@@ -1489,3 +1504,615 @@ static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp)
1489 } 1504 }
1490 bnx2x_dcbx_print_cos_params(bp, pfc_fw_cfg); 1505 bnx2x_dcbx_print_cos_params(bp, pfc_fw_cfg);
1491} 1506}
1507/* DCB netlink */
1508#ifdef BCM_DCB
1509#include <linux/dcbnl.h>
1510
1511#define BNX2X_DCBX_CAPS (DCB_CAP_DCBX_LLD_MANAGED | \
1512 DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_STATIC)
1513
1514static inline bool bnx2x_dcbnl_set_valid(struct bnx2x *bp)
1515{
1516 /* validate dcbnl call that may change HW state:
1517 * DCB is on and DCBX mode was SUCCESSFULLY set by the user.
1518 */
1519 return bp->dcb_state && bp->dcbx_mode_uset;
1520}
1521
1522static u8 bnx2x_dcbnl_get_state(struct net_device *netdev)
1523{
1524 struct bnx2x *bp = netdev_priv(netdev);
1525 DP(NETIF_MSG_LINK, "state = %d\n", bp->dcb_state);
1526 return bp->dcb_state;
1527}
1528
1529static u8 bnx2x_dcbnl_set_state(struct net_device *netdev, u8 state)
1530{
1531 struct bnx2x *bp = netdev_priv(netdev);
1532 DP(NETIF_MSG_LINK, "state = %s\n", state ? "on" : "off");
1533
1534 bnx2x_dcbx_set_state(bp, (state ? true : false), bp->dcbx_enabled);
1535 return 0;
1536}
1537
1538static void bnx2x_dcbnl_get_perm_hw_addr(struct net_device *netdev,
1539 u8 *perm_addr)
1540{
1541 struct bnx2x *bp = netdev_priv(netdev);
1542 DP(NETIF_MSG_LINK, "GET-PERM-ADDR\n");
1543
1544 /* first the HW mac address */
1545 memcpy(perm_addr, netdev->dev_addr, netdev->addr_len);
1546
1547#ifdef BCM_CNIC
1548 /* second SAN address */
1549 memcpy(perm_addr+netdev->addr_len, bp->fip_mac, netdev->addr_len);
1550#endif
1551}
1552
1553static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device *netdev, int prio,
1554 u8 prio_type, u8 pgid, u8 bw_pct,
1555 u8 up_map)
1556{
1557 struct bnx2x *bp = netdev_priv(netdev);
1558
1559 DP(NETIF_MSG_LINK, "prio[%d] = %d\n", prio, pgid);
1560 if (!bnx2x_dcbnl_set_valid(bp) || prio >= DCBX_MAX_NUM_PRI_PG_ENTRIES)
1561 return;
1562
1563 /**
1564 * bw_pct ingnored - band-width percentage devision between user
1565 * priorities within the same group is not
1566 * standard and hence not supported
1567 *
1568 * prio_type igonred - priority levels within the same group are not
1569 * standard and hence are not supported. According
1570 * to the standard pgid 15 is dedicated to strict
1571 * prioirty traffic (on the port level).
1572 *
1573 * up_map ignored
1574 */
1575
1576 bp->dcbx_config_params.admin_configuration_ets_pg[prio] = pgid;
1577 bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
1578}
1579
1580static void bnx2x_dcbnl_set_pg_bwgcfg_tx(struct net_device *netdev,
1581 int pgid, u8 bw_pct)
1582{
1583 struct bnx2x *bp = netdev_priv(netdev);
1584 DP(NETIF_MSG_LINK, "pgid[%d] = %d\n", pgid, bw_pct);
1585
1586 if (!bnx2x_dcbnl_set_valid(bp) || pgid >= DCBX_MAX_NUM_PG_BW_ENTRIES)
1587 return;
1588
1589 bp->dcbx_config_params.admin_configuration_bw_precentage[pgid] = bw_pct;
1590 bp->dcbx_config_params.admin_ets_configuration_tx_enable = 1;
1591}
1592
1593static void bnx2x_dcbnl_set_pg_tccfg_rx(struct net_device *netdev, int prio,
1594 u8 prio_type, u8 pgid, u8 bw_pct,
1595 u8 up_map)
1596{
1597 struct bnx2x *bp = netdev_priv(netdev);
1598 DP(NETIF_MSG_LINK, "Nothing to set; No RX support\n");
1599}
1600
1601static void bnx2x_dcbnl_set_pg_bwgcfg_rx(struct net_device *netdev,
1602 int pgid, u8 bw_pct)
1603{
1604 struct bnx2x *bp = netdev_priv(netdev);
1605 DP(NETIF_MSG_LINK, "Nothing to set; No RX support\n");
1606}
1607
1608static void bnx2x_dcbnl_get_pg_tccfg_tx(struct net_device *netdev, int prio,
1609 u8 *prio_type, u8 *pgid, u8 *bw_pct,
1610 u8 *up_map)
1611{
1612 struct bnx2x *bp = netdev_priv(netdev);
1613 DP(NETIF_MSG_LINK, "prio = %d\n", prio);
1614
1615 /**
1616 * bw_pct ingnored - band-width percentage devision between user
1617 * priorities within the same group is not
1618 * standard and hence not supported
1619 *
1620 * prio_type igonred - priority levels within the same group are not
1621 * standard and hence are not supported. According
1622 * to the standard pgid 15 is dedicated to strict
1623 * prioirty traffic (on the port level).
1624 *
1625 * up_map ignored
1626 */
1627 *up_map = *bw_pct = *prio_type = *pgid = 0;
1628
1629 if (!bp->dcb_state || prio >= DCBX_MAX_NUM_PRI_PG_ENTRIES)
1630 return;
1631
1632 *pgid = DCBX_PRI_PG_GET(bp->dcbx_local_feat.ets.pri_pg_tbl, prio);
1633}
1634
1635static void bnx2x_dcbnl_get_pg_bwgcfg_tx(struct net_device *netdev,
1636 int pgid, u8 *bw_pct)
1637{
1638 struct bnx2x *bp = netdev_priv(netdev);
1639 DP(NETIF_MSG_LINK, "pgid = %d\n", pgid);
1640
1641 *bw_pct = 0;
1642
1643 if (!bp->dcb_state || pgid >= DCBX_MAX_NUM_PG_BW_ENTRIES)
1644 return;
1645
1646 *bw_pct = DCBX_PG_BW_GET(bp->dcbx_local_feat.ets.pg_bw_tbl, pgid);
1647}
1648
1649static void bnx2x_dcbnl_get_pg_tccfg_rx(struct net_device *netdev, int prio,
1650 u8 *prio_type, u8 *pgid, u8 *bw_pct,
1651 u8 *up_map)
1652{
1653 struct bnx2x *bp = netdev_priv(netdev);
1654 DP(NETIF_MSG_LINK, "Nothing to get; No RX support\n");
1655
1656 *prio_type = *pgid = *bw_pct = *up_map = 0;
1657}
1658
1659static void bnx2x_dcbnl_get_pg_bwgcfg_rx(struct net_device *netdev,
1660 int pgid, u8 *bw_pct)
1661{
1662 struct bnx2x *bp = netdev_priv(netdev);
1663 DP(NETIF_MSG_LINK, "Nothing to get; No RX support\n");
1664
1665 *bw_pct = 0;
1666}
1667
1668static void bnx2x_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio,
1669 u8 setting)
1670{
1671 struct bnx2x *bp = netdev_priv(netdev);
1672 DP(NETIF_MSG_LINK, "prio[%d] = %d\n", prio, setting);
1673
1674 if (!bnx2x_dcbnl_set_valid(bp) || prio >= MAX_PFC_PRIORITIES)
1675 return;
1676
1677 bp->dcbx_config_params.admin_pfc_bitmap |= ((setting ? 1 : 0) << prio);
1678
1679 if (setting)
1680 bp->dcbx_config_params.admin_pfc_tx_enable = 1;
1681}
1682
1683static void bnx2x_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio,
1684 u8 *setting)
1685{
1686 struct bnx2x *bp = netdev_priv(netdev);
1687 DP(NETIF_MSG_LINK, "prio = %d\n", prio);
1688
1689 *setting = 0;
1690
1691 if (!bp->dcb_state || prio >= MAX_PFC_PRIORITIES)
1692 return;
1693
1694 *setting = (bp->dcbx_local_feat.pfc.pri_en_bitmap >> prio) & 0x1;
1695}
1696
1697static u8 bnx2x_dcbnl_set_all(struct net_device *netdev)
1698{
1699 struct bnx2x *bp = netdev_priv(netdev);
1700 int rc = 0;
1701
1702 DP(NETIF_MSG_LINK, "SET-ALL\n");
1703
1704 if (!bnx2x_dcbnl_set_valid(bp))
1705 return 1;
1706
1707 if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
1708 netdev_err(bp->dev, "Handling parity error recovery. "
1709 "Try again later\n");
1710 return 1;
1711 }
1712 if (netif_running(bp->dev)) {
1713 bnx2x_nic_unload(bp, UNLOAD_NORMAL);
1714 rc = bnx2x_nic_load(bp, LOAD_NORMAL);
1715 }
1716 DP(NETIF_MSG_LINK, "set_dcbx_params done (%d)\n", rc);
1717 if (rc)
1718 return 1;
1719
1720 return 0;
1721}
1722
1723static u8 bnx2x_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap)
1724{
1725 struct bnx2x *bp = netdev_priv(netdev);
1726 u8 rval = 0;
1727
1728 if (bp->dcb_state) {
1729 switch (capid) {
1730 case DCB_CAP_ATTR_PG:
1731 *cap = true;
1732 break;
1733 case DCB_CAP_ATTR_PFC:
1734 *cap = true;
1735 break;
1736 case DCB_CAP_ATTR_UP2TC:
1737 *cap = false;
1738 break;
1739 case DCB_CAP_ATTR_PG_TCS:
1740 *cap = 0x80; /* 8 priorities for PGs */
1741 break;
1742 case DCB_CAP_ATTR_PFC_TCS:
1743 *cap = 0x80; /* 8 priorities for PFC */
1744 break;
1745 case DCB_CAP_ATTR_GSP:
1746 *cap = true;
1747 break;
1748 case DCB_CAP_ATTR_BCN:
1749 *cap = false;
1750 break;
1751 case DCB_CAP_ATTR_DCBX:
1752 *cap = BNX2X_DCBX_CAPS;
1753 default:
1754 rval = -EINVAL;
1755 break;
1756 }
1757 } else
1758 rval = -EINVAL;
1759
1760 DP(NETIF_MSG_LINK, "capid %d:%x\n", capid, *cap);
1761 return rval;
1762}
1763
1764static u8 bnx2x_dcbnl_get_numtcs(struct net_device *netdev, int tcid, u8 *num)
1765{
1766 struct bnx2x *bp = netdev_priv(netdev);
1767 u8 rval = 0;
1768
1769 DP(NETIF_MSG_LINK, "tcid %d\n", tcid);
1770
1771 if (bp->dcb_state) {
1772 switch (tcid) {
1773 case DCB_NUMTCS_ATTR_PG:
1774 *num = E2_NUM_OF_COS;
1775 break;
1776 case DCB_NUMTCS_ATTR_PFC:
1777 *num = E2_NUM_OF_COS;
1778 break;
1779 default:
1780 rval = -EINVAL;
1781 break;
1782 }
1783 } else
1784 rval = -EINVAL;
1785
1786 return rval;
1787}
1788
1789static u8 bnx2x_dcbnl_set_numtcs(struct net_device *netdev, int tcid, u8 num)
1790{
1791 struct bnx2x *bp = netdev_priv(netdev);
1792 DP(NETIF_MSG_LINK, "num tcs = %d; Not supported\n", num);
1793 return -EINVAL;
1794}
1795
1796static u8 bnx2x_dcbnl_get_pfc_state(struct net_device *netdev)
1797{
1798 struct bnx2x *bp = netdev_priv(netdev);
1799 DP(NETIF_MSG_LINK, "state = %d\n", bp->dcbx_local_feat.pfc.enabled);
1800
1801 if (!bp->dcb_state)
1802 return 0;
1803
1804 return bp->dcbx_local_feat.pfc.enabled;
1805}
1806
1807static void bnx2x_dcbnl_set_pfc_state(struct net_device *netdev, u8 state)
1808{
1809 struct bnx2x *bp = netdev_priv(netdev);
1810 DP(NETIF_MSG_LINK, "state = %s\n", state ? "on" : "off");
1811
1812 if (!bnx2x_dcbnl_set_valid(bp))
1813 return;
1814
1815 bp->dcbx_config_params.admin_pfc_tx_enable =
1816 bp->dcbx_config_params.admin_pfc_enable = (state ? 1 : 0);
1817}
1818
1819static bool bnx2x_app_is_equal(struct dcbx_app_priority_entry *app_ent,
1820 u8 idtype, u16 idval)
1821{
1822 if (!(app_ent->appBitfield & DCBX_APP_ENTRY_VALID))
1823 return false;
1824
1825 switch (idtype) {
1826 case DCB_APP_IDTYPE_ETHTYPE:
1827 if ((app_ent->appBitfield & DCBX_APP_ENTRY_SF_MASK) !=
1828 DCBX_APP_SF_ETH_TYPE)
1829 return false;
1830 break;
1831 case DCB_APP_IDTYPE_PORTNUM:
1832 if ((app_ent->appBitfield & DCBX_APP_ENTRY_SF_MASK) !=
1833 DCBX_APP_SF_PORT)
1834 return false;
1835 break;
1836 default:
1837 return false;
1838 }
1839 if (app_ent->app_id != idval)
1840 return false;
1841
1842 return true;
1843}
1844
1845static void bnx2x_admin_app_set_ent(
1846 struct bnx2x_admin_priority_app_table *app_ent,
1847 u8 idtype, u16 idval, u8 up)
1848{
1849 app_ent->valid = 1;
1850
1851 switch (idtype) {
1852 case DCB_APP_IDTYPE_ETHTYPE:
1853 app_ent->traffic_type = TRAFFIC_TYPE_ETH;
1854 break;
1855 case DCB_APP_IDTYPE_PORTNUM:
1856 app_ent->traffic_type = TRAFFIC_TYPE_PORT;
1857 break;
1858 default:
1859 break; /* never gets here */
1860 }
1861 app_ent->app_id = idval;
1862 app_ent->priority = up;
1863}
1864
1865static bool bnx2x_admin_app_is_equal(
1866 struct bnx2x_admin_priority_app_table *app_ent,
1867 u8 idtype, u16 idval)
1868{
1869 if (!app_ent->valid)
1870 return false;
1871
1872 switch (idtype) {
1873 case DCB_APP_IDTYPE_ETHTYPE:
1874 if (app_ent->traffic_type != TRAFFIC_TYPE_ETH)
1875 return false;
1876 break;
1877 case DCB_APP_IDTYPE_PORTNUM:
1878 if (app_ent->traffic_type != TRAFFIC_TYPE_PORT)
1879 return false;
1880 break;
1881 default:
1882 return false;
1883 }
1884 if (app_ent->app_id != idval)
1885 return false;
1886
1887 return true;
1888}
1889
1890static int bnx2x_set_admin_app_up(struct bnx2x *bp, u8 idtype, u16 idval, u8 up)
1891{
1892 int i, ff;
1893
1894 /* iterate over the app entries looking for idtype and idval */
1895 for (i = 0, ff = -1; i < 4; i++) {
1896 struct bnx2x_admin_priority_app_table *app_ent =
1897 &bp->dcbx_config_params.admin_priority_app_table[i];
1898 if (bnx2x_admin_app_is_equal(app_ent, idtype, idval))
1899 break;
1900
1901 if (ff < 0 && !app_ent->valid)
1902 ff = i;
1903 }
1904 if (i < 4)
1905 /* if found overwrite up */
1906 bp->dcbx_config_params.
1907 admin_priority_app_table[i].priority = up;
1908 else if (ff >= 0)
1909 /* not found use first-free */
1910 bnx2x_admin_app_set_ent(
1911 &bp->dcbx_config_params.admin_priority_app_table[ff],
1912 idtype, idval, up);
1913 else
1914 /* app table is full */
1915 return -EBUSY;
1916
1917 /* up configured, if not 0 make sure feature is enabled */
1918 if (up)
1919 bp->dcbx_config_params.admin_application_priority_tx_enable = 1;
1920
1921 return 0;
1922}
1923
1924static u8 bnx2x_dcbnl_set_app_up(struct net_device *netdev, u8 idtype,
1925 u16 idval, u8 up)
1926{
1927 struct bnx2x *bp = netdev_priv(netdev);
1928
1929 DP(NETIF_MSG_LINK, "app_type %d, app_id %x, prio bitmap %d\n",
1930 idtype, idval, up);
1931
1932 if (!bnx2x_dcbnl_set_valid(bp))
1933 return -EINVAL;
1934
1935 /* verify idtype */
1936 switch (idtype) {
1937 case DCB_APP_IDTYPE_ETHTYPE:
1938 case DCB_APP_IDTYPE_PORTNUM:
1939 break;
1940 default:
1941 return -EINVAL;
1942 }
1943 return bnx2x_set_admin_app_up(bp, idtype, idval, up);
1944}
1945
1946static u8 bnx2x_dcbnl_get_app_up(struct net_device *netdev, u8 idtype,
1947 u16 idval)
1948{
1949 int i;
1950 u8 up = 0;
1951
1952 struct bnx2x *bp = netdev_priv(netdev);
1953 DP(NETIF_MSG_LINK, "app_type %d, app_id 0x%x\n", idtype, idval);
1954
1955 /* iterate over the app entries looking for idtype and idval */
1956 for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++)
1957 if (bnx2x_app_is_equal(&bp->dcbx_local_feat.app.app_pri_tbl[i],
1958 idtype, idval))
1959 break;
1960
1961 if (i < DCBX_MAX_APP_PROTOCOL)
1962 /* if found return up */
1963 up = bp->dcbx_local_feat.app.app_pri_tbl[i].pri_bitmap;
1964 else
1965 DP(NETIF_MSG_LINK, "app not found\n");
1966
1967 return up;
1968}
1969
1970static u8 bnx2x_dcbnl_get_dcbx(struct net_device *netdev)
1971{
1972 struct bnx2x *bp = netdev_priv(netdev);
1973 u8 state;
1974
1975 state = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_CEE;
1976
1977 if (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_ON_NEG_OFF)
1978 state |= DCB_CAP_DCBX_STATIC;
1979
1980 return state;
1981}
1982
1983static u8 bnx2x_dcbnl_set_dcbx(struct net_device *netdev, u8 state)
1984{
1985 struct bnx2x *bp = netdev_priv(netdev);
1986 DP(NETIF_MSG_LINK, "state = %02x\n", state);
1987
1988 /* set dcbx mode */
1989
1990 if ((state & BNX2X_DCBX_CAPS) != state) {
1991 BNX2X_ERR("Requested DCBX mode %x is beyond advertised "
1992 "capabilities\n", state);
1993 return 1;
1994 }
1995
1996 if (bp->dcb_state != BNX2X_DCB_STATE_ON) {
1997 BNX2X_ERR("DCB turned off, DCBX configuration is invalid\n");
1998 return 1;
1999 }
2000
2001 if (state & DCB_CAP_DCBX_STATIC)
2002 bp->dcbx_enabled = BNX2X_DCBX_ENABLED_ON_NEG_OFF;
2003 else
2004 bp->dcbx_enabled = BNX2X_DCBX_ENABLED_ON_NEG_ON;
2005
2006 bp->dcbx_mode_uset = true;
2007 return 0;
2008}
2009
2010
2011static u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid,
2012 u8 *flags)
2013{
2014 struct bnx2x *bp = netdev_priv(netdev);
2015 u8 rval = 0;
2016
2017 DP(NETIF_MSG_LINK, "featid %d\n", featid);
2018
2019 if (bp->dcb_state) {
2020 *flags = 0;
2021 switch (featid) {
2022 case DCB_FEATCFG_ATTR_PG:
2023 if (bp->dcbx_local_feat.ets.enabled)
2024 *flags |= DCB_FEATCFG_ENABLE;
2025 if (bp->dcbx_error & DCBX_LOCAL_ETS_ERROR)
2026 *flags |= DCB_FEATCFG_ERROR;
2027 break;
2028 case DCB_FEATCFG_ATTR_PFC:
2029 if (bp->dcbx_local_feat.pfc.enabled)
2030 *flags |= DCB_FEATCFG_ENABLE;
2031 if (bp->dcbx_error & (DCBX_LOCAL_PFC_ERROR |
2032 DCBX_LOCAL_PFC_MISMATCH))
2033 *flags |= DCB_FEATCFG_ERROR;
2034 break;
2035 case DCB_FEATCFG_ATTR_APP:
2036 if (bp->dcbx_local_feat.app.enabled)
2037 *flags |= DCB_FEATCFG_ENABLE;
2038 if (bp->dcbx_error & (DCBX_LOCAL_APP_ERROR |
2039 DCBX_LOCAL_APP_MISMATCH))
2040 *flags |= DCB_FEATCFG_ERROR;
2041 break;
2042 default:
2043 rval = -EINVAL;
2044 break;
2045 }
2046 } else
2047 rval = -EINVAL;
2048
2049 return rval;
2050}
2051
2052static u8 bnx2x_dcbnl_set_featcfg(struct net_device *netdev, int featid,
2053 u8 flags)
2054{
2055 struct bnx2x *bp = netdev_priv(netdev);
2056 u8 rval = 0;
2057
2058 DP(NETIF_MSG_LINK, "featid = %d flags = %02x\n", featid, flags);
2059
2060 /* ignore the 'advertise' flag */
2061 if (bnx2x_dcbnl_set_valid(bp)) {
2062 switch (featid) {
2063 case DCB_FEATCFG_ATTR_PG:
2064 bp->dcbx_config_params.admin_ets_enable =
2065 flags & DCB_FEATCFG_ENABLE ? 1 : 0;
2066 bp->dcbx_config_params.admin_ets_willing =
2067 flags & DCB_FEATCFG_WILLING ? 1 : 0;
2068 break;
2069 case DCB_FEATCFG_ATTR_PFC:
2070 bp->dcbx_config_params.admin_pfc_enable =
2071 flags & DCB_FEATCFG_ENABLE ? 1 : 0;
2072 bp->dcbx_config_params.admin_pfc_willing =
2073 flags & DCB_FEATCFG_WILLING ? 1 : 0;
2074 break;
2075 case DCB_FEATCFG_ATTR_APP:
2076 /* ignore enable, always enabled */
2077 bp->dcbx_config_params.admin_app_priority_willing =
2078 flags & DCB_FEATCFG_WILLING ? 1 : 0;
2079 break;
2080 default:
2081 rval = -EINVAL;
2082 break;
2083 }
2084 } else
2085 rval = -EINVAL;
2086
2087 return rval;
2088}
2089
2090const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops = {
2091 .getstate = bnx2x_dcbnl_get_state,
2092 .setstate = bnx2x_dcbnl_set_state,
2093 .getpermhwaddr = bnx2x_dcbnl_get_perm_hw_addr,
2094 .setpgtccfgtx = bnx2x_dcbnl_set_pg_tccfg_tx,
2095 .setpgbwgcfgtx = bnx2x_dcbnl_set_pg_bwgcfg_tx,
2096 .setpgtccfgrx = bnx2x_dcbnl_set_pg_tccfg_rx,
2097 .setpgbwgcfgrx = bnx2x_dcbnl_set_pg_bwgcfg_rx,
2098 .getpgtccfgtx = bnx2x_dcbnl_get_pg_tccfg_tx,
2099 .getpgbwgcfgtx = bnx2x_dcbnl_get_pg_bwgcfg_tx,
2100 .getpgtccfgrx = bnx2x_dcbnl_get_pg_tccfg_rx,
2101 .getpgbwgcfgrx = bnx2x_dcbnl_get_pg_bwgcfg_rx,
2102 .setpfccfg = bnx2x_dcbnl_set_pfc_cfg,
2103 .getpfccfg = bnx2x_dcbnl_get_pfc_cfg,
2104 .setall = bnx2x_dcbnl_set_all,
2105 .getcap = bnx2x_dcbnl_get_cap,
2106 .getnumtcs = bnx2x_dcbnl_get_numtcs,
2107 .setnumtcs = bnx2x_dcbnl_set_numtcs,
2108 .getpfcstate = bnx2x_dcbnl_get_pfc_state,
2109 .setpfcstate = bnx2x_dcbnl_set_pfc_state,
2110 .getapp = bnx2x_dcbnl_get_app_up,
2111 .setapp = bnx2x_dcbnl_set_app_up,
2112 .getdcbx = bnx2x_dcbnl_get_dcbx,
2113 .setdcbx = bnx2x_dcbnl_set_dcbx,
2114 .getfeatcfg = bnx2x_dcbnl_get_featcfg,
2115 .setfeatcfg = bnx2x_dcbnl_set_featcfg,
2116};
2117
2118#endif /* BCM_DCB */
diff --git a/drivers/net/bnx2x/bnx2x_dcb.h b/drivers/net/bnx2x/bnx2x_dcb.h
index 8dea56b511f5..f650f98e4092 100644
--- a/drivers/net/bnx2x/bnx2x_dcb.h
+++ b/drivers/net/bnx2x/bnx2x_dcb.h
@@ -51,7 +51,6 @@ struct bnx2x_dcbx_pfc_params {
51}; 51};
52 52
53struct bnx2x_dcbx_port_params { 53struct bnx2x_dcbx_port_params {
54 u32 dcbx_enabled;
55 struct bnx2x_dcbx_pfc_params pfc; 54 struct bnx2x_dcbx_pfc_params pfc;
56 struct bnx2x_dcbx_pg_params ets; 55 struct bnx2x_dcbx_pg_params ets;
57 struct bnx2x_dcbx_app_params app; 56 struct bnx2x_dcbx_app_params app;
@@ -88,8 +87,6 @@ struct bnx2x_admin_priority_app_table {
88 * DCBX protocol configuration parameters. 87 * DCBX protocol configuration parameters.
89 ******************************************************************************/ 88 ******************************************************************************/
90struct bnx2x_config_dcbx_params { 89struct bnx2x_config_dcbx_params {
91 u32 dcb_enable;
92 u32 admin_dcbx_enable;
93 u32 overwrite_settings; 90 u32 overwrite_settings;
94 u32 admin_dcbx_version; 91 u32 admin_dcbx_version;
95 u32 admin_ets_enable; 92 u32 admin_ets_enable;
@@ -182,6 +179,7 @@ struct bnx2x;
182void bnx2x_dcb_init_intmem_pfc(struct bnx2x *bp); 179void bnx2x_dcb_init_intmem_pfc(struct bnx2x *bp);
183void bnx2x_dcbx_update(struct work_struct *work); 180void bnx2x_dcbx_update(struct work_struct *work);
184void bnx2x_dcbx_init_params(struct bnx2x *bp); 181void bnx2x_dcbx_init_params(struct bnx2x *bp);
182void bnx2x_dcbx_set_state(struct bnx2x *bp, bool dcb_on, u32 dcbx_enabled);
185 183
186enum { 184enum {
187 BNX2X_DCBX_STATE_NEG_RECEIVED = 0x1, 185 BNX2X_DCBX_STATE_NEG_RECEIVED = 0x1,
@@ -190,4 +188,9 @@ enum {
190}; 188};
191void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state); 189void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state);
192 190
191/* DCB netlink */
192#ifdef BCM_DCB
193extern const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops;
194#endif /* BCM_DCB */
195
193#endif /* BNX2X_DCB_H */ 196#endif /* BNX2X_DCB_H */
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index cf54427a8d80..489a5512a04d 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -3107,7 +3107,8 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn)
3107 bnx2x_pmf_update(bp); 3107 bnx2x_pmf_update(bp);
3108 3108
3109 if (bp->port.pmf && 3109 if (bp->port.pmf &&
3110 (val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS)) 3110 (val & DRV_STATUS_DCBX_NEGOTIATION_RESULTS) &&
3111 bp->dcbx_enabled > 0)
3111 /* start dcbx state machine */ 3112 /* start dcbx state machine */
3112 bnx2x_dcbx_set_params(bp, 3113 bnx2x_dcbx_set_params(bp,
3113 BNX2X_DCBX_STATE_NEG_RECEIVED); 3114 BNX2X_DCBX_STATE_NEG_RECEIVED);
@@ -8795,6 +8796,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
8795 bp->timer.data = (unsigned long) bp; 8796 bp->timer.data = (unsigned long) bp;
8796 bp->timer.function = bnx2x_timer; 8797 bp->timer.function = bnx2x_timer;
8797 8798
8799 bnx2x_dcbx_set_state(bp, true, BNX2X_DCBX_ENABLED_ON_NEG_ON);
8798 bnx2x_dcbx_init_params(bp); 8800 bnx2x_dcbx_init_params(bp);
8799 8801
8800 return rc; 8802 return rc;
@@ -9146,6 +9148,10 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
9146 dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO_ECN); 9148 dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
9147 dev->vlan_features |= NETIF_F_TSO6; 9149 dev->vlan_features |= NETIF_F_TSO6;
9148 9150
9151#ifdef BCM_DCB
9152 dev->dcbnl_ops = &bnx2x_dcbnl_ops;
9153#endif
9154
9149 /* get_port_hwinfo() will set prtad and mmds properly */ 9155 /* get_port_hwinfo() will set prtad and mmds properly */
9150 bp->mdio.prtad = MDIO_PRTAD_NONE; 9156 bp->mdio.prtad = MDIO_PRTAD_NONE;
9151 bp->mdio.mmds = 0; 9157 bp->mdio.mmds = 0;