diff options
Diffstat (limited to 'drivers/net/thunderbolt.c')
| -rw-r--r-- | drivers/net/thunderbolt.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/drivers/net/thunderbolt.c b/drivers/net/thunderbolt.c index ca5e375de27c..e0d6760f3219 100644 --- a/drivers/net/thunderbolt.c +++ b/drivers/net/thunderbolt.c | |||
| @@ -166,6 +166,8 @@ struct tbnet_ring { | |||
| 166 | * @connected_work: Worker that finalizes the ThunderboltIP connection | 166 | * @connected_work: Worker that finalizes the ThunderboltIP connection |
| 167 | * setup and enables DMA paths for high speed data | 167 | * setup and enables DMA paths for high speed data |
| 168 | * transfers | 168 | * transfers |
| 169 | * @disconnect_work: Worker that handles tearing down the ThunderboltIP | ||
| 170 | * connection | ||
| 169 | * @rx_hdr: Copy of the currently processed Rx frame. Used when a | 171 | * @rx_hdr: Copy of the currently processed Rx frame. Used when a |
| 170 | * network packet consists of multiple Thunderbolt frames. | 172 | * network packet consists of multiple Thunderbolt frames. |
| 171 | * In host byte order. | 173 | * In host byte order. |
| @@ -190,6 +192,7 @@ struct tbnet { | |||
| 190 | int login_retries; | 192 | int login_retries; |
| 191 | struct delayed_work login_work; | 193 | struct delayed_work login_work; |
| 192 | struct work_struct connected_work; | 194 | struct work_struct connected_work; |
| 195 | struct work_struct disconnect_work; | ||
| 193 | struct thunderbolt_ip_frame_header rx_hdr; | 196 | struct thunderbolt_ip_frame_header rx_hdr; |
| 194 | struct tbnet_ring rx_ring; | 197 | struct tbnet_ring rx_ring; |
| 195 | atomic_t frame_id; | 198 | atomic_t frame_id; |
| @@ -445,7 +448,7 @@ static int tbnet_handle_packet(const void *buf, size_t size, void *data) | |||
| 445 | case TBIP_LOGOUT: | 448 | case TBIP_LOGOUT: |
| 446 | ret = tbnet_logout_response(net, route, sequence, command_id); | 449 | ret = tbnet_logout_response(net, route, sequence, command_id); |
| 447 | if (!ret) | 450 | if (!ret) |
| 448 | tbnet_tear_down(net, false); | 451 | queue_work(system_long_wq, &net->disconnect_work); |
| 449 | break; | 452 | break; |
| 450 | 453 | ||
| 451 | default: | 454 | default: |
| @@ -659,6 +662,13 @@ static void tbnet_login_work(struct work_struct *work) | |||
| 659 | } | 662 | } |
| 660 | } | 663 | } |
| 661 | 664 | ||
| 665 | static void tbnet_disconnect_work(struct work_struct *work) | ||
| 666 | { | ||
| 667 | struct tbnet *net = container_of(work, typeof(*net), disconnect_work); | ||
| 668 | |||
| 669 | tbnet_tear_down(net, false); | ||
| 670 | } | ||
| 671 | |||
| 662 | static bool tbnet_check_frame(struct tbnet *net, const struct tbnet_frame *tf, | 672 | static bool tbnet_check_frame(struct tbnet *net, const struct tbnet_frame *tf, |
| 663 | const struct thunderbolt_ip_frame_header *hdr) | 673 | const struct thunderbolt_ip_frame_header *hdr) |
| 664 | { | 674 | { |
| @@ -881,6 +891,7 @@ static int tbnet_stop(struct net_device *dev) | |||
| 881 | 891 | ||
| 882 | napi_disable(&net->napi); | 892 | napi_disable(&net->napi); |
| 883 | 893 | ||
| 894 | cancel_work_sync(&net->disconnect_work); | ||
| 884 | tbnet_tear_down(net, true); | 895 | tbnet_tear_down(net, true); |
| 885 | 896 | ||
| 886 | tb_ring_free(net->rx_ring.ring); | 897 | tb_ring_free(net->rx_ring.ring); |
| @@ -1195,6 +1206,7 @@ static int tbnet_probe(struct tb_service *svc, const struct tb_service_id *id) | |||
| 1195 | net = netdev_priv(dev); | 1206 | net = netdev_priv(dev); |
| 1196 | INIT_DELAYED_WORK(&net->login_work, tbnet_login_work); | 1207 | INIT_DELAYED_WORK(&net->login_work, tbnet_login_work); |
| 1197 | INIT_WORK(&net->connected_work, tbnet_connected_work); | 1208 | INIT_WORK(&net->connected_work, tbnet_connected_work); |
| 1209 | INIT_WORK(&net->disconnect_work, tbnet_disconnect_work); | ||
| 1198 | mutex_init(&net->connection_lock); | 1210 | mutex_init(&net->connection_lock); |
| 1199 | atomic_set(&net->command_id, 0); | 1211 | atomic_set(&net->command_id, 0); |
| 1200 | atomic_set(&net->frame_id, 0); | 1212 | atomic_set(&net->frame_id, 0); |
| @@ -1270,10 +1282,7 @@ static int __maybe_unused tbnet_suspend(struct device *dev) | |||
| 1270 | stop_login(net); | 1282 | stop_login(net); |
| 1271 | if (netif_running(net->dev)) { | 1283 | if (netif_running(net->dev)) { |
| 1272 | netif_device_detach(net->dev); | 1284 | netif_device_detach(net->dev); |
| 1273 | tb_ring_stop(net->rx_ring.ring); | 1285 | tbnet_tear_down(net, true); |
| 1274 | tb_ring_stop(net->tx_ring.ring); | ||
| 1275 | tbnet_free_buffers(&net->rx_ring); | ||
| 1276 | tbnet_free_buffers(&net->tx_ring); | ||
| 1277 | } | 1286 | } |
| 1278 | 1287 | ||
| 1279 | return 0; | 1288 | return 0; |
