|
@@ -166,6 +166,8 @@ struct tbnet_ring {
|
|
|
* @connected_work: Worker that finalizes the ThunderboltIP connection
|
|
|
* setup and enables DMA paths for high speed data
|
|
|
* transfers
|
|
|
+ * @disconnect_work: Worker that handles tearing down the ThunderboltIP
|
|
|
+ * connection
|
|
|
* @rx_hdr: Copy of the currently processed Rx frame. Used when a
|
|
|
* network packet consists of multiple Thunderbolt frames.
|
|
|
* In host byte order.
|
|
@@ -190,6 +192,7 @@ struct tbnet {
|
|
|
int login_retries;
|
|
|
struct delayed_work login_work;
|
|
|
struct work_struct connected_work;
|
|
|
+ struct work_struct disconnect_work;
|
|
|
struct thunderbolt_ip_frame_header rx_hdr;
|
|
|
struct tbnet_ring rx_ring;
|
|
|
atomic_t frame_id;
|
|
@@ -445,7 +448,7 @@ static int tbnet_handle_packet(const void *buf, size_t size, void *data)
|
|
|
case TBIP_LOGOUT:
|
|
|
ret = tbnet_logout_response(net, route, sequence, command_id);
|
|
|
if (!ret)
|
|
|
- tbnet_tear_down(net, false);
|
|
|
+ queue_work(system_long_wq, &net->disconnect_work);
|
|
|
break;
|
|
|
|
|
|
default:
|
|
@@ -659,6 +662,13 @@ static void tbnet_login_work(struct work_struct *work)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void tbnet_disconnect_work(struct work_struct *work)
|
|
|
+{
|
|
|
+ struct tbnet *net = container_of(work, typeof(*net), disconnect_work);
|
|
|
+
|
|
|
+ tbnet_tear_down(net, false);
|
|
|
+}
|
|
|
+
|
|
|
static bool tbnet_check_frame(struct tbnet *net, const struct tbnet_frame *tf,
|
|
|
const struct thunderbolt_ip_frame_header *hdr)
|
|
|
{
|
|
@@ -881,6 +891,7 @@ static int tbnet_stop(struct net_device *dev)
|
|
|
|
|
|
napi_disable(&net->napi);
|
|
|
|
|
|
+ cancel_work_sync(&net->disconnect_work);
|
|
|
tbnet_tear_down(net, true);
|
|
|
|
|
|
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)
|
|
|
net = netdev_priv(dev);
|
|
|
INIT_DELAYED_WORK(&net->login_work, tbnet_login_work);
|
|
|
INIT_WORK(&net->connected_work, tbnet_connected_work);
|
|
|
+ INIT_WORK(&net->disconnect_work, tbnet_disconnect_work);
|
|
|
mutex_init(&net->connection_lock);
|
|
|
atomic_set(&net->command_id, 0);
|
|
|
atomic_set(&net->frame_id, 0);
|