sched: fix debug build
[dpdk.git] / kernel / linux / kni / kni_net.c
index f25b127..611719b 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/skbuff.h>
 #include <linux/kthread.h>
 #include <linux/delay.h>
+#include <linux/rtnetlink.h>
 
 #include <rte_kni_common.h>
 #include <kni_fifo.h>
@@ -36,6 +37,22 @@ static void kni_net_rx_normal(struct kni_dev *kni);
 /* kni rx function pointer, with default to normal rx */
 static kni_net_rx_t kni_net_rx_func = kni_net_rx_normal;
 
+#ifdef HAVE_IOVA_TO_KVA_MAPPING_SUPPORT
+/* iova to kernel virtual address */
+static inline void *
+iova2kva(struct kni_dev *kni, void *iova)
+{
+       return phys_to_virt(iova_to_phys(kni->usr_tsk, (unsigned long)iova));
+}
+
+static inline void *
+iova2data_kva(struct kni_dev *kni, struct rte_kni_mbuf *m)
+{
+       return phys_to_virt(iova_to_phys(kni->usr_tsk, m->buf_iova) +
+                           m->data_off);
+}
+#endif
+
 /* physical address to kernel virtual address */
 static void *
 pa2kva(void *pa)
@@ -51,7 +68,7 @@ pa2va(void *pa, struct rte_kni_mbuf *m)
 
        va = (void *)((unsigned long)pa +
                        (unsigned long)m->buf_addr -
-                       (unsigned long)m->buf_physaddr);
+                       (unsigned long)m->buf_iova);
        return va;
 }
 
@@ -59,23 +76,49 @@ pa2va(void *pa, struct rte_kni_mbuf *m)
 static void *
 kva2data_kva(struct rte_kni_mbuf *m)
 {
-       return phys_to_virt(m->buf_physaddr + m->data_off);
+       return phys_to_virt(m->buf_iova + m->data_off);
+}
+
+static inline void *
+get_kva(struct kni_dev *kni, void *pa)
+{
+#ifdef HAVE_IOVA_TO_KVA_MAPPING_SUPPORT
+       if (kni->iova_mode == 1)
+               return iova2kva(kni, pa);
+#endif
+       return pa2kva(pa);
+}
+
+static inline void *
+get_data_kva(struct kni_dev *kni, void *pkt_kva)
+{
+#ifdef HAVE_IOVA_TO_KVA_MAPPING_SUPPORT
+       if (kni->iova_mode == 1)
+               return iova2data_kva(kni, pkt_kva);
+#endif
+       return kva2data_kva(pkt_kva);
 }
 
 /*
  * It can be called to process the request.
  */
 static int
-kni_net_process_request(struct kni_dev *kni, struct rte_kni_request *req)
+kni_net_process_request(struct net_device *dev, struct rte_kni_request *req)
 {
+       struct kni_dev *kni = netdev_priv(dev);
        int ret = -1;
        void *resp_va;
        uint32_t num;
        int ret_val;
 
-       if (!kni || !req) {
-               pr_err("No kni instance or request\n");
-               return -EINVAL;
+       ASSERT_RTNL();
+
+       /* If we need to wait and RTNL mutex is held
+        * drop the mutex and hold reference to keep device
+        */
+       if (req->async == 0) {
+               dev_hold(dev);
+               rtnl_unlock();
        }
 
        mutex_lock(&kni->sync_lock);
@@ -89,6 +132,14 @@ kni_net_process_request(struct kni_dev *kni, struct rte_kni_request *req)
                goto fail;
        }
 
+       /* No result available since request is handled
+        * asynchronously. set response to success.
+        */
+       if (req->async != 0) {
+               req->result = 0;
+               goto async;
+       }
+
        ret_val = wait_event_interruptible_timeout(kni->wq,
                        kni_fifo_count(kni->resp_q), 3 * HZ);
        if (signal_pending(current) || ret_val <= 0) {
@@ -104,10 +155,15 @@ kni_net_process_request(struct kni_dev *kni, struct rte_kni_request *req)
        }
 
        memcpy(req, kni->sync_kva, sizeof(struct rte_kni_request));
+async:
        ret = 0;
 
 fail:
        mutex_unlock(&kni->sync_lock);
+       if (req->async == 0) {
+               rtnl_lock();
+               dev_put(dev);
+       }
        return ret;
 }
 
@@ -119,10 +175,9 @@ kni_net_open(struct net_device *dev)
 {
        int ret;
        struct rte_kni_request req;
-       struct kni_dev *kni = netdev_priv(dev);
 
        netif_start_queue(dev);
-       if (dflt_carrier == 1)
+       if (kni_dflt_carrier == 1)
                netif_carrier_on(dev);
        else
                netif_carrier_off(dev);
@@ -132,7 +187,7 @@ kni_net_open(struct net_device *dev)
 
        /* Setting if_up to non-zero means up */
        req.if_up = 1;
-       ret = kni_net_process_request(kni, &req);
+       ret = kni_net_process_request(dev, &req);
 
        return (ret == 0) ? req.result : ret;
 }
@@ -142,7 +197,6 @@ kni_net_release(struct net_device *dev)
 {
        int ret;
        struct rte_kni_request req;
-       struct kni_dev *kni = netdev_priv(dev);
 
        netif_stop_queue(dev); /* can't transmit any more */
        netif_carrier_off(dev);
@@ -152,7 +206,11 @@ kni_net_release(struct net_device *dev)
 
        /* Setting if_up to 0 means down */
        req.if_up = 0;
-       ret = kni_net_process_request(kni, &req);
+
+       /* request async because of the deadlock problem */
+       req.async = 1;
+
+       ret = kni_net_process_request(dev, &req);
 
        return (ret == 0) ? req.result : ret;
 }
@@ -178,7 +236,7 @@ kni_fifo_trans_pa2va(struct kni_dev *kni,
                        return;
 
                for (i = 0; i < num_rx; i++) {
-                       kva = pa2kva(kni->pa[i]);
+                       kva = get_kva(kni, kni->pa[i]);
                        kni->va[i] = pa2va(kni->pa[i], kva);
 
                        kva_nb_segs = kva->nb_segs;
@@ -187,7 +245,7 @@ kni_fifo_trans_pa2va(struct kni_dev *kni,
                                        break;
 
                                prev_kva = kva;
-                               kva = pa2kva(kva->next);
+                               kva = get_kva(kni, kva->next);
                                /* Convert physical address to virtual address */
                                prev_kva->next = pa2va(prev_kva->next, kva);
                        }
@@ -266,8 +324,8 @@ kni_net_tx(struct sk_buff *skb, struct net_device *dev)
        if (likely(ret == 1)) {
                void *data_kva;
 
-               pkt_kva = pa2kva(pkt_pa);
-               data_kva = kva2data_kva(pkt_kva);
+               pkt_kva = get_kva(kni, pkt_pa);
+               data_kva = get_data_kva(kni, pkt_kva);
                pkt_va = pa2va(pkt_pa, pkt_kva);
 
                len = skb->len;
@@ -338,9 +396,9 @@ kni_net_rx_normal(struct kni_dev *kni)
 
        /* Transfer received packets to netif */
        for (i = 0; i < num_rx; i++) {
-               kva = pa2kva(kni->pa[i]);
+               kva = get_kva(kni, kni->pa[i]);
                len = kva->pkt_len;
-               data_kva = kva2data_kva(kva);
+               data_kva = get_data_kva(kni, kva);
                kni->va[i] = pa2va(kni->pa[i], kva);
 
                skb = netdev_alloc_skb(dev, len);
@@ -364,7 +422,7 @@ kni_net_rx_normal(struct kni_dev *kni)
                                        break;
 
                                prev_kva = kva;
-                               kva = pa2kva(kva->next);
+                               kva = get_kva(kni, kva->next);
                                data_kva = kva2data_kva(kva);
                                /* Convert physical address to virtual address */
                                prev_kva->next = pa2va(prev_kva->next, kva);
@@ -437,20 +495,20 @@ kni_net_rx_lo_fifo(struct kni_dev *kni)
                num = ret;
                /* Copy mbufs */
                for (i = 0; i < num; i++) {
-                       kva = pa2kva(kni->pa[i]);
+                       kva = get_kva(kni, kni->pa[i]);
                        len = kva->data_len;
-                       data_kva = kva2data_kva(kva);
+                       data_kva = get_data_kva(kni, kva);
                        kni->va[i] = pa2va(kni->pa[i], kva);
 
                        while (kva->next) {
-                               next_kva = pa2kva(kva->next);
+                               next_kva = get_kva(kni, kva->next);
                                /* Convert physical address to virtual address */
                                kva->next = pa2va(kva->next, next_kva);
                                kva = next_kva;
                        }
 
-                       alloc_kva = pa2kva(kni->alloc_pa[i]);
-                       alloc_data_kva = kva2data_kva(alloc_kva);
+                       alloc_kva = get_kva(kni, kni->alloc_pa[i]);
+                       alloc_data_kva = get_data_kva(kni, alloc_kva);
                        kni->alloc_va[i] = pa2va(kni->alloc_pa[i], alloc_kva);
 
                        memcpy(alloc_data_kva, data_kva, len);
@@ -517,9 +575,9 @@ kni_net_rx_lo_fifo_skb(struct kni_dev *kni)
 
        /* Copy mbufs to sk buffer and then call tx interface */
        for (i = 0; i < num; i++) {
-               kva = pa2kva(kni->pa[i]);
+               kva = get_kva(kni, kni->pa[i]);
                len = kva->pkt_len;
-               data_kva = kva2data_kva(kva);
+               data_kva = get_data_kva(kni, kva);
                kni->va[i] = pa2va(kni->pa[i], kva);
 
                skb = netdev_alloc_skb(dev, len);
@@ -550,8 +608,8 @@ kni_net_rx_lo_fifo_skb(struct kni_dev *kni)
                                        break;
 
                                prev_kva = kva;
-                               kva = pa2kva(kva->next);
-                               data_kva = kva2data_kva(kva);
+                               kva = get_kva(kni, kva->next);
+                               data_kva = get_data_kva(kni, kva);
                                /* Convert physical address to virtual address */
                                prev_kva->next = pa2va(prev_kva->next, kva);
                        }
@@ -587,8 +645,13 @@ kni_net_rx(struct kni_dev *kni)
 /*
  * Deal with a transmit timeout.
  */
+#ifdef HAVE_TX_TIMEOUT_TXQUEUE
+static void
+kni_net_tx_timeout(struct net_device *dev, unsigned int txqueue)
+#else
 static void
 kni_net_tx_timeout(struct net_device *dev)
+#endif
 {
        pr_debug("Transmit timeout at %ld, latency %ld\n", jiffies,
                        jiffies - dev_trans_start(dev));
@@ -602,14 +665,13 @@ kni_net_change_mtu(struct net_device *dev, int new_mtu)
 {
        int ret;
        struct rte_kni_request req;
-       struct kni_dev *kni = netdev_priv(dev);
 
        pr_debug("kni_net_change_mtu new mtu %d to be set\n", new_mtu);
 
        memset(&req, 0, sizeof(req));
        req.req_id = RTE_KNI_REQ_CHANGE_MTU;
        req.new_mtu = new_mtu;
-       ret = kni_net_process_request(kni, &req);
+       ret = kni_net_process_request(dev, &req);
        if (ret == 0 && req.result == 0)
                dev->mtu = new_mtu;
 
@@ -620,7 +682,6 @@ static void
 kni_net_change_rx_flags(struct net_device *netdev, int flags)
 {
        struct rte_kni_request req;
-       struct kni_dev *kni = netdev_priv(netdev);
 
        memset(&req, 0, sizeof(req));
 
@@ -642,7 +703,7 @@ kni_net_change_rx_flags(struct net_device *netdev, int flags)
                        req.promiscusity = 0;
        }
 
-       kni_net_process_request(kni, &req);
+       kni_net_process_request(netdev, &req);
 }
 
 /*
@@ -701,7 +762,6 @@ kni_net_set_mac(struct net_device *netdev, void *p)
 {
        int ret;
        struct rte_kni_request req;
-       struct kni_dev *kni;
        struct sockaddr *addr = p;
 
        memset(&req, 0, sizeof(req));
@@ -713,8 +773,7 @@ kni_net_set_mac(struct net_device *netdev, void *p)
        memcpy(req.mac_addr, addr->sa_data, netdev->addr_len);
        memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
 
-       kni = netdev_priv(netdev);
-       ret = kni_net_process_request(kni, &req);
+       ret = kni_net_process_request(netdev, &req);
 
        return (ret == 0 ? req.result : ret);
 }