thunderbolt: Allow multiple DMA tunnels over a single XDomain connection
[linux-2.6-microblaze.git] / drivers / thunderbolt / domain.c
index 89ae614..a7d83ee 100644 (file)
@@ -341,9 +341,34 @@ struct device_type tb_domain_type = {
        .release = tb_domain_release,
 };
 
+static bool tb_domain_event_cb(void *data, enum tb_cfg_pkg_type type,
+                              const void *buf, size_t size)
+{
+       struct tb *tb = data;
+
+       if (!tb->cm_ops->handle_event) {
+               tb_warn(tb, "domain does not have event handler\n");
+               return true;
+       }
+
+       switch (type) {
+       case TB_CFG_PKG_XDOMAIN_REQ:
+       case TB_CFG_PKG_XDOMAIN_RESP:
+               if (tb_is_xdomain_enabled())
+                       return tb_xdomain_handle_request(tb, type, buf, size);
+               break;
+
+       default:
+               tb->cm_ops->handle_event(tb, type, buf, size);
+       }
+
+       return true;
+}
+
 /**
  * tb_domain_alloc() - Allocate a domain
  * @nhi: Pointer to the host controller
+ * @timeout_msec: Control channel timeout for non-raw messages
  * @privsize: Size of the connection manager private data
  *
  * Allocates and initializes a new Thunderbolt domain. Connection
@@ -355,7 +380,7 @@ struct device_type tb_domain_type = {
  *
  * Return: allocated domain structure on %NULL in case of error
  */
-struct tb *tb_domain_alloc(struct tb_nhi *nhi, size_t privsize)
+struct tb *tb_domain_alloc(struct tb_nhi *nhi, int timeout_msec, size_t privsize)
 {
        struct tb *tb;
 
@@ -382,6 +407,10 @@ struct tb *tb_domain_alloc(struct tb_nhi *nhi, size_t privsize)
        if (!tb->wq)
                goto err_remove_ida;
 
+       tb->ctl = tb_ctl_alloc(nhi, timeout_msec, tb_domain_event_cb, tb);
+       if (!tb->ctl)
+               goto err_destroy_wq;
+
        tb->dev.parent = &nhi->pdev->dev;
        tb->dev.bus = &tb_bus_type;
        tb->dev.type = &tb_domain_type;
@@ -391,6 +420,8 @@ struct tb *tb_domain_alloc(struct tb_nhi *nhi, size_t privsize)
 
        return tb;
 
+err_destroy_wq:
+       destroy_workqueue(tb->wq);
 err_remove_ida:
        ida_simple_remove(&tb_domain_ida, tb->index);
 err_free:
@@ -399,30 +430,6 @@ err_free:
        return NULL;
 }
 
-static bool tb_domain_event_cb(void *data, enum tb_cfg_pkg_type type,
-                              const void *buf, size_t size)
-{
-       struct tb *tb = data;
-
-       if (!tb->cm_ops->handle_event) {
-               tb_warn(tb, "domain does not have event handler\n");
-               return true;
-       }
-
-       switch (type) {
-       case TB_CFG_PKG_XDOMAIN_REQ:
-       case TB_CFG_PKG_XDOMAIN_RESP:
-               if (tb_is_xdomain_enabled())
-                       return tb_xdomain_handle_request(tb, type, buf, size);
-               break;
-
-       default:
-               tb->cm_ops->handle_event(tb, type, buf, size);
-       }
-
-       return true;
-}
-
 /**
  * tb_domain_add() - Add domain to the system
  * @tb: Domain to add
@@ -442,13 +449,6 @@ int tb_domain_add(struct tb *tb)
                return -EINVAL;
 
        mutex_lock(&tb->lock);
-
-       tb->ctl = tb_ctl_alloc(tb->nhi, tb_domain_event_cb, tb);
-       if (!tb->ctl) {
-               ret = -ENOMEM;
-               goto err_unlock;
-       }
-
        /*
         * tb_schedule_hotplug_handler may be called as soon as the config
         * channel is started. Thats why we have to hold the lock here.
@@ -493,8 +493,6 @@ err_domain_del:
        device_del(&tb->dev);
 err_ctl_stop:
        tb_ctl_stop(tb->ctl);
-err_unlock:
-       mutex_unlock(&tb->lock);
 
        return ret;
 }
@@ -793,6 +791,10 @@ int tb_domain_disconnect_pcie_paths(struct tb *tb)
  * tb_domain_approve_xdomain_paths() - Enable DMA paths for XDomain
  * @tb: Domain enabling the DMA paths
  * @xd: XDomain DMA paths are created to
+ * @transmit_path: HopID we are using to send out packets
+ * @transmit_ring: DMA ring used to send out packets
+ * @receive_path: HopID the other end is using to send packets to us
+ * @receive_ring: DMA ring used to receive packets from @receive_path
  *
  * Calls connection manager specific method to enable DMA paths to the
  * XDomain in question.
@@ -801,18 +803,25 @@ int tb_domain_disconnect_pcie_paths(struct tb *tb)
  * particular returns %-ENOTSUPP if the connection manager
  * implementation does not support XDomains.
  */
-int tb_domain_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd)
+int tb_domain_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,
+                                   int transmit_path, int transmit_ring,
+                                   int receive_path, int receive_ring)
 {
        if (!tb->cm_ops->approve_xdomain_paths)
                return -ENOTSUPP;
 
-       return tb->cm_ops->approve_xdomain_paths(tb, xd);
+       return tb->cm_ops->approve_xdomain_paths(tb, xd, transmit_path,
+                       transmit_ring, receive_path, receive_ring);
 }
 
 /**
  * tb_domain_disconnect_xdomain_paths() - Disable DMA paths for XDomain
  * @tb: Domain disabling the DMA paths
  * @xd: XDomain whose DMA paths are disconnected
+ * @transmit_path: HopID we are using to send out packets
+ * @transmit_ring: DMA ring used to send out packets
+ * @receive_path: HopID the other end is using to send packets to us
+ * @receive_ring: DMA ring used to receive packets from @receive_path
  *
  * Calls connection manager specific method to disconnect DMA paths to
  * the XDomain in question.
@@ -821,12 +830,15 @@ int tb_domain_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd)
  * particular returns %-ENOTSUPP if the connection manager
  * implementation does not support XDomains.
  */
-int tb_domain_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd)
+int tb_domain_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd,
+                                      int transmit_path, int transmit_ring,
+                                      int receive_path, int receive_ring)
 {
        if (!tb->cm_ops->disconnect_xdomain_paths)
                return -ENOTSUPP;
 
-       return tb->cm_ops->disconnect_xdomain_paths(tb, xd);
+       return tb->cm_ops->disconnect_xdomain_paths(tb, xd, transmit_path,
+                       transmit_ring, receive_path, receive_ring);
 }
 
 static int disconnect_xdomain(struct device *dev, void *data)
@@ -837,7 +849,7 @@ static int disconnect_xdomain(struct device *dev, void *data)
 
        xd = tb_to_xdomain(dev);
        if (xd && xd->tb == tb)
-               ret = tb_xdomain_disable_paths(xd);
+               ret = tb_xdomain_disable_all_paths(xd);
 
        return ret;
 }