summaryrefslogtreecommitdiff
path: root/drivers/net/thunderbolt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/thunderbolt.c')
-rw-r--r--drivers/net/thunderbolt.c56
1 files changed, 42 insertions, 14 deletions
diff --git a/drivers/net/thunderbolt.c b/drivers/net/thunderbolt.c
index ed3743dc62b9..9a6a8353e192 100644
--- a/drivers/net/thunderbolt.c
+++ b/drivers/net/thunderbolt.c
@@ -25,13 +25,13 @@
/* Protocol timeouts in ms */
#define TBNET_LOGIN_DELAY 4500
#define TBNET_LOGIN_TIMEOUT 500
-#define TBNET_LOGOUT_TIMEOUT 100
+#define TBNET_LOGOUT_TIMEOUT 1000
#define TBNET_RING_SIZE 256
-#define TBNET_LOCAL_PATH 0xf
#define TBNET_LOGIN_RETRIES 60
-#define TBNET_LOGOUT_RETRIES 5
+#define TBNET_LOGOUT_RETRIES 10
#define TBNET_MATCH_FRAGS_ID BIT(1)
+#define TBNET_64K_FRAMES BIT(2)
#define TBNET_MAX_MTU SZ_64K
#define TBNET_FRAME_SIZE SZ_4K
#define TBNET_MAX_PAYLOAD_SIZE \
@@ -154,8 +154,8 @@ struct tbnet_ring {
* @login_sent: ThunderboltIP login message successfully sent
* @login_received: ThunderboltIP login message received from the remote
* host
- * @transmit_path: HopID the other end needs to use building the
- * opposite side path.
+ * @local_transmit_path: HopID we are using to send out packets
+ * @remote_transmit_path: HopID the other end is using to send packets to us
* @connection_lock: Lock serializing access to @login_sent,
* @login_received and @transmit_path.
* @login_retries: Number of login retries currently done
@@ -184,7 +184,8 @@ struct tbnet {
atomic_t command_id;
bool login_sent;
bool login_received;
- u32 transmit_path;
+ int local_transmit_path;
+ int remote_transmit_path;
struct mutex connection_lock;
int login_retries;
struct delayed_work login_work;
@@ -257,7 +258,7 @@ static int tbnet_login_request(struct tbnet *net, u8 sequence)
atomic_inc_return(&net->command_id));
request.proto_version = TBIP_LOGIN_PROTO_VERSION;
- request.transmit_path = TBNET_LOCAL_PATH;
+ request.transmit_path = net->local_transmit_path;
return tb_xdomain_request(xd, &request, sizeof(request),
TB_CFG_PKG_XDOMAIN_RESP, &reply,
@@ -364,10 +365,10 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout)
mutex_lock(&net->connection_lock);
if (net->login_sent && net->login_received) {
- int retries = TBNET_LOGOUT_RETRIES;
+ int ret, retries = TBNET_LOGOUT_RETRIES;
while (send_logout && retries-- > 0) {
- int ret = tbnet_logout_request(net);
+ ret = tbnet_logout_request(net);
if (ret != -ETIMEDOUT)
break;
}
@@ -377,8 +378,16 @@ static void tbnet_tear_down(struct tbnet *net, bool send_logout)
tbnet_free_buffers(&net->rx_ring);
tbnet_free_buffers(&net->tx_ring);
- if (tb_xdomain_disable_paths(net->xd))
+ ret = tb_xdomain_disable_paths(net->xd,
+ net->local_transmit_path,
+ net->rx_ring.ring->hop,
+ net->remote_transmit_path,
+ net->tx_ring.ring->hop);
+ if (ret)
netdev_warn(net->dev, "failed to disable DMA paths\n");
+
+ tb_xdomain_release_in_hopid(net->xd, net->remote_transmit_path);
+ net->remote_transmit_path = 0;
}
net->login_retries = 0;
@@ -424,7 +433,7 @@ static int tbnet_handle_packet(const void *buf, size_t size, void *data)
if (!ret) {
mutex_lock(&net->connection_lock);
net->login_received = true;
- net->transmit_path = pkg->transmit_path;
+ net->remote_transmit_path = pkg->transmit_path;
/* If we reached the number of max retries or
* previous logout, schedule another round of
@@ -597,12 +606,18 @@ static void tbnet_connected_work(struct work_struct *work)
if (!connected)
return;
+ ret = tb_xdomain_alloc_in_hopid(net->xd, net->remote_transmit_path);
+ if (ret != net->remote_transmit_path) {
+ netdev_err(net->dev, "failed to allocate Rx HopID\n");
+ return;
+ }
+
/* Both logins successful so enable the high-speed DMA paths and
* start the network device queue.
*/
- ret = tb_xdomain_enable_paths(net->xd, TBNET_LOCAL_PATH,
+ ret = tb_xdomain_enable_paths(net->xd, net->local_transmit_path,
net->rx_ring.ring->hop,
- net->transmit_path,
+ net->remote_transmit_path,
net->tx_ring.ring->hop);
if (ret) {
netdev_err(net->dev, "failed to enable DMA paths\n");
@@ -629,6 +644,7 @@ err_free_rx_buffers:
err_stop_rings:
tb_ring_stop(net->rx_ring.ring);
tb_ring_stop(net->tx_ring.ring);
+ tb_xdomain_release_in_hopid(net->xd, net->remote_transmit_path);
}
static void tbnet_login_work(struct work_struct *work)
@@ -851,6 +867,7 @@ static int tbnet_open(struct net_device *dev)
struct tb_xdomain *xd = net->xd;
u16 sof_mask, eof_mask;
struct tb_ring *ring;
+ int hopid;
netif_carrier_off(dev);
@@ -862,6 +879,15 @@ static int tbnet_open(struct net_device *dev)
}
net->tx_ring.ring = ring;
+ hopid = tb_xdomain_alloc_out_hopid(xd, -1);
+ if (hopid < 0) {
+ netdev_err(dev, "failed to allocate Tx HopID\n");
+ tb_ring_free(net->tx_ring.ring);
+ net->tx_ring.ring = NULL;
+ return hopid;
+ }
+ net->local_transmit_path = hopid;
+
sof_mask = BIT(TBIP_PDF_FRAME_START);
eof_mask = BIT(TBIP_PDF_FRAME_END);
@@ -893,6 +919,8 @@ static int tbnet_stop(struct net_device *dev)
tb_ring_free(net->rx_ring.ring);
net->rx_ring.ring = NULL;
+
+ tb_xdomain_release_out_hopid(net->xd, net->local_transmit_path);
tb_ring_free(net->tx_ring.ring);
net->tx_ring.ring = NULL;
@@ -1340,7 +1368,7 @@ static int __init tbnet_init(void)
* the moment.
*/
tb_property_add_immediate(tbnet_dir, "prtcstns",
- TBNET_MATCH_FRAGS_ID);
+ TBNET_MATCH_FRAGS_ID | TBNET_64K_FRAMES);
ret = tb_register_property_dir("network", tbnet_dir);
if (ret) {