diff options
Diffstat (limited to 'drivers/net/cxgb3/cxgb3_main.c')
-rw-r--r-- | drivers/net/cxgb3/cxgb3_main.c | 90 |
1 files changed, 81 insertions, 9 deletions
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 7ff834e45d6..d5538361055 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/workqueue.h> | 42 | #include <linux/workqueue.h> |
43 | #include <linux/proc_fs.h> | 43 | #include <linux/proc_fs.h> |
44 | #include <linux/rtnetlink.h> | 44 | #include <linux/rtnetlink.h> |
45 | #include <linux/firmware.h> | ||
45 | #include <asm/uaccess.h> | 46 | #include <asm/uaccess.h> |
46 | 47 | ||
47 | #include "common.h" | 48 | #include "common.h" |
@@ -707,6 +708,28 @@ static void bind_qsets(struct adapter *adap) | |||
707 | } | 708 | } |
708 | } | 709 | } |
709 | 710 | ||
711 | #define FW_FNAME "t3fw-%d.%d.bin" | ||
712 | |||
713 | static int upgrade_fw(struct adapter *adap) | ||
714 | { | ||
715 | int ret; | ||
716 | char buf[64]; | ||
717 | const struct firmware *fw; | ||
718 | struct device *dev = &adap->pdev->dev; | ||
719 | |||
720 | snprintf(buf, sizeof(buf), FW_FNAME, FW_VERSION_MAJOR, | ||
721 | FW_VERSION_MINOR); | ||
722 | ret = request_firmware(&fw, buf, dev); | ||
723 | if (ret < 0) { | ||
724 | dev_err(dev, "could not upgrade firmware: unable to load %s\n", | ||
725 | buf); | ||
726 | return ret; | ||
727 | } | ||
728 | ret = t3_load_fw(adap, fw->data, fw->size); | ||
729 | release_firmware(fw); | ||
730 | return ret; | ||
731 | } | ||
732 | |||
710 | /** | 733 | /** |
711 | * cxgb_up - enable the adapter | 734 | * cxgb_up - enable the adapter |
712 | * @adapter: adapter being enabled | 735 | * @adapter: adapter being enabled |
@@ -723,6 +746,8 @@ static int cxgb_up(struct adapter *adap) | |||
723 | 746 | ||
724 | if (!(adap->flags & FULL_INIT_DONE)) { | 747 | if (!(adap->flags & FULL_INIT_DONE)) { |
725 | err = t3_check_fw_version(adap); | 748 | err = t3_check_fw_version(adap); |
749 | if (err == -EINVAL) | ||
750 | err = upgrade_fw(adap); | ||
726 | if (err) | 751 | if (err) |
727 | goto out; | 752 | goto out; |
728 | 753 | ||
@@ -1031,7 +1056,11 @@ static char stats_strings[][ETH_GSTRING_LEN] = { | |||
1031 | "VLANinsertions ", | 1056 | "VLANinsertions ", |
1032 | "TxCsumOffload ", | 1057 | "TxCsumOffload ", |
1033 | "RxCsumGood ", | 1058 | "RxCsumGood ", |
1034 | "RxDrops " | 1059 | "RxDrops ", |
1060 | |||
1061 | "CheckTXEnToggled ", | ||
1062 | "CheckResets ", | ||
1063 | |||
1035 | }; | 1064 | }; |
1036 | 1065 | ||
1037 | static int get_stats_count(struct net_device *dev) | 1066 | static int get_stats_count(struct net_device *dev) |
@@ -1145,6 +1174,9 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, | |||
1145 | *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM); | 1174 | *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM); |
1146 | *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD); | 1175 | *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD); |
1147 | *data++ = s->rx_cong_drops; | 1176 | *data++ = s->rx_cong_drops; |
1177 | |||
1178 | *data++ = s->num_toggled; | ||
1179 | *data++ = s->num_resets; | ||
1148 | } | 1180 | } |
1149 | 1181 | ||
1150 | static inline void reg_block_dump(struct adapter *ap, void *buf, | 1182 | static inline void reg_block_dump(struct adapter *ap, void *buf, |
@@ -1362,23 +1394,27 @@ static int set_rx_csum(struct net_device *dev, u32 data) | |||
1362 | 1394 | ||
1363 | static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e) | 1395 | static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e) |
1364 | { | 1396 | { |
1365 | struct adapter *adapter = dev->priv; | 1397 | const struct adapter *adapter = dev->priv; |
1398 | const struct port_info *pi = netdev_priv(dev); | ||
1399 | const struct qset_params *q = &adapter->params.sge.qset[pi->first_qset]; | ||
1366 | 1400 | ||
1367 | e->rx_max_pending = MAX_RX_BUFFERS; | 1401 | e->rx_max_pending = MAX_RX_BUFFERS; |
1368 | e->rx_mini_max_pending = 0; | 1402 | e->rx_mini_max_pending = 0; |
1369 | e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS; | 1403 | e->rx_jumbo_max_pending = MAX_RX_JUMBO_BUFFERS; |
1370 | e->tx_max_pending = MAX_TXQ_ENTRIES; | 1404 | e->tx_max_pending = MAX_TXQ_ENTRIES; |
1371 | 1405 | ||
1372 | e->rx_pending = adapter->params.sge.qset[0].fl_size; | 1406 | e->rx_pending = q->fl_size; |
1373 | e->rx_mini_pending = adapter->params.sge.qset[0].rspq_size; | 1407 | e->rx_mini_pending = q->rspq_size; |
1374 | e->rx_jumbo_pending = adapter->params.sge.qset[0].jumbo_size; | 1408 | e->rx_jumbo_pending = q->jumbo_size; |
1375 | e->tx_pending = adapter->params.sge.qset[0].txq_size[0]; | 1409 | e->tx_pending = q->txq_size[0]; |
1376 | } | 1410 | } |
1377 | 1411 | ||
1378 | static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e) | 1412 | static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e) |
1379 | { | 1413 | { |
1380 | int i; | 1414 | int i; |
1415 | struct qset_params *q; | ||
1381 | struct adapter *adapter = dev->priv; | 1416 | struct adapter *adapter = dev->priv; |
1417 | const struct port_info *pi = netdev_priv(dev); | ||
1382 | 1418 | ||
1383 | if (e->rx_pending > MAX_RX_BUFFERS || | 1419 | if (e->rx_pending > MAX_RX_BUFFERS || |
1384 | e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS || | 1420 | e->rx_jumbo_pending > MAX_RX_JUMBO_BUFFERS || |
@@ -1393,9 +1429,8 @@ static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e) | |||
1393 | if (adapter->flags & FULL_INIT_DONE) | 1429 | if (adapter->flags & FULL_INIT_DONE) |
1394 | return -EBUSY; | 1430 | return -EBUSY; |
1395 | 1431 | ||
1396 | for (i = 0; i < SGE_QSETS; ++i) { | 1432 | q = &adapter->params.sge.qset[pi->first_qset]; |
1397 | struct qset_params *q = &adapter->params.sge.qset[i]; | 1433 | for (i = 0; i < pi->nqsets; ++i, ++q) { |
1398 | |||
1399 | q->rspq_size = e->rx_mini_pending; | 1434 | q->rspq_size = e->rx_mini_pending; |
1400 | q->fl_size = e->rx_pending; | 1435 | q->fl_size = e->rx_pending; |
1401 | q->jumbo_size = e->rx_jumbo_pending; | 1436 | q->jumbo_size = e->rx_jumbo_pending; |
@@ -2067,6 +2102,40 @@ static void check_link_status(struct adapter *adapter) | |||
2067 | } | 2102 | } |
2068 | } | 2103 | } |
2069 | 2104 | ||
2105 | static void check_t3b2_mac(struct adapter *adapter) | ||
2106 | { | ||
2107 | int i; | ||
2108 | |||
2109 | rtnl_lock(); /* synchronize with ifdown */ | ||
2110 | for_each_port(adapter, i) { | ||
2111 | struct net_device *dev = adapter->port[i]; | ||
2112 | struct port_info *p = netdev_priv(dev); | ||
2113 | int status; | ||
2114 | |||
2115 | if (!netif_running(dev)) | ||
2116 | continue; | ||
2117 | |||
2118 | status = 0; | ||
2119 | if (netif_running(dev)) | ||
2120 | status = t3b2_mac_watchdog_task(&p->mac); | ||
2121 | if (status == 1) | ||
2122 | p->mac.stats.num_toggled++; | ||
2123 | else if (status == 2) { | ||
2124 | struct cmac *mac = &p->mac; | ||
2125 | |||
2126 | t3_mac_set_mtu(mac, dev->mtu); | ||
2127 | t3_mac_set_address(mac, 0, dev->dev_addr); | ||
2128 | cxgb_set_rxmode(dev); | ||
2129 | t3_link_start(&p->phy, mac, &p->link_config); | ||
2130 | t3_mac_enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX); | ||
2131 | t3_port_intr_enable(adapter, p->port_id); | ||
2132 | p->mac.stats.num_resets++; | ||
2133 | } | ||
2134 | } | ||
2135 | rtnl_unlock(); | ||
2136 | } | ||
2137 | |||
2138 | |||
2070 | static void t3_adap_check_task(struct work_struct *work) | 2139 | static void t3_adap_check_task(struct work_struct *work) |
2071 | { | 2140 | { |
2072 | struct adapter *adapter = container_of(work, struct adapter, | 2141 | struct adapter *adapter = container_of(work, struct adapter, |
@@ -2087,6 +2156,9 @@ static void t3_adap_check_task(struct work_struct *work) | |||
2087 | adapter->check_task_cnt = 0; | 2156 | adapter->check_task_cnt = 0; |
2088 | } | 2157 | } |
2089 | 2158 | ||
2159 | if (p->rev == T3_REV_B2) | ||
2160 | check_t3b2_mac(adapter); | ||
2161 | |||
2090 | /* Schedule the next check update if any port is active. */ | 2162 | /* Schedule the next check update if any port is active. */ |
2091 | spin_lock(&adapter->work_lock); | 2163 | spin_lock(&adapter->work_lock); |
2092 | if (adapter->open_device_map & PORT_MASK) | 2164 | if (adapter->open_device_map & PORT_MASK) |