staging: most: make interface drivers allocate coherent memory
authorChristian Gromm <christian.gromm@microchip.com>
Tue, 8 May 2018 09:45:03 +0000 (11:45 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 8 May 2018 11:41:50 +0000 (13:41 +0200)
On arm64/aarch64 architectures the allocation of coherent memory needs a
device that has the dma_ops properly set. That's why the core module of
the MOST driver is no longer able to allocate this type or memory. This
patch moves the allocation process down to the interface drivers where
the proper devices exist (e.g. platform device or USB system software).

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/most/core.c
drivers/staging/most/core.h
drivers/staging/most/dim2/dim2.c
drivers/staging/most/usb/usb.c

index db3c7e243deb98d30c985d0995e1d3e8c7205dc4..f4c464625a67b7869c2a419cb829aee2ca0468c0 100644 (file)
@@ -111,8 +111,10 @@ static void most_free_mbo_coherent(struct mbo *mbo)
        struct most_channel *c = mbo->context;
        u16 const coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
 
-       dma_free_coherent(NULL, coherent_buf_size, mbo->virt_address,
-                         mbo->bus_address);
+       if (c->iface->dma_free)
+               c->iface->dma_free(mbo, coherent_buf_size);
+       else
+               kfree(mbo->virt_address);
        kfree(mbo);
        if (atomic_sub_and_test(1, &c->mbo_ref))
                complete(&c->cleanup);
@@ -988,10 +990,13 @@ static int arm_mbo_chain(struct most_channel *c, int dir,
                mbo->context = c;
                mbo->ifp = c->iface;
                mbo->hdm_channel_id = c->channel_id;
-               mbo->virt_address = dma_alloc_coherent(NULL,
-                                                      coherent_buf_size,
-                                                      &mbo->bus_address,
-                                                      GFP_KERNEL);
+               if (c->iface->dma_alloc) {
+                       mbo->virt_address =
+                               c->iface->dma_alloc(mbo, coherent_buf_size);
+               } else {
+                       mbo->virt_address =
+                               kzalloc(coherent_buf_size, GFP_KERNEL);
+               }
                if (!mbo->virt_address)
                        goto release_mbo;
 
index 5b184e6d4721a5f5278725b163983573c2940f3e..7a3c70bead19b61fa0f30484c565337feff9c332 100644 (file)
@@ -235,6 +235,8 @@ struct most_interface {
        const char *description;
        unsigned int num_channels;
        struct most_channel_capability *channel_vector;
+       void *(*dma_alloc)(struct mbo *mbo, u32 size);
+       void (*dma_free)(struct mbo *mbo, u32 size);
        int (*configure)(struct most_interface *iface, int channel_idx,
                         struct most_channel_config *channel_config);
        int (*enqueue)(struct most_interface *iface, int channel_idx,
index d15867a1ba2daeddf43c54361c8c538c57aca7e3..3c385b3fabecfd99a44eaba52adb7b69295e3713 100644 (file)
@@ -703,6 +703,16 @@ static int poison_channel(struct most_interface *most_iface, int ch_idx)
        return ret;
 }
 
+static void *dma_alloc(struct mbo *mbo, u32 size)
+{
+       return dma_alloc_coherent(NULL, size, &mbo->bus_address, GFP_KERNEL);
+}
+
+static void dma_free(struct mbo *mbo, u32 size)
+{
+       dma_free_coherent(NULL, size, mbo->virt_address, mbo->bus_address);
+}
+
 /*
  * dim2_probe - dim2 probe handler
  * @pdev: platform device structure
@@ -800,6 +810,8 @@ static int dim2_probe(struct platform_device *pdev)
        dev->most_iface.channel_vector = dev->capabilities;
        dev->most_iface.configure = configure_channel;
        dev->most_iface.enqueue = enqueue;
+       dev->most_iface.dma_alloc = dma_alloc;
+       dev->most_iface.dma_free = dma_free;
        dev->most_iface.poison_channel = poison_channel;
        dev->most_iface.request_netinfo = request_netinfo;
        dev->dev.init_name = "dim2_state";
index 31f184cfcd694cb86c653b3b4ac9296636326d88..5ed1dccc0839b4d47bc80d336ad185b047af8430 100644 (file)
@@ -618,6 +618,22 @@ _error:
        return retval;
 }
 
+static void *hdm_dma_alloc(struct mbo *mbo, u32 size)
+{
+       struct most_dev *mdev = to_mdev(mbo->ifp);
+
+       return usb_alloc_coherent(mdev->usb_device, size, GFP_KERNEL,
+                                 &mbo->bus_address);
+}
+
+static void hdm_dma_free(struct mbo *mbo, u32 size)
+{
+       struct most_dev *mdev = to_mdev(mbo->ifp);
+
+       usb_free_coherent(mdev->usb_device, size, mbo->virt_address,
+                         mbo->bus_address);
+}
+
 /**
  * hdm_configure_channel - receive channel configuration from core
  * @iface: interface
@@ -1032,6 +1048,8 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
        mdev->iface.request_netinfo = hdm_request_netinfo;
        mdev->iface.enqueue = hdm_enqueue;
        mdev->iface.poison_channel = hdm_poison_channel;
+       mdev->iface.dma_alloc = hdm_dma_alloc;
+       mdev->iface.dma_free = hdm_dma_free;
        mdev->iface.description = mdev->description;
        mdev->iface.num_channels = num_endpoints;