aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxiong <xiong@qca.qualcomm.com>2013-01-19 13:15:01 +0800
committerLuis R. Rodriguez <mcgrof@do-not-panic.com>2013-01-24 07:56:06 -0800
commit4a06ca7ef3adaa2841e2d4ca2e8e42111aff2652 (patch)
tree0fd067f5c70f77e7fa2b72111b15281fb0083bf1
parent1d7338dafc4b77b3d6cd9c561cf0b89c9d394398 (diff)
downloadalx-4a06ca7ef3adaa2841e2d4ca2e8e42111aff2652.tar.gz
alx: fix tx-timeout after sleep/resume
tx-timeout after sleep/resume is caused by wrong interrupt mode used after resume. Signed-off-by: xiong <xiong@qca.qualcomm.com> Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
-rw-r--r--src/alx_hw.h13
-rw-r--r--src/alx_main.c237
2 files changed, 136 insertions, 114 deletions
diff --git a/src/alx_hw.h b/src/alx_hw.h
index 8790869..2d16aff 100644
--- a/src/alx_hw.h
+++ b/src/alx_hw.h
@@ -382,6 +382,19 @@ struct alx_hw_stats {
(_speed) == SPEED_10 + HALF_DUPLEX ? ADVERTISED_10baseT_Half : \
0)
+#define speed_desc(_s) (\
+ (_s) == SPEED_1000 + FULL_DUPLEX ? \
+ "1 Gbps Full" : \
+ (_s) == SPEED_100 + FULL_DUPLEX ? \
+ "100 Mbps Full" : \
+ (_s) == SPEED_100 + HALF_DUPLEX ? \
+ "100 Mbps Half" : \
+ (_s) == SPEED_10 + FULL_DUPLEX ? \
+ "10 Mbps Full" : \
+ (_s) == SPEED_10 + HALF_DUPLEX ? \
+ "10 Mbps Half" : \
+ "Unknown speed")
+
/* for FlowControl */
#define ALX_FC_RX 0x01
#define ALX_FC_TX 0x02
diff --git a/src/alx_main.c b/src/alx_main.c
index 60f52e6..322aea3 100644
--- a/src/alx_main.c
+++ b/src/alx_main.c
@@ -34,7 +34,7 @@
#define DRV_MAJ 1
#define DRV_MIN 2
#define DRV_PATCH 1
-#define DRV_MODULE_VER \
+#define DRV_MODULE_VER \
__stringify(DRV_MAJ) "." __stringify(DRV_MIN) "." \
__stringify(DRV_PATCH)
@@ -935,8 +935,6 @@ static int alx_request_irq(struct alx_adapter *adpt)
adpt->nr_vec = 1;
adpt->nr_hwrxq = 1;
alx_configure_rss(hw, false);
- netif_set_real_num_tx_queues(adpt->netdev, adpt->nr_txq);
- netif_set_real_num_rx_queues(adpt->netdev, adpt->nr_rxq);
if (!pci_enable_msi(pdev))
ALX_FLAG_SET(adpt, USING_MSI);
@@ -968,12 +966,14 @@ static int alx_request_irq(struct alx_adapter *adpt)
out:
if (likely(!err)) {
alx_config_vector_mapping(adpt);
- netif_info(adpt, intr, adpt->netdev,
+
+ netif_info(adpt, drv, adpt->netdev,
"nr_rxq=%d, nr_txq=%d, nr_napi=%d, nr_vec=%d\n",
adpt->nr_rxq, adpt->nr_txq,
adpt->nr_napi, adpt->nr_vec);
- netif_info(adpt, intr, adpt->netdev,
- "Interrupt Mode: %s\n",
+ netif_info(adpt, drv, adpt->netdev,
+ "flags=%lX, Interrupt Mode: %s\n",
+ adpt->flags,
ALX_FLAG(adpt, USING_MSIX) ? "MSIX" :
ALX_FLAG(adpt, USING_MSI) ? "MSI" : "INTx");
} else
@@ -1217,10 +1217,12 @@ static void alx_netif_stop(struct alx_adapter *adpt)
int i;
adpt->netdev->trans_start = jiffies;
- netif_carrier_off(adpt->netdev);
- netif_tx_disable(adpt->netdev);
- for (i = 0; i < adpt->nr_napi; i++)
- napi_disable(&adpt->qnapi[i]->napi);
+ if (netif_carrier_ok(adpt->netdev)) {
+ netif_carrier_off(adpt->netdev);
+ netif_tx_disable(adpt->netdev);
+ for (i = 0; i < adpt->nr_napi; i++)
+ napi_disable(&adpt->qnapi[i]->napi);
+ }
}
static void alx_netif_start(struct alx_adapter *adpt)
@@ -1233,11 +1235,84 @@ static void alx_netif_start(struct alx_adapter *adpt)
netif_carrier_on(adpt->netdev);
}
-static int __alx_open(struct alx_adapter *adpt)
+static bool alx_enable_msix(struct alx_adapter *adpt)
+{
+ int nr_txq, nr_rxq, vec_req;
+ int i, err;
+
+ nr_txq = min_t(int, num_online_cpus(), ALX_MAX_TX_QUEUES);
+ nr_rxq = min_t(int, num_online_cpus(), ALX_MAX_RX_QUEUES);
+ nr_rxq = rounddown_pow_of_two(nr_rxq);
+ /* one more vector for PHY link change & timer & other events */
+ vec_req = max_t(int, nr_txq, nr_rxq) + 1;
+
+ if (vec_req <= 2) {
+ netif_info(adpt, intr, adpt->netdev,
+ "cpu core num is less, MSI-X isn't necessary\n");
+ return false;
+ }
+
+ adpt->msix_ent = kcalloc(vec_req,
+ sizeof(struct msix_entry),
+ GFP_KERNEL);
+ if (!adpt->msix_ent) {
+ netif_warn(adpt, intr, adpt->netdev,
+ "can't alloc msix entries\n");
+ return false;
+ }
+ for (i = 0; i < vec_req; i++)
+ adpt->msix_ent[i].entry = i;
+
+ err = pci_enable_msix(adpt->pdev, adpt->msix_ent, vec_req);
+ if (err) {
+ kfree(adpt->msix_ent);
+ adpt->msix_ent = NULL;
+ netif_warn(adpt, intr, adpt->netdev,
+ "can't enable MSI-X interrupt\n");
+ return false;
+ }
+
+ adpt->nr_txq = nr_txq;
+ adpt->nr_rxq = nr_rxq;
+ adpt->nr_vec = vec_req;
+ adpt->nr_napi = vec_req - 1;
+ adpt->nr_hwrxq = ALX_CAP(&adpt->hw, MRQ) ? adpt->nr_rxq : 1;
+
+ return true;
+}
+
+static void alx_init_intr(struct alx_adapter *adpt)
+{
+ struct alx_hw *hw = &adpt->hw;
+
+ if ((ALX_CAP(hw, MTQ) || ALX_CAP(hw, RSS)) && ALX_CAP(hw, MSIX)) {
+ if (alx_enable_msix(adpt))
+ ALX_FLAG_SET(adpt, USING_MSIX);
+ }
+ if (!ALX_FLAG(adpt, USING_MSIX)) {
+ adpt->nr_txq = ALX_CAP(hw, MTQ) ? ALX_MAX_TX_QUEUES : 1;
+ adpt->nr_rxq = 1;
+ adpt->nr_napi = 1;
+ adpt->nr_vec = 1;
+ adpt->nr_hwrxq = 1;
+
+ if (!pci_enable_msi(adpt->pdev))
+ ALX_FLAG_SET(adpt, USING_MSI);
+ }
+}
+
+static int __alx_open(struct alx_adapter *adpt, bool resume)
{
int err;
- netif_carrier_off(adpt->netdev);
+ /* decide interrupt mode, some resources allocation depend on it */
+ alx_init_intr(adpt);
+
+ /* init rss indirection table */
+ alx_init_def_rss_idt(adpt);
+
+ if (!resume)
+ netif_carrier_off(adpt->netdev);
/* allocate all memory resources */
err = alx_setup_all_ring_resources(adpt);
@@ -1251,6 +1326,14 @@ static int __alx_open(struct alx_adapter *adpt)
if (err)
goto err_out;
+ /* netif_set_real_num_tx/rx_queues need rtnl_lock held */
+ if (resume)
+ rtnl_lock();
+ netif_set_real_num_tx_queues(adpt->netdev, adpt->nr_txq);
+ netif_set_real_num_rx_queues(adpt->netdev, adpt->nr_rxq);
+ if (resume)
+ rtnl_unlock();
+
ALX_FLAG_CLEAR(adpt, HALT);
/* clear old interrupts */
@@ -1258,7 +1341,8 @@ static int __alx_open(struct alx_adapter *adpt)
alx_irq_enable(adpt);
- netif_tx_start_all_queues(adpt->netdev);
+ if (!resume)
+ netif_tx_start_all_queues(adpt->netdev);
ALX_FLAG_SET(adpt, TASK_CHK_LINK);
alx_schedule_work(adpt);
@@ -1279,7 +1363,11 @@ static void alx_halt(struct alx_adapter *adpt)
alx_cancel_work(adpt);
alx_netif_stop(adpt);
+ hw->link_up = false;
+ hw->link_speed = SPEED_0;
+
alx_reset_mac(hw);
+
/* disable l0s/l1 */
alx_enable_aspm(hw, false, false);
alx_irq_disable(adpt);
@@ -1311,76 +1399,6 @@ static void __alx_stop(struct alx_adapter *adpt)
alx_free_all_ring_resources(adpt);
}
-static bool alx_enable_msix(struct alx_adapter *adpt)
-{
- int nr_txq, nr_rxq, vec_req;
- int i, err;
-
- nr_txq = min_t(int, num_online_cpus(), ALX_MAX_TX_QUEUES);
- nr_rxq = min_t(int, num_online_cpus(), ALX_MAX_RX_QUEUES);
- nr_rxq = rounddown_pow_of_two(nr_rxq);
- /* one more vector for PHY link change & timer & other events */
- vec_req = max_t(int, nr_txq, nr_rxq) + 1;
-
- if (vec_req <= 2) {
- netif_info(adpt, intr, adpt->netdev,
- "cpu core num is less, MSI-X isn't necessary\n");
- return false;
- }
-
- adpt->msix_ent = kcalloc(vec_req,
- sizeof(struct msix_entry),
- GFP_KERNEL);
- if (!adpt->msix_ent) {
- netif_warn(adpt, intr, adpt->netdev,
- "can't alloc msix entries\n");
- return false;
- }
- for (i = 0; i < vec_req; i++)
- adpt->msix_ent[i].entry = i;
-
- err = pci_enable_msix(adpt->pdev, adpt->msix_ent, vec_req);
- if (err) {
- kfree(adpt->msix_ent);
- adpt->msix_ent = NULL;
- netif_warn(adpt, intr, adpt->netdev,
- "can't enable MSI-X interrupt\n");
- return false;
- }
-
- adpt->nr_txq = nr_txq;
- adpt->nr_rxq = nr_rxq;
- adpt->nr_vec = vec_req;
- adpt->nr_napi = vec_req - 1;
- adpt->nr_hwrxq = ALX_CAP(&adpt->hw, MRQ) ? adpt->nr_rxq : 1;
-
- return true;
-}
-
-static void alx_init_intr(struct alx_adapter *adpt)
-{
- struct alx_hw *hw = &adpt->hw;
-
- if ((ALX_CAP(hw, MTQ) || ALX_CAP(hw, RSS)) && ALX_CAP(hw, MSIX)) {
- if (alx_enable_msix(adpt))
- ALX_FLAG_SET(adpt, USING_MSIX);
- }
- if (!ALX_FLAG(adpt, USING_MSIX)) {
- adpt->nr_txq = ALX_CAP(hw, MTQ) ? ALX_MAX_TX_QUEUES : 1;
- adpt->nr_rxq = 1;
- adpt->nr_napi = 1;
- adpt->nr_vec = 1;
- adpt->nr_hwrxq = 1;
-
- if (!pci_enable_msi(adpt->pdev))
- ALX_FLAG_SET(adpt, USING_MSI);
- }
-
- netif_set_real_num_tx_queues(adpt->netdev, adpt->nr_txq);
- netif_set_real_num_rx_queues(adpt->netdev, adpt->nr_rxq);
-
-}
-
static void alx_init_ring_ptrs(struct alx_adapter *adpt)
{
struct alx_hw *hw = &adpt->hw;
@@ -1431,22 +1449,9 @@ static void alx_init_ring_ptrs(struct alx_adapter *adpt)
static void alx_show_speed(struct alx_adapter *adpt, u16 speed)
{
- char *desc;
-
- desc = speed == SPEED_1000 + FULL_DUPLEX ?
- "1 Gbps Duplex Full" :
- speed == SPEED_100 + FULL_DUPLEX ?
- "100 Mbps Duplex Full" :
- speed == SPEED_100 + HALF_DUPLEX ?
- "100 Mbps Duplex Half" :
- speed == SPEED_10 + FULL_DUPLEX ?
- "10 Mbps Duplex Full" :
- speed == SPEED_10 + HALF_DUPLEX ?
- "10 Mbps Duplex Half" :
- "Unknown speed";
netif_info(adpt, link, adpt->netdev,
"NIC Link Up: %s\n",
- desc);
+ speed_desc(speed));
}
static int alx_reinit_rings(struct alx_adapter *adpt)
@@ -1569,13 +1574,7 @@ static int alx_open(struct net_device *netdev)
if (ALX_FLAG(adpt, TESTING))
return -EBUSY;
- /* decide interrupt mode, some resources allocation depend on it */
- alx_init_intr(adpt);
-
- /* init rss indirection table */
- alx_init_def_rss_idt(adpt);
-
- err = __alx_open(adpt);
+ err = __alx_open(adpt, false);
return err;
}
@@ -1587,8 +1586,6 @@ static int alx_stop(struct net_device *netdev)
WARN_ON(ALX_FLAG(adpt, RESETING));
- netif_info(adpt, ifdown, adpt->netdev, "alx_stop\n");
-
__alx_stop(adpt);
return 0;
@@ -1616,14 +1613,18 @@ static int __alx_shutdown(struct pci_dev *pdev, bool *wol_en)
if (!err)
err = alx_clear_phy_intr(hw);
if (!err)
- err = alx_config_wol(hw);
- if (!err)
err = alx_pre_suspend(hw, speed);
+ if (!err)
+ err = alx_config_wol(hw);
if (err)
goto out;
*wol_en = false;
if (hw->sleep_ctrl & ALX_SLEEP_ACTIVE) {
+ netif_info(adpt, wol, netdev,
+ "wol: ctrl=%X, speed=%X\n",
+ hw->sleep_ctrl, speed);
+
device_set_wakeup_enable(&pdev->dev, true);
*wol_en = true;
}
@@ -1655,7 +1656,6 @@ static void alx_shutdown(struct pci_dev *pdev)
}
}
-
#ifdef CONFIG_PM_SLEEP
static int alx_suspend(struct device *dev)
{
@@ -1700,6 +1700,7 @@ static int alx_resume(struct device *dev)
hw->link_up = false;
hw->link_speed = SPEED_0;
+ hw->imask = ALX_ISR_MISC;
alx_reset_pcie(hw);
alx_reset_phy(hw, !hw->hib_patch);
@@ -1719,7 +1720,7 @@ static int alx_resume(struct device *dev)
}
if (netif_running(netdev)) {
- err = __alx_open(adpt);
+ err = __alx_open(adpt, true);
if (err)
return err;
}
@@ -2320,8 +2321,8 @@ static void alx_dump_state(struct alx_adapter *adpt)
for (i = 0; i < adpt->nr_txq; i++) {
txq = adpt->qnapi[i]->txq;
- begin = txq->pidx >= 16 ? (txq->pidx - 16) :
- (txq->count + txq->pidx - 16);
+ begin = txq->pidx >= 8 ? (txq->pidx - 8) :
+ (txq->count + txq->pidx - 8);
end = txq->pidx + 4;
if (end >= txq->count)
end -= txq->count;
@@ -2343,8 +2344,8 @@ static void alx_dump_state(struct alx_adapter *adpt)
netif_err(adpt, tx_err, adpt->netdev,
"---------------dump registers-----------------\n");
- end = 0x2000;
- for (begin = 0; begin < end; begin += 16) {
+ end = 0x1800;
+ for (begin = 0x1400; begin < end; begin += 16) {
u32 v1, v2, v3, v4;
ALX_MEM_R32(hw, begin, &v1);
@@ -2578,6 +2579,8 @@ alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* reset PHY to a known stable status */
if (!phy_cfged)
alx_reset_phy(hw, !hw->hib_patch);
+ else
+ dev_info(&pdev->dev, "PHY has been configured.\n");
/* reset mac/dma controller */
err = alx_reset_mac(hw);
@@ -2706,6 +2709,8 @@ static pci_ers_result_t alx_pci_error_detected(struct pci_dev *pdev,
struct net_device *netdev = adpt->netdev;
pci_ers_result_t rc = PCI_ERS_RESULT_NEED_RESET;
+ dev_info(&pdev->dev, "pci error detected\n");
+
rtnl_lock();
if (netif_running(netdev)) {
@@ -2729,6 +2734,8 @@ static pci_ers_result_t alx_pci_error_slot_reset(struct pci_dev *pdev)
struct alx_hw *hw = &adpt->hw;
pci_ers_result_t rc = PCI_ERS_RESULT_DISCONNECT;
+ dev_info(&pdev->dev, "pci error slot reset\n");
+
rtnl_lock();
if (pci_enable_device(pdev)) {
@@ -2757,6 +2764,8 @@ static void alx_pci_error_resume(struct pci_dev *pdev)
struct alx_adapter *adpt = pci_get_drvdata(pdev);
struct net_device *netdev = adpt->netdev;
+ dev_info(&pdev->dev, "pci error resume\n");
+
rtnl_lock();
if (netif_running(netdev)) {