|
@@ -618,6 +618,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
|
|
struct wmi_vring_cfg_done_event cmd;
|
|
struct wmi_vring_cfg_done_event cmd;
|
|
} __packed reply;
|
|
} __packed reply;
|
|
struct vring *vring = &wil->vring_tx[id];
|
|
struct vring *vring = &wil->vring_tx[id];
|
|
|
|
+ struct vring_tx_data *txdata = &wil->vring_tx_data[id];
|
|
|
|
|
|
if (vring->va) {
|
|
if (vring->va) {
|
|
wil_err(wil, "Tx ring [%d] already allocated\n", id);
|
|
wil_err(wil, "Tx ring [%d] already allocated\n", id);
|
|
@@ -625,6 +626,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ memset(txdata, 0, sizeof(*txdata));
|
|
vring->size = size;
|
|
vring->size = size;
|
|
rc = wil_vring_alloc(wil, vring);
|
|
rc = wil_vring_alloc(wil, vring);
|
|
if (rc)
|
|
if (rc)
|
|
@@ -648,6 +650,8 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
|
|
}
|
|
}
|
|
vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);
|
|
vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);
|
|
|
|
|
|
|
|
+ txdata->enabled = 1;
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
out_free:
|
|
out_free:
|
|
wil_vring_free(wil, vring, 1);
|
|
wil_vring_free(wil, vring, 1);
|
|
@@ -660,9 +664,16 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
|
|
{
|
|
{
|
|
struct vring *vring = &wil->vring_tx[id];
|
|
struct vring *vring = &wil->vring_tx[id];
|
|
|
|
|
|
|
|
+ WARN_ON(!mutex_is_locked(&wil->mutex));
|
|
|
|
+
|
|
if (!vring->va)
|
|
if (!vring->va)
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
+ /* make sure NAPI won't touch this vring */
|
|
|
|
+ wil->vring_tx_data[id].enabled = 0;
|
|
|
|
+ if (test_bit(wil_status_napi_en, &wil->status))
|
|
|
|
+ napi_synchronize(&wil->napi_tx);
|
|
|
|
+
|
|
wil_vring_free(wil, vring, 1);
|
|
wil_vring_free(wil, vring, 1);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1028,6 +1039,7 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
|
|
struct net_device *ndev = wil_to_ndev(wil);
|
|
struct net_device *ndev = wil_to_ndev(wil);
|
|
struct device *dev = wil_to_dev(wil);
|
|
struct device *dev = wil_to_dev(wil);
|
|
struct vring *vring = &wil->vring_tx[ringid];
|
|
struct vring *vring = &wil->vring_tx[ringid];
|
|
|
|
+ struct vring_tx_data *txdata = &wil->vring_tx_data[ringid];
|
|
int done = 0;
|
|
int done = 0;
|
|
int cid = wil->vring2cid_tid[ringid][0];
|
|
int cid = wil->vring2cid_tid[ringid][0];
|
|
struct wil_net_stats *stats = &wil->sta[cid].stats;
|
|
struct wil_net_stats *stats = &wil->sta[cid].stats;
|
|
@@ -1038,6 +1050,11 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (!txdata->enabled) {
|
|
|
|
+ wil_info(wil, "Tx irq[%d]: vring disabled\n", ringid);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid);
|
|
wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid);
|
|
|
|
|
|
while (!wil_vring_is_empty(vring)) {
|
|
while (!wil_vring_is_empty(vring)) {
|