@@ -196,6 +196,20 @@ static void stmmac_start_all_queues(struct stmmac_priv *priv)
196
196
netif_tx_start_queue (netdev_get_tx_queue (priv -> dev , queue ));
197
197
}
198
198
199
+ static void stmmac_service_event_schedule (struct stmmac_priv * priv )
200
+ {
201
+ if (!test_bit (STMMAC_DOWN , & priv -> state ) &&
202
+ !test_and_set_bit (STMMAC_SERVICE_SCHED , & priv -> state ))
203
+ queue_work (priv -> wq , & priv -> service_task );
204
+ }
205
+
206
+ static void stmmac_global_err (struct stmmac_priv * priv )
207
+ {
208
+ netif_carrier_off (priv -> dev );
209
+ set_bit (STMMAC_RESET_REQUESTED , & priv -> state );
210
+ stmmac_service_event_schedule (priv );
211
+ }
212
+
199
213
/**
200
214
* stmmac_clk_csr_set - dynamically set the MDC clock
201
215
* @priv: driver private structure
@@ -3587,12 +3601,8 @@ static int stmmac_poll(struct napi_struct *napi, int budget)
3587
3601
static void stmmac_tx_timeout (struct net_device * dev )
3588
3602
{
3589
3603
struct stmmac_priv * priv = netdev_priv (dev );
3590
- u32 tx_count = priv -> plat -> tx_queues_to_use ;
3591
- u32 chan ;
3592
3604
3593
- /* Clear Tx resources and restart transmitting again */
3594
- for (chan = 0 ; chan < tx_count ; chan ++ )
3595
- stmmac_tx_err (priv , chan );
3605
+ stmmac_global_err (priv );
3596
3606
}
3597
3607
3598
3608
/**
@@ -3716,6 +3726,10 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
3716
3726
return IRQ_NONE ;
3717
3727
}
3718
3728
3729
+ /* Check if adapter is up */
3730
+ if (test_bit (STMMAC_DOWN , & priv -> state ))
3731
+ return IRQ_HANDLED ;
3732
+
3719
3733
/* To handle GMAC own interrupts */
3720
3734
if ((priv -> plat -> has_gmac ) || (priv -> plat -> has_gmac4 )) {
3721
3735
int status = priv -> hw -> mac -> host_irq_status (priv -> hw ,
@@ -4051,6 +4065,37 @@ static const struct net_device_ops stmmac_netdev_ops = {
4051
4065
.ndo_set_mac_address = stmmac_set_mac_address ,
4052
4066
};
4053
4067
4068
+ static void stmmac_reset_subtask (struct stmmac_priv * priv )
4069
+ {
4070
+ if (!test_and_clear_bit (STMMAC_RESET_REQUESTED , & priv -> state ))
4071
+ return ;
4072
+ if (test_bit (STMMAC_DOWN , & priv -> state ))
4073
+ return ;
4074
+
4075
+ netdev_err (priv -> dev , "Reset adapter.\n" );
4076
+
4077
+ rtnl_lock ();
4078
+ netif_trans_update (priv -> dev );
4079
+ while (test_and_set_bit (STMMAC_RESETING , & priv -> state ))
4080
+ usleep_range (1000 , 2000 );
4081
+
4082
+ set_bit (STMMAC_DOWN , & priv -> state );
4083
+ dev_close (priv -> dev );
4084
+ dev_open (priv -> dev );
4085
+ clear_bit (STMMAC_DOWN , & priv -> state );
4086
+ clear_bit (STMMAC_RESETING , & priv -> state );
4087
+ rtnl_unlock ();
4088
+ }
4089
+
4090
+ static void stmmac_service_task (struct work_struct * work )
4091
+ {
4092
+ struct stmmac_priv * priv = container_of (work , struct stmmac_priv ,
4093
+ service_task );
4094
+
4095
+ stmmac_reset_subtask (priv );
4096
+ clear_bit (STMMAC_SERVICE_SCHED , & priv -> state );
4097
+ }
4098
+
4054
4099
/**
4055
4100
* stmmac_hw_init - Init the MAC device
4056
4101
* @priv: driver private structure
@@ -4212,6 +4257,15 @@ int stmmac_dvr_probe(struct device *device,
4212
4257
/* Verify driver arguments */
4213
4258
stmmac_verify_args ();
4214
4259
4260
+ /* Allocate workqueue */
4261
+ priv -> wq = create_singlethread_workqueue ("stmmac_wq" );
4262
+ if (!priv -> wq ) {
4263
+ dev_err (priv -> device , "failed to create workqueue\n" );
4264
+ goto error_wq ;
4265
+ }
4266
+
4267
+ INIT_WORK (& priv -> service_task , stmmac_service_task );
4268
+
4215
4269
/* Override with kernel parameters if supplied XXX CRS XXX
4216
4270
* this needs to have multiple instances
4217
4271
*/
@@ -4342,6 +4396,8 @@ int stmmac_dvr_probe(struct device *device,
4342
4396
netif_napi_del (& rx_q -> napi );
4343
4397
}
4344
4398
error_hw_init :
4399
+ destroy_workqueue (priv -> wq );
4400
+ error_wq :
4345
4401
free_netdev (ndev );
4346
4402
4347
4403
return ret ;
@@ -4374,6 +4430,7 @@ int stmmac_dvr_remove(struct device *dev)
4374
4430
priv -> hw -> pcs != STMMAC_PCS_TBI &&
4375
4431
priv -> hw -> pcs != STMMAC_PCS_RTBI )
4376
4432
stmmac_mdio_unregister (ndev );
4433
+ destroy_workqueue (priv -> wq );
4377
4434
free_netdev (ndev );
4378
4435
4379
4436
return 0 ;
0 commit comments