]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
SPARC64: UEK4 LDOMS DOMAIN SERVICES UPDATE 2
authorAaron Young <Aaron.Young@oracle.com>
Thu, 10 Dec 2015 14:39:54 +0000 (06:39 -0800)
committerAllen Pais <allen.pais@oracle.com>
Fri, 11 Dec 2015 14:27:29 +0000 (19:57 +0530)
    This update provides fixes for LDom domain services on UEK4.
    Including:

    1. Add control vlds device for non-device specific operations.
    2. Allocate larger LDC rx/tx queues based on MTU - same
       algorithm as Solaris.
    3. Fix default MTU for all ds devices to 4096 bytes.

Signed-off-by: Aaron Young <aaron.young@oracle.com>
    Orabug: 22347667
(cherry picked from commit f2cf5889f22fd3d1062a7fe985a6ab574eebdbf5)

arch/sparc/kernel/ds.c
arch/sparc/kernel/ldc.c
drivers/char/vlds.c
include/uapi/linux/vlds.h

index 28ce1ecd226b9b11d3fc9fb2e64c2ebc6f57247e..9ed18a51dac221be058934dd46fd9eb9fd26ec08 100644 (file)
@@ -114,7 +114,6 @@ MODULE_VERSION(DRV_MODULE_VERSION);
  * The largest contiguous buffer the kernel seems to allow is 8MB.
  */
 #define        DS_DEFAULT_SP_BUF_SIZE  (8*1024*1024)
-#define        DS_DEFAULT_SP_MTU       (8*1024*1024)
 
 #define        DS_PRIMARY_ID           0
 
@@ -198,7 +197,7 @@ struct ds_dev {
 
        /* LDC receive data buffer for this ds_dev */
        u8                      *rcv_buf;
-       int                     rcv_buf_len;
+       u64                     rcv_buf_len;
        u32                     mtu;
 
        /* service registration timer */
@@ -4321,9 +4320,6 @@ static int ds_probe(struct vio_dev *vdev, const struct vio_device_id *id)
                        goto out_free_ds;
 
                ds->rcv_buf_len = DS_DEFAULT_SP_BUF_SIZE;
-
-               ds_cfg.mtu = DS_DEFAULT_SP_MTU;
-
        } else {
                ds->rcv_buf = kzalloc(DS_DEFAULT_BUF_SIZE,
                    GFP_KERNEL);
@@ -4331,11 +4327,11 @@ static int ds_probe(struct vio_dev *vdev, const struct vio_device_id *id)
                        goto out_free_ds;
 
                ds->rcv_buf_len = DS_DEFAULT_BUF_SIZE;
-
-               ds_cfg.mtu = DS_DEFAULT_MTU;
        }
 
+       ds_cfg.mtu = DS_DEFAULT_MTU;
        ds->mtu = ds_cfg.mtu;
+
        ds->hs_state = DS_HS_LDC_DOWN;
        ds_cfg.debug = 0;
        ds_cfg.tx_irq = vdev->tx_irq;
index d6ac8969d315880d7e302cd0670e046e597a2c1c..0f5aad4da8d43aa118ea0a3213aea3245baeb827 100644 (file)
@@ -86,7 +86,8 @@ static struct ldc_version ver_arr[] = {
 };
 
 #define LDC_DEFAULT_MTU                        (4 * LDC_PACKET_SIZE)
-#define LDC_DEFAULT_NUM_ENTRIES                (PAGE_SIZE / LDC_PACKET_SIZE)
+#define LDC_MTU_MSGS                   (4)
+#define LDC_MIN_NUM_ENTRIES            (512)
 
 struct ldc_channel;
 
@@ -1157,6 +1158,7 @@ struct ldc_channel *ldc_alloc(unsigned long id,
        const struct ldc_mode_ops *mops;
        unsigned long dummy1, dummy2, hv_err;
        u8 mss, *mssbuf;
+       u32 num_entries;
        int err;
 
        err = -ENODEV;
@@ -1234,11 +1236,26 @@ struct ldc_channel *ldc_alloc(unsigned long id,
 
        lp->event_arg = event_arg;
 
-       /* XXX allow setting via ldc_channel_config to override defaults
-        * XXX or use some formula based upon mtu
-        */
-       lp->tx_num_entries = LDC_DEFAULT_NUM_ENTRIES;
-       lp->rx_num_entries = LDC_DEFAULT_NUM_ENTRIES;
+       /* calculate the number of rx/tx queue entries */
+       num_entries = (lp->cfg.mtu * LDC_MTU_MSGS) / mss;
+
+       /* round num_entries up to nearest power of 2 - per spec */
+       if ((num_entries & (num_entries - 1)) != 0) {
+
+               uint64_t        tmp = 1;
+
+               while (num_entries) {
+                       num_entries >>= 1; tmp <<= 1;
+               }
+               num_entries = tmp;
+       }
+
+       /* guarantee a minimum number of queue entries */
+       if (num_entries < LDC_MIN_NUM_ENTRIES)
+               num_entries = LDC_MIN_NUM_ENTRIES;
+
+       lp->tx_num_entries = num_entries;
+       lp->rx_num_entries = num_entries;
 
        err = alloc_queue("TX", lp->tx_num_entries,
                          &lp->tx_base, &lp->tx_ra);
index be6946db9c25c7cc0329609b777e0f1ac25bad42..8d5498058187530fb21be0eddf1a606713b25e57 100644 (file)
@@ -87,6 +87,10 @@ struct vlds_dev {
 struct vlds_dev *sp_vlds;
 #define        IS_SP_VLDS(vlds_dev)    ((vlds_dev) == sp_vlds)
 
+/* Control device to provide non-device specific operations */
+struct vlds_dev *ctrl_vlds;
+#define        IS_CTRL_VLDS(vlds_dev)  ((vlds_dev) == ctrl_vlds)
+
 /*
  * Service info to describe a service and process(es) using the service.
  * Services can be regsitered as shared (the default) or exclusive.
@@ -2064,6 +2068,19 @@ static long vlds_fops_ioctl(struct file *filp, unsigned int cmd,
                return -ENXIO;
        }
 
+       if (IS_CTRL_VLDS(vlds)) {
+               /*
+                * For the control device,
+                * we only allow the following operations.
+                */
+               if (cmd != VLDS_IOCTL_SET_EVENT_FD &&
+                   cmd != VLDS_IOCTL_UNSET_EVENT_FD &&
+                   cmd != VLDS_IOCTL_GET_NEXT_EVENT) {
+                       mutex_unlock(&vlds->vlds_mutex);
+                       return -EINVAL;
+               }
+       }
+
        mutex_unlock(&vlds->vlds_mutex);
 
        switch (cmd) {
@@ -2506,6 +2523,12 @@ static int __init vlds_init(void)
        /* set callback to create devices under /dev/vlds directory */
        vlds_data.chrdev_class->devnode = vlds_devnode;
 
+       /* Create the control device */
+       rv = vlds_alloc_vlds_dev(VLDS_CTRL_DEV_NAME, VLDS_CTRL_DEV_NAME,
+           NULL, VLDS_INVALID_HANDLE, &ctrl_vlds);
+       if (rv != 0)
+               dprintk("Failed to create control vlds device (%d)\n", rv);
+
        /*
         * If there is a SP DS present on the system (in the MD),
         * add a device for the SP directly since there is no
@@ -2558,6 +2581,21 @@ static void __exit vlds_exit(void)
                mutex_unlock(&vlds_data_mutex);
        }
 
+       if (ctrl_vlds) {
+
+               mutex_lock(&vlds_data_mutex);
+               mutex_lock(&ctrl_vlds->vlds_mutex);
+
+               /* Cleanup the associated cdev, /sys and /dev entry */
+               device_destroy(vlds_data.chrdev_class, ctrl_vlds->devt);
+               cdev_del(&ctrl_vlds->cdev);
+
+               vlds_free_vlds_dev(ctrl_vlds);
+               ctrl_vlds = NULL;
+
+               mutex_unlock(&vlds_data_mutex);
+       }
+
        /*
         * Note - vio_unregister_driver() will invoke a call to
         * vlds_remove() for every successfully probed device.
index 99f26c561bbc89d15e659f9afecf7417b87ad188..bd064ef351226d3b1be6d3ad9f1aa64400bd5522 100644 (file)
@@ -10,7 +10,9 @@
 
 #define        VLDS_DEV_DIR            "/dev/vlds"
 #define        VLDS_SP_DEV_NAME        "sp" /* SP DS device name */
+#define        VLDS_CTRL_DEV_NAME      "ctrl" /* Control DS device name */
 #define        VLDS_DEV_DOMAIN_FILENAME_TAG    "host:"
+#define        VLDS_INVALID_HANDLE     0xFFFFFFFFFFFFFFFFUL
 
 /* String arguments to ioctl */
 typedef struct vlds_string_arg {