Skip to content

Commit 9b894cd

Browse files
committed
Merge branch 'aquantia-fixes'
Igor Russkikh says: ==================== Aquantia atlantic hot fixes 03-2018 This is a set of atlantic driver hot fixes for various areas: Some issues with hardware reset covered, Fixed napi_poll flood happening on some traffic conditions, Allow system to change MAC address on live device, Add pci shutdown handler. patch v2: - reverse christmas tree - remove driver private parameter, replacing it with define. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 1959031 + c89bf1c commit 9b894cd

File tree

10 files changed

+99
-30
lines changed

10 files changed

+99
-30
lines changed

drivers/net/ethernet/aquantia/atlantic/aq_cfg.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
#define AQ_CFG_TX_FRAME_MAX (16U * 1024U)
3737
#define AQ_CFG_RX_FRAME_MAX (4U * 1024U)
3838

39+
#define AQ_CFG_TX_CLEAN_BUDGET 256U
40+
3941
/* LRO */
4042
#define AQ_CFG_IS_LRO_DEF 1U
4143

drivers/net/ethernet/aquantia/atlantic/aq_nic.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ void aq_nic_ndev_init(struct aq_nic_s *self)
247247
self->ndev->hw_features |= aq_hw_caps->hw_features;
248248
self->ndev->features = aq_hw_caps->hw_features;
249249
self->ndev->priv_flags = aq_hw_caps->hw_priv_flags;
250+
self->ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
251+
250252
self->ndev->mtu = aq_nic_cfg->mtu - ETH_HLEN;
251253
self->ndev->max_mtu = aq_hw_caps->mtu - ETH_FCS_LEN - ETH_HLEN;
252254

@@ -937,3 +939,23 @@ int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg)
937939
out:
938940
return err;
939941
}
942+
943+
void aq_nic_shutdown(struct aq_nic_s *self)
944+
{
945+
int err = 0;
946+
947+
if (!self->ndev)
948+
return;
949+
950+
rtnl_lock();
951+
952+
netif_device_detach(self->ndev);
953+
954+
err = aq_nic_stop(self);
955+
if (err < 0)
956+
goto err_exit;
957+
aq_nic_deinit(self);
958+
959+
err_exit:
960+
rtnl_unlock();
961+
}

drivers/net/ethernet/aquantia/atlantic/aq_nic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,5 +118,6 @@ struct aq_nic_cfg_s *aq_nic_get_cfg(struct aq_nic_s *self);
118118
u32 aq_nic_get_fw_version(struct aq_nic_s *self);
119119
int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg);
120120
int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self);
121+
void aq_nic_shutdown(struct aq_nic_s *self);
121122

122123
#endif /* AQ_NIC_H */

drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,20 @@ static void aq_pci_remove(struct pci_dev *pdev)
323323
pci_disable_device(pdev);
324324
}
325325

326+
static void aq_pci_shutdown(struct pci_dev *pdev)
327+
{
328+
struct aq_nic_s *self = pci_get_drvdata(pdev);
329+
330+
aq_nic_shutdown(self);
331+
332+
pci_disable_device(pdev);
333+
334+
if (system_state == SYSTEM_POWER_OFF) {
335+
pci_wake_from_d3(pdev, false);
336+
pci_set_power_state(pdev, PCI_D3hot);
337+
}
338+
}
339+
326340
static int aq_pci_suspend(struct pci_dev *pdev, pm_message_t pm_msg)
327341
{
328342
struct aq_nic_s *self = pci_get_drvdata(pdev);
@@ -345,6 +359,7 @@ static struct pci_driver aq_pci_ops = {
345359
.remove = aq_pci_remove,
346360
.suspend = aq_pci_suspend,
347361
.resume = aq_pci_resume,
362+
.shutdown = aq_pci_shutdown,
348363
};
349364

350365
module_pci_driver(aq_pci_ops);

drivers/net/ethernet/aquantia/atlantic/aq_ring.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,12 @@ void aq_ring_queue_stop(struct aq_ring_s *ring)
136136
netif_stop_subqueue(ndev, ring->idx);
137137
}
138138

139-
void aq_ring_tx_clean(struct aq_ring_s *self)
139+
bool aq_ring_tx_clean(struct aq_ring_s *self)
140140
{
141141
struct device *dev = aq_nic_get_dev(self->aq_nic);
142+
unsigned int budget = AQ_CFG_TX_CLEAN_BUDGET;
142143

143-
for (; self->sw_head != self->hw_head;
144+
for (; self->sw_head != self->hw_head && budget--;
144145
self->sw_head = aq_ring_next_dx(self, self->sw_head)) {
145146
struct aq_ring_buff_s *buff = &self->buff_ring[self->sw_head];
146147

@@ -167,6 +168,8 @@ void aq_ring_tx_clean(struct aq_ring_s *self)
167168
buff->pa = 0U;
168169
buff->eop_index = 0xffffU;
169170
}
171+
172+
return !!budget;
170173
}
171174

172175
#define AQ_SKB_ALIGN SKB_DATA_ALIGN(sizeof(struct skb_shared_info))

drivers/net/ethernet/aquantia/atlantic/aq_ring.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ void aq_ring_free(struct aq_ring_s *self);
153153
void aq_ring_update_queue_state(struct aq_ring_s *ring);
154154
void aq_ring_queue_wake(struct aq_ring_s *ring);
155155
void aq_ring_queue_stop(struct aq_ring_s *ring);
156-
void aq_ring_tx_clean(struct aq_ring_s *self);
156+
bool aq_ring_tx_clean(struct aq_ring_s *self);
157157
int aq_ring_rx_clean(struct aq_ring_s *self,
158158
struct napi_struct *napi,
159159
int *work_done,

drivers/net/ethernet/aquantia/atlantic/aq_vec.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ struct aq_vec_s {
3535
static int aq_vec_poll(struct napi_struct *napi, int budget)
3636
{
3737
struct aq_vec_s *self = container_of(napi, struct aq_vec_s, napi);
38+
unsigned int sw_tail_old = 0U;
3839
struct aq_ring_s *ring = NULL;
40+
bool was_tx_cleaned = true;
41+
unsigned int i = 0U;
3942
int work_done = 0;
4043
int err = 0;
41-
unsigned int i = 0U;
42-
unsigned int sw_tail_old = 0U;
43-
bool was_tx_cleaned = false;
4444

4545
if (!self) {
4646
err = -EINVAL;
@@ -57,9 +57,8 @@ static int aq_vec_poll(struct napi_struct *napi, int budget)
5757

5858
if (ring[AQ_VEC_TX_ID].sw_head !=
5959
ring[AQ_VEC_TX_ID].hw_head) {
60-
aq_ring_tx_clean(&ring[AQ_VEC_TX_ID]);
60+
was_tx_cleaned = aq_ring_tx_clean(&ring[AQ_VEC_TX_ID]);
6161
aq_ring_update_queue_state(&ring[AQ_VEC_TX_ID]);
62-
was_tx_cleaned = true;
6362
}
6463

6564
err = self->aq_hw_ops->hw_ring_rx_receive(self->aq_hw,
@@ -90,7 +89,7 @@ static int aq_vec_poll(struct napi_struct *napi, int budget)
9089
}
9190
}
9291

93-
if (was_tx_cleaned)
92+
if (!was_tx_cleaned)
9493
work_done = budget;
9594

9695
if (work_done < budget) {

drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121

2222
#define HW_ATL_UCP_0X370_REG 0x0370U
2323

24+
#define HW_ATL_MIF_CMD 0x0200U
25+
#define HW_ATL_MIF_ADDR 0x0208U
26+
#define HW_ATL_MIF_VAL 0x020CU
27+
2428
#define HW_ATL_FW_SM_RAM 0x2U
2529
#define HW_ATL_MPI_FW_VERSION 0x18
2630
#define HW_ATL_MPI_CONTROL_ADR 0x0368U
@@ -79,16 +83,15 @@ int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
7983

8084
static int hw_atl_utils_soft_reset_flb(struct aq_hw_s *self)
8185
{
86+
u32 gsr, val;
8287
int k = 0;
83-
u32 gsr;
8488

8589
aq_hw_write_reg(self, 0x404, 0x40e1);
8690
AQ_HW_SLEEP(50);
8791

8892
/* Cleanup SPI */
89-
aq_hw_write_reg(self, 0x534, 0xA0);
90-
aq_hw_write_reg(self, 0x100, 0x9F);
91-
aq_hw_write_reg(self, 0x100, 0x809F);
93+
val = aq_hw_read_reg(self, 0x53C);
94+
aq_hw_write_reg(self, 0x53C, val | 0x10);
9295

9396
gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
9497
aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
@@ -97,7 +100,14 @@ static int hw_atl_utils_soft_reset_flb(struct aq_hw_s *self)
97100
aq_hw_write_reg(self, 0x404, 0x80e0);
98101
aq_hw_write_reg(self, 0x32a8, 0x0);
99102
aq_hw_write_reg(self, 0x520, 0x1);
103+
104+
/* Reset SPI again because of possible interrupted SPI burst */
105+
val = aq_hw_read_reg(self, 0x53C);
106+
aq_hw_write_reg(self, 0x53C, val | 0x10);
100107
AQ_HW_SLEEP(10);
108+
/* Clear SPI reset state */
109+
aq_hw_write_reg(self, 0x53C, val & ~0x10);
110+
101111
aq_hw_write_reg(self, 0x404, 0x180e0);
102112

103113
for (k = 0; k < 1000; k++) {
@@ -141,13 +151,15 @@ static int hw_atl_utils_soft_reset_flb(struct aq_hw_s *self)
141151
aq_pr_err("FW kickstart failed\n");
142152
return -EIO;
143153
}
154+
/* Old FW requires fixed delay after init */
155+
AQ_HW_SLEEP(15);
144156

145157
return 0;
146158
}
147159

148160
static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self)
149161
{
150-
u32 gsr, rbl_status;
162+
u32 gsr, val, rbl_status;
151163
int k;
152164

153165
aq_hw_write_reg(self, 0x404, 0x40e1);
@@ -157,6 +169,10 @@ static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self)
157169
/* Alter RBL status */
158170
aq_hw_write_reg(self, 0x388, 0xDEAD);
159171

172+
/* Cleanup SPI */
173+
val = aq_hw_read_reg(self, 0x53C);
174+
aq_hw_write_reg(self, 0x53C, val | 0x10);
175+
160176
/* Global software reset*/
161177
hw_atl_rx_rx_reg_res_dis_set(self, 0U);
162178
hw_atl_tx_tx_reg_res_dis_set(self, 0U);
@@ -204,6 +220,8 @@ static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self)
204220
aq_pr_err("FW kickstart failed\n");
205221
return -EIO;
206222
}
223+
/* Old FW requires fixed delay after init */
224+
AQ_HW_SLEEP(15);
207225

208226
return 0;
209227
}
@@ -255,18 +273,22 @@ int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
255273
}
256274
}
257275

258-
aq_hw_write_reg(self, 0x00000208U, a);
259-
260-
for (++cnt; --cnt;) {
261-
u32 i = 0U;
276+
aq_hw_write_reg(self, HW_ATL_MIF_ADDR, a);
262277

263-
aq_hw_write_reg(self, 0x00000200U, 0x00008000U);
278+
for (++cnt; --cnt && !err;) {
279+
aq_hw_write_reg(self, HW_ATL_MIF_CMD, 0x00008000U);
264280

265-
for (i = 1024U;
266-
(0x100U & aq_hw_read_reg(self, 0x00000200U)) && --i;) {
267-
}
281+
if (IS_CHIP_FEATURE(REVISION_B1))
282+
AQ_HW_WAIT_FOR(a != aq_hw_read_reg(self,
283+
HW_ATL_MIF_ADDR),
284+
1, 1000U);
285+
else
286+
AQ_HW_WAIT_FOR(!(0x100 & aq_hw_read_reg(self,
287+
HW_ATL_MIF_CMD)),
288+
1, 1000U);
268289

269-
*(p++) = aq_hw_read_reg(self, 0x0000020CU);
290+
*(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL);
291+
a += 4;
270292
}
271293

272294
hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
@@ -662,14 +684,18 @@ void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
662684
u32 val = hw_atl_reg_glb_mif_id_get(self);
663685
u32 mif_rev = val & 0xFFU;
664686

665-
if ((3U & mif_rev) == 1U) {
666-
chip_features |=
667-
HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 |
687+
if ((0xFU & mif_rev) == 1U) {
688+
chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 |
668689
HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
669690
HAL_ATLANTIC_UTILS_CHIP_MIPS;
670-
} else if ((3U & mif_rev) == 2U) {
671-
chip_features |=
672-
HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 |
691+
} else if ((0xFU & mif_rev) == 2U) {
692+
chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 |
693+
HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
694+
HAL_ATLANTIC_UTILS_CHIP_MIPS |
695+
HAL_ATLANTIC_UTILS_CHIP_TPO2 |
696+
HAL_ATLANTIC_UTILS_CHIP_RPF2;
697+
} else if ((0xFU & mif_rev) == 0xAU) {
698+
chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 |
673699
HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
674700
HAL_ATLANTIC_UTILS_CHIP_MIPS |
675701
HAL_ATLANTIC_UTILS_CHIP_TPO2 |

drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ struct __packed hw_aq_atl_utils_mbox {
161161
#define HAL_ATLANTIC_UTILS_CHIP_MPI_AQ 0x00000010U
162162
#define HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 0x01000000U
163163
#define HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 0x02000000U
164+
#define HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 0x04000000U
164165

165166
#define IS_CHIP_FEATURE(_F_) (HAL_ATLANTIC_UTILS_CHIP_##_F_ & \
166167
self->chip_features)

drivers/net/ethernet/aquantia/atlantic/ver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#define NIC_MAJOR_DRIVER_VERSION 2
1414
#define NIC_MINOR_DRIVER_VERSION 0
1515
#define NIC_BUILD_DRIVER_VERSION 2
16-
#define NIC_REVISION_DRIVER_VERSION 0
16+
#define NIC_REVISION_DRIVER_VERSION 1
1717

1818
#define AQ_CFG_DRV_VERSION_SUFFIX "-kern"
1919

0 commit comments

Comments
 (0)