diff options
Diffstat (limited to 'drivers/staging/vc04_services')
28 files changed, 1232 insertions, 1786 deletions
diff --git a/drivers/staging/vc04_services/bcm2835-audio/Kconfig b/drivers/staging/vc04_services/bcm2835-audio/Kconfig index 9f536533c257..62c1c8ba4ad4 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/Kconfig +++ b/drivers/staging/vc04_services/bcm2835-audio/Kconfig @@ -1,6 +1,6 @@ config SND_BCM2835 tristate "BCM2835 Audio" - depends on ARCH_BCM2835 && SND + depends on (ARCH_BCM2835 || COMPILE_TEST) && SND select SND_PCM select BCM2835_VCHIQ help diff --git a/drivers/staging/vc04_services/bcm2835-audio/TODO b/drivers/staging/vc04_services/bcm2835-audio/TODO index 73d41fa631ac..cb8ead3e9108 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/TODO +++ b/drivers/staging/vc04_services/bcm2835-audio/TODO @@ -4,26 +4,7 @@ * * ***************************************************************************** +1) Revisit multi-cards options and PCM route mixer control (as per comment +https://lkml.org/lkml/2018/9/8/200) -1) Document the device tree node - -The downstream tree(the tree that the driver was imported from) at -http://www.github.com/raspberrypi/linux uses this node: - -audio: audio { - compatible = "brcm,bcm2835-audio"; - brcm,pwm-channels = <8>; -}; - -Since the driver requires the use of VCHIQ, it may be useful to have a link -in the device tree to the VCHIQ driver. - -2) Gracefully handle the case where VCHIQ is missing from the device tree or -it has not been initialized yet. - -3) Review error handling and remove duplicate code. - -4) Cleanup the logging mechanism. The driver should probably be using the -standard kernel logging mechanisms such as dev_info, dev_dbg, and friends. - -5) Fix the remaining checkpatch.pl errors and warnings. +2) Fix the remaining checkpatch.pl errors and warnings. diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c index e66da11af5cf..bc1eaa3a0773 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-pcm.c @@ -74,6 +74,7 @@ void bcm2835_playback_fifo(struct bcm2835_alsa_stream *alsa_stream, atomic_set(&alsa_stream->pos, pos); alsa_stream->period_offset += bytes; + alsa_stream->interpolate_start = ktime_get(); if (alsa_stream->period_offset >= alsa_stream->period_size) { alsa_stream->period_offset %= alsa_stream->period_size; snd_pcm_period_elapsed(substream); @@ -164,14 +165,11 @@ static int snd_bcm2835_playback_spdif_open(struct snd_pcm_substream *substream) return snd_bcm2835_playback_open_generic(substream, 1); } -/* close callback */ static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream) { - /* the hardware-specific codes will be here */ - - struct bcm2835_chip *chip; - struct snd_pcm_runtime *runtime; struct bcm2835_alsa_stream *alsa_stream; + struct snd_pcm_runtime *runtime; + struct bcm2835_chip *chip; chip = snd_pcm_substream_chip(substream); mutex_lock(&chip->audio_mutex); @@ -195,20 +193,17 @@ static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream) return 0; } -/* hw_params callback */ static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); } -/* hw_free callback */ static int snd_bcm2835_pcm_hw_free(struct snd_pcm_substream *substream) { return snd_pcm_lib_free_pages(substream); } -/* prepare callback */ static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream) { struct bcm2835_chip *chip = snd_pcm_substream_chip(substream); @@ -243,6 +238,7 @@ static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream) atomic_set(&alsa_stream->pos, 0); alsa_stream->period_offset = 0; alsa_stream->draining = false; + alsa_stream->interpolate_start = ktime_get(); return 0; } @@ -292,6 +288,24 @@ snd_bcm2835_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct bcm2835_alsa_stream *alsa_stream = runtime->private_data; + ktime_t now = ktime_get(); + + /* Give userspace better delay reporting by interpolating between GPU + * notifications, assuming audio speed is close enough to the clock + * used for ktime + */ + + if ((ktime_to_ns(alsa_stream->interpolate_start)) && + (ktime_compare(alsa_stream->interpolate_start, now) < 0)) { + u64 interval = + (ktime_to_ns(ktime_sub(now, + alsa_stream->interpolate_start))); + u64 frames_output_in_interval = + div_u64((interval * runtime->rate), 1000000000); + snd_pcm_sframes_t frames_output_in_interval_sized = + -frames_output_in_interval; + runtime->delay = frames_output_in_interval_sized; + } return snd_pcm_indirect_playback_pointer(substream, &alsa_stream->pcm_indirect, diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c index 781754f36da7..23fba01107b9 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c @@ -89,19 +89,14 @@ static int bcm2835_audio_send_simple(struct bcm2835_audio_instance *instance, return bcm2835_audio_send_msg(instance, &m, wait); } -static const u32 BCM2835_AUDIO_WRITE_COOKIE1 = ('B' << 24 | 'C' << 16 | - 'M' << 8 | 'A'); -static const u32 BCM2835_AUDIO_WRITE_COOKIE2 = ('D' << 24 | 'A' << 16 | - 'T' << 8 | 'A'); - static void audio_vchi_callback(void *param, const VCHI_CALLBACK_REASON_T reason, void *msg_handle) { struct bcm2835_audio_instance *instance = param; - int status; - int msg_len; struct vc_audio_msg m; + int msg_len; + int status; if (reason != VCHI_CALLBACK_MSG_AVAILABLE) return; @@ -109,15 +104,15 @@ static void audio_vchi_callback(void *param, status = vchi_msg_dequeue(instance->vchi_handle, &m, sizeof(m), &msg_len, VCHI_FLAGS_NONE); if (m.type == VC_AUDIO_MSG_TYPE_RESULT) { - instance->result = m.u.result.success; + instance->result = m.result.success; complete(&instance->msg_avail_comp); } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) { - if (m.u.complete.cookie1 != BCM2835_AUDIO_WRITE_COOKIE1 || - m.u.complete.cookie2 != BCM2835_AUDIO_WRITE_COOKIE2) + if (m.complete.cookie1 != VC_AUDIO_WRITE_COOKIE1 || + m.complete.cookie2 != VC_AUDIO_WRITE_COOKIE2) dev_err(instance->dev, "invalid cookie\n"); else bcm2835_playback_fifo(instance->alsa_stream, - m.u.complete.count); + m.complete.count); } else { dev_err(instance->dev, "unexpected callback type=%d\n", m.type); } @@ -127,7 +122,7 @@ static int vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance, struct bcm2835_audio_instance *instance) { - SERVICE_CREATION_T params = { + struct service_creation params = { .version = VCHI_VERSION_EX(VC_AUDIOSERV_VER, VC_AUDIOSERV_MIN_VER), .service_id = VC_AUDIO_SERVER_NAME, .callback = audio_vchi_callback, @@ -143,7 +138,6 @@ vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance, dev_err(instance->dev, "failed to open VCHI service connection (status=%d)\n", status); - kfree(instance); return -EPERM; } @@ -254,11 +248,11 @@ int bcm2835_audio_set_ctls(struct bcm2835_alsa_stream *alsa_stream) struct vc_audio_msg m = {}; m.type = VC_AUDIO_MSG_TYPE_CONTROL; - m.u.control.dest = chip->dest; + m.control.dest = chip->dest; if (!chip->mute) - m.u.control.volume = CHIP_MIN_VOLUME; + m.control.volume = CHIP_MIN_VOLUME; else - m.u.control.volume = alsa2chip(chip->volume); + m.control.volume = alsa2chip(chip->volume); return bcm2835_audio_send_msg(alsa_stream->instance, &m, true); } @@ -269,9 +263,9 @@ int bcm2835_audio_set_params(struct bcm2835_alsa_stream *alsa_stream, { struct vc_audio_msg m = { .type = VC_AUDIO_MSG_TYPE_CONFIG, - .u.config.channels = channels, - .u.config.samplerate = samplerate, - .u.config.bps = bps, + .config.channels = channels, + .config.samplerate = samplerate, + .config.bps = bps, }; int err; @@ -299,7 +293,7 @@ int bcm2835_audio_drain(struct bcm2835_alsa_stream *alsa_stream) { struct vc_audio_msg m = { .type = VC_AUDIO_MSG_TYPE_STOP, - .u.stop.draining = 1, + .stop.draining = 1, }; return bcm2835_audio_send_msg(alsa_stream->instance, &m, false); @@ -327,10 +321,10 @@ int bcm2835_audio_write(struct bcm2835_alsa_stream *alsa_stream, struct bcm2835_audio_instance *instance = alsa_stream->instance; struct vc_audio_msg m = { .type = VC_AUDIO_MSG_TYPE_WRITE, - .u.write.count = size, - .u.write.max_packet = instance->max_packet, - .u.write.cookie1 = BCM2835_AUDIO_WRITE_COOKIE1, - .u.write.cookie2 = BCM2835_AUDIO_WRITE_COOKIE2, + .write.count = size, + .write.max_packet = instance->max_packet, + .write.cookie1 = VC_AUDIO_WRITE_COOKIE1, + .write.cookie2 = VC_AUDIO_WRITE_COOKIE2, }; unsigned int count; int err, status; diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c index 87d56ab1ffa0..cf5f80f5ca6b 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c @@ -6,13 +6,13 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/of.h> #include "bcm2835.h" static bool enable_hdmi; static bool enable_headphones; static bool enable_compat_alsa = true; +static int num_channels = MAX_SUBSTREAMS; module_param(enable_hdmi, bool, 0444); MODULE_PARM_DESC(enable_hdmi, "Enables HDMI virtual audio device"); @@ -21,6 +21,8 @@ MODULE_PARM_DESC(enable_headphones, "Enables Headphones virtual audio device"); module_param(enable_compat_alsa, bool, 0444); MODULE_PARM_DESC(enable_compat_alsa, "Enables ALSA compatibility virtual audio device"); +module_param(num_channels, int, 0644); +MODULE_PARM_DESC(num_channels, "Number of audio channels (default: 8)"); static void bcm2835_devm_free_vchi_ctx(struct device *dev, void *res) { @@ -39,8 +41,6 @@ static int bcm2835_devm_add_vchi_ctx(struct device *dev) if (!vchi_ctx) return -ENOMEM; - memset(vchi_ctx, 0, sizeof(*vchi_ctx)); - ret = bcm2835_new_vchi_ctx(dev, vchi_ctx); if (ret) { devres_free(vchi_ctx); @@ -163,8 +163,8 @@ static int snd_add_child_device(struct device *dev, struct bcm2835_audio_driver *audio_driver, u32 numchans) { - struct snd_card *card; struct bcm2835_chip *chip; + struct snd_card *card; int err; err = snd_card_new(dev, -1, NULL, THIS_MODULE, sizeof(*chip), &card); @@ -227,12 +227,12 @@ static int snd_add_child_device(struct device *dev, static int snd_add_child_devices(struct device *device, u32 numchans) { - int i; - int count_devices = 0; - int minchannels = 0; - int extrachannels = 0; int extrachannels_per_driver = 0; int extrachannels_remainder = 0; + int count_devices = 0; + int extrachannels = 0; + int minchannels = 0; + int i; for (i = 0; i < ARRAY_SIZE(children_devices); i++) if (*children_devices[i].is_enabled) @@ -260,9 +260,9 @@ static int snd_add_child_devices(struct device *device, u32 numchans) extrachannels_remainder); for (i = 0; i < ARRAY_SIZE(children_devices); i++) { - int err; - int numchannels_this_device; struct bcm2835_audio_driver *audio_driver; + int numchannels_this_device; + int err; if (!*children_devices[i].is_enabled) continue; @@ -293,31 +293,22 @@ static int snd_add_child_devices(struct device *device, u32 numchans) return 0; } -static int snd_bcm2835_alsa_probe_dt(struct platform_device *pdev) +static int snd_bcm2835_alsa_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - u32 numchans; int err; - err = of_property_read_u32(dev->of_node, "brcm,pwm-channels", - &numchans); - if (err) { - dev_err(dev, "Failed to get DT property 'brcm,pwm-channels'"); - return err; - } - - if (numchans == 0 || numchans > MAX_SUBSTREAMS) { - numchans = MAX_SUBSTREAMS; - dev_warn(dev, - "Illegal 'brcm,pwm-channels' value, will use %u\n", - numchans); + if (num_channels <= 0 || num_channels > MAX_SUBSTREAMS) { + num_channels = MAX_SUBSTREAMS; + dev_warn(dev, "Illegal num_channels value, will use %u\n", + num_channels); } err = bcm2835_devm_add_vchi_ctx(dev); if (err) return err; - err = snd_add_child_devices(dev, numchans); + err = snd_add_child_devices(dev, num_channels); if (err) return err; @@ -339,43 +330,19 @@ static int snd_bcm2835_alsa_resume(struct platform_device *pdev) #endif -static const struct of_device_id snd_bcm2835_of_match_table[] = { - { .compatible = "brcm,bcm2835-audio",}, - {}, -}; -MODULE_DEVICE_TABLE(of, snd_bcm2835_of_match_table); - -static struct platform_driver bcm2835_alsa0_driver = { - .probe = snd_bcm2835_alsa_probe_dt, +static struct platform_driver bcm2835_alsa_driver = { + .probe = snd_bcm2835_alsa_probe, #ifdef CONFIG_PM .suspend = snd_bcm2835_alsa_suspend, .resume = snd_bcm2835_alsa_resume, #endif .driver = { .name = "bcm2835_audio", - .of_match_table = snd_bcm2835_of_match_table, }, }; - -static int bcm2835_alsa_device_init(void) -{ - int retval; - - retval = platform_driver_register(&bcm2835_alsa0_driver); - if (retval) - pr_err("Error registering bcm2835_audio driver %d .\n", retval); - - return retval; -} - -static void bcm2835_alsa_device_exit(void) -{ - platform_driver_unregister(&bcm2835_alsa0_driver); -} - -late_initcall(bcm2835_alsa_device_init); -module_exit(bcm2835_alsa_device_exit); +module_platform_driver(bcm2835_alsa_driver); MODULE_AUTHOR("Dom Cobley"); MODULE_DESCRIPTION("Alsa driver for BCM2835 chip"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:bcm2835_audio"); diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h index 34a0125ce646..ed0feb34b6c8 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h @@ -77,6 +77,7 @@ struct bcm2835_alsa_stream { unsigned int period_offset; unsigned int buffer_size; unsigned int period_size; + ktime_t interpolate_start; struct bcm2835_audio_instance *instance; int idx; diff --git a/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h b/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h index 1a7f0884ac9c..d6401e914ac9 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h +++ b/drivers/staging/vc04_services/bcm2835-audio/vc_vchi_audioserv_defs.h @@ -7,8 +7,10 @@ #define VC_AUDIOSERV_MIN_VER 1 #define VC_AUDIOSERV_VER 2 -/* FourCC code used for VCHI connection */ +/* FourCC codes used for VCHI communication */ #define VC_AUDIO_SERVER_NAME MAKE_FOURCC("AUDS") +#define VC_AUDIO_WRITE_COOKIE1 MAKE_FOURCC("BCMA") +#define VC_AUDIO_WRITE_COOKIE2 MAKE_FOURCC("DATA") /* * List of screens that are currently supported @@ -91,7 +93,7 @@ struct vc_audio_msg { struct vc_audio_write write; struct vc_audio_result result; struct vc_audio_complete complete; - } u; + }; }; #endif /* _VC_AUDIO_DEFS_H_ */ diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c index c04bdf070c87..611a6ee2943a 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c +++ b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c @@ -43,11 +43,6 @@ #define MAX_BCM2835_CAMERAS 2 -MODULE_DESCRIPTION("Broadcom 2835 MMAL video capture"); -MODULE_AUTHOR("Vincent Sanders"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(BM2835_MMAL_VERSION); - int bcm2835_v4l2_debug; module_param_named(debug, bcm2835_v4l2_debug, int, 0644); MODULE_PARM_DESC(bcm2835_v4l2_debug, "Debug level 0-2"); @@ -1544,8 +1539,11 @@ static int mmal_init(struct bm2835_mmal_dev *dev) struct vchiq_mmal_component *camera; ret = vchiq_mmal_init(&dev->instance); - if (ret < 0) + if (ret < 0) { + v4l2_err(&dev->v4l2_dev, "%s: vchiq mmal init failed %d\n", + __func__, ret); return ret; + } /* get the camera component ready */ ret = vchiq_mmal_component_init(dev->instance, "ril.camera", @@ -1554,7 +1552,9 @@ static int mmal_init(struct bm2835_mmal_dev *dev) goto unreg_mmal; camera = dev->component[MMAL_COMPONENT_CAMERA]; - if (camera->outputs < MMAL_CAMERA_PORT_COUNT) { + if (camera->outputs < MMAL_CAMERA_PORT_COUNT) { + v4l2_err(&dev->v4l2_dev, "%s: too few camera outputs %d needed %d\n", + __func__, camera->outputs, MMAL_CAMERA_PORT_COUNT); ret = -EINVAL; goto unreg_camera; } @@ -1562,8 +1562,11 @@ static int mmal_init(struct bm2835_mmal_dev *dev) ret = set_camera_parameters(dev->instance, camera, dev); - if (ret < 0) + if (ret < 0) { + v4l2_err(&dev->v4l2_dev, "%s: unable to set camera parameters: %d\n", + __func__, ret); goto unreg_camera; + } /* There was an error in the firmware that meant the camera component * produced BGR instead of RGB. @@ -1652,8 +1655,8 @@ static int mmal_init(struct bm2835_mmal_dev *dev) if (dev->component[MMAL_COMPONENT_PREVIEW]->inputs < 1) { ret = -EINVAL; - pr_debug("too few input ports %d needed %d\n", - dev->component[MMAL_COMPONENT_PREVIEW]->inputs, 1); + v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n", + __func__, dev->component[MMAL_COMPONENT_PREVIEW]->inputs, 1); goto unreg_preview; } @@ -1666,8 +1669,8 @@ static int mmal_init(struct bm2835_mmal_dev *dev) if (dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs < 1) { ret = -EINVAL; - v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n", - dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs, + v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n", + __func__, dev->component[MMAL_COMPONENT_IMAGE_ENCODE]->inputs, 1); goto unreg_image_encoder; } @@ -1681,8 +1684,8 @@ static int mmal_init(struct bm2835_mmal_dev *dev) if (dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs < 1) { ret = -EINVAL; - v4l2_err(&dev->v4l2_dev, "too few input ports %d needed %d\n", - dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs, + v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n", + __func__, dev->component[MMAL_COMPONENT_VIDEO_ENCODE]->inputs, 1); goto unreg_vid_encoder; } @@ -1711,8 +1714,11 @@ static int mmal_init(struct bm2835_mmal_dev *dev) sizeof(enable)); } ret = bm2835_mmal_set_all_camera_controls(dev); - if (ret < 0) + if (ret < 0) { + v4l2_err(&dev->v4l2_dev, "%s: failed to set all camera controls: %d\n", + __func__, ret); goto unreg_vid_encoder; + } return 0; @@ -1841,6 +1847,12 @@ static int bcm2835_mmal_probe(struct platform_device *pdev) num_cameras = get_num_cameras(instance, resolutions, MAX_BCM2835_CAMERAS); + + if (num_cameras < 1) { + ret = -ENODEV; + goto cleanup_mmal; + } + if (num_cameras > MAX_BCM2835_CAMERAS) num_cameras = MAX_BCM2835_CAMERAS; @@ -1872,21 +1884,29 @@ static int bcm2835_mmal_probe(struct platform_device *pdev) snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s", BM2835_MMAL_MODULE_NAME); ret = v4l2_device_register(NULL, &dev->v4l2_dev); - if (ret) + if (ret) { + dev_err(&pdev->dev, "%s: could not register V4L2 device: %d\n", + __func__, ret); goto free_dev; + } /* setup v4l controls */ ret = bm2835_mmal_init_controls(dev, &dev->ctrl_handler); - if (ret < 0) + if (ret < 0) { + v4l2_err(&dev->v4l2_dev, "%s: could not init controls: %d\n", + __func__, ret); goto unreg_dev; + } dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler; /* mmal init */ dev->instance = instance; ret = mmal_init(dev); - if (ret < 0) + if (ret < 0) { + v4l2_err(&dev->v4l2_dev, "%s: mmal init failed: %d\n", + __func__, ret); goto unreg_dev; - + } /* initialize queue */ q = &dev->capture.vb_vidq; memset(q, 0, sizeof(*q)); @@ -1904,16 +1924,19 @@ static int bcm2835_mmal_probe(struct platform_device *pdev) /* initialise video devices */ ret = bm2835_mmal_init_device(dev, &dev->vdev); - if (ret < 0) + if (ret < 0) { + v4l2_err(&dev->v4l2_dev, "%s: could not init device: %d\n", + __func__, ret); goto unreg_dev; + } /* Really want to call vidioc_s_fmt_vid_cap with the default * format, but currently the APIs don't join up. */ ret = mmal_setup_components(dev, &default_v4l2_format); if (ret < 0) { - v4l2_err(&dev->v4l2_dev, - "%s: could not setup components\n", __func__); + v4l2_err(&dev->v4l2_dev, "%s: could not setup components: %d\n", + __func__, ret); goto unreg_dev; } @@ -1937,8 +1960,9 @@ cleanup_gdev: bcm2835_cleanup_instance(gdev[i]); gdev[i] = NULL; } - pr_info("%s: error %d while loading driver\n", - BM2835_MMAL_MODULE_NAME, ret); + +cleanup_mmal: + vchiq_mmal_finalise(instance); return ret; } @@ -1966,3 +1990,9 @@ static struct platform_driver bcm2835_camera_driver = { }; module_platform_driver(bcm2835_camera_driver) + +MODULE_DESCRIPTION("Broadcom 2835 MMAL video capture"); +MODULE_AUTHOR("Vincent Sanders"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(BM2835_MMAL_VERSION); +MODULE_ALIAS("platform:bcm2835-camera"); diff --git a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c index cc2d9933b969..16af735af5c3 100644 --- a/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c +++ b/drivers/staging/vc04_services/bcm2835-camera/mmal-vchiq.c @@ -139,7 +139,7 @@ struct mmal_msg_context { struct { /* message handle to release */ - VCHI_HELD_MSG_T msg_handle; + struct vchi_held_msg msg_handle; /* pointer to received message */ struct mmal_msg *msg; /* received message length */ @@ -527,7 +527,7 @@ static void service_callback(void *param, int status; u32 msg_len; struct mmal_msg *msg; - VCHI_HELD_MSG_T msg_handle; + struct vchi_held_msg msg_handle; struct mmal_msg_context *msg_context; if (!instance) { @@ -625,7 +625,7 @@ static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance, struct mmal_msg *msg, unsigned int payload_len, struct mmal_msg **msg_out, - VCHI_HELD_MSG_T *msg_handle_out) + struct vchi_held_msg *msg_handle_out) { struct mmal_msg_context *msg_context; int ret; @@ -751,7 +751,7 @@ static int port_info_set(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - VCHI_HELD_MSG_T rmsg_handle; + struct vchi_held_msg rmsg_handle; pr_debug("setting port info port %p\n", port); if (!port) @@ -812,7 +812,7 @@ static int port_info_get(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - VCHI_HELD_MSG_T rmsg_handle; + struct vchi_held_msg rmsg_handle; /* port info time */ m.h.type = MMAL_MSG_TYPE_PORT_INFO_GET; @@ -908,7 +908,7 @@ static int create_component(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - VCHI_HELD_MSG_T rmsg_handle; + struct vchi_held_msg rmsg_handle; /* build component create message */ m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE; @@ -955,7 +955,7 @@ static int destroy_component(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - VCHI_HELD_MSG_T rmsg_handle; + struct vchi_held_msg rmsg_handle; m.h.type = MMAL_MSG_TYPE_COMPONENT_DESTROY; m.u.component_destroy.component_handle = component->handle; @@ -988,7 +988,7 @@ static int enable_component(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - VCHI_HELD_MSG_T rmsg_handle; + struct vchi_held_msg rmsg_handle; m.h.type = MMAL_MSG_TYPE_COMPONENT_ENABLE; m.u.component_enable.component_handle = component->handle; @@ -1020,7 +1020,7 @@ static int disable_component(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - VCHI_HELD_MSG_T rmsg_handle; + struct vchi_held_msg rmsg_handle; m.h.type = MMAL_MSG_TYPE_COMPONENT_DISABLE; m.u.component_disable.component_handle = component->handle; @@ -1053,7 +1053,7 @@ static int get_version(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - VCHI_HELD_MSG_T rmsg_handle; + struct vchi_held_msg rmsg_handle; m.h.type = MMAL_MSG_TYPE_GET_VERSION; @@ -1086,7 +1086,7 @@ static int port_action_port(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - VCHI_HELD_MSG_T rmsg_handle; + struct vchi_held_msg rmsg_handle; m.h.type = MMAL_MSG_TYPE_PORT_ACTION; m.u.port_action_port.component_handle = port->component->handle; @@ -1130,7 +1130,7 @@ static int port_action_handle(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - VCHI_HELD_MSG_T rmsg_handle; + struct vchi_held_msg rmsg_handle; m.h.type = MMAL_MSG_TYPE_PORT_ACTION; @@ -1175,7 +1175,7 @@ static int port_parameter_set(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - VCHI_HELD_MSG_T rmsg_handle; + struct vchi_held_msg rmsg_handle; m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_SET; @@ -1216,7 +1216,7 @@ static int port_parameter_get(struct vchiq_mmal_instance *instance, int ret; struct mmal_msg m; struct mmal_msg *rmsg; - VCHI_HELD_MSG_T rmsg_handle; + struct vchi_held_msg rmsg_handle; m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_GET; @@ -1623,8 +1623,11 @@ int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance, component = &instance->component[instance->component_idx]; ret = create_component(instance, component, name); - if (ret < 0) + if (ret < 0) { + pr_err("%s: failed to create component %d (Not enough GPU mem?)\n", + __func__, ret); goto unlock; + } /* ports info needs gathering */ component->control.type = MMAL_PORT_TYPE_CONTROL; @@ -1803,7 +1806,7 @@ int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance) int status; struct vchiq_mmal_instance *instance; static VCHI_INSTANCE_T vchi_instance; - SERVICE_CREATION_T params = { + struct service_creation params = { .version = VCHI_VERSION_EX(VC_MMAL_VER, VC_MMAL_MIN_VER), .service_id = VC_MMAL_SERVER_NAME, .callback = service_callback, diff --git a/drivers/staging/vc04_services/interface/vchi/TODO b/drivers/staging/vc04_services/interface/vchi/TODO index 0b3ec75ff627..fc2752bc95b2 100644 --- a/drivers/staging/vc04_services/interface/vchi/TODO +++ b/drivers/staging/vc04_services/interface/vchi/TODO @@ -49,3 +49,45 @@ such as dev_info, dev_dbg, and friends. A short top-down description of this driver's architecture (function of kthreads, userspace, limitations) could be very helpful for reviewers. + +7) Review and comment memory barriers + +There is a heavy use of memory barriers in this driver, it would be very +beneficial to go over all of them and, if correct, comment on their merits. +Extra points to whomever confidently reviews the remote_event_*() family of +functions. + +8) Get rid of custom function return values + +Most functions use a custom set of return values, we should force proper Linux +error numbers. Special care is needed for VCHIQ_RETRY. + +9) Reformat core code with more sane indentations + +The code follows the 80 characters limitation yet tends to go 3 or 4 levels of +indentation deep making it very unpleasant to read. This is specially relevant +in the character driver ioctl code and in the core thread functions. + +10) Reorganize file structure: Move char driver to it's own file and join both +platform files + +The cdev is defined alongside with the platform code in vchiq_arm.c. It would +be nice to completely decouple it from the actual core code. For instance to be +able to use bcm2835-audio without having /dev/vchiq created. One could argue +it's better for security reasons or general cleanliness. It could even be +interesting to create two different kernel modules, something the likes of +vchiq-core.ko and vchiq-dev.ko. This would also ease the upstreaming process. + +The code in vchiq_bcm2835_arm.c should fit in the generic platform file. + +12) Get rid of all the struct typedefs + +Most structs are typedefd, it's not encouraged in the kernel. + +13) Get rid of all non essential global structures and create a proper per +device structure + +The first thing one generally sees in a probe function is a memory allocation +for all the device specific data. This structure is then passed all over the +driver. This is good practice since it makes the driver work regardless of the +number of devices probed. diff --git a/drivers/staging/vc04_services/interface/vchi/vchi.h b/drivers/staging/vc04_services/interface/vchi/vchi.h index 01381904775d..0b6fc0d31f4c 100644 --- a/drivers/staging/vc04_services/interface/vchi/vchi.h +++ b/drivers/staging/vc04_services/interface/vchi/vchi.h @@ -36,7 +36,6 @@ #include "interface/vchi/vchi_cfg.h" #include "interface/vchi/vchi_common.h" -#include "vchi_mh.h" /****************************************************************************** Global defs @@ -67,18 +66,18 @@ struct opaque_vchi_service_t; // Descriptor for a held message. Allocated by client, initialised by vchi_msg_hold, // vchi_msg_iter_hold or vchi_msg_iter_hold_next. Fields are for internal VCHI use only. -typedef struct { +struct vchi_held_msg { struct opaque_vchi_service_t *service; void *message; -} VCHI_HELD_MSG_T; +}; // structure used to provide the information needed to open a server or a client -typedef struct { +struct service_creation { struct vchi_version version; int32_t service_id; VCHI_CALLBACK_T callback; void *callback_param; -} SERVICE_CREATION_T; +}; // Opaque handle for a VCHI instance typedef struct opaque_vchi_instance_handle_t *VCHI_INSTANCE_T; @@ -113,17 +112,12 @@ extern uint32_t vchi_current_time(VCHI_INSTANCE_T instance_handle); /****************************************************************************** Global service API *****************************************************************************/ -// Routine to create a named service -extern int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle, - SERVICE_CREATION_T *setup, - VCHI_SERVICE_HANDLE_T *handle); - // Routine to destroy a service extern int32_t vchi_service_destroy(const VCHI_SERVICE_HANDLE_T handle); // Routine to open a named service extern int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle, - SERVICE_CREATION_T *setup, + struct service_creation *setup, VCHI_SERVICE_HANDLE_T *handle); extern int32_t vchi_get_peer_version(const VCHI_SERVICE_HANDLE_T handle, @@ -182,11 +176,11 @@ extern int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle, void **data, // } may be NULL, as info can be uint32_t *msg_size, // } obtained from HELD_MSG_T VCHI_FLAGS_T flags, - VCHI_HELD_MSG_T *message_descriptor); + struct vchi_held_msg *message_descriptor); // Initialise an iterator to look through messages in place extern int32_t vchi_msg_look_ahead(VCHI_SERVICE_HANDLE_T handle, - VCHI_MSG_ITER_T *iter, + struct vchi_msg_iter *iter, VCHI_FLAGS_T flags); /****************************************************************************** @@ -194,42 +188,42 @@ extern int32_t vchi_msg_look_ahead(VCHI_SERVICE_HANDLE_T handle, *****************************************************************************/ // Routine to get the address of a held message -extern void *vchi_held_msg_ptr(const VCHI_HELD_MSG_T *message); +extern void *vchi_held_msg_ptr(const struct vchi_held_msg *message); // Routine to get the size of a held message -extern int32_t vchi_held_msg_size(const VCHI_HELD_MSG_T *message); +extern int32_t vchi_held_msg_size(const struct vchi_held_msg *message); // Routine to get the transmit timestamp as written into the header by the peer -extern uint32_t vchi_held_msg_tx_timestamp(const VCHI_HELD_MSG_T *message); +extern uint32_t vchi_held_msg_tx_timestamp(const struct vchi_held_msg *message); // Routine to get the reception timestamp, written as we parsed the header -extern uint32_t vchi_held_msg_rx_timestamp(const VCHI_HELD_MSG_T *message); +extern uint32_t vchi_held_msg_rx_timestamp(const struct vchi_held_msg *message); // Routine to release a held message after it has been processed -extern int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message); +extern int32_t vchi_held_msg_release(struct vchi_held_msg *message); // Indicates whether the iterator has a next message. -extern int32_t vchi_msg_iter_has_next(const VCHI_MSG_ITER_T *iter); +extern int32_t vchi_msg_iter_has_next(const struct vchi_msg_iter *iter); // Return the pointer and length for the next message and advance the iterator. -extern int32_t vchi_msg_iter_next(VCHI_MSG_ITER_T *iter, +extern int32_t vchi_msg_iter_next(struct vchi_msg_iter *iter, void **data, uint32_t *msg_size); // Remove the last message returned by vchi_msg_iter_next. // Can only be called once after each call to vchi_msg_iter_next. -extern int32_t vchi_msg_iter_remove(VCHI_MSG_ITER_T *iter); +extern int32_t vchi_msg_iter_remove(struct vchi_msg_iter *iter); // Hold the last message returned by vchi_msg_iter_next. // Can only be called once after each call to vchi_msg_iter_next. -extern int32_t vchi_msg_iter_hold(VCHI_MSG_ITER_T *iter, - VCHI_HELD_MSG_T *message); +extern int32_t vchi_msg_iter_hold(struct vchi_msg_iter *iter, + struct vchi_held_msg *message); // Return information for the next message, and hold it, advancing the iterator. -extern int32_t vchi_msg_iter_hold_next(VCHI_MSG_ITER_T *iter, +extern int32_t vchi_msg_iter_hold_next(struct vchi_msg_iter *iter, void **data, // } may be NULL uint32_t *msg_size, // } - VCHI_HELD_MSG_T *message); + struct vchi_held_msg *message); /****************************************************************************** Global bulk API @@ -244,7 +238,6 @@ extern int32_t vchi_bulk_queue_receive(VCHI_SERVICE_HANDLE_T handle, // Prepare interface for a transfer from the other side into relocatable memory. int32_t vchi_bulk_queue_receive_reloc(const VCHI_SERVICE_HANDLE_T handle, - VCHI_MEM_HANDLE_T h_dst, uint32_t offset, uint32_t data_size, const VCHI_FLAGS_T flags, @@ -266,7 +259,6 @@ extern int32_t vchi_bulk_queue_transmit(VCHI_SERVICE_HANDLE_T handle, #endif extern int32_t vchi_bulk_queue_transmit_reloc(VCHI_SERVICE_HANDLE_T handle, - VCHI_MEM_HANDLE_T h_src, uint32_t offset, uint32_t data_size, VCHI_FLAGS_T flags, diff --git a/drivers/staging/vc04_services/interface/vchi/vchi_common.h b/drivers/staging/vc04_services/interface/vchi/vchi_common.h index 8eb2bb9f0fe2..35f331f80812 100644 --- a/drivers/staging/vc04_services/interface/vchi/vchi_common.h +++ b/drivers/staging/vc04_services/interface/vchi/vchi_common.h @@ -127,9 +127,9 @@ typedef void (*VCHI_CALLBACK_T)(void *callback_param, //my service local param * '-vec_len' elements. Thus to append a header onto an existing vector, * you can do this: * - * void foo(const VCHI_MSG_VECTOR_T *v, int n) + * void foo(const struct vchi_msg_vector *v, int n) * { - * VCHI_MSG_VECTOR_T nv[2]; + * struct vchi_msg_vector nv[2]; * nv[0].vec_base = my_header; * nv[0].vec_len = sizeof my_header; * nv[1].vec_base = v; @@ -137,10 +137,10 @@ typedef void (*VCHI_CALLBACK_T)(void *callback_param, //my service local param * ... * */ -typedef struct vchi_msg_vector { +struct vchi_msg_vector { const void *vec_base; int32_t vec_len; -} VCHI_MSG_VECTOR_T; +}; // Opaque type for a connection API typedef struct opaque_vchi_connection_api_t VCHI_CONNECTION_API_T; @@ -154,11 +154,11 @@ typedef struct opaque_vchi_message_driver_t VCHI_MESSAGE_DRIVER_T; // will not proceed to messages received since. Behaviour is undefined if an iterator // is used again after messages for that service are removed/dequeued by any // means other than vchi_msg_iter_... calls on the iterator itself. -typedef struct { +struct vchi_msg_iter { struct opaque_vchi_service_t *service; void *last; void *next; void *remove; -} VCHI_MSG_ITER_T; +}; #endif // VCHI_COMMON_H_ diff --git a/drivers/staging/vc04_services/interface/vchi/vchi_mh.h b/drivers/staging/vc04_services/interface/vchi/vchi_mh.h deleted file mode 100644 index 198bd076b666..000000000000 --- a/drivers/staging/vc04_services/interface/vchi/vchi_mh.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) 2010-2012 Broadcom. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2, as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef VCHI_MH_H_ -#define VCHI_MH_H_ - -#include <linux/types.h> - -typedef int32_t VCHI_MEM_HANDLE_T; -#define VCHI_MEM_HANDLE_INVALID 0 - -#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index 83d740feab96..338b6e952515 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -48,7 +48,6 @@ #include "vchiq_arm.h" #include "vchiq_connected.h" -#include "vchiq_killable.h" #include "vchiq_pagelist.h" #define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2) @@ -61,11 +60,11 @@ struct vchiq_2835_state { int inited; - VCHIQ_ARM_STATE_T arm_state; + struct vchiq_arm_state arm_state; }; struct vchiq_pagelist_info { - PAGELIST_T *pagelist; + struct pagelist *pagelist; size_t pagelist_buffer_size; dma_addr_t dma_addr; enum dma_data_direction dma_dir; @@ -106,12 +105,12 @@ static void free_pagelist(struct vchiq_pagelist_info *pagelistinfo, int actual); -int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) +int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state) { struct device *dev = &pdev->dev; struct vchiq_drvdata *drvdata = platform_get_drvdata(pdev); struct rpi_firmware *fw = drvdata->fw; - VCHIQ_SLOT_ZERO_T *vchiq_slot_zero; + struct vchiq_slot_zero *vchiq_slot_zero; struct resource *res; void *slot_mem; dma_addr_t slot_phys; @@ -163,7 +162,7 @@ int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) *(char **)&g_fragments_base[i * g_fragments_size] = NULL; sema_init(&g_free_fragments_sema, MAX_FRAGMENTS); - if (vchiq_init_state(state, vchiq_slot_zero, 0) != VCHIQ_SUCCESS) + if (vchiq_init_state(state, vchiq_slot_zero) != VCHIQ_SUCCESS) return -EINVAL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -204,7 +203,7 @@ int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state) } VCHIQ_STATUS_T -vchiq_platform_init_state(VCHIQ_STATE_T *state) +vchiq_platform_init_state(struct vchiq_state *state) { VCHIQ_STATUS_T status = VCHIQ_SUCCESS; struct vchiq_2835_state *platform_state; @@ -221,8 +220,8 @@ vchiq_platform_init_state(VCHIQ_STATE_T *state) return status; } -VCHIQ_ARM_STATE_T* -vchiq_platform_get_arm_state(VCHIQ_STATE_T *state) +struct vchiq_arm_state* +vchiq_platform_get_arm_state(struct vchiq_state *state) { struct vchiq_2835_state *platform_state; @@ -234,7 +233,7 @@ vchiq_platform_get_arm_state(VCHIQ_STATE_T *state) } void -remote_event_signal(REMOTE_EVENT_T *event) +remote_event_signal(struct remote_event *event) { wmb(); @@ -247,13 +246,11 @@ remote_event_signal(REMOTE_EVENT_T *event) } VCHIQ_STATUS_T -vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle, - void *offset, int size, int dir) +vchiq_prepare_bulk_data(struct vchiq_bulk *bulk, void *offset, int size, + int dir) { struct vchiq_pagelist_info *pagelistinfo; - WARN_ON(memhandle != VCHI_MEM_HANDLE_INVALID); - pagelistinfo = create_pagelist((char __user *)offset, size, (dir == VCHIQ_BULK_RECEIVE) ? PAGELIST_READ @@ -262,7 +259,6 @@ vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle, if (!pagelistinfo) return VCHIQ_ERROR; - bulk->handle = memhandle; bulk->data = (void *)(unsigned long)pagelistinfo->dma_addr; /* @@ -275,7 +271,7 @@ vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, VCHI_MEM_HANDLE_T memhandle, } void -vchiq_complete_bulk(VCHIQ_BULK_T *bulk) +vchiq_complete_bulk(struct vchiq_bulk *bulk) { if (bulk && bulk->remote_data && bulk->actual) free_pagelist((struct vchiq_pagelist_info *)bulk->remote_data, @@ -283,16 +279,6 @@ vchiq_complete_bulk(VCHIQ_BULK_T *bulk) } void -vchiq_transfer_bulk(VCHIQ_BULK_T *bulk) -{ - /* - * This should only be called on the master (VideoCore) side, but - * provide an implementation to avoid the need for ifdefery. - */ - BUG(); -} - -void vchiq_dump_platform_state(void *dump_context) { char buf[80]; @@ -304,29 +290,29 @@ vchiq_dump_platform_state(void *dump_context) } VCHIQ_STATUS_T -vchiq_platform_suspend(VCHIQ_STATE_T *state) +vchiq_platform_suspend(struct vchiq_state *state) { return VCHIQ_ERROR; } VCHIQ_STATUS_T -vchiq_platform_resume(VCHIQ_STATE_T *state) +vchiq_platform_resume(struct vchiq_state *state) { return VCHIQ_SUCCESS; } void -vchiq_platform_paused(VCHIQ_STATE_T *state) +vchiq_platform_paused(struct vchiq_state *state) { } void -vchiq_platform_resumed(VCHIQ_STATE_T *state) +vchiq_platform_resumed(struct vchiq_state *state) { } int -vchiq_platform_videocore_wanted(VCHIQ_STATE_T *state) +vchiq_platform_videocore_wanted(struct vchiq_state *state) { return 1; // autosuspend not supported - videocore always wanted } @@ -337,12 +323,12 @@ vchiq_platform_use_suspend_timer(void) return 0; } void -vchiq_dump_platform_use_state(VCHIQ_STATE_T *state) +vchiq_dump_platform_use_state(struct vchiq_state *state) { vchiq_log_info(vchiq_arm_log_level, "Suspend timer not in use"); } void -vchiq_platform_handle_timeout(VCHIQ_STATE_T *state) +vchiq_platform_handle_timeout(struct vchiq_state *state) { (void)state; } @@ -353,7 +339,7 @@ vchiq_platform_handle_timeout(VCHIQ_STATE_T *state) static irqreturn_t vchiq_doorbell_irq(int irq, void *dev_id) { - VCHIQ_STATE_T *state = dev_id; + struct vchiq_state *state = dev_id; irqreturn_t ret = IRQ_NONE; unsigned int status; @@ -398,7 +384,7 @@ cleanup_pagelistinfo(struct vchiq_pagelist_info *pagelistinfo) static struct vchiq_pagelist_info * create_pagelist(char __user *buf, size_t count, unsigned short type) { - PAGELIST_T *pagelist; + struct pagelist *pagelist; struct vchiq_pagelist_info *pagelistinfo; struct page **pages; u32 *addrs; @@ -412,7 +398,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type) offset = ((unsigned int)(unsigned long)buf & (PAGE_SIZE - 1)); num_pages = DIV_ROUND_UP(count + offset, PAGE_SIZE); - pagelist_size = sizeof(PAGELIST_T) + + pagelist_size = sizeof(struct pagelist) + (num_pages * sizeof(u32)) + (num_pages * sizeof(pages[0]) + (num_pages * sizeof(struct scatterlist))) + @@ -557,7 +543,7 @@ create_pagelist(char __user *buf, size_t count, unsigned short type) (g_cache_line_size - 1)))) { char *fragments; - if (down_interruptible(&g_free_fragments_sema) != 0) { + if (down_killable(&g_free_fragments_sema)) { cleanup_pagelistinfo(pagelistinfo); return NULL; } @@ -580,8 +566,8 @@ static void free_pagelist(struct vchiq_pagelist_info *pagelistinfo, int actual) { - PAGELIST_T *pagelist = pagelistinfo->pagelist; - struct page **pages = pagelistinfo->pages; + struct pagelist *pagelist = pagelistinfo->pagelist; + struct page **pages = pagelistinfo->pages; unsigned int num_pages = pagelistinfo->num_pages; vchiq_log_trace(vchiq_arm_log_level, "%s - %pK, %d", diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index 45de21c210c1..804daf83be35 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -44,18 +44,18 @@ #include <linux/highmem.h> #include <linux/pagemap.h> #include <linux/bug.h> -#include <linux/semaphore.h> +#include <linux/completion.h> #include <linux/list.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/compat.h> +#include <linux/dma-mapping.h> #include <soc/bcm2835/raspberrypi-firmware.h> #include "vchiq_core.h" #include "vchiq_ioctl.h" #include "vchiq_arm.h" #include "vchiq_debugfs.h" -#include "vchiq_killable.h" #define DEVICE_NAME "vchiq" @@ -63,8 +63,6 @@ #undef MODULE_PARAM_PREFIX #define MODULE_PARAM_PREFIX DEVICE_NAME "." -#define VCHIQ_MINOR 0 - /* Some per-instance constants */ #define MAX_COMPLETIONS 128 #define MAX_SERVICES 64 @@ -111,8 +109,8 @@ static const char *const resume_state_names[] = { static void suspend_timer_callback(struct timer_list *t); -typedef struct user_service_struct { - VCHIQ_SERVICE_T *service; +struct user_service { + struct vchiq_service *service; void *userdata; VCHIQ_INSTANCE_T instance; char is_vchi; @@ -121,11 +119,11 @@ typedef struct user_service_struct { int message_available_pos; int msg_insert; int msg_remove; - struct semaphore insert_event; - struct semaphore remove_event; - struct semaphore close_event; - VCHIQ_HEADER_T * msg_queue[MSG_QUEUE_SIZE]; -} USER_SERVICE_T; + struct completion insert_event; + struct completion remove_event; + struct completion close_event; + struct vchiq_header *msg_queue[MSG_QUEUE_SIZE]; +}; struct bulk_waiter_node { struct bulk_waiter bulk_waiter; @@ -134,12 +132,12 @@ struct bulk_waiter_node { }; struct vchiq_instance_struct { - VCHIQ_STATE_T *state; - VCHIQ_COMPLETION_DATA_T completions[MAX_COMPLETIONS]; + struct vchiq_state *state; + struct vchiq_completion_data completions[MAX_COMPLETIONS]; int completion_insert; int completion_remove; - struct semaphore insert_event; - struct semaphore remove_event; + struct completion insert_event; + struct completion remove_event; struct mutex completion_mutex; int connected; @@ -152,23 +150,23 @@ struct vchiq_instance_struct { struct list_head bulk_waiter_list; struct mutex bulk_waiter_list_mutex; - VCHIQ_DEBUGFS_NODE_T debugfs_node; + struct vchiq_debugfs_node debugfs_node; }; -typedef struct dump_context_struct { +struct dump_context { char __user *buf; size_t actual; size_t space; loff_t offset; -} DUMP_CONTEXT_T; +}; static struct cdev vchiq_cdev; static dev_t vchiq_devid; -static VCHIQ_STATE_T g_state; +static struct vchiq_state g_state; static struct class *vchiq_class; -static struct device *vchiq_dev; static DEFINE_SPINLOCK(msg_queue_spinlock); static struct platform_device *bcm2835_camera; +static struct platform_device *bcm2835_audio; static struct vchiq_drvdata bcm2835_drvdata = { .cache_line_size = 32, @@ -210,7 +208,7 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *instance_out) { VCHIQ_STATUS_T status = VCHIQ_ERROR; - VCHIQ_STATE_T *state; + struct vchiq_state *state; VCHIQ_INSTANCE_T instance = NULL; int i; @@ -263,7 +261,7 @@ EXPORT_SYMBOL(vchiq_initialise); VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance) { VCHIQ_STATUS_T status; - VCHIQ_STATE_T *state = instance->state; + struct vchiq_state *state = instance->state; vchiq_log_trace(vchiq_core_log_level, "%s(%p) called", __func__, instance); @@ -280,16 +278,11 @@ VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance) "%s(%p): returning %d", __func__, instance, status); if (status == VCHIQ_SUCCESS) { - struct list_head *pos, *next; + struct bulk_waiter_node *waiter, *next; - list_for_each_safe(pos, next, - &instance->bulk_waiter_list) { - struct bulk_waiter_node *waiter; - - waiter = list_entry(pos, - struct bulk_waiter_node, - list); - list_del(pos); + list_for_each_entry_safe(waiter, next, + &instance->bulk_waiter_list, list) { + list_del(&waiter->list); vchiq_log_info(vchiq_arm_log_level, "bulk_waiter - cleaned up %pK for pid %d", waiter, waiter->pid); @@ -310,7 +303,7 @@ static int vchiq_is_connected(VCHIQ_INSTANCE_T instance) VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance) { VCHIQ_STATUS_T status; - VCHIQ_STATE_T *state = instance->state; + struct vchiq_state *state = instance->state; vchiq_log_trace(vchiq_core_log_level, "%s(%p) called", __func__, instance); @@ -338,12 +331,12 @@ EXPORT_SYMBOL(vchiq_connect); VCHIQ_STATUS_T vchiq_add_service( VCHIQ_INSTANCE_T instance, - const VCHIQ_SERVICE_PARAMS_T *params, + const struct vchiq_service_params *params, VCHIQ_SERVICE_HANDLE_T *phandle) { VCHIQ_STATUS_T status; - VCHIQ_STATE_T *state = instance->state; - VCHIQ_SERVICE_T *service = NULL; + struct vchiq_state *state = instance->state; + struct vchiq_service *service = NULL; int srvstate; vchiq_log_trace(vchiq_core_log_level, @@ -377,12 +370,12 @@ EXPORT_SYMBOL(vchiq_add_service); VCHIQ_STATUS_T vchiq_open_service( VCHIQ_INSTANCE_T instance, - const VCHIQ_SERVICE_PARAMS_T *params, + const struct vchiq_service_params *params, VCHIQ_SERVICE_HANDLE_T *phandle) { VCHIQ_STATUS_T status = VCHIQ_ERROR; - VCHIQ_STATE_T *state = instance->state; - VCHIQ_SERVICE_T *service = NULL; + struct vchiq_state *state = instance->state; + struct vchiq_service *service = NULL; vchiq_log_trace(vchiq_core_log_level, "%s(%p) called", __func__, instance); @@ -424,9 +417,9 @@ vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T handle, const void *data, switch (mode) { case VCHIQ_BULK_MODE_NOCALLBACK: case VCHIQ_BULK_MODE_CALLBACK: - status = vchiq_bulk_transfer(handle, - VCHI_MEM_HANDLE_INVALID, (void *)data, size, userdata, - mode, VCHIQ_BULK_TRANSMIT); + status = vchiq_bulk_transfer(handle, (void *)data, size, + userdata, mode, + VCHIQ_BULK_TRANSMIT); break; case VCHIQ_BULK_MODE_BLOCKING: status = vchiq_blocking_bulk_transfer(handle, @@ -449,9 +442,8 @@ vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T handle, void *data, switch (mode) { case VCHIQ_BULK_MODE_NOCALLBACK: case VCHIQ_BULK_MODE_CALLBACK: - status = vchiq_bulk_transfer(handle, - VCHI_MEM_HANDLE_INVALID, data, size, userdata, - mode, VCHIQ_BULK_RECEIVE); + status = vchiq_bulk_transfer(handle, data, size, userdata, + mode, VCHIQ_BULK_RECEIVE); break; case VCHIQ_BULK_MODE_BLOCKING: status = vchiq_blocking_bulk_transfer(handle, @@ -470,10 +462,9 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, unsigned int size, VCHIQ_BULK_DIR_T dir) { VCHIQ_INSTANCE_T instance; - VCHIQ_SERVICE_T *service; + struct vchiq_service *service; VCHIQ_STATUS_T status; struct bulk_waiter_node *waiter = NULL; - struct list_head *pos; service = find_service_by_handle(handle); if (!service) @@ -484,20 +475,16 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, unlock_service(service); mutex_lock(&instance->bulk_waiter_list_mutex); - list_for_each(pos, &instance->bulk_waiter_list) { - if (list_entry(pos, struct bulk_waiter_node, - list)->pid == current->pid) { - waiter = list_entry(pos, - struct bulk_waiter_node, - list); - list_del(pos); + list_for_each_entry(waiter, &instance->bulk_waiter_list, list) { + if (waiter->pid == current->pid) { + list_del(&waiter->list); break; } } mutex_unlock(&instance->bulk_waiter_list_mutex); if (waiter) { - VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk; + struct vchiq_bulk *bulk = waiter->bulk_waiter.bulk; if (bulk) { /* This thread has an outstanding bulk transfer. */ @@ -523,12 +510,11 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, } } - status = vchiq_bulk_transfer(handle, VCHI_MEM_HANDLE_INVALID, - data, size, &waiter->bulk_waiter, VCHIQ_BULK_MODE_BLOCKING, - dir); + status = vchiq_bulk_transfer(handle, data, size, &waiter->bulk_waiter, + VCHIQ_BULK_MODE_BLOCKING, dir); if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) || !waiter->bulk_waiter.bulk) { - VCHIQ_BULK_T *bulk = waiter->bulk_waiter.bulk; + struct vchiq_bulk *bulk = waiter->bulk_waiter.bulk; if (bulk) { /* Cancel the signal when the transfer @@ -559,10 +545,10 @@ vchiq_blocking_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *data, static VCHIQ_STATUS_T add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, - VCHIQ_HEADER_T *header, USER_SERVICE_T *user_service, - void *bulk_userdata) + struct vchiq_header *header, struct user_service *user_service, + void *bulk_userdata) { - VCHIQ_COMPLETION_DATA_T *completion; + struct vchiq_completion_data *completion; int insert; DEBUG_INITIALISE(g_state.local) @@ -574,7 +560,7 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, vchiq_log_trace(vchiq_arm_log_level, "%s - completion queue full", __func__); DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); - if (down_interruptible(&instance->remove_event) != 0) { + if (wait_for_completion_killable( &instance->remove_event)) { vchiq_log_info(vchiq_arm_log_level, "service_callback interrupted"); return VCHIQ_RETRY; @@ -612,7 +598,7 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, insert++; instance->completion_insert = insert; - up(&instance->insert_event); + complete(&instance->insert_event); return VCHIQ_SUCCESS; } @@ -624,16 +610,16 @@ add_completion(VCHIQ_INSTANCE_T instance, VCHIQ_REASON_T reason, ***************************************************************************/ static VCHIQ_STATUS_T -service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, - VCHIQ_SERVICE_HANDLE_T handle, void *bulk_userdata) +service_callback(VCHIQ_REASON_T reason, struct vchiq_header *header, + VCHIQ_SERVICE_HANDLE_T handle, void *bulk_userdata) { /* How do we ensure the callback goes to the right client? - ** The service_user data points to a USER_SERVICE_T record containing - ** the original callback and the user state structure, which contains a - ** circular buffer for completion records. + ** The service_user data points to a user_service record + ** containing the original callback and the user state structure, which + ** contains a circular buffer for completion records. */ - USER_SERVICE_T *user_service; - VCHIQ_SERVICE_T *service; + struct user_service *user_service; + struct vchiq_service *service; VCHIQ_INSTANCE_T instance; bool skip_completion = false; @@ -643,7 +629,7 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, service = handle_to_service(handle); BUG_ON(!service); - user_service = (USER_SERVICE_T *)service->base.userdata; + user_service = (struct user_service *)service->base.userdata; instance = user_service->instance; if (!instance || instance->closing) @@ -685,7 +671,8 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, } DEBUG_TRACE(SERVICE_CALLBACK_LINE); - if (down_interruptible(&user_service->remove_event) + if (wait_for_completion_killable( + &user_service->remove_event) != 0) { vchiq_log_info(vchiq_arm_log_level, "%s interrupted", __func__); @@ -717,7 +704,7 @@ service_callback(VCHIQ_REASON_T reason, VCHIQ_HEADER_T *header, } spin_unlock(&msg_queue_spinlock); - up(&user_service->insert_event); + complete(&user_service->insert_event); header = NULL; } @@ -746,7 +733,7 @@ user_service_free(void *userdata) * close_delivered * ***************************************************************************/ -static void close_delivered(USER_SERVICE_T *user_service) +static void close_delivered(struct user_service *user_service) { vchiq_log_info(vchiq_arm_log_level, "%s(handle=%x)", @@ -757,81 +744,55 @@ static void close_delivered(USER_SERVICE_T *user_service) unlock_service(user_service->service); /* Wake the user-thread blocked in close_ or remove_service */ - up(&user_service->close_event); + complete(&user_service->close_event); user_service->close_pending = 0; } } struct vchiq_io_copy_callback_context { - struct vchiq_element *current_element; - size_t current_element_offset; + struct vchiq_element *element; + size_t element_offset; unsigned long elements_to_go; - size_t current_offset; }; -static ssize_t -vchiq_ioc_copy_element_data( - void *context, - void *dest, - size_t offset, - size_t maxsize) +static ssize_t vchiq_ioc_copy_element_data(void *context, void *dest, + size_t offset, size_t maxsize) { - long res; + struct vchiq_io_copy_callback_context *cc = context; + size_t total_bytes_copied = 0; size_t bytes_this_round; - struct vchiq_io_copy_callback_context *copy_context = - (struct vchiq_io_copy_callback_context *)context; - if (offset != copy_context->current_offset) - return 0; - - if (!copy_context->elements_to_go) - return 0; - - /* - * Complex logic here to handle the case of 0 size elements - * in the middle of the array of elements. - * - * Need to skip over these 0 size elements. - */ - while (1) { - bytes_this_round = min(copy_context->current_element->size - - copy_context->current_element_offset, - maxsize); + while (total_bytes_copied < maxsize) { + if (!cc->elements_to_go) + return total_bytes_copied; - if (bytes_this_round) - break; - - copy_context->elements_to_go--; - copy_context->current_element++; - copy_context->current_element_offset = 0; - - if (!copy_context->elements_to_go) - return 0; - } + if (!cc->element->size) { + cc->elements_to_go--; + cc->element++; + cc->element_offset = 0; + continue; + } - res = copy_from_user(dest, - copy_context->current_element->data + - copy_context->current_element_offset, - bytes_this_round); + bytes_this_round = min(cc->element->size - cc->element_offset, + maxsize - total_bytes_copied); - if (res != 0) - return -EFAULT; + if (copy_from_user(dest + total_bytes_copied, + cc->element->data + cc->element_offset, + bytes_this_round)) + return -EFAULT; - copy_context->current_element_offset += bytes_this_round; - copy_context->current_offset += bytes_this_round; + cc->element_offset += bytes_this_round; + total_bytes_copied += bytes_this_round; - /* - * Check if done with current element, and if so advance to the next. - */ - if (copy_context->current_element_offset == - copy_context->current_element->size) { - copy_context->elements_to_go--; - copy_context->current_element++; - copy_context->current_element_offset = 0; + if (cc->element_offset == cc->element->size) { + cc->elements_to_go--; + cc->element++; + cc->element_offset = 0; + } } - return bytes_this_round; + return maxsize; } /************************************************************************** @@ -848,10 +809,9 @@ vchiq_ioc_queue_message(VCHIQ_SERVICE_HANDLE_T handle, unsigned long i; size_t total_size = 0; - context.current_element = elements; - context.current_element_offset = 0; + context.element = elements; + context.element_offset = 0; context.elements_to_go = count; - context.current_offset = 0; for (i = 0; i < count; i++) { if (!elements[i].data && elements[i].size != 0) @@ -874,7 +834,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { VCHIQ_INSTANCE_T instance = file->private_data; VCHIQ_STATUS_T status = VCHIQ_SUCCESS; - VCHIQ_SERVICE_T *service = NULL; + struct vchiq_service *service = NULL; long ret = 0; int i, rc; @@ -906,7 +866,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (status == VCHIQ_SUCCESS) { /* Wake the completion thread and ask it to exit */ instance->closing = 1; - up(&instance->insert_event); + complete(&instance->insert_event); } break; @@ -936,8 +896,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; case VCHIQ_IOC_CREATE_SERVICE: { - VCHIQ_CREATE_SERVICE_T args; - USER_SERVICE_T *user_service = NULL; + struct vchiq_create_service args; + struct user_service *user_service = NULL; void *userdata; int srvstate; @@ -948,7 +908,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } - user_service = kmalloc(sizeof(USER_SERVICE_T), GFP_KERNEL); + user_service = kmalloc(sizeof(*user_service), GFP_KERNEL); if (!user_service) { ret = -ENOMEM; break; @@ -987,9 +947,9 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) instance->completion_remove - 1; user_service->msg_insert = 0; user_service->msg_remove = 0; - sema_init(&user_service->insert_event, 0); - sema_init(&user_service->remove_event, 0); - sema_init(&user_service->close_event, 0); + init_completion(&user_service->insert_event); + init_completion(&user_service->remove_event); + init_completion(&user_service->close_event); if (args.is_open) { status = vchiq_open_service_internal @@ -1004,7 +964,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } if (copy_to_user((void __user *) - &(((VCHIQ_CREATE_SERVICE_T __user *) + &(((struct vchiq_create_service __user *) arg)->handle), (const void *)&service->handle, sizeof(service->handle)) != 0) { @@ -1019,55 +979,38 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } } break; - case VCHIQ_IOC_CLOSE_SERVICE: { + case VCHIQ_IOC_CLOSE_SERVICE: + case VCHIQ_IOC_REMOVE_SERVICE: { VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; + struct user_service *user_service; service = find_service_for_instance(instance, handle); - if (service != NULL) { - USER_SERVICE_T *user_service = - (USER_SERVICE_T *)service->base.userdata; - /* close_pending is false on first entry, and when the - wait in vchiq_close_service has been interrupted. */ - if (!user_service->close_pending) { - status = vchiq_close_service(service->handle); - if (status != VCHIQ_SUCCESS) - break; - } - - /* close_pending is true once the underlying service - has been closed until the client library calls the - CLOSE_DELIVERED ioctl, signalling close_event. */ - if (user_service->close_pending && - down_interruptible(&user_service->close_event)) - status = VCHIQ_RETRY; - } else + if (!service) { ret = -EINVAL; - } break; + break; + } - case VCHIQ_IOC_REMOVE_SERVICE: { - VCHIQ_SERVICE_HANDLE_T handle = (VCHIQ_SERVICE_HANDLE_T)arg; + user_service = service->base.userdata; - service = find_service_for_instance(instance, handle); - if (service != NULL) { - USER_SERVICE_T *user_service = - (USER_SERVICE_T *)service->base.userdata; - /* close_pending is false on first entry, and when the - wait in vchiq_close_service has been interrupted. */ - if (!user_service->close_pending) { - status = vchiq_remove_service(service->handle); - if (status != VCHIQ_SUCCESS) - break; - } + /* close_pending is false on first entry, and when the + wait in vchiq_close_service has been interrupted. */ + if (!user_service->close_pending) { + status = (cmd == VCHIQ_IOC_CLOSE_SERVICE) ? + vchiq_close_service(service->handle) : + vchiq_remove_service(service->handle); + if (status != VCHIQ_SUCCESS) + break; + } - /* close_pending is true once the underlying service - has been closed until the client library calls the - CLOSE_DELIVERED ioctl, signalling close_event. */ - if (user_service->close_pending && - down_interruptible(&user_service->close_event)) - status = VCHIQ_RETRY; - } else - ret = -EINVAL; - } break; + /* close_pending is true once the underlying service + has been closed until the client library calls the + CLOSE_DELIVERED ioctl, signalling close_event. */ + if (user_service->close_pending && + wait_for_completion_killable( + &user_service->close_event)) + status = VCHIQ_RETRY; + break; + } case VCHIQ_IOC_USE_SERVICE: case VCHIQ_IOC_RELEASE_SERVICE: { @@ -1097,7 +1040,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } break; case VCHIQ_IOC_QUEUE_MESSAGE: { - VCHIQ_QUEUE_MESSAGE_T args; + struct vchiq_queue_message args; if (copy_from_user (&args, (const void __user *)arg, @@ -1126,7 +1069,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case VCHIQ_IOC_QUEUE_BULK_TRANSMIT: case VCHIQ_IOC_QUEUE_BULK_RECEIVE: { - VCHIQ_QUEUE_BULK_TRANSFER_T args; + struct vchiq_queue_bulk_transfer args; struct bulk_waiter_node *waiter = NULL; VCHIQ_BULK_DIR_T dir = @@ -1153,21 +1096,16 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ret = -ENOMEM; break; } + args.userdata = &waiter->bulk_waiter; } else if (args.mode == VCHIQ_BULK_MODE_WAITING) { - struct list_head *pos; - mutex_lock(&instance->bulk_waiter_list_mutex); - list_for_each(pos, &instance->bulk_waiter_list) { - if (list_entry(pos, struct bulk_waiter_node, - list)->pid == current->pid) { - waiter = list_entry(pos, - struct bulk_waiter_node, - list); - list_del(pos); + list_for_each_entry(waiter, &instance->bulk_waiter_list, + list) { + if (waiter->pid == current->pid) { + list_del(&waiter->list); break; } - } mutex_unlock(&instance->bulk_waiter_list_mutex); if (!waiter) { @@ -1182,14 +1120,13 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) current->pid); args.userdata = &waiter->bulk_waiter; } - status = vchiq_bulk_transfer - (args.handle, - VCHI_MEM_HANDLE_INVALID, - args.data, args.size, - args.userdata, args.mode, - dir); + + status = vchiq_bulk_transfer(args.handle, args.data, args.size, + args.userdata, args.mode, dir); + if (!waiter) break; + if ((status != VCHIQ_RETRY) || fatal_signal_pending(current) || !waiter->bulk_waiter.bulk) { if (waiter->bulk_waiter.bulk) { @@ -1212,7 +1149,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) waiter, current->pid); if (copy_to_user((void __user *) - &(((VCHIQ_QUEUE_BULK_TRANSFER_T __user *) + &(((struct vchiq_queue_bulk_transfer __user *) arg)->mode), (const void *)&mode_waiting, sizeof(mode_waiting)) != 0) @@ -1221,7 +1158,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } break; case VCHIQ_IOC_AWAIT_COMPLETION: { - VCHIQ_AWAIT_COMPLETION_T args; + struct vchiq_await_completion args; DEBUG_TRACE(AWAIT_COMPLETION_LINE); if (!instance->connected) { @@ -1245,7 +1182,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) DEBUG_TRACE(AWAIT_COMPLETION_LINE); mutex_unlock(&instance->completion_mutex); - rc = down_interruptible(&instance->insert_event); + rc = wait_for_completion_killable( + &instance->insert_event); mutex_lock(&instance->completion_mutex); if (rc != 0) { DEBUG_TRACE(AWAIT_COMPLETION_LINE); @@ -1262,10 +1200,10 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int remove = instance->completion_remove; for (ret = 0; ret < args.count; ret++) { - VCHIQ_COMPLETION_DATA_T *completion; - VCHIQ_SERVICE_T *service; - USER_SERVICE_T *user_service; - VCHIQ_HEADER_T *header; + struct vchiq_completion_data *completion; + struct vchiq_service *service; + struct user_service *user_service; + struct vchiq_header *header; if (remove == instance->completion_insert) break; @@ -1290,7 +1228,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int msglen; msglen = header->size + - sizeof(VCHIQ_HEADER_T); + sizeof(struct vchiq_header); /* This must be a VCHIQ-style service */ if (args.msgbufsize < msglen) { vchiq_log_error( @@ -1343,10 +1281,11 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) unlock_service(service); if (copy_to_user((void __user *)( - (size_t)args.buf + - ret * sizeof(VCHIQ_COMPLETION_DATA_T)), + (size_t)args.buf + ret * + sizeof(struct vchiq_completion_data)), completion, - sizeof(VCHIQ_COMPLETION_DATA_T)) != 0) { + sizeof(struct vchiq_completion_data)) + != 0) { if (ret == 0) ret = -EFAULT; break; @@ -1363,8 +1302,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (msgbufcount != args.msgbufcount) { if (copy_to_user((void __user *) - &((VCHIQ_AWAIT_COMPLETION_T *)arg)-> - msgbufcount, + &((struct vchiq_await_completion *)arg) + ->msgbufcount, &msgbufcount, sizeof(msgbufcount)) != 0) { ret = -EFAULT; @@ -1373,15 +1312,15 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } if (ret != 0) - up(&instance->remove_event); + complete(&instance->remove_event); mutex_unlock(&instance->completion_mutex); DEBUG_TRACE(AWAIT_COMPLETION_LINE); } break; case VCHIQ_IOC_DEQUEUE_MESSAGE: { - VCHIQ_DEQUEUE_MESSAGE_T args; - USER_SERVICE_T *user_service; - VCHIQ_HEADER_T *header; + struct vchiq_dequeue_message args; + struct user_service *user_service; + struct vchiq_header *header; DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); if (copy_from_user @@ -1395,7 +1334,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ret = -EINVAL; break; } - user_service = (USER_SERVICE_T *)service->base.userdata; + user_service = (struct user_service *)service->base.userdata; if (user_service->is_vchi == 0) { ret = -EINVAL; break; @@ -1413,8 +1352,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) do { spin_unlock(&msg_queue_spinlock); DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); - if (down_interruptible( - &user_service->insert_event) != 0) { + if (wait_for_completion_killable( + &user_service->insert_event)) { vchiq_log_info(vchiq_arm_log_level, "DEQUEUE_MESSAGE interrupted"); ret = -EINTR; @@ -1436,7 +1375,7 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) user_service->msg_remove++; spin_unlock(&msg_queue_spinlock); - up(&user_service->remove_event); + complete(&user_service->remove_event); if (header == NULL) ret = -ENOTCONN; else if (header->size <= args.bufsize) { @@ -1468,8 +1407,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } break; case VCHIQ_IOC_GET_CONFIG: { - VCHIQ_GET_CONFIG_T args; - VCHIQ_CONFIG_T config; + struct vchiq_get_config args; + struct vchiq_config config; if (copy_from_user(&args, (const void __user *)arg, sizeof(args)) != 0) { @@ -1480,18 +1419,16 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ret = -EINVAL; break; } - status = vchiq_get_config(instance, args.config_size, &config); - if (status == VCHIQ_SUCCESS) { - if (copy_to_user((void __user *)args.pconfig, - &config, args.config_size) != 0) { - ret = -EFAULT; - break; - } + + vchiq_get_config(&config); + if (copy_to_user(args.pconfig, &config, args.config_size)) { + ret = -EFAULT; + break; } } break; case VCHIQ_IOC_SET_SERVICE_OPTION: { - VCHIQ_SET_SERVICE_OPTION_T args; + struct vchiq_set_service_option args; if (copy_from_user( &args, (const void __user *)arg, @@ -1524,8 +1461,8 @@ vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) service = find_closed_service_for_instance(instance, handle); if (service != NULL) { - USER_SERVICE_T *user_service = - (USER_SERVICE_T *)service->base.userdata; + struct user_service *user_service = + (struct user_service *)service->base.userdata; close_delivered(user_service); } else ret = -EINVAL; @@ -1593,7 +1530,7 @@ vchiq_compat_ioctl_create_service( unsigned int cmd, unsigned long arg) { - VCHIQ_CREATE_SERVICE_T __user *args; + struct vchiq_create_service __user *args; struct vchiq_create_service32 __user *ptrargs32 = (struct vchiq_create_service32 __user *)arg; struct vchiq_create_service32 args32; @@ -1656,8 +1593,8 @@ vchiq_compat_ioctl_queue_message(struct file *file, unsigned int cmd, unsigned long arg) { - VCHIQ_QUEUE_MESSAGE_T *args; - struct vchiq_element *elements; + struct vchiq_queue_message *args; + struct vchiq_element __user *elements; struct vchiq_queue_message32 args32; unsigned int count; @@ -1723,7 +1660,7 @@ vchiq_compat_ioctl_queue_bulk(struct file *file, unsigned int cmd, unsigned long arg) { - VCHIQ_QUEUE_BULK_TRANSFER_T *args; + struct vchiq_queue_bulk_transfer __user *args; struct vchiq_queue_bulk_transfer32 args32; struct vchiq_queue_bulk_transfer32 *ptrargs32 = (struct vchiq_queue_bulk_transfer32 *)arg; @@ -1789,16 +1726,16 @@ vchiq_compat_ioctl_await_completion(struct file *file, unsigned int cmd, unsigned long arg) { - VCHIQ_AWAIT_COMPLETION_T *args; - VCHIQ_COMPLETION_DATA_T *completion; - VCHIQ_COMPLETION_DATA_T completiontemp; + struct vchiq_await_completion __user *args; + struct vchiq_completion_data __user *completion; + struct vchiq_completion_data completiontemp; struct vchiq_await_completion32 args32; struct vchiq_completion_data32 completion32; - unsigned int *msgbufcount32; + unsigned int __user *msgbufcount32; unsigned int msgbufcount_native; compat_uptr_t msgbuf32; - void *msgbuf; - void **msgbufptr; + void __user *msgbuf; + void * __user *msgbufptr; long ret; args = compat_alloc_user_space(sizeof(*args) + @@ -1807,11 +1744,11 @@ vchiq_compat_ioctl_await_completion(struct file *file, if (!args) return -EFAULT; - completion = (VCHIQ_COMPLETION_DATA_T *)(args + 1); - msgbufptr = (void __user **)(completion + 1); + completion = (struct vchiq_completion_data __user *)(args + 1); + msgbufptr = (void * __user *)(completion + 1); if (copy_from_user(&args32, - (struct vchiq_completion_data32 *)arg, + (struct vchiq_completion_data32 __user *)arg, sizeof(args32))) return -EFAULT; @@ -1939,7 +1876,7 @@ vchiq_compat_ioctl_dequeue_message(struct file *file, unsigned int cmd, unsigned long arg) { - VCHIQ_DEQUEUE_MESSAGE_T *args; + struct vchiq_dequeue_message __user *args; struct vchiq_dequeue_message32 args32; args = compat_alloc_user_space(sizeof(*args)); @@ -1947,7 +1884,7 @@ vchiq_compat_ioctl_dequeue_message(struct file *file, return -EFAULT; if (copy_from_user(&args32, - (struct vchiq_dequeue_message32 *)arg, + (struct vchiq_dequeue_message32 __user *)arg, sizeof(args32))) return -EFAULT; @@ -1974,7 +1911,7 @@ vchiq_compat_ioctl_get_config(struct file *file, unsigned int cmd, unsigned long arg) { - VCHIQ_GET_CONFIG_T *args; + struct vchiq_get_config __user *args; struct vchiq_get_config32 args32; args = compat_alloc_user_space(sizeof(*args)); @@ -1982,7 +1919,7 @@ vchiq_compat_ioctl_get_config(struct file *file, return -EFAULT; if (copy_from_user(&args32, - (struct vchiq_get_config32 *)arg, + (struct vchiq_get_config32 __user *)arg, sizeof(args32))) return -EFAULT; @@ -2017,201 +1954,152 @@ vchiq_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) #endif -/**************************************************************************** -* -* vchiq_open -* -***************************************************************************/ - -static int -vchiq_open(struct inode *inode, struct file *file) +static int vchiq_open(struct inode *inode, struct file *file) { - int dev = iminor(inode) & 0x0f; + struct vchiq_state *state = vchiq_get_state(); + VCHIQ_INSTANCE_T instance; vchiq_log_info(vchiq_arm_log_level, "vchiq_open"); - switch (dev) { - case VCHIQ_MINOR: { - VCHIQ_STATE_T *state = vchiq_get_state(); - VCHIQ_INSTANCE_T instance; - if (!state) { - vchiq_log_error(vchiq_arm_log_level, + if (!state) { + vchiq_log_error(vchiq_arm_log_level, "vchiq has no connection to VideoCore"); - return -ENOTCONN; - } - - instance = kzalloc(sizeof(*instance), GFP_KERNEL); - if (!instance) - return -ENOMEM; + return -ENOTCONN; + } - instance->state = state; - instance->pid = current->tgid; + instance = kzalloc(sizeof(*instance), GFP_KERNEL); + if (!instance) + return -ENOMEM; - vchiq_debugfs_add_instance(instance); + instance->state = state; + instance->pid = current->tgid; - sema_init(&instance->insert_event, 0); - sema_init(&instance->remove_event, 0); - mutex_init(&instance->completion_mutex); - mutex_init(&instance->bulk_waiter_list_mutex); - INIT_LIST_HEAD(&instance->bulk_waiter_list); + vchiq_debugfs_add_instance(instance); - file->private_data = instance; - } break; + init_completion(&instance->insert_event); + init_completion(&instance->remove_event); + mutex_init(&instance->completion_mutex); + mutex_init(&instance->bulk_waiter_list_mutex); + INIT_LIST_HEAD(&instance->bulk_waiter_list); - default: - vchiq_log_error(vchiq_arm_log_level, - "Unknown minor device: %d", dev); - return -ENXIO; - } + file->private_data = instance; return 0; } -/**************************************************************************** -* -* vchiq_release -* -***************************************************************************/ - -static int -vchiq_release(struct inode *inode, struct file *file) +static int vchiq_release(struct inode *inode, struct file *file) { - int dev = iminor(inode) & 0x0f; + VCHIQ_INSTANCE_T instance = file->private_data; + struct vchiq_state *state = vchiq_get_state(); + struct vchiq_service *service; int ret = 0; + int i; - switch (dev) { - case VCHIQ_MINOR: { - VCHIQ_INSTANCE_T instance = file->private_data; - VCHIQ_STATE_T *state = vchiq_get_state(); - VCHIQ_SERVICE_T *service; - int i; - - vchiq_log_info(vchiq_arm_log_level, - "%s: instance=%lx", - __func__, (unsigned long)instance); - - if (!state) { - ret = -EPERM; - goto out; - } + vchiq_log_info(vchiq_arm_log_level, "%s: instance=%lx", __func__, + (unsigned long)instance); - /* Ensure videocore is awake to allow termination. */ - vchiq_use_internal(instance->state, NULL, - USE_TYPE_VCHIQ); + if (!state) { + ret = -EPERM; + goto out; + } - mutex_lock(&instance->completion_mutex); + /* Ensure videocore is awake to allow termination. */ + vchiq_use_internal(instance->state, NULL, USE_TYPE_VCHIQ); - /* Wake the completion thread and ask it to exit */ - instance->closing = 1; - up(&instance->insert_event); + mutex_lock(&instance->completion_mutex); - mutex_unlock(&instance->completion_mutex); + /* Wake the completion thread and ask it to exit */ + instance->closing = 1; + complete(&instance->insert_event); - /* Wake the slot handler if the completion queue is full. */ - up(&instance->remove_event); + mutex_unlock(&instance->completion_mutex); - /* Mark all services for termination... */ - i = 0; - while ((service = next_service_by_instance(state, instance, - &i)) != NULL) { - USER_SERVICE_T *user_service = service->base.userdata; + /* Wake the slot handler if the completion queue is full. */ + complete(&instance->remove_event); - /* Wake the slot handler if the msg queue is full. */ - up(&user_service->remove_event); + /* Mark all services for termination... */ + i = 0; + while ((service = next_service_by_instance(state, instance, &i))) { + struct user_service *user_service = service->base.userdata; - vchiq_terminate_service_internal(service); - unlock_service(service); - } + /* Wake the slot handler if the msg queue is full. */ + complete(&user_service->remove_event); - /* ...and wait for them to die */ - i = 0; - while ((service = next_service_by_instance(state, instance, &i)) - != NULL) { - USER_SERVICE_T *user_service = service->base.userdata; + vchiq_terminate_service_internal(service); + unlock_service(service); + } - down(&service->remove_event); + /* ...and wait for them to die */ + i = 0; + while ((service = next_service_by_instance(state, instance, &i))) { + struct user_service *user_service = service->base.userdata; - BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); + wait_for_completion(&service->remove_event); - spin_lock(&msg_queue_spinlock); + BUG_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); - while (user_service->msg_remove != - user_service->msg_insert) { - VCHIQ_HEADER_T *header; - int m = user_service->msg_remove & - (MSG_QUEUE_SIZE - 1); + spin_lock(&msg_queue_spinlock); - header = user_service->msg_queue[m]; - user_service->msg_remove++; - spin_unlock(&msg_queue_spinlock); - - if (header) - vchiq_release_message( - service->handle, - header); - spin_lock(&msg_queue_spinlock); - } + while (user_service->msg_remove != user_service->msg_insert) { + struct vchiq_header *header; + int m = user_service->msg_remove & (MSG_QUEUE_SIZE - 1); + header = user_service->msg_queue[m]; + user_service->msg_remove++; spin_unlock(&msg_queue_spinlock); - unlock_service(service); + if (header) + vchiq_release_message(service->handle, header); + spin_lock(&msg_queue_spinlock); } - /* Release any closed services */ - while (instance->completion_remove != - instance->completion_insert) { - VCHIQ_COMPLETION_DATA_T *completion; - VCHIQ_SERVICE_T *service; - - completion = &instance->completions[ - instance->completion_remove & - (MAX_COMPLETIONS - 1)]; - service = completion->service_userdata; - if (completion->reason == VCHIQ_SERVICE_CLOSED) { - USER_SERVICE_T *user_service = - service->base.userdata; - - /* Wake any blocked user-thread */ - if (instance->use_close_delivered) - up(&user_service->close_event); - unlock_service(service); - } - instance->completion_remove++; - } + spin_unlock(&msg_queue_spinlock); - /* Release the PEER service count. */ - vchiq_release_internal(instance->state, NULL); + unlock_service(service); + } - { - struct list_head *pos, *next; + /* Release any closed services */ + while (instance->completion_remove != + instance->completion_insert) { + struct vchiq_completion_data *completion; + struct vchiq_service *service; - list_for_each_safe(pos, next, - &instance->bulk_waiter_list) { - struct bulk_waiter_node *waiter; + completion = &instance->completions[ + instance->completion_remove & (MAX_COMPLETIONS - 1)]; + service = completion->service_userdata; + if (completion->reason == VCHIQ_SERVICE_CLOSED) { + struct user_service *user_service = + service->base.userdata; - waiter = list_entry(pos, - struct bulk_waiter_node, - list); - list_del(pos); - vchiq_log_info(vchiq_arm_log_level, - "bulk_waiter - cleaned up %pK for pid %d", - waiter, waiter->pid); - kfree(waiter); - } + /* Wake any blocked user-thread */ + if (instance->use_close_delivered) + complete(&user_service->close_event); + unlock_service(service); } + instance->completion_remove++; + } - vchiq_debugfs_remove_instance(instance); + /* Release the PEER service count. */ + vchiq_release_internal(instance->state, NULL); - kfree(instance); - file->private_data = NULL; - } break; + { + struct bulk_waiter_node *waiter, *next; - default: - vchiq_log_error(vchiq_arm_log_level, - "Unknown minor device: %d", dev); - ret = -ENXIO; + list_for_each_entry_safe(waiter, next, + &instance->bulk_waiter_list, list) { + list_del(&waiter->list); + vchiq_log_info(vchiq_arm_log_level, + "bulk_waiter - cleaned up %pK for pid %d", + waiter, waiter->pid); + kfree(waiter); + } } + vchiq_debugfs_remove_instance(instance); + + kfree(instance); + file->private_data = NULL; + out: return ret; } @@ -2225,7 +2113,7 @@ out: void vchiq_dump(void *dump_context, const char *str, int len) { - DUMP_CONTEXT_T *context = (DUMP_CONTEXT_T *)dump_context; + struct dump_context *context = (struct dump_context *)dump_context; if (context->actual < context->space) { int copy_bytes; @@ -2270,7 +2158,7 @@ vchiq_dump(void *dump_context, const char *str, int len) void vchiq_dump_platform_instances(void *dump_context) { - VCHIQ_STATE_T *state = vchiq_get_state(); + struct vchiq_state *state = vchiq_get_state(); char buf[80]; int len; int i; @@ -2279,7 +2167,7 @@ vchiq_dump_platform_instances(void *dump_context) marking those that have been dumped. */ for (i = 0; i < state->unused_service; i++) { - VCHIQ_SERVICE_T *service = state->services[i]; + struct vchiq_service *service = state->services[i]; VCHIQ_INSTANCE_T instance; if (service && (service->base.callback == service_callback)) { @@ -2290,7 +2178,7 @@ vchiq_dump_platform_instances(void *dump_context) } for (i = 0; i < state->unused_service; i++) { - VCHIQ_SERVICE_T *service = state->services[i]; + struct vchiq_service *service = state->services[i]; VCHIQ_INSTANCE_T instance; if (service && (service->base.callback == service_callback)) { @@ -2320,9 +2208,11 @@ vchiq_dump_platform_instances(void *dump_context) ***************************************************************************/ void -vchiq_dump_platform_service_state(void *dump_context, VCHIQ_SERVICE_T *service) +vchiq_dump_platform_service_state(void *dump_context, + struct vchiq_service *service) { - USER_SERVICE_T *user_service = (USER_SERVICE_T *)service->base.userdata; + struct user_service *user_service = + (struct user_service *)service->base.userdata; char buf[80]; int len; @@ -2353,7 +2243,7 @@ static ssize_t vchiq_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - DUMP_CONTEXT_T context; + struct dump_context context; context.buf = buf; context.actual = 0; @@ -2367,7 +2257,7 @@ vchiq_read(struct file *file, char __user *buf, return context.actual; } -VCHIQ_STATE_T * +struct vchiq_state * vchiq_get_state(void) { @@ -2398,9 +2288,9 @@ vchiq_fops = { */ int -vchiq_videocore_wanted(VCHIQ_STATE_T *state) +vchiq_videocore_wanted(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); if (!arm_state) /* autosuspend not supported - always return wanted */ @@ -2420,7 +2310,7 @@ vchiq_videocore_wanted(VCHIQ_STATE_T *state) static VCHIQ_STATUS_T vchiq_keepalive_vchiq_callback(VCHIQ_REASON_T reason, - VCHIQ_HEADER_T *header, + struct vchiq_header *header, VCHIQ_SERVICE_HANDLE_T service_user, void *bulk_user) { @@ -2432,14 +2322,14 @@ vchiq_keepalive_vchiq_callback(VCHIQ_REASON_T reason, static int vchiq_keepalive_thread_func(void *v) { - VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_state *state = (struct vchiq_state *)v; + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); VCHIQ_STATUS_T status; VCHIQ_INSTANCE_T instance; VCHIQ_SERVICE_HANDLE_T ka_handle; - VCHIQ_SERVICE_PARAMS_T params = { + struct vchiq_service_params params = { .fourcc = VCHIQ_MAKE_FOURCC('K', 'E', 'E', 'P'), .callback = vchiq_keepalive_vchiq_callback, .version = KEEPALIVE_VER, @@ -2470,7 +2360,7 @@ vchiq_keepalive_thread_func(void *v) while (1) { long rc = 0, uc = 0; - if (wait_for_completion_interruptible(&arm_state->ka_evt) + if (wait_for_completion_killable(&arm_state->ka_evt) != 0) { vchiq_log_error(vchiq_susp_log_level, "%s interrupted", __func__); @@ -2511,7 +2401,8 @@ exit: } VCHIQ_STATUS_T -vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state) +vchiq_arm_init_state(struct vchiq_state *state, + struct vchiq_arm_state *arm_state) { if (arm_state) { rwlock_init(&arm_state->susp_res_lock); @@ -2607,8 +2498,8 @@ vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state) */ void -set_suspend_state(VCHIQ_ARM_STATE_T *arm_state, - enum vc_suspend_status new_state) +set_suspend_state(struct vchiq_arm_state *arm_state, + enum vc_suspend_status new_state) { /* set the state in all cases */ arm_state->vc_suspend_state = new_state; @@ -2644,8 +2535,8 @@ set_suspend_state(VCHIQ_ARM_STATE_T *arm_state, } void -set_resume_state(VCHIQ_ARM_STATE_T *arm_state, - enum vc_resume_status new_state) +set_resume_state(struct vchiq_arm_state *arm_state, + enum vc_resume_status new_state) { /* set the state in all cases */ arm_state->vc_resume_state = new_state; @@ -2673,7 +2564,7 @@ set_resume_state(VCHIQ_ARM_STATE_T *arm_state, /* should be called with the write lock held */ inline void -start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) +start_suspend_timer(struct vchiq_arm_state *arm_state) { del_timer(&arm_state->suspend_timer); arm_state->suspend_timer.expires = jiffies + @@ -2684,7 +2575,7 @@ start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) /* should be called with the write lock held */ static inline void -stop_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) +stop_suspend_timer(struct vchiq_arm_state *arm_state) { if (arm_state->suspend_timer_running) { del_timer(&arm_state->suspend_timer); @@ -2693,9 +2584,9 @@ stop_suspend_timer(VCHIQ_ARM_STATE_T *arm_state) } static inline int -need_resume(VCHIQ_STATE_T *state) +need_resume(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); return (arm_state->vc_suspend_state > VC_SUSPEND_IDLE) && (arm_state->vc_resume_state < VC_RESUME_REQUESTED) && @@ -2703,7 +2594,7 @@ need_resume(VCHIQ_STATE_T *state) } static int -block_resume(VCHIQ_ARM_STATE_T *arm_state) +block_resume(struct vchiq_arm_state *arm_state) { int status = VCHIQ_SUCCESS; const unsigned long timeout_val = @@ -2720,7 +2611,7 @@ block_resume(VCHIQ_ARM_STATE_T *arm_state) write_unlock_bh(&arm_state->susp_res_lock); vchiq_log_info(vchiq_susp_log_level, "%s wait for previously " "blocked clients", __func__); - if (wait_for_completion_interruptible_timeout( + if (wait_for_completion_killable_timeout( &arm_state->blocked_blocker, timeout_val) <= 0) { vchiq_log_error(vchiq_susp_log_level, "%s wait for " @@ -2746,7 +2637,7 @@ block_resume(VCHIQ_ARM_STATE_T *arm_state) write_unlock_bh(&arm_state->susp_res_lock); vchiq_log_info(vchiq_susp_log_level, "%s wait for resume", __func__); - if (wait_for_completion_interruptible_timeout( + if (wait_for_completion_killable_timeout( &arm_state->vc_resume_complete, timeout_val) <= 0) { vchiq_log_error(vchiq_susp_log_level, "%s wait for " @@ -2769,7 +2660,7 @@ out: } static inline void -unblock_resume(VCHIQ_ARM_STATE_T *arm_state) +unblock_resume(struct vchiq_arm_state *arm_state) { complete_all(&arm_state->resume_blocker); arm_state->resume_blocked = 0; @@ -2778,10 +2669,10 @@ unblock_resume(VCHIQ_ARM_STATE_T *arm_state) /* Initiate suspend via slot handler. Should be called with the write lock * held */ VCHIQ_STATUS_T -vchiq_arm_vcsuspend(VCHIQ_STATE_T *state) +vchiq_arm_vcsuspend(struct vchiq_state *state) { VCHIQ_STATUS_T status = VCHIQ_ERROR; - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); if (!arm_state) goto out; @@ -2827,9 +2718,9 @@ out: } void -vchiq_platform_check_suspend(VCHIQ_STATE_T *state) +vchiq_platform_check_suspend(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); int susp = 0; if (!arm_state) @@ -2854,9 +2745,9 @@ out: } static void -output_timeout_error(VCHIQ_STATE_T *state) +output_timeout_error(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); char err[50] = ""; int vc_use_count = arm_state->videocore_use_count; int active_services = state->unused_service; @@ -2867,7 +2758,7 @@ output_timeout_error(VCHIQ_STATE_T *state) goto output_msg; } for (i = 0; i < active_services; i++) { - VCHIQ_SERVICE_T *service_ptr = state->services[i]; + struct vchiq_service *service_ptr = state->services[i]; if (service_ptr && service_ptr->service_use_count && (service_ptr->srvstate != VCHIQ_SRVSTATE_FREE)) { @@ -2899,9 +2790,9 @@ output_msg: ** videocore failed to suspend in time or VCHIQ_ERROR if interrupted. */ VCHIQ_STATUS_T -vchiq_arm_force_suspend(VCHIQ_STATE_T *state) +vchiq_arm_force_suspend(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); VCHIQ_STATUS_T status = VCHIQ_ERROR; long rc = 0; int repeat = -1; @@ -2953,7 +2844,7 @@ vchiq_arm_force_suspend(VCHIQ_STATE_T *state) do { write_unlock_bh(&arm_state->susp_res_lock); - rc = wait_for_completion_interruptible_timeout( + rc = wait_for_completion_killable_timeout( &arm_state->vc_suspend_complete, msecs_to_jiffies(FORCE_SUSPEND_TIMEOUT_MS)); @@ -3010,9 +2901,9 @@ out: } void -vchiq_check_suspend(VCHIQ_STATE_T *state) +vchiq_check_suspend(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); if (!arm_state) goto out; @@ -3032,9 +2923,9 @@ out: } int -vchiq_arm_allow_resume(VCHIQ_STATE_T *state) +vchiq_arm_allow_resume(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); int resume = 0; int ret = -1; @@ -3049,7 +2940,7 @@ vchiq_arm_allow_resume(VCHIQ_STATE_T *state) write_unlock_bh(&arm_state->susp_res_lock); if (resume) { - if (wait_for_completion_interruptible( + if (wait_for_completion_killable( &arm_state->vc_resume_complete) < 0) { vchiq_log_error(vchiq_susp_log_level, "%s interrupted", __func__); @@ -3076,9 +2967,9 @@ out: /* This function should be called with the write lock held */ int -vchiq_check_resume(VCHIQ_STATE_T *state) +vchiq_check_resume(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); int resume = 0; if (!arm_state) @@ -3098,10 +2989,10 @@ out: } VCHIQ_STATUS_T -vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, - enum USE_TYPE_E use_type) +vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, + enum USE_TYPE_E use_type) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); VCHIQ_STATUS_T ret = VCHIQ_SUCCESS; char entity[16]; int *entity_uc; @@ -3231,9 +3122,9 @@ out: } VCHIQ_STATUS_T -vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service) +vchiq_release_internal(struct vchiq_state *state, struct vchiq_service *service) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); VCHIQ_STATUS_T ret = VCHIQ_SUCCESS; char entity[16]; int *entity_uc; @@ -3293,9 +3184,9 @@ out: } void -vchiq_on_remote_use(VCHIQ_STATE_T *state) +vchiq_on_remote_use(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); atomic_inc(&arm_state->ka_use_count); @@ -3303,9 +3194,9 @@ vchiq_on_remote_use(VCHIQ_STATE_T *state) } void -vchiq_on_remote_release(VCHIQ_STATE_T *state) +vchiq_on_remote_release(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); vchiq_log_trace(vchiq_susp_log_level, "%s", __func__); atomic_inc(&arm_state->ka_release_count); @@ -3313,18 +3204,18 @@ vchiq_on_remote_release(VCHIQ_STATE_T *state) } VCHIQ_STATUS_T -vchiq_use_service_internal(VCHIQ_SERVICE_T *service) +vchiq_use_service_internal(struct vchiq_service *service) { return vchiq_use_internal(service->state, service, USE_TYPE_SERVICE); } VCHIQ_STATUS_T -vchiq_release_service_internal(VCHIQ_SERVICE_T *service) +vchiq_release_service_internal(struct vchiq_service *service) { return vchiq_release_internal(service->state, service); } -VCHIQ_DEBUGFS_NODE_T * +struct vchiq_debugfs_node * vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance) { return &instance->debugfs_node; @@ -3333,7 +3224,7 @@ vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance) int vchiq_instance_get_use_count(VCHIQ_INSTANCE_T instance) { - VCHIQ_SERVICE_T *service; + struct vchiq_service *service; int use_count = 0, i; i = 0; @@ -3360,7 +3251,7 @@ vchiq_instance_get_trace(VCHIQ_INSTANCE_T instance) void vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace) { - VCHIQ_SERVICE_T *service; + struct vchiq_service *service; int i; i = 0; @@ -3374,8 +3265,9 @@ vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace) static void suspend_timer_callback(struct timer_list *t) { - VCHIQ_ARM_STATE_T *arm_state = from_timer(arm_state, t, suspend_timer); - VCHIQ_STATE_T *state = arm_state->state; + struct vchiq_arm_state *arm_state = + from_timer(arm_state, t, suspend_timer); + struct vchiq_state *state = arm_state->state; vchiq_log_info(vchiq_susp_log_level, "%s - suspend timer expired - check suspend", __func__); @@ -3386,7 +3278,7 @@ VCHIQ_STATUS_T vchiq_use_service_no_resume(VCHIQ_SERVICE_HANDLE_T handle) { VCHIQ_STATUS_T ret = VCHIQ_ERROR; - VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + struct vchiq_service *service = find_service_by_handle(handle); if (service) { ret = vchiq_use_internal(service->state, service, @@ -3400,7 +3292,7 @@ VCHIQ_STATUS_T vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle) { VCHIQ_STATUS_T ret = VCHIQ_ERROR; - VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + struct vchiq_service *service = find_service_by_handle(handle); if (service) { ret = vchiq_use_internal(service->state, service, @@ -3414,7 +3306,7 @@ VCHIQ_STATUS_T vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle) { VCHIQ_STATUS_T ret = VCHIQ_ERROR; - VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + struct vchiq_service *service = find_service_by_handle(handle); if (service) { ret = vchiq_release_internal(service->state, service); @@ -3430,9 +3322,9 @@ struct service_data_struct { }; void -vchiq_dump_service_use_state(VCHIQ_STATE_T *state) +vchiq_dump_service_use_state(struct vchiq_state *state) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); struct service_data_struct *service_data; int i, found = 0; /* If there's more than 64 services, only dump ones with @@ -3464,7 +3356,7 @@ vchiq_dump_service_use_state(VCHIQ_STATE_T *state) only_nonzero = 1; for (i = 0; i < active_services; i++) { - VCHIQ_SERVICE_T *service_ptr = state->services[i]; + struct vchiq_service *service_ptr = state->services[i]; if (!service_ptr) continue; @@ -3516,9 +3408,9 @@ vchiq_dump_service_use_state(VCHIQ_STATE_T *state) } VCHIQ_STATUS_T -vchiq_check_service(VCHIQ_SERVICE_T *service) +vchiq_check_service(struct vchiq_service *service) { - VCHIQ_ARM_STATE_T *arm_state; + struct vchiq_arm_state *arm_state; VCHIQ_STATUS_T ret = VCHIQ_ERROR; if (!service || !service->state) @@ -3549,15 +3441,16 @@ out: } /* stub functions */ -void vchiq_on_remote_use_active(VCHIQ_STATE_T *state) +void vchiq_on_remote_use_active(struct vchiq_state *state) { (void)state; } -void vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, - VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate) +void vchiq_platform_conn_state_changed(struct vchiq_state *state, + VCHIQ_CONNSTATE_T oldstate, + VCHIQ_CONNSTATE_T newstate) { - VCHIQ_ARM_STATE_T *arm_state = vchiq_platform_get_arm_state(state); + struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); vchiq_log_info(vchiq_susp_log_level, "%d: %s->%s", state->id, get_conn_state_name(oldstate), get_conn_state_name(newstate)); @@ -3593,6 +3486,28 @@ static const struct of_device_id vchiq_of_match[] = { }; MODULE_DEVICE_TABLE(of, vchiq_of_match); +static struct platform_device * +vchiq_register_child(struct platform_device *pdev, const char *name) +{ + struct platform_device_info pdevinfo; + struct platform_device *child; + + memset(&pdevinfo, 0, sizeof(pdevinfo)); + + pdevinfo.parent = &pdev->dev; + pdevinfo.name = name; + pdevinfo.id = PLATFORM_DEVID_NONE; + pdevinfo.dma_mask = DMA_BIT_MASK(32); + + child = platform_device_register_full(&pdevinfo); + if (IS_ERR(child)) { + dev_warn(&pdev->dev, "%s not registered\n", name); + child = NULL; + } + + return child; +} + static int vchiq_probe(struct platform_device *pdev) { struct device_node *fw_node; @@ -3623,34 +3538,19 @@ static int vchiq_probe(struct platform_device *pdev) if (err != 0) goto failed_platform_init; - err = alloc_chrdev_region(&vchiq_devid, VCHIQ_MINOR, 1, DEVICE_NAME); - if (err != 0) { - vchiq_log_error(vchiq_arm_log_level, - "Unable to allocate device number"); - goto failed_platform_init; - } cdev_init(&vchiq_cdev, &vchiq_fops); vchiq_cdev.owner = THIS_MODULE; err = cdev_add(&vchiq_cdev, vchiq_devid, 1); if (err != 0) { vchiq_log_error(vchiq_arm_log_level, "Unable to register device"); - goto failed_cdev_add; + goto failed_platform_init; } - /* create sysfs entries */ - vchiq_class = class_create(THIS_MODULE, DEVICE_NAME); - err = PTR_ERR(vchiq_class); - if (IS_ERR(vchiq_class)) - goto failed_class_create; - - vchiq_dev = device_create(vchiq_class, NULL, - vchiq_devid, NULL, "vchiq"); - err = PTR_ERR(vchiq_dev); - if (IS_ERR(vchiq_dev)) + if (IS_ERR(device_create(vchiq_class, &pdev->dev, vchiq_devid, + NULL, "vchiq"))) goto failed_device_create; - /* create debugfs entries */ vchiq_debugfs_init(); vchiq_log_info(vchiq_arm_log_level, @@ -3658,18 +3558,13 @@ static int vchiq_probe(struct platform_device *pdev) VCHIQ_VERSION, VCHIQ_VERSION_MIN, MAJOR(vchiq_devid), MINOR(vchiq_devid)); - bcm2835_camera = platform_device_register_data(&pdev->dev, - "bcm2835-camera", -1, - NULL, 0); + bcm2835_camera = vchiq_register_child(pdev, "bcm2835-camera"); + bcm2835_audio = vchiq_register_child(pdev, "bcm2835_audio"); return 0; failed_device_create: - class_destroy(vchiq_class); -failed_class_create: cdev_del(&vchiq_cdev); -failed_cdev_add: - unregister_chrdev_region(vchiq_devid, 1); failed_platform_init: vchiq_log_warning(vchiq_arm_log_level, "could not load vchiq"); return err; @@ -3680,9 +3575,7 @@ static int vchiq_remove(struct platform_device *pdev) platform_device_unregister(bcm2835_camera); vchiq_debugfs_deinit(); device_destroy(vchiq_class, vchiq_devid); - class_destroy(vchiq_class); cdev_del(&vchiq_cdev); - unregister_chrdev_region(vchiq_devid, 1); return 0; } @@ -3695,7 +3588,48 @@ static struct platform_driver vchiq_driver = { .probe = vchiq_probe, .remove = vchiq_remove, }; -module_platform_driver(vchiq_driver); + +static int __init vchiq_driver_init(void) +{ + int ret; + + vchiq_class = class_create(THIS_MODULE, DEVICE_NAME); + if (IS_ERR(vchiq_class)) { + pr_err("Failed to create vchiq class\n"); + return PTR_ERR(vchiq_class); + } + + ret = alloc_chrdev_region(&vchiq_devid, 0, 1, DEVICE_NAME); + if (ret) { + pr_err("Failed to allocate vchiq's chrdev region\n"); + goto class_destroy; + } + + ret = platform_driver_register(&vchiq_driver); + if (ret) { + pr_err("Failed to register vchiq driver\n"); + goto region_unregister; + } + + return 0; + +region_unregister: + platform_driver_unregister(&vchiq_driver); + +class_destroy: + class_destroy(vchiq_class); + + return ret; +} +module_init(vchiq_driver_init); + +static void __exit vchiq_driver_exit(void) +{ + platform_driver_unregister(&vchiq_driver); + unregister_chrdev_region(vchiq_devid, 1); + class_destroy(vchiq_class); +} +module_exit(vchiq_driver_exit); MODULE_LICENSE("Dual BSD/GPL"); MODULE_DESCRIPTION("Videocore VCHIQ driver"); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h index 2f3ebc99cbcf..cdb963054975 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h @@ -66,7 +66,7 @@ enum USE_TYPE_E { USE_TYPE_VCHIQ }; -typedef struct vchiq_arm_state_struct { +struct vchiq_arm_state { /* Keepalive-related data */ struct task_struct *ka_thread; struct completion ka_evt; @@ -83,7 +83,7 @@ typedef struct vchiq_arm_state_struct { unsigned int wake_address; - VCHIQ_STATE_T *state; + struct vchiq_state *state; struct timer_list suspend_timer; int suspend_timer_timeout; int suspend_timer_running; @@ -121,7 +121,7 @@ typedef struct vchiq_arm_state_struct { unsigned long long resume_start_time; unsigned long long last_wake_time; -} VCHIQ_ARM_STATE_T; +}; struct vchiq_drvdata { const unsigned int cache_line_size; @@ -131,31 +131,33 @@ struct vchiq_drvdata { extern int vchiq_arm_log_level; extern int vchiq_susp_log_level; -int vchiq_platform_init(struct platform_device *pdev, VCHIQ_STATE_T *state); +int vchiq_platform_init(struct platform_device *pdev, + struct vchiq_state *state); -extern VCHIQ_STATE_T * +extern struct vchiq_state * vchiq_get_state(void); extern VCHIQ_STATUS_T -vchiq_arm_vcsuspend(VCHIQ_STATE_T *state); +vchiq_arm_vcsuspend(struct vchiq_state *state); extern VCHIQ_STATUS_T -vchiq_arm_force_suspend(VCHIQ_STATE_T *state); +vchiq_arm_force_suspend(struct vchiq_state *state); extern int -vchiq_arm_allow_resume(VCHIQ_STATE_T *state); +vchiq_arm_allow_resume(struct vchiq_state *state); extern VCHIQ_STATUS_T -vchiq_arm_vcresume(VCHIQ_STATE_T *state); +vchiq_arm_vcresume(struct vchiq_state *state); extern VCHIQ_STATUS_T -vchiq_arm_init_state(VCHIQ_STATE_T *state, VCHIQ_ARM_STATE_T *arm_state); +vchiq_arm_init_state(struct vchiq_state *state, + struct vchiq_arm_state *arm_state); extern int -vchiq_check_resume(VCHIQ_STATE_T *state); +vchiq_check_resume(struct vchiq_state *state); extern void -vchiq_check_suspend(VCHIQ_STATE_T *state); +vchiq_check_suspend(struct vchiq_state *state); VCHIQ_STATUS_T vchiq_use_service(VCHIQ_SERVICE_HANDLE_T handle); @@ -163,36 +165,37 @@ extern VCHIQ_STATUS_T vchiq_release_service(VCHIQ_SERVICE_HANDLE_T handle); extern VCHIQ_STATUS_T -vchiq_check_service(VCHIQ_SERVICE_T *service); +vchiq_check_service(struct vchiq_service *service); extern VCHIQ_STATUS_T -vchiq_platform_suspend(VCHIQ_STATE_T *state); +vchiq_platform_suspend(struct vchiq_state *state); extern int -vchiq_platform_videocore_wanted(VCHIQ_STATE_T *state); +vchiq_platform_videocore_wanted(struct vchiq_state *state); extern int vchiq_platform_use_suspend_timer(void); extern void -vchiq_dump_platform_use_state(VCHIQ_STATE_T *state); +vchiq_dump_platform_use_state(struct vchiq_state *state); extern void -vchiq_dump_service_use_state(VCHIQ_STATE_T *state); +vchiq_dump_service_use_state(struct vchiq_state *state); -extern VCHIQ_ARM_STATE_T* -vchiq_platform_get_arm_state(VCHIQ_STATE_T *state); +extern struct vchiq_arm_state* +vchiq_platform_get_arm_state(struct vchiq_state *state); extern int -vchiq_videocore_wanted(VCHIQ_STATE_T *state); +vchiq_videocore_wanted(struct vchiq_state *state); extern VCHIQ_STATUS_T -vchiq_use_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, - enum USE_TYPE_E use_type); +vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, + enum USE_TYPE_E use_type); extern VCHIQ_STATUS_T -vchiq_release_internal(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service); +vchiq_release_internal(struct vchiq_state *state, + struct vchiq_service *service); -extern VCHIQ_DEBUGFS_NODE_T * +extern struct vchiq_debugfs_node * vchiq_instance_get_debugfs_node(VCHIQ_INSTANCE_T instance); extern int @@ -208,14 +211,14 @@ extern void vchiq_instance_set_trace(VCHIQ_INSTANCE_T instance, int trace); extern void -set_suspend_state(VCHIQ_ARM_STATE_T *arm_state, - enum vc_suspend_status new_state); +set_suspend_state(struct vchiq_arm_state *arm_state, + enum vc_suspend_status new_state); extern void -set_resume_state(VCHIQ_ARM_STATE_T *arm_state, - enum vc_resume_status new_state); +set_resume_state(struct vchiq_arm_state *arm_state, + enum vc_resume_status new_state); extern void -start_suspend_timer(VCHIQ_ARM_STATE_T *arm_state); +start_suspend_timer(struct vchiq_arm_state *arm_state); #endif /* VCHIQ_ARM_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.c index 7ea29665bd0c..7d64e2ed7b42 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_connected.c @@ -33,7 +33,6 @@ #include "vchiq_connected.h" #include "vchiq_core.h" -#include "vchiq_killable.h" #include <linux/module.h> #include <linux/mutex.h> diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c index 7642ced31436..9e17ec651bde 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -32,7 +32,6 @@ */ #include "vchiq_core.h" -#include "vchiq_killable.h" #define VCHIQ_SLOT_HANDLER_STACK 8192 @@ -73,8 +72,8 @@ enum { }; /* we require this for consistency between endpoints */ -vchiq_static_assert(sizeof(VCHIQ_HEADER_T) == 8); -vchiq_static_assert(IS_POW2(sizeof(VCHIQ_HEADER_T))); +vchiq_static_assert(sizeof(struct vchiq_header) == 8); +vchiq_static_assert(IS_POW2(sizeof(struct vchiq_header))); vchiq_static_assert(IS_POW2(VCHIQ_NUM_CURRENT_BULKS)); vchiq_static_assert(IS_POW2(VCHIQ_NUM_SERVICE_BULKS)); vchiq_static_assert(IS_POW2(VCHIQ_MAX_SERVICES)); @@ -85,13 +84,11 @@ int vchiq_core_log_level = VCHIQ_LOG_DEFAULT; int vchiq_core_msg_log_level = VCHIQ_LOG_DEFAULT; int vchiq_sync_log_level = VCHIQ_LOG_DEFAULT; -static atomic_t pause_bulks_count = ATOMIC_INIT(0); - static DEFINE_SPINLOCK(service_spinlock); DEFINE_SPINLOCK(bulk_waiter_spinlock); static DEFINE_SPINLOCK(quota_spinlock); -VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES]; +struct vchiq_state *vchiq_states[VCHIQ_MAX_STATES]; static unsigned int handle_seq; static const char *const srvstate_names[] = { @@ -130,7 +127,7 @@ static const char *const conn_state_names[] = { }; static void -release_message_sync(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header); +release_message_sync(struct vchiq_state *state, struct vchiq_header *header); static const char *msg_type_str(unsigned int msg_type) { @@ -155,7 +152,7 @@ static const char *msg_type_str(unsigned int msg_type) } static inline void -vchiq_set_service_state(VCHIQ_SERVICE_T *service, int newstate) +vchiq_set_service_state(struct vchiq_service *service, int newstate) { vchiq_log_info(vchiq_core_log_level, "%d: srv:%d %s->%s", service->state->id, service->localport, @@ -164,10 +161,10 @@ vchiq_set_service_state(VCHIQ_SERVICE_T *service, int newstate) service->srvstate = newstate; } -VCHIQ_SERVICE_T * +struct vchiq_service * find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle) { - VCHIQ_SERVICE_T *service; + struct vchiq_service *service; spin_lock(&service_spinlock); service = handle_to_service(handle); @@ -186,10 +183,10 @@ find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle) return service; } -VCHIQ_SERVICE_T * -find_service_by_port(VCHIQ_STATE_T *state, int localport) +struct vchiq_service * +find_service_by_port(struct vchiq_state *state, int localport) { - VCHIQ_SERVICE_T *service = NULL; + struct vchiq_service *service = NULL; if ((unsigned int)localport <= VCHIQ_PORT_MAX) { spin_lock(&service_spinlock); @@ -209,11 +206,11 @@ find_service_by_port(VCHIQ_STATE_T *state, int localport) return service; } -VCHIQ_SERVICE_T * +struct vchiq_service * find_service_for_instance(VCHIQ_INSTANCE_T instance, VCHIQ_SERVICE_HANDLE_T handle) { - VCHIQ_SERVICE_T *service; + struct vchiq_service *service; spin_lock(&service_spinlock); service = handle_to_service(handle); @@ -233,11 +230,11 @@ find_service_for_instance(VCHIQ_INSTANCE_T instance, return service; } -VCHIQ_SERVICE_T * +struct vchiq_service * find_closed_service_for_instance(VCHIQ_INSTANCE_T instance, VCHIQ_SERVICE_HANDLE_T handle) { - VCHIQ_SERVICE_T *service; + struct vchiq_service *service; spin_lock(&service_spinlock); service = handle_to_service(handle); @@ -259,16 +256,16 @@ find_closed_service_for_instance(VCHIQ_INSTANCE_T instance, return service; } -VCHIQ_SERVICE_T * -next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance, - int *pidx) +struct vchiq_service * +next_service_by_instance(struct vchiq_state *state, VCHIQ_INSTANCE_T instance, + int *pidx) { - VCHIQ_SERVICE_T *service = NULL; + struct vchiq_service *service = NULL; int idx = *pidx; spin_lock(&service_spinlock); while (idx < state->unused_service) { - VCHIQ_SERVICE_T *srv = state->services[idx++]; + struct vchiq_service *srv = state->services[idx++]; if (srv && (srv->srvstate != VCHIQ_SRVSTATE_FREE) && (srv->instance == instance)) { @@ -286,7 +283,7 @@ next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance, } void -lock_service(VCHIQ_SERVICE_T *service) +lock_service(struct vchiq_service *service) { spin_lock(&service_spinlock); WARN_ON(!service); @@ -298,7 +295,7 @@ lock_service(VCHIQ_SERVICE_T *service) } void -unlock_service(VCHIQ_SERVICE_T *service) +unlock_service(struct vchiq_service *service) { spin_lock(&service_spinlock); if (!service) { @@ -311,7 +308,7 @@ unlock_service(VCHIQ_SERVICE_T *service) } service->ref_count--; if (!service->ref_count) { - VCHIQ_STATE_T *state = service->state; + struct vchiq_state *state = service->state; WARN_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); state->services[service->localport] = NULL; @@ -330,7 +327,7 @@ unlock: int vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T handle) { - VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + struct vchiq_service *service = find_service_by_handle(handle); int id; id = service ? service->client_id : 0; @@ -343,7 +340,7 @@ vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T handle) void * vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T handle) { - VCHIQ_SERVICE_T *service = handle_to_service(handle); + struct vchiq_service *service = handle_to_service(handle); return service ? service->base.userdata : NULL; } @@ -351,16 +348,16 @@ vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T handle) int vchiq_get_service_fourcc(VCHIQ_SERVICE_HANDLE_T handle) { - VCHIQ_SERVICE_T *service = handle_to_service(handle); + struct vchiq_service *service = handle_to_service(handle); return service ? service->base.fourcc : 0; } static void -mark_service_closing_internal(VCHIQ_SERVICE_T *service, int sh_thread) +mark_service_closing_internal(struct vchiq_service *service, int sh_thread) { - VCHIQ_STATE_T *state = service->state; - VCHIQ_SERVICE_QUOTA_T *service_quota; + struct vchiq_state *state = service->state; + struct vchiq_service_quota *service_quota; service->closing = 1; @@ -378,18 +375,18 @@ mark_service_closing_internal(VCHIQ_SERVICE_T *service, int sh_thread) /* Unblock any sending thread. */ service_quota = &state->service_quotas[service->localport]; - up(&service_quota->quota_event); + complete(&service_quota->quota_event); } static void -mark_service_closing(VCHIQ_SERVICE_T *service) +mark_service_closing(struct vchiq_service *service) { mark_service_closing_internal(service, 0); } static inline VCHIQ_STATUS_T -make_service_callback(VCHIQ_SERVICE_T *service, VCHIQ_REASON_T reason, - VCHIQ_HEADER_T *header, void *bulk_userdata) +make_service_callback(struct vchiq_service *service, VCHIQ_REASON_T reason, + struct vchiq_header *header, void *bulk_userdata) { VCHIQ_STATUS_T status; @@ -408,7 +405,7 @@ make_service_callback(VCHIQ_SERVICE_T *service, VCHIQ_REASON_T reason, } inline void -vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate) +vchiq_set_conn_state(struct vchiq_state *state, VCHIQ_CONNSTATE_T newstate) { VCHIQ_CONNSTATE_T oldstate = state->conn_state; @@ -420,27 +417,23 @@ vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate) } static inline void -remote_event_create(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event) +remote_event_create(wait_queue_head_t *wq, struct remote_event *event) { event->armed = 0; /* Don't clear the 'fired' flag because it may already have been set ** by the other side. */ - sema_init((struct semaphore *)((char *)state + event->event), 0); + init_waitqueue_head(wq); } static inline int -remote_event_wait(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event) +remote_event_wait(wait_queue_head_t *wq, struct remote_event *event) { if (!event->fired) { event->armed = 1; dsb(sy); - if (!event->fired) { - if (down_interruptible( - (struct semaphore *) - ((char *)state + event->event)) != 0) { - event->armed = 0; - return 0; - } + if (wait_event_killable(*wq, event->fired)) { + event->armed = 0; + return 0; } event->armed = 0; wmb(); @@ -451,26 +444,26 @@ remote_event_wait(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event) } static inline void -remote_event_signal_local(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event) +remote_event_signal_local(wait_queue_head_t *wq, struct remote_event *event) { event->armed = 0; - up((struct semaphore *)((char *)state + event->event)); + wake_up_all(wq); } static inline void -remote_event_poll(VCHIQ_STATE_T *state, REMOTE_EVENT_T *event) +remote_event_poll(wait_queue_head_t *wq, struct remote_event *event) { if (event->fired && event->armed) - remote_event_signal_local(state, event); + remote_event_signal_local(wq, event); } void -remote_event_pollall(VCHIQ_STATE_T *state) +remote_event_pollall(struct vchiq_state *state) { - remote_event_poll(state, &state->local->sync_trigger); - remote_event_poll(state, &state->local->sync_release); - remote_event_poll(state, &state->local->trigger); - remote_event_poll(state, &state->local->recycle); + remote_event_poll(&state->sync_trigger_event, &state->local->sync_trigger); + remote_event_poll(&state->sync_release_event, &state->local->sync_release); + remote_event_poll(&state->trigger_event, &state->local->trigger); + remote_event_poll(&state->recycle_event, &state->local->recycle); } /* Round up message sizes so that any space at the end of a slot is always big @@ -481,23 +474,23 @@ static inline size_t calc_stride(size_t size) { /* Allow room for the header */ - size += sizeof(VCHIQ_HEADER_T); + size += sizeof(struct vchiq_header); /* Round up */ - return (size + sizeof(VCHIQ_HEADER_T) - 1) & ~(sizeof(VCHIQ_HEADER_T) - - 1); + return (size + sizeof(struct vchiq_header) - 1) & + ~(sizeof(struct vchiq_header) - 1); } /* Called by the slot handler thread */ -static VCHIQ_SERVICE_T * -get_listening_service(VCHIQ_STATE_T *state, int fourcc) +static struct vchiq_service * +get_listening_service(struct vchiq_state *state, int fourcc) { int i; WARN_ON(fourcc == VCHIQ_FOURCC_INVALID); for (i = 0; i < state->unused_service; i++) { - VCHIQ_SERVICE_T *service = state->services[i]; + struct vchiq_service *service = state->services[i]; if (service && (service->public_fourcc == fourcc) && @@ -513,13 +506,13 @@ get_listening_service(VCHIQ_STATE_T *state, int fourcc) } /* Called by the slot handler thread */ -static VCHIQ_SERVICE_T * -get_connected_service(VCHIQ_STATE_T *state, unsigned int port) +static struct vchiq_service * +get_connected_service(struct vchiq_state *state, unsigned int port) { int i; for (i = 0; i < state->unused_service; i++) { - VCHIQ_SERVICE_T *service = state->services[i]; + struct vchiq_service *service = state->services[i]; if (service && (service->srvstate == VCHIQ_SRVSTATE_OPEN) && (service->remoteport == port)) { @@ -531,7 +524,8 @@ get_connected_service(VCHIQ_STATE_T *state, unsigned int port) } inline void -request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type) +request_poll(struct vchiq_state *state, struct vchiq_service *service, + int poll_type) { u32 value; @@ -554,26 +548,26 @@ request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type) wmb(); /* ... and ensure the slot handler runs. */ - remote_event_signal_local(state, &state->local->trigger); + remote_event_signal_local(&state->trigger_event, &state->local->trigger); } /* Called from queue_message, by the slot handler and application threads, ** with slot_mutex held */ -static VCHIQ_HEADER_T * -reserve_space(VCHIQ_STATE_T *state, size_t space, int is_blocking) +static struct vchiq_header * +reserve_space(struct vchiq_state *state, size_t space, int is_blocking) { - VCHIQ_SHARED_STATE_T *local = state->local; + struct vchiq_shared_state *local = state->local; int tx_pos = state->local_tx_pos; int slot_space = VCHIQ_SLOT_SIZE - (tx_pos & VCHIQ_SLOT_MASK); if (space > slot_space) { - VCHIQ_HEADER_T *header; + struct vchiq_header *header; /* Fill the remaining space with padding */ WARN_ON(state->tx_data == NULL); - header = (VCHIQ_HEADER_T *) + header = (struct vchiq_header *) (state->tx_data + (tx_pos & VCHIQ_SLOT_MASK)); header->msgid = VCHIQ_MSGID_PADDING; - header->size = slot_space - sizeof(VCHIQ_HEADER_T); + header->size = slot_space - sizeof(struct vchiq_header); tx_pos += slot_space; } @@ -584,7 +578,7 @@ reserve_space(VCHIQ_STATE_T *state, size_t space, int is_blocking) /* If there is no free slot... */ - if (down_trylock(&state->slot_available_event) != 0) { + if (!try_wait_for_completion(&state->slot_available_event)) { /* ...wait for one. */ VCHIQ_STATS_INC(state, slot_stalls); @@ -595,13 +589,13 @@ reserve_space(VCHIQ_STATE_T *state, size_t space, int is_blocking) remote_event_signal(&state->remote->trigger); if (!is_blocking || - (down_interruptible( - &state->slot_available_event) != 0)) + (wait_for_completion_killable( + &state->slot_available_event))) return NULL; /* No space available */ } if (tx_pos == (state->slot_queue_available * VCHIQ_SLOT_SIZE)) { - up(&state->slot_available_event); + complete(&state->slot_available_event); pr_warn("%s: invalid tx_pos: %d\n", __func__, tx_pos); return NULL; } @@ -615,14 +609,16 @@ reserve_space(VCHIQ_STATE_T *state, size_t space, int is_blocking) state->local_tx_pos = tx_pos + space; - return (VCHIQ_HEADER_T *)(state->tx_data + (tx_pos & VCHIQ_SLOT_MASK)); + return (struct vchiq_header *)(state->tx_data + + (tx_pos & VCHIQ_SLOT_MASK)); } /* Called by the recycle thread. */ static void -process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length) +process_free_queue(struct vchiq_state *state, BITSET_T *service_found, + size_t length) { - VCHIQ_SHARED_STATE_T *local = state->local; + struct vchiq_shared_state *local = state->local; int slot_queue_available; /* Find slots which have been freed by the other side, and return them @@ -660,13 +656,13 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length) pos = 0; while (pos < VCHIQ_SLOT_SIZE) { - VCHIQ_HEADER_T *header = - (VCHIQ_HEADER_T *)(data + pos); + struct vchiq_header *header = + (struct vchiq_header *)(data + pos); int msgid = header->msgid; if (VCHIQ_MSG_TYPE(msgid) == VCHIQ_MSG_DATA) { int port = VCHIQ_MSG_SRCPORT(msgid); - VCHIQ_SERVICE_QUOTA_T *service_quota = + struct vchiq_service_quota *service_quota = &state->service_quotas[port]; int count; @@ -681,7 +677,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length) /* Signal the service that it ** has dropped below its quota */ - up(&service_quota->quota_event); + complete(&service_quota->quota_event); else if (count == 0) { vchiq_log_error(vchiq_core_log_level, "service %d message_use_count=%d (header %pK, msgid %x, header->msgid %x, header->size %x)", @@ -706,7 +702,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length) /* Signal the service in case ** it has dropped below its ** quota */ - up(&service_quota->quota_event); + complete(&service_quota->quota_event); vchiq_log_trace( vchiq_core_log_level, "%d: pfq:%d %x@%pK - slot_use->%d", @@ -747,7 +743,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length) count - 1; spin_unlock("a_spinlock); if (count == state->data_quota) - up(&state->data_quota_event); + complete(&state->data_quota_event); } /* @@ -757,7 +753,7 @@ process_free_queue(VCHIQ_STATE_T *state, BITSET_T *service_found, size_t length) mb(); state->slot_queue_available = slot_queue_available; - up(&state->slot_available_event); + complete(&state->slot_available_event); } } @@ -805,17 +801,15 @@ copy_message_data( /* Called by the slot handler and application threads */ static VCHIQ_STATUS_T -queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, - int msgid, - ssize_t (*copy_callback)(void *context, void *dest, - size_t offset, size_t maxsize), - void *context, - size_t size, - int flags) -{ - VCHIQ_SHARED_STATE_T *local; - VCHIQ_SERVICE_QUOTA_T *service_quota = NULL; - VCHIQ_HEADER_T *header; +queue_message(struct vchiq_state *state, struct vchiq_service *service, + int msgid, + ssize_t (*copy_callback)(void *context, void *dest, + size_t offset, size_t maxsize), + void *context, size_t size, int flags) +{ + struct vchiq_shared_state *local; + struct vchiq_service_quota *service_quota = NULL; + struct vchiq_header *header; int type = VCHIQ_MSG_TYPE(msgid); size_t stride; @@ -865,8 +859,8 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, spin_unlock("a_spinlock); mutex_unlock(&state->slot_mutex); - if (down_interruptible(&state->data_quota_event) - != 0) + if (wait_for_completion_killable( + &state->data_quota_event)) return VCHIQ_RETRY; mutex_lock(&state->slot_mutex); @@ -876,7 +870,7 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, if ((tx_end_index == state->previous_data_index) || (state->data_use_count < state->data_quota)) { /* Pass the signal on to other waiters */ - up(&state->data_quota_event); + complete(&state->data_quota_event); break; } } @@ -896,8 +890,8 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, service_quota->slot_use_count); VCHIQ_SERVICE_STATS_INC(service, quota_stalls); mutex_unlock(&state->slot_mutex); - if (down_interruptible(&service_quota->quota_event) - != 0) + if (wait_for_completion_killable( + &service_quota->quota_event)) return VCHIQ_RETRY; if (service->closing) return VCHIQ_ERROR; @@ -1055,16 +1049,14 @@ queue_message(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, /* Called by the slot handler and application threads */ static VCHIQ_STATUS_T -queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, - int msgid, - ssize_t (*copy_callback)(void *context, void *dest, - size_t offset, size_t maxsize), - void *context, - int size, - int is_blocking) -{ - VCHIQ_SHARED_STATE_T *local; - VCHIQ_HEADER_T *header; +queue_message_sync(struct vchiq_state *state, struct vchiq_service *service, + int msgid, + ssize_t (*copy_callback)(void *context, void *dest, + size_t offset, size_t maxsize), + void *context, int size, int is_blocking) +{ + struct vchiq_shared_state *local; + struct vchiq_header *header; ssize_t callback_result; local = state->local; @@ -1073,11 +1065,11 @@ queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, (mutex_lock_killable(&state->sync_mutex) != 0)) return VCHIQ_RETRY; - remote_event_wait(state, &local->sync_release); + remote_event_wait(&state->sync_release_event, &local->sync_release); rmb(); - header = (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, + header = (struct vchiq_header *)SLOT_DATA_FROM_INDEX(state, local->slot_sync); { @@ -1140,9 +1132,6 @@ queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, size); } - /* Make sure the new header is visible to the peer. */ - wmb(); - remote_event_signal(&state->remote->sync_trigger); if (VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_PAUSE) @@ -1152,14 +1141,14 @@ queue_message_sync(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, } static inline void -claim_slot(VCHIQ_SLOT_INFO_T *slot) +claim_slot(struct vchiq_slot_info *slot) { slot->use_count++; } static void -release_slot(VCHIQ_STATE_T *state, VCHIQ_SLOT_INFO_T *slot_info, - VCHIQ_HEADER_T *header, VCHIQ_SERVICE_T *service) +release_slot(struct vchiq_state *state, struct vchiq_slot_info *slot_info, + struct vchiq_header *header, struct vchiq_service *service) { int release_count; @@ -1211,8 +1200,8 @@ release_slot(VCHIQ_STATE_T *state, VCHIQ_SLOT_INFO_T *slot_info, /* Called by the slot handler - don't hold the bulk mutex */ static VCHIQ_STATUS_T -notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue, - int retry_poll) +notify_bulks(struct vchiq_service *service, struct vchiq_bulk_queue *queue, + int retry_poll) { VCHIQ_STATUS_T status = VCHIQ_SUCCESS; @@ -1222,36 +1211,11 @@ notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue, (queue == &service->bulk_tx) ? 't' : 'r', queue->process, queue->remote_notify, queue->remove); - if (service->state->is_master) { - while (queue->remote_notify != queue->process) { - VCHIQ_BULK_T *bulk = - &queue->bulks[BULK_INDEX(queue->remote_notify)]; - int msgtype = (bulk->dir == VCHIQ_BULK_TRANSMIT) ? - VCHIQ_MSG_BULK_RX_DONE : VCHIQ_MSG_BULK_TX_DONE; - int msgid = VCHIQ_MAKE_MSG(msgtype, service->localport, - service->remoteport); - /* Only reply to non-dummy bulk requests */ - if (bulk->remote_data) { - status = queue_message( - service->state, - NULL, - msgid, - memcpy_copy_callback, - &bulk->actual, - 4, - 0); - if (status != VCHIQ_SUCCESS) - break; - } - queue->remote_notify++; - } - } else { - queue->remote_notify = queue->process; - } + queue->remote_notify = queue->process; if (status == VCHIQ_SUCCESS) { while (queue->remove != queue->remote_notify) { - VCHIQ_BULK_T *bulk = + struct vchiq_bulk *bulk = &queue->bulks[BULK_INDEX(queue->remove)]; /* Only generate callbacks for non-dummy bulk @@ -1282,7 +1246,7 @@ notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue, waiter = bulk->userdata; if (waiter) { waiter->actual = bulk->actual; - up(&waiter->event); + complete(&waiter->event); } spin_unlock(&bulk_waiter_spinlock); } else if (bulk->mode == @@ -1305,7 +1269,7 @@ notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue, } queue->remove++; - up(&service->bulk_remove_event); + complete(&service->bulk_remove_event); } if (!retry_poll) status = VCHIQ_SUCCESS; @@ -1321,7 +1285,7 @@ notify_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue, /* Called by the slot handler thread */ static void -poll_services(VCHIQ_STATE_T *state) +poll_services(struct vchiq_state *state) { int group, i; @@ -1331,7 +1295,7 @@ poll_services(VCHIQ_STATE_T *state) flags = atomic_xchg(&state->poll_services[group], 0); for (i = 0; flags; i++) { if (flags & (1 << i)) { - VCHIQ_SERVICE_T *service = + struct vchiq_service *service = find_service_by_port(state, (group<<5) + i); u32 service_flags; @@ -1385,66 +1349,10 @@ poll_services(VCHIQ_STATE_T *state) } } -/* Called by the slot handler or application threads, holding the bulk mutex. */ -static int -resolve_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue) -{ - VCHIQ_STATE_T *state = service->state; - int resolved = 0; - - while ((queue->process != queue->local_insert) && - (queue->process != queue->remote_insert)) { - VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->process)]; - - vchiq_log_trace(vchiq_core_log_level, - "%d: rb:%d %cx - li=%x ri=%x p=%x", - state->id, service->localport, - (queue == &service->bulk_tx) ? 't' : 'r', - queue->local_insert, queue->remote_insert, - queue->process); - - WARN_ON(!((int)(queue->local_insert - queue->process) > 0)); - WARN_ON(!((int)(queue->remote_insert - queue->process) > 0)); - - if (mutex_lock_killable(&state->bulk_transfer_mutex)) - break; - - vchiq_transfer_bulk(bulk); - mutex_unlock(&state->bulk_transfer_mutex); - - if (SRVTRACE_ENABLED(service, VCHIQ_LOG_INFO)) { - const char *header = (queue == &service->bulk_tx) ? - "Send Bulk to" : "Recv Bulk from"; - if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) - vchiq_log_info(SRVTRACE_LEVEL(service), - "%s %c%c%c%c d:%d len:%d %pK<->%pK", - header, - VCHIQ_FOURCC_AS_4CHARS( - service->base.fourcc), - service->remoteport, bulk->size, - bulk->data, bulk->remote_data); - else - vchiq_log_info(SRVTRACE_LEVEL(service), - "%s %c%c%c%c d:%d ABORTED - tx len:%d," - " rx len:%d %pK<->%pK", - header, - VCHIQ_FOURCC_AS_4CHARS( - service->base.fourcc), - service->remoteport, - bulk->size, bulk->remote_size, - bulk->data, bulk->remote_data); - } - - vchiq_complete_bulk(bulk); - queue->process++; - resolved++; - } - return resolved; -} - /* Called with the bulk_mutex held */ static void -abort_outstanding_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue) +abort_outstanding_bulks(struct vchiq_service *service, + struct vchiq_bulk_queue *queue) { int is_tx = (queue == &service->bulk_tx); @@ -1458,7 +1366,8 @@ abort_outstanding_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue) while ((queue->process != queue->local_insert) || (queue->process != queue->remote_insert)) { - VCHIQ_BULK_T *bulk = &queue->bulks[BULK_INDEX(queue->process)]; + struct vchiq_bulk *bulk = + &queue->bulks[BULK_INDEX(queue->process)]; if (queue->process == queue->remote_insert) { /* fabricate a matching dummy bulk */ @@ -1492,69 +1401,10 @@ abort_outstanding_bulks(VCHIQ_SERVICE_T *service, VCHIQ_BULK_QUEUE_T *queue) } } -/* Called from the slot handler thread */ -static void -pause_bulks(VCHIQ_STATE_T *state) -{ - if (unlikely(atomic_inc_return(&pause_bulks_count) != 1)) { - WARN_ON_ONCE(1); - atomic_set(&pause_bulks_count, 1); - return; - } - - /* Block bulk transfers from all services */ - mutex_lock(&state->bulk_transfer_mutex); -} - -/* Called from the slot handler thread */ -static void -resume_bulks(VCHIQ_STATE_T *state) -{ - int i; - - if (unlikely(atomic_dec_return(&pause_bulks_count) != 0)) { - WARN_ON_ONCE(1); - atomic_set(&pause_bulks_count, 0); - return; - } - - /* Allow bulk transfers from all services */ - mutex_unlock(&state->bulk_transfer_mutex); - - if (state->deferred_bulks == 0) - return; - - /* Deal with any bulks which had to be deferred due to being in - * paused state. Don't try to match up to number of deferred bulks - * in case we've had something come and close the service in the - * interim - just process all bulk queues for all services */ - vchiq_log_info(vchiq_core_log_level, "%s: processing %d deferred bulks", - __func__, state->deferred_bulks); - - for (i = 0; i < state->unused_service; i++) { - VCHIQ_SERVICE_T *service = state->services[i]; - int resolved_rx = 0; - int resolved_tx = 0; - - if (!service || (service->srvstate != VCHIQ_SRVSTATE_OPEN)) - continue; - - mutex_lock(&service->bulk_mutex); - resolved_rx = resolve_bulks(service, &service->bulk_rx); - resolved_tx = resolve_bulks(service, &service->bulk_tx); - mutex_unlock(&service->bulk_mutex); - if (resolved_rx) - notify_bulks(service, &service->bulk_rx, 1); - if (resolved_tx) - notify_bulks(service, &service->bulk_tx, 1); - } - state->deferred_bulks = 0; -} - static int -parse_open(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header) +parse_open(struct vchiq_state *state, struct vchiq_header *header) { - VCHIQ_SERVICE_T *service = NULL; + struct vchiq_service *service = NULL; int msgid, size; unsigned int localport, remoteport; @@ -1608,9 +1458,7 @@ parse_open(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header) service->sync = 0; /* Acknowledge the OPEN */ - if (service->sync && - (state->version_common >= - VCHIQ_VERSION_SYNCHRONOUS_MODE)) { + if (service->sync) { if (queue_message_sync( state, NULL, @@ -1676,10 +1524,10 @@ bail_not_ready: /* Called by the slot handler thread */ static void -parse_rx_slots(VCHIQ_STATE_T *state) +parse_rx_slots(struct vchiq_state *state) { - VCHIQ_SHARED_STATE_T *remote = state->remote; - VCHIQ_SERVICE_T *service = NULL; + struct vchiq_shared_state *remote = state->remote; + struct vchiq_service *service = NULL; int tx_pos; DEBUG_INITIALISE(state->local) @@ -1687,7 +1535,7 @@ parse_rx_slots(VCHIQ_STATE_T *state) tx_pos = remote->tx_pos; while (state->rx_pos != tx_pos) { - VCHIQ_HEADER_T *header; + struct vchiq_header *header; int msgid, size; int type; unsigned int localport, remoteport; @@ -1711,7 +1559,7 @@ parse_rx_slots(VCHIQ_STATE_T *state) state->rx_info->release_count = 0; } - header = (VCHIQ_HEADER_T *)(state->rx_data + + header = (struct vchiq_header *)(state->rx_data + (state->rx_pos & VCHIQ_SLOT_MASK)); DEBUG_VALUE(PARSE_HEADER, (int)(long)header); msgid = header->msgid; @@ -1814,7 +1662,7 @@ parse_rx_slots(VCHIQ_STATE_T *state) service->remoteport = remoteport; vchiq_set_service_state(service, VCHIQ_SRVSTATE_OPEN); - up(&service->remove_event); + complete(&service->remove_event); } else vchiq_log_error(vchiq_core_log_level, "OPENACK received in state %s", @@ -1866,90 +1714,32 @@ parse_rx_slots(VCHIQ_STATE_T *state) case VCHIQ_MSG_CONNECT: vchiq_log_info(vchiq_core_log_level, "%d: prs CONNECT@%pK", state->id, header); - state->version_common = ((VCHIQ_SLOT_ZERO_T *) + state->version_common = ((struct vchiq_slot_zero *) state->slot_data)->version; - up(&state->connect); + complete(&state->connect); break; case VCHIQ_MSG_BULK_RX: - case VCHIQ_MSG_BULK_TX: { - VCHIQ_BULK_QUEUE_T *queue; - - WARN_ON(!state->is_master); - queue = (type == VCHIQ_MSG_BULK_RX) ? - &service->bulk_tx : &service->bulk_rx; - if ((service->remoteport == remoteport) - && (service->srvstate == - VCHIQ_SRVSTATE_OPEN)) { - VCHIQ_BULK_T *bulk; - int resolved = 0; - - DEBUG_TRACE(PARSE_LINE); - if (mutex_lock_killable( - &service->bulk_mutex) != 0) { - DEBUG_TRACE(PARSE_LINE); - goto bail_not_ready; - } - - WARN_ON(!(queue->remote_insert < queue->remove + - VCHIQ_NUM_SERVICE_BULKS)); - bulk = &queue->bulks[ - BULK_INDEX(queue->remote_insert)]; - bulk->remote_data = - (void *)(long)((int *)header->data)[0]; - bulk->remote_size = ((int *)header->data)[1]; - wmb(); - - vchiq_log_info(vchiq_core_log_level, - "%d: prs %s@%pK (%d->%d) %x@%pK", - state->id, msg_type_str(type), - header, remoteport, localport, - bulk->remote_size, bulk->remote_data); - - queue->remote_insert++; - - if (atomic_read(&pause_bulks_count)) { - state->deferred_bulks++; - vchiq_log_info(vchiq_core_log_level, - "%s: deferring bulk (%d)", - __func__, - state->deferred_bulks); - if (state->conn_state != - VCHIQ_CONNSTATE_PAUSE_SENT) - vchiq_log_error( - vchiq_core_log_level, - "%s: bulks paused in " - "unexpected state %s", - __func__, - conn_state_names[ - state->conn_state]); - } else if (state->conn_state == - VCHIQ_CONNSTATE_CONNECTED) { - DEBUG_TRACE(PARSE_LINE); - resolved = resolve_bulks(service, - queue); - } - - mutex_unlock(&service->bulk_mutex); - if (resolved) - notify_bulks(service, queue, - 1/*retry_poll*/); - } - } break; + case VCHIQ_MSG_BULK_TX: + /* + * We should never receive a bulk request from the + * other side since we're not setup to perform as the + * master. + */ + WARN_ON(1); + break; case VCHIQ_MSG_BULK_RX_DONE: case VCHIQ_MSG_BULK_TX_DONE: - WARN_ON(state->is_master); if ((service->remoteport == remoteport) && (service->srvstate != VCHIQ_SRVSTATE_FREE)) { - VCHIQ_BULK_QUEUE_T *queue; - VCHIQ_BULK_T *bulk; + struct vchiq_bulk_queue *queue; + struct vchiq_bulk *bulk; queue = (type == VCHIQ_MSG_BULK_RX_DONE) ? &service->bulk_rx : &service->bulk_tx; DEBUG_TRACE(PARSE_LINE); - if (mutex_lock_killable( - &service->bulk_mutex) != 0) { + if (mutex_lock_killable(&service->bulk_mutex)) { DEBUG_TRACE(PARSE_LINE); goto bail_not_ready; } @@ -2026,8 +1816,6 @@ parse_rx_slots(VCHIQ_STATE_T *state) NULL, NULL, 0, QMFLAGS_NO_MUTEX_UNLOCK) == VCHIQ_RETRY) goto bail_not_ready; - if (state->is_master) - pause_bulks(state); } /* At this point slot_mutex is held */ vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSED); @@ -2039,8 +1827,6 @@ parse_rx_slots(VCHIQ_STATE_T *state) state->id, header, size); /* Release the slot mutex */ mutex_unlock(&state->slot_mutex); - if (state->is_master) - resume_bulks(state); vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); vchiq_platform_resumed(state); break; @@ -2090,15 +1876,15 @@ bail_not_ready: static int slot_handler_func(void *v) { - VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; - VCHIQ_SHARED_STATE_T *local = state->local; + struct vchiq_state *state = (struct vchiq_state *)v; + struct vchiq_shared_state *local = state->local; DEBUG_INITIALISE(local) while (1) { DEBUG_COUNT(SLOT_HANDLER_COUNT); DEBUG_TRACE(SLOT_HANDLER_LINE); - remote_event_wait(state, &local->trigger); + remote_event_wait(&state->trigger_event, &local->trigger); rmb(); @@ -2119,8 +1905,6 @@ slot_handler_func(void *v) break; case VCHIQ_CONNSTATE_PAUSING: - if (state->is_master) - pause_bulks(state); if (queue_message(state, NULL, VCHIQ_MAKE_MSG(VCHIQ_MSG_PAUSE, 0, 0), NULL, NULL, 0, @@ -2129,8 +1913,6 @@ slot_handler_func(void *v) vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSE_SENT); } else { - if (state->is_master) - resume_bulks(state); /* Retry later */ state->poll_needed = 1; } @@ -2145,8 +1927,6 @@ slot_handler_func(void *v) VCHIQ_MAKE_MSG(VCHIQ_MSG_RESUME, 0, 0), NULL, NULL, 0, QMFLAGS_NO_MUTEX_LOCK) != VCHIQ_RETRY) { - if (state->is_master) - resume_bulks(state); vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); vchiq_platform_resumed(state); @@ -2180,8 +1960,8 @@ slot_handler_func(void *v) static int recycle_func(void *v) { - VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; - VCHIQ_SHARED_STATE_T *local = state->local; + struct vchiq_state *state = (struct vchiq_state *)v; + struct vchiq_shared_state *local = state->local; BITSET_T *found; size_t length; @@ -2193,7 +1973,7 @@ recycle_func(void *v) return -ENOMEM; while (1) { - remote_event_wait(state, &local->recycle); + remote_event_wait(&state->recycle_event, &local->recycle); process_free_queue(state, found, length); } @@ -2204,18 +1984,19 @@ recycle_func(void *v) static int sync_func(void *v) { - VCHIQ_STATE_T *state = (VCHIQ_STATE_T *) v; - VCHIQ_SHARED_STATE_T *local = state->local; - VCHIQ_HEADER_T *header = (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, - state->remote->slot_sync); + struct vchiq_state *state = (struct vchiq_state *)v; + struct vchiq_shared_state *local = state->local; + struct vchiq_header *header = + (struct vchiq_header *)SLOT_DATA_FROM_INDEX(state, + state->remote->slot_sync); while (1) { - VCHIQ_SERVICE_T *service; + struct vchiq_service *service; int msgid, size; int type; unsigned int localport, remoteport; - remote_event_wait(state, &local->sync_trigger); + remote_event_wait(&state->sync_trigger_event, &local->sync_trigger); rmb(); @@ -2269,7 +2050,7 @@ sync_func(void *v) vchiq_set_service_state(service, VCHIQ_SRVSTATE_OPENSYNC); service->sync = 1; - up(&service->remove_event); + complete(&service->remove_event); } release_message_sync(state, header); break; @@ -2308,7 +2089,7 @@ sync_func(void *v) } static void -init_bulk_queue(VCHIQ_BULK_QUEUE_T *queue) +init_bulk_queue(struct vchiq_bulk_queue *queue) { queue->local_insert = 0; queue->remote_insert = 0; @@ -2323,13 +2104,13 @@ get_conn_state_name(VCHIQ_CONNSTATE_T conn_state) return conn_state_names[conn_state]; } -VCHIQ_SLOT_ZERO_T * +struct vchiq_slot_zero * vchiq_init_slots(void *mem_base, int mem_size) { int mem_align = (int)((VCHIQ_SLOT_SIZE - (long)mem_base) & VCHIQ_SLOT_MASK); - VCHIQ_SLOT_ZERO_T *slot_zero = - (VCHIQ_SLOT_ZERO_T *)((char *)mem_base + mem_align); + struct vchiq_slot_zero *slot_zero = + (struct vchiq_slot_zero *)((char *)mem_base + mem_align); int num_slots = (mem_size - mem_align)/VCHIQ_SLOT_SIZE; int first_data_slot = VCHIQ_SLOT_ZERO_SLOTS; @@ -2343,12 +2124,12 @@ vchiq_init_slots(void *mem_base, int mem_size) return NULL; } - memset(slot_zero, 0, sizeof(VCHIQ_SLOT_ZERO_T)); + memset(slot_zero, 0, sizeof(struct vchiq_slot_zero)); slot_zero->magic = VCHIQ_MAGIC; slot_zero->version = VCHIQ_VERSION; slot_zero->version_min = VCHIQ_VERSION_MIN; - slot_zero->slot_zero_size = sizeof(VCHIQ_SLOT_ZERO_T); + slot_zero->slot_zero_size = sizeof(struct vchiq_slot_zero); slot_zero->slot_size = VCHIQ_SLOT_SIZE; slot_zero->max_slots = VCHIQ_MAX_SLOTS; slot_zero->max_slots_per_side = VCHIQ_MAX_SLOTS_PER_SIDE; @@ -2364,90 +2145,24 @@ vchiq_init_slots(void *mem_base, int mem_size) } VCHIQ_STATUS_T -vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, - int is_master) +vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero) { - VCHIQ_SHARED_STATE_T *local; - VCHIQ_SHARED_STATE_T *remote; + struct vchiq_shared_state *local; + struct vchiq_shared_state *remote; VCHIQ_STATUS_T status; char threadname[16]; int i; vchiq_log_warning(vchiq_core_log_level, - "%s: slot_zero = %pK, is_master = %d", - __func__, slot_zero, is_master); + "%s: slot_zero = %pK", __func__, slot_zero); if (vchiq_states[0]) { pr_err("%s: VCHIQ state already initialized\n", __func__); return VCHIQ_ERROR; } - /* Check the input configuration */ - - if (slot_zero->magic != VCHIQ_MAGIC) { - vchiq_loud_error_header(); - vchiq_loud_error("Invalid VCHIQ magic value found."); - vchiq_loud_error("slot_zero=%pK: magic=%x (expected %x)", - slot_zero, slot_zero->magic, VCHIQ_MAGIC); - vchiq_loud_error_footer(); - return VCHIQ_ERROR; - } - - if (slot_zero->version < VCHIQ_VERSION_MIN) { - vchiq_loud_error_header(); - vchiq_loud_error("Incompatible VCHIQ versions found."); - vchiq_loud_error("slot_zero=%pK: VideoCore version=%d (minimum %d)", - slot_zero, slot_zero->version, VCHIQ_VERSION_MIN); - vchiq_loud_error("Restart with a newer VideoCore image."); - vchiq_loud_error_footer(); - return VCHIQ_ERROR; - } - - if (VCHIQ_VERSION < slot_zero->version_min) { - vchiq_loud_error_header(); - vchiq_loud_error("Incompatible VCHIQ versions found."); - vchiq_loud_error("slot_zero=%pK: version=%d (VideoCore minimum %d)", - slot_zero, VCHIQ_VERSION, slot_zero->version_min); - vchiq_loud_error("Restart with a newer kernel."); - vchiq_loud_error_footer(); - return VCHIQ_ERROR; - } - - if ((slot_zero->slot_zero_size != sizeof(VCHIQ_SLOT_ZERO_T)) || - (slot_zero->slot_size != VCHIQ_SLOT_SIZE) || - (slot_zero->max_slots != VCHIQ_MAX_SLOTS) || - (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE)) { - vchiq_loud_error_header(); - if (slot_zero->slot_zero_size != sizeof(VCHIQ_SLOT_ZERO_T)) - vchiq_loud_error("slot_zero=%pK: slot_zero_size=%d (expected %d)", - slot_zero, slot_zero->slot_zero_size, - (int)sizeof(VCHIQ_SLOT_ZERO_T)); - if (slot_zero->slot_size != VCHIQ_SLOT_SIZE) - vchiq_loud_error("slot_zero=%pK: slot_size=%d (expected %d)", - slot_zero, slot_zero->slot_size, - VCHIQ_SLOT_SIZE); - if (slot_zero->max_slots != VCHIQ_MAX_SLOTS) - vchiq_loud_error("slot_zero=%pK: max_slots=%d (expected %d)", - slot_zero, slot_zero->max_slots, - VCHIQ_MAX_SLOTS); - if (slot_zero->max_slots_per_side != VCHIQ_MAX_SLOTS_PER_SIDE) - vchiq_loud_error("slot_zero=%pK: max_slots_per_side=%d (expected %d)", - slot_zero, slot_zero->max_slots_per_side, - VCHIQ_MAX_SLOTS_PER_SIDE); - vchiq_loud_error_footer(); - return VCHIQ_ERROR; - } - - if (VCHIQ_VERSION < slot_zero->version) - slot_zero->version = VCHIQ_VERSION; - - if (is_master) { - local = &slot_zero->master; - remote = &slot_zero->slave; - } else { - local = &slot_zero->slave; - remote = &slot_zero->master; - } + local = &slot_zero->slave; + remote = &slot_zero->master; if (local->initialised) { vchiq_loud_error_header(); @@ -2455,15 +2170,12 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, vchiq_loud_error("local state has already been " "initialised"); else - vchiq_loud_error("master/slave mismatch - two %ss", - is_master ? "master" : "slave"); + vchiq_loud_error("master/slave mismatch two slaves"); vchiq_loud_error_footer(); return VCHIQ_ERROR; } - memset(state, 0, sizeof(VCHIQ_STATE_T)); - - state->is_master = is_master; + memset(state, 0, sizeof(struct vchiq_state)); /* initialize shared state pointers @@ -2471,39 +2183,34 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, state->local = local; state->remote = remote; - state->slot_data = (VCHIQ_SLOT_T *)slot_zero; + state->slot_data = (struct vchiq_slot *)slot_zero; /* initialize events and mutexes */ - sema_init(&state->connect, 0); + init_completion(&state->connect); mutex_init(&state->mutex); - sema_init(&state->trigger_event, 0); - sema_init(&state->recycle_event, 0); - sema_init(&state->sync_trigger_event, 0); - sema_init(&state->sync_release_event, 0); - mutex_init(&state->slot_mutex); mutex_init(&state->recycle_mutex); mutex_init(&state->sync_mutex); mutex_init(&state->bulk_transfer_mutex); - sema_init(&state->slot_available_event, 0); - sema_init(&state->slot_remove_event, 0); - sema_init(&state->data_quota_event, 0); + init_completion(&state->slot_available_event); + init_completion(&state->slot_remove_event); + init_completion(&state->data_quota_event); state->slot_queue_available = 0; for (i = 0; i < VCHIQ_MAX_SERVICES; i++) { - VCHIQ_SERVICE_QUOTA_T *service_quota = + struct vchiq_service_quota *service_quota = &state->service_quotas[i]; - sema_init(&service_quota->quota_event, 0); + init_completion(&service_quota->quota_event); } for (i = local->slot_first; i <= local->slot_last; i++) { local->slot_queue[state->slot_queue_available++] = i; - up(&state->slot_available_event); + complete(&state->slot_available_event); } state->default_slot_quota = state->slot_queue_available/2; @@ -2515,24 +2222,18 @@ vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, state->data_use_count = 0; state->data_quota = state->slot_queue_available - 1; - local->trigger.event = offsetof(VCHIQ_STATE_T, trigger_event); - remote_event_create(state, &local->trigger); + remote_event_create(&state->trigger_event, &local->trigger); local->tx_pos = 0; - - local->recycle.event = offsetof(VCHIQ_STATE_T, recycle_event); - remote_event_create(state, &local->recycle); + remote_event_create(&state->recycle_event, &local->recycle); local->slot_queue_recycle = state->slot_queue_available; - - local->sync_trigger.event = offsetof(VCHIQ_STATE_T, sync_trigger_event); - remote_event_create(state, &local->sync_trigger); - - local->sync_release.event = offsetof(VCHIQ_STATE_T, sync_release_event); - remote_event_create(state, &local->sync_release); + remote_event_create(&state->sync_trigger_event, &local->sync_trigger); + remote_event_create(&state->sync_release_event, &local->sync_release); /* At start-of-day, the slot is empty and available */ - ((VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, local->slot_sync))->msgid - = VCHIQ_MSGID_PADDING; - remote_event_signal_local(state, &local->sync_release); + ((struct vchiq_header *) + SLOT_DATA_FROM_INDEX(state, local->slot_sync))->msgid = + VCHIQ_MSGID_PADDING; + remote_event_signal_local(&state->sync_release_event, &local->sync_release); local->debug[DEBUG_ENTRIES] = DEBUG_MAX; @@ -2598,17 +2299,18 @@ fail_free_handler_thread: } /* Called from application thread when a client or server service is created. */ -VCHIQ_SERVICE_T * -vchiq_add_service_internal(VCHIQ_STATE_T *state, - const VCHIQ_SERVICE_PARAMS_T *params, int srvstate, - VCHIQ_INSTANCE_T instance, VCHIQ_USERDATA_TERM_T userdata_term) -{ - VCHIQ_SERVICE_T *service; - VCHIQ_SERVICE_T **pservice = NULL; - VCHIQ_SERVICE_QUOTA_T *service_quota; +struct vchiq_service * +vchiq_add_service_internal(struct vchiq_state *state, + const struct vchiq_service_params *params, + int srvstate, VCHIQ_INSTANCE_T instance, + VCHIQ_USERDATA_TERM_T userdata_term) +{ + struct vchiq_service *service; + struct vchiq_service **pservice = NULL; + struct vchiq_service_quota *service_quota; int i; - service = kmalloc(sizeof(VCHIQ_SERVICE_T), GFP_KERNEL); + service = kmalloc(sizeof(*service), GFP_KERNEL); if (!service) return service; @@ -2637,8 +2339,8 @@ vchiq_add_service_internal(VCHIQ_STATE_T *state, service->service_use_count = 0; init_bulk_queue(&service->bulk_tx); init_bulk_queue(&service->bulk_rx); - sema_init(&service->remove_event, 0); - sema_init(&service->bulk_remove_event, 0); + init_completion(&service->remove_event); + init_completion(&service->bulk_remove_event); mutex_init(&service->bulk_mutex); memset(&service->stats, 0, sizeof(service->stats)); @@ -2660,7 +2362,7 @@ vchiq_add_service_internal(VCHIQ_STATE_T *state, if (srvstate == VCHIQ_SRVSTATE_OPENING) { for (i = 0; i < state->unused_service; i++) { - VCHIQ_SERVICE_T *srv = state->services[i]; + struct vchiq_service *srv = state->services[i]; if (!srv) { pservice = &state->services[i]; @@ -2669,7 +2371,7 @@ vchiq_add_service_internal(VCHIQ_STATE_T *state, } } else { for (i = (state->unused_service - 1); i >= 0; i--) { - VCHIQ_SERVICE_T *srv = state->services[i]; + struct vchiq_service *srv = state->services[i]; if (!srv) pservice = &state->services[i]; @@ -2730,7 +2432,7 @@ vchiq_add_service_internal(VCHIQ_STATE_T *state, } VCHIQ_STATUS_T -vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id) +vchiq_open_service_internal(struct vchiq_service *service, int client_id) { struct vchiq_open_payload payload = { service->base.fourcc, @@ -2753,7 +2455,7 @@ vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id) QMFLAGS_IS_BLOCKING); if (status == VCHIQ_SUCCESS) { /* Wait for the ACK/NAK */ - if (down_interruptible(&service->remove_event) != 0) { + if (wait_for_completion_killable(&service->remove_event)) { status = VCHIQ_RETRY; vchiq_release_service_internal(service); } else if ((service->srvstate != VCHIQ_SRVSTATE_OPEN) && @@ -2773,17 +2475,17 @@ vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id) } static void -release_service_messages(VCHIQ_SERVICE_T *service) +release_service_messages(struct vchiq_service *service) { - VCHIQ_STATE_T *state = service->state; + struct vchiq_state *state = service->state; int slot_last = state->remote->slot_last; int i; /* Release any claimed messages aimed at this service */ if (service->sync) { - VCHIQ_HEADER_T *header = - (VCHIQ_HEADER_T *)SLOT_DATA_FROM_INDEX(state, + struct vchiq_header *header = + (struct vchiq_header *)SLOT_DATA_FROM_INDEX(state, state->remote->slot_sync); if (VCHIQ_MSG_DSTPORT(header->msgid) == service->localport) release_message_sync(state, header); @@ -2792,7 +2494,7 @@ release_service_messages(VCHIQ_SERVICE_T *service) } for (i = state->remote->slot_first; i <= slot_last; i++) { - VCHIQ_SLOT_INFO_T *slot_info = + struct vchiq_slot_info *slot_info = SLOT_INFO_FROM_INDEX(state, i); if (slot_info->release_count != slot_info->use_count) { char *data = @@ -2808,8 +2510,8 @@ release_service_messages(VCHIQ_SERVICE_T *service) pos = 0; while (pos < end) { - VCHIQ_HEADER_T *header = - (VCHIQ_HEADER_T *)(data + pos); + struct vchiq_header *header = + (struct vchiq_header *)(data + pos); int msgid = header->msgid; int port = VCHIQ_MSG_DSTPORT(msgid); @@ -2834,7 +2536,7 @@ release_service_messages(VCHIQ_SERVICE_T *service) } static int -do_abort_bulks(VCHIQ_SERVICE_T *service) +do_abort_bulks(struct vchiq_service *service) { VCHIQ_STATUS_T status; @@ -2853,7 +2555,7 @@ do_abort_bulks(VCHIQ_SERVICE_T *service) } static VCHIQ_STATUS_T -close_service_complete(VCHIQ_SERVICE_T *service, int failstate) +close_service_complete(struct vchiq_service *service, int failstate) { VCHIQ_STATUS_T status; int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID); @@ -2905,7 +2607,7 @@ close_service_complete(VCHIQ_SERVICE_T *service, int failstate) if (is_server) service->closing = 0; - up(&service->remove_event); + complete(&service->remove_event); } } else vchiq_set_service_state(service, failstate); @@ -2915,9 +2617,9 @@ close_service_complete(VCHIQ_SERVICE_T *service, int failstate) /* Called by the slot handler */ VCHIQ_STATUS_T -vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd) +vchiq_close_service_internal(struct vchiq_service *service, int close_recvd) { - VCHIQ_STATE_T *state = service->state; + struct vchiq_state *state = service->state; VCHIQ_STATUS_T status = VCHIQ_SUCCESS; int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID); @@ -2946,7 +2648,7 @@ vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd) vchiq_set_service_state(service, VCHIQ_SRVSTATE_LISTENING); } - up(&service->remove_event); + complete(&service->remove_event); } else vchiq_free_service_internal(service); break; @@ -2955,7 +2657,7 @@ vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd) /* The open was rejected - tell the user */ vchiq_set_service_state(service, VCHIQ_SRVSTATE_CLOSEWAIT); - up(&service->remove_event); + complete(&service->remove_event); } else { /* Shutdown mid-open - let the other side know */ status = queue_message(state, service, @@ -2971,7 +2673,7 @@ vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd) mutex_lock(&state->sync_mutex); /* fall through */ case VCHIQ_SRVSTATE_OPEN: - if (state->is_master || close_recvd) { + if (close_recvd) { if (!do_abort_bulks(service)) status = VCHIQ_RETRY; } @@ -3018,11 +2720,9 @@ vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd) /* This happens when a process is killed mid-close */ break; - if (!state->is_master) { - if (!do_abort_bulks(service)) { - status = VCHIQ_RETRY; - break; - } + if (!do_abort_bulks(service)) { + status = VCHIQ_RETRY; + break; } if (status == VCHIQ_SUCCESS) @@ -3051,9 +2751,9 @@ vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd) /* Called from the application process upon process death */ void -vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service) +vchiq_terminate_service_internal(struct vchiq_service *service) { - VCHIQ_STATE_T *state = service->state; + struct vchiq_state *state = service->state; vchiq_log_info(vchiq_core_log_level, "%d: tsi - (%d<->%d)", state->id, service->localport, service->remoteport); @@ -3066,9 +2766,9 @@ vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service) /* Called from the slot handler */ void -vchiq_free_service_internal(VCHIQ_SERVICE_T *service) +vchiq_free_service_internal(struct vchiq_service *service) { - VCHIQ_STATE_T *state = service->state; + struct vchiq_state *state = service->state; vchiq_log_info(vchiq_core_log_level, "%d: fsi - (%d)", state->id, service->localport); @@ -3090,16 +2790,16 @@ vchiq_free_service_internal(VCHIQ_SERVICE_T *service) vchiq_set_service_state(service, VCHIQ_SRVSTATE_FREE); - up(&service->remove_event); + complete(&service->remove_event); /* Release the initial lock */ unlock_service(service); } VCHIQ_STATUS_T -vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance) +vchiq_connect_internal(struct vchiq_state *state, VCHIQ_INSTANCE_T instance) { - VCHIQ_SERVICE_T *service; + struct vchiq_service *service; int i; /* Find all services registered to this client and enable them. */ @@ -3122,20 +2822,20 @@ vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance) } if (state->conn_state == VCHIQ_CONNSTATE_CONNECTING) { - if (down_interruptible(&state->connect) != 0) + if (wait_for_completion_killable(&state->connect)) return VCHIQ_RETRY; vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); - up(&state->connect); + complete(&state->connect); } return VCHIQ_SUCCESS; } VCHIQ_STATUS_T -vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance) +vchiq_shutdown_internal(struct vchiq_state *state, VCHIQ_INSTANCE_T instance) { - VCHIQ_SERVICE_T *service; + struct vchiq_service *service; int i; /* Find all services registered to this client and enable them. */ @@ -3150,7 +2850,7 @@ vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance) } VCHIQ_STATUS_T -vchiq_pause_internal(VCHIQ_STATE_T *state) +vchiq_pause_internal(struct vchiq_state *state) { VCHIQ_STATUS_T status = VCHIQ_SUCCESS; @@ -3173,7 +2873,7 @@ vchiq_pause_internal(VCHIQ_STATE_T *state) } VCHIQ_STATUS_T -vchiq_resume_internal(VCHIQ_STATE_T *state) +vchiq_resume_internal(struct vchiq_state *state) { VCHIQ_STATUS_T status = VCHIQ_SUCCESS; @@ -3192,7 +2892,7 @@ VCHIQ_STATUS_T vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle) { /* Unregister the service */ - VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + struct vchiq_service *service = find_service_by_handle(handle); VCHIQ_STATUS_T status = VCHIQ_SUCCESS; if (!service) @@ -3221,7 +2921,7 @@ vchiq_close_service(VCHIQ_SERVICE_HANDLE_T handle) } while (1) { - if (down_interruptible(&service->remove_event) != 0) { + if (wait_for_completion_killable(&service->remove_event)) { status = VCHIQ_RETRY; break; } @@ -3251,7 +2951,7 @@ VCHIQ_STATUS_T vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle) { /* Unregister the service */ - VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + struct vchiq_service *service = find_service_by_handle(handle); VCHIQ_STATUS_T status = VCHIQ_SUCCESS; if (!service) @@ -3282,7 +2982,7 @@ vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle) request_poll(service->state, service, VCHIQ_POLL_REMOVE); } while (1) { - if (down_interruptible(&service->remove_event) != 0) { + if (wait_for_completion_killable(&service->remove_event)) { status = VCHIQ_RETRY; break; } @@ -3313,25 +3013,24 @@ vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T handle) * When called in blocking mode, the userdata field points to a bulk_waiter * structure. */ -VCHIQ_STATUS_T -vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, - VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata, - VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir) -{ - VCHIQ_SERVICE_T *service = find_service_by_handle(handle); - VCHIQ_BULK_QUEUE_T *queue; - VCHIQ_BULK_T *bulk; - VCHIQ_STATE_T *state; +VCHIQ_STATUS_T vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, + void *offset, int size, void *userdata, + VCHIQ_BULK_MODE_T mode, + VCHIQ_BULK_DIR_T dir) +{ + struct vchiq_service *service = find_service_by_handle(handle); + struct vchiq_bulk_queue *queue; + struct vchiq_bulk *bulk; + struct vchiq_state *state; struct bulk_waiter *bulk_waiter = NULL; const char dir_char = (dir == VCHIQ_BULK_TRANSMIT) ? 't' : 'r'; const int dir_msgtype = (dir == VCHIQ_BULK_TRANSMIT) ? VCHIQ_MSG_BULK_TX : VCHIQ_MSG_BULK_RX; VCHIQ_STATUS_T status = VCHIQ_ERROR; + int payload[2]; - if (!service || - (service->srvstate != VCHIQ_SRVSTATE_OPEN) || - ((memhandle == VCHI_MEM_HANDLE_INVALID) && (offset == NULL)) || - (vchiq_check_service(service) != VCHIQ_SUCCESS)) + if (!service || service->srvstate != VCHIQ_SRVSTATE_OPEN || + !offset || vchiq_check_service(service) != VCHIQ_SUCCESS) goto error_exit; switch (mode) { @@ -3340,7 +3039,7 @@ vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, break; case VCHIQ_BULK_MODE_BLOCKING: bulk_waiter = (struct bulk_waiter *)userdata; - sema_init(&bulk_waiter->event, 0); + init_completion(&bulk_waiter->event); bulk_waiter->actual = 0; bulk_waiter->bulk = NULL; break; @@ -3366,8 +3065,8 @@ vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, VCHIQ_SERVICE_STATS_INC(service, bulk_stalls); do { mutex_unlock(&service->bulk_mutex); - if (down_interruptible(&service->bulk_remove_event) - != 0) { + if (wait_for_completion_killable( + &service->bulk_remove_event)) { status = VCHIQ_RETRY; goto error_exit; } @@ -3388,8 +3087,7 @@ vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, bulk->size = size; bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED; - if (vchiq_prepare_bulk_data(bulk, memhandle, offset, size, dir) != - VCHIQ_SUCCESS) + if (vchiq_prepare_bulk_data(bulk, offset, size, dir) != VCHIQ_SUCCESS) goto unlock_error_exit; wmb(); @@ -3409,32 +3107,25 @@ vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, if (service->srvstate != VCHIQ_SRVSTATE_OPEN) goto unlock_both_error_exit; - if (state->is_master) { - queue->local_insert++; - if (resolve_bulks(service, queue)) - request_poll(state, service, - (dir == VCHIQ_BULK_TRANSMIT) ? - VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY); - } else { - int payload[2] = { (int)(long)bulk->data, bulk->size }; - - status = queue_message(state, - NULL, - VCHIQ_MAKE_MSG(dir_msgtype, - service->localport, - service->remoteport), - memcpy_copy_callback, - &payload, - sizeof(payload), - QMFLAGS_IS_BLOCKING | - QMFLAGS_NO_MUTEX_LOCK | - QMFLAGS_NO_MUTEX_UNLOCK); - if (status != VCHIQ_SUCCESS) { - goto unlock_both_error_exit; - } - queue->local_insert++; + payload[0] = (int)(long)bulk->data; + payload[1] = bulk->size; + status = queue_message(state, + NULL, + VCHIQ_MAKE_MSG(dir_msgtype, + service->localport, + service->remoteport), + memcpy_copy_callback, + &payload, + sizeof(payload), + QMFLAGS_IS_BLOCKING | + QMFLAGS_NO_MUTEX_LOCK | + QMFLAGS_NO_MUTEX_UNLOCK); + if (status != VCHIQ_SUCCESS) { + goto unlock_both_error_exit; } + queue->local_insert++; + mutex_unlock(&state->slot_mutex); mutex_unlock(&service->bulk_mutex); @@ -3451,7 +3142,7 @@ waiting: if (bulk_waiter) { bulk_waiter->bulk = bulk; - if (down_interruptible(&bulk_waiter->event) != 0) + if (wait_for_completion_killable(&bulk_waiter->event)) status = VCHIQ_RETRY; else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED) status = VCHIQ_ERROR; @@ -3479,7 +3170,7 @@ vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle, void *context, size_t size) { - VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + struct vchiq_service *service = find_service_by_handle(handle); VCHIQ_STATUS_T status = VCHIQ_ERROR; if (!service || @@ -3525,11 +3216,12 @@ error_exit: } void -vchiq_release_message(VCHIQ_SERVICE_HANDLE_T handle, VCHIQ_HEADER_T *header) +vchiq_release_message(VCHIQ_SERVICE_HANDLE_T handle, + struct vchiq_header *header) { - VCHIQ_SERVICE_T *service = find_service_by_handle(handle); - VCHIQ_SHARED_STATE_T *remote; - VCHIQ_STATE_T *state; + struct vchiq_service *service = find_service_by_handle(handle); + struct vchiq_shared_state *remote; + struct vchiq_state *state; int slot_index; if (!service) @@ -3545,7 +3237,7 @@ vchiq_release_message(VCHIQ_SERVICE_HANDLE_T handle, VCHIQ_HEADER_T *header) int msgid = header->msgid; if (msgid & VCHIQ_MSGID_CLAIMED) { - VCHIQ_SLOT_INFO_T *slot_info = + struct vchiq_slot_info *slot_info = SLOT_INFO_FROM_INDEX(state, slot_index); release_slot(state, slot_info, header, service); @@ -3557,10 +3249,9 @@ vchiq_release_message(VCHIQ_SERVICE_HANDLE_T handle, VCHIQ_HEADER_T *header) } static void -release_message_sync(VCHIQ_STATE_T *state, VCHIQ_HEADER_T *header) +release_message_sync(struct vchiq_state *state, struct vchiq_header *header) { header->msgid = VCHIQ_MSGID_PADDING; - wmb(); remote_event_signal(&state->remote->sync_release); } @@ -3568,7 +3259,7 @@ VCHIQ_STATUS_T vchiq_get_peer_version(VCHIQ_SERVICE_HANDLE_T handle, short *peer_version) { VCHIQ_STATUS_T status = VCHIQ_ERROR; - VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + struct vchiq_service *service = find_service_by_handle(handle); if (!service || (vchiq_check_service(service) != VCHIQ_SUCCESS) || @@ -3583,35 +3274,21 @@ exit: return status; } -VCHIQ_STATUS_T -vchiq_get_config(VCHIQ_INSTANCE_T instance, - int config_size, VCHIQ_CONFIG_T *pconfig) +void vchiq_get_config(struct vchiq_config *config) { - VCHIQ_CONFIG_T config; - - (void)instance; - - config.max_msg_size = VCHIQ_MAX_MSG_SIZE; - config.bulk_threshold = VCHIQ_MAX_MSG_SIZE; - config.max_outstanding_bulks = VCHIQ_NUM_SERVICE_BULKS; - config.max_services = VCHIQ_MAX_SERVICES; - config.version = VCHIQ_VERSION; - config.version_min = VCHIQ_VERSION_MIN; - - if (config_size > sizeof(VCHIQ_CONFIG_T)) - return VCHIQ_ERROR; - - memcpy(pconfig, &config, - min(config_size, (int)(sizeof(VCHIQ_CONFIG_T)))); - - return VCHIQ_SUCCESS; + config->max_msg_size = VCHIQ_MAX_MSG_SIZE; + config->bulk_threshold = VCHIQ_MAX_MSG_SIZE; + config->max_outstanding_bulks = VCHIQ_NUM_SERVICE_BULKS; + config->max_services = VCHIQ_MAX_SERVICES; + config->version = VCHIQ_VERSION; + config->version_min = VCHIQ_VERSION_MIN; } VCHIQ_STATUS_T vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle, VCHIQ_SERVICE_OPTION_T option, int value) { - VCHIQ_SERVICE_T *service = find_service_by_handle(handle); + struct vchiq_service *service = find_service_by_handle(handle); VCHIQ_STATUS_T status = VCHIQ_ERROR; if (service) { @@ -3622,7 +3299,7 @@ vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle, break; case VCHIQ_SERVICE_OPTION_SLOT_QUOTA: { - VCHIQ_SERVICE_QUOTA_T *service_quota = + struct vchiq_service_quota *service_quota = &service->state->service_quotas[ service->localport]; if (value == 0) @@ -3635,14 +3312,14 @@ vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle, service_quota->message_use_count)) { /* Signal the service that it may have ** dropped below its quota */ - up(&service_quota->quota_event); + complete(&service_quota->quota_event); } status = VCHIQ_SUCCESS; } } break; case VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA: { - VCHIQ_SERVICE_QUOTA_T *service_quota = + struct vchiq_service_quota *service_quota = &service->state->service_quotas[ service->localport]; if (value == 0) @@ -3656,7 +3333,7 @@ vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle, service_quota->slot_use_count)) /* Signal the service that it may have ** dropped below its quota */ - up(&service_quota->quota_event); + complete(&service_quota->quota_event); status = VCHIQ_SUCCESS; } } break; @@ -3685,8 +3362,8 @@ vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T handle, } static void -vchiq_dump_shared_state(void *dump_context, VCHIQ_STATE_T *state, - VCHIQ_SHARED_STATE_T *shared, const char *label) +vchiq_dump_shared_state(void *dump_context, struct vchiq_state *state, + struct vchiq_shared_state *shared, const char *label) { static const char *const debug_names[] = { "<entries>", @@ -3716,7 +3393,8 @@ vchiq_dump_shared_state(void *dump_context, VCHIQ_STATE_T *state, vchiq_dump(dump_context, buf, len + 1); for (i = shared->slot_first; i <= shared->slot_last; i++) { - VCHIQ_SLOT_INFO_T slot_info = *SLOT_INFO_FROM_INDEX(state, i); + struct vchiq_slot_info slot_info = + *SLOT_INFO_FROM_INDEX(state, i); if (slot_info.use_count != slot_info.release_count) { len = snprintf(buf, sizeof(buf), " %d: %d/%d", i, slot_info.use_count, @@ -3733,7 +3411,7 @@ vchiq_dump_shared_state(void *dump_context, VCHIQ_STATE_T *state, } void -vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state) +vchiq_dump_state(void *dump_context, struct vchiq_state *state) { char buf[80]; int len; @@ -3783,7 +3461,7 @@ vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state) vchiq_dump_platform_instances(dump_context); for (i = 0; i < state->unused_service; i++) { - VCHIQ_SERVICE_T *service = find_service_by_port(state, i); + struct vchiq_service *service = find_service_by_port(state, i); if (service) { vchiq_dump_service_state(dump_context, service); @@ -3793,7 +3471,7 @@ vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state) } void -vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service) +vchiq_dump_service_state(void *dump_context, struct vchiq_service *service) { char buf[80]; int len; @@ -3804,7 +3482,7 @@ vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service) if (service->srvstate != VCHIQ_SRVSTATE_FREE) { char remoteport[30]; - VCHIQ_SERVICE_QUOTA_T *service_quota = + struct vchiq_service_quota *service_quota = &service->state->service_quotas[service->localport]; int fourcc = service->base.fourcc; int tx_pending, rx_pending; @@ -3909,7 +3587,7 @@ vchiq_loud_error_footer(void) "================"); } -VCHIQ_STATUS_T vchiq_send_remote_use(VCHIQ_STATE_T *state) +VCHIQ_STATUS_T vchiq_send_remote_use(struct vchiq_state *state) { VCHIQ_STATUS_T status = VCHIQ_RETRY; @@ -3920,7 +3598,7 @@ VCHIQ_STATUS_T vchiq_send_remote_use(VCHIQ_STATE_T *state) return status; } -VCHIQ_STATUS_T vchiq_send_remote_release(VCHIQ_STATE_T *state) +VCHIQ_STATUS_T vchiq_send_remote_release(struct vchiq_state *state) { VCHIQ_STATUS_T status = VCHIQ_RETRY; @@ -3931,7 +3609,7 @@ VCHIQ_STATUS_T vchiq_send_remote_release(VCHIQ_STATE_T *state) return status; } -VCHIQ_STATUS_T vchiq_send_remote_use_active(VCHIQ_STATE_T *state) +VCHIQ_STATUS_T vchiq_send_remote_use_active(struct vchiq_state *state) { VCHIQ_STATUS_T status = VCHIQ_RETRY; diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h index 10deb5745dda..5f07db519633 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h @@ -35,8 +35,9 @@ #define VCHIQ_CORE_H #include <linux/mutex.h> -#include <linux/semaphore.h> +#include <linux/completion.h> #include <linux/kthread.h> +#include <linux/wait.h> #include "vchiq_cfg.h" @@ -89,7 +90,7 @@ vchiq_static_assert(IS_POW2(VCHIQ_MAX_SLOTS_PER_SIDE)); #define VCHIQ_SLOT_MASK (VCHIQ_SLOT_SIZE - 1) #define VCHIQ_SLOT_QUEUE_MASK (VCHIQ_MAX_SLOTS_PER_SIDE - 1) -#define VCHIQ_SLOT_ZERO_SLOTS ((sizeof(VCHIQ_SLOT_ZERO_T) + \ +#define VCHIQ_SLOT_ZERO_SLOTS ((sizeof(struct vchiq_slot_zero) + \ VCHIQ_SLOT_SIZE - 1) / VCHIQ_SLOT_SIZE) #define VCHIQ_MSG_PADDING 0 /* - */ @@ -238,51 +239,47 @@ typedef enum { typedef void (*VCHIQ_USERDATA_TERM_T)(void *userdata); -typedef struct vchiq_bulk_struct { +struct vchiq_bulk { short mode; short dir; void *userdata; - VCHI_MEM_HANDLE_T handle; void *data; int size; void *remote_data; int remote_size; int actual; -} VCHIQ_BULK_T; +}; -typedef struct vchiq_bulk_queue_struct { +struct vchiq_bulk_queue { int local_insert; /* Where to insert the next local bulk */ int remote_insert; /* Where to insert the next remote bulk (master) */ int process; /* Bulk to transfer next */ int remote_notify; /* Bulk to notify the remote client of next (mstr) */ int remove; /* Bulk to notify the local client of, and remove, ** next */ - VCHIQ_BULK_T bulks[VCHIQ_NUM_SERVICE_BULKS]; -} VCHIQ_BULK_QUEUE_T; + struct vchiq_bulk bulks[VCHIQ_NUM_SERVICE_BULKS]; +}; -typedef struct remote_event_struct { +struct remote_event { int armed; int fired; - /* Contains offset from the beginning of the VCHIQ_STATE_T structure */ - u32 event; -} REMOTE_EVENT_T; + u32 __unused; +}; typedef struct opaque_platform_state_t *VCHIQ_PLATFORM_STATE_T; -typedef struct vchiq_state_struct VCHIQ_STATE_T; - -typedef struct vchiq_slot_struct { +struct vchiq_slot { char data[VCHIQ_SLOT_SIZE]; -} VCHIQ_SLOT_T; +}; -typedef struct vchiq_slot_info_struct { +struct vchiq_slot_info { /* Use two counters rather than one to avoid the need for a mutex. */ short use_count; short release_count; -} VCHIQ_SLOT_INFO_T; +}; -typedef struct vchiq_service_struct { - VCHIQ_SERVICE_BASE_T base; +struct vchiq_service { + struct vchiq_service_base base; VCHIQ_SERVICE_HANDLE_T handle; unsigned int ref_count; int srvstate; @@ -300,16 +297,16 @@ typedef struct vchiq_service_struct { short version_min; short peer_version; - VCHIQ_STATE_T *state; + struct vchiq_state *state; VCHIQ_INSTANCE_T instance; int service_use_count; - VCHIQ_BULK_QUEUE_T bulk_tx; - VCHIQ_BULK_QUEUE_T bulk_rx; + struct vchiq_bulk_queue bulk_tx; + struct vchiq_bulk_queue bulk_rx; - struct semaphore remove_event; - struct semaphore bulk_remove_event; + struct completion remove_event; + struct completion bulk_remove_event; struct mutex bulk_mutex; struct service_stats_struct { @@ -327,22 +324,22 @@ typedef struct vchiq_service_struct { uint64_t bulk_tx_bytes; uint64_t bulk_rx_bytes; } stats; -} VCHIQ_SERVICE_T; +}; -/* The quota information is outside VCHIQ_SERVICE_T so that it can be - statically allocated, since for accounting reasons a service's slot - usage is carried over between users of the same port number. +/* The quota information is outside struct vchiq_service so that it can + * be statically allocated, since for accounting reasons a service's slot + * usage is carried over between users of the same port number. */ -typedef struct vchiq_service_quota_struct { +struct vchiq_service_quota { unsigned short slot_quota; unsigned short slot_use_count; unsigned short message_quota; unsigned short message_use_count; - struct semaphore quota_event; + struct completion quota_event; int previous_tx_index; -} VCHIQ_SERVICE_QUOTA_T; +}; -typedef struct vchiq_shared_state_struct { +struct vchiq_shared_state { /* A non-zero value here indicates that the content is valid. */ int initialised; @@ -356,7 +353,7 @@ typedef struct vchiq_shared_state_struct { /* Signalling this event indicates that owner's slot handler thread ** should run. */ - REMOTE_EVENT_T trigger; + struct remote_event trigger; /* Indicates the byte position within the stream where the next message ** will be written. The least significant bits are an index into the @@ -364,26 +361,26 @@ typedef struct vchiq_shared_state_struct { int tx_pos; /* This event should be signalled when a slot is recycled. */ - REMOTE_EVENT_T recycle; + struct remote_event recycle; /* The slot_queue index where the next recycled slot will be written. */ int slot_queue_recycle; /* This event should be signalled when a synchronous message is sent. */ - REMOTE_EVENT_T sync_trigger; + struct remote_event sync_trigger; /* This event should be signalled when a synchronous message has been ** released. */ - REMOTE_EVENT_T sync_release; + struct remote_event sync_release; /* A circular buffer of slot indexes. */ int slot_queue[VCHIQ_MAX_SLOTS_PER_SIDE]; /* Debugging state */ int debug[DEBUG_MAX]; -} VCHIQ_SHARED_STATE_T; +}; -typedef struct vchiq_slot_zero_struct { +struct vchiq_slot_zero { int magic; short version; short version_min; @@ -392,27 +389,26 @@ typedef struct vchiq_slot_zero_struct { int max_slots; int max_slots_per_side; int platform_data[2]; - VCHIQ_SHARED_STATE_T master; - VCHIQ_SHARED_STATE_T slave; - VCHIQ_SLOT_INFO_T slots[VCHIQ_MAX_SLOTS]; -} VCHIQ_SLOT_ZERO_T; + struct vchiq_shared_state master; + struct vchiq_shared_state slave; + struct vchiq_slot_info slots[VCHIQ_MAX_SLOTS]; +}; -struct vchiq_state_struct { +struct vchiq_state { int id; int initialised; VCHIQ_CONNSTATE_T conn_state; - int is_master; short version_common; - VCHIQ_SHARED_STATE_T *local; - VCHIQ_SHARED_STATE_T *remote; - VCHIQ_SLOT_T *slot_data; + struct vchiq_shared_state *local; + struct vchiq_shared_state *remote; + struct vchiq_slot *slot_data; unsigned short default_slot_quota; unsigned short default_message_quota; /* Event indicating connect message received */ - struct semaphore connect; + struct completion connect; /* Mutex protecting services */ struct mutex mutex; @@ -428,20 +424,20 @@ struct vchiq_state_struct { struct task_struct *sync_thread; /* Local implementation of the trigger remote event */ - struct semaphore trigger_event; + wait_queue_head_t trigger_event; /* Local implementation of the recycle remote event */ - struct semaphore recycle_event; + wait_queue_head_t recycle_event; /* Local implementation of the sync trigger remote event */ - struct semaphore sync_trigger_event; + wait_queue_head_t sync_trigger_event; /* Local implementation of the sync release remote event */ - struct semaphore sync_release_event; + wait_queue_head_t sync_release_event; char *tx_data; char *rx_data; - VCHIQ_SLOT_INFO_T *rx_info; + struct vchiq_slot_info *rx_info; struct mutex slot_mutex; @@ -483,16 +479,12 @@ struct vchiq_state_struct { int unused_service; /* Signalled when a free slot becomes available. */ - struct semaphore slot_available_event; + struct completion slot_available_event; - struct semaphore slot_remove_event; + struct completion slot_remove_event; /* Signalled when a free data slot becomes available. */ - struct semaphore data_quota_event; - - /* Incremented when there are bulk transfers which cannot be processed - * whilst paused and must be processed on resume */ - int deferred_bulks; + struct completion data_quota_event; struct state_stats_struct { int slot_stalls; @@ -502,16 +494,16 @@ struct vchiq_state_struct { int error_count; } stats; - VCHIQ_SERVICE_T * services[VCHIQ_MAX_SERVICES]; - VCHIQ_SERVICE_QUOTA_T service_quotas[VCHIQ_MAX_SERVICES]; - VCHIQ_SLOT_INFO_T slot_info[VCHIQ_MAX_SLOTS]; + struct vchiq_service *services[VCHIQ_MAX_SERVICES]; + struct vchiq_service_quota service_quotas[VCHIQ_MAX_SERVICES]; + struct vchiq_slot_info slot_info[VCHIQ_MAX_SLOTS]; VCHIQ_PLATFORM_STATE_T platform_state; }; struct bulk_waiter { - VCHIQ_BULK_T *bulk; - struct semaphore event; + struct vchiq_bulk *bulk; + struct completion event; int actual; }; @@ -521,60 +513,60 @@ extern int vchiq_core_log_level; extern int vchiq_core_msg_log_level; extern int vchiq_sync_log_level; -extern VCHIQ_STATE_T *vchiq_states[VCHIQ_MAX_STATES]; +extern struct vchiq_state *vchiq_states[VCHIQ_MAX_STATES]; extern const char * get_conn_state_name(VCHIQ_CONNSTATE_T conn_state); -extern VCHIQ_SLOT_ZERO_T * +extern struct vchiq_slot_zero * vchiq_init_slots(void *mem_base, int mem_size); extern VCHIQ_STATUS_T -vchiq_init_state(VCHIQ_STATE_T *state, VCHIQ_SLOT_ZERO_T *slot_zero, - int is_master); +vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero); extern VCHIQ_STATUS_T -vchiq_connect_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance); +vchiq_connect_internal(struct vchiq_state *state, VCHIQ_INSTANCE_T instance); -extern VCHIQ_SERVICE_T * -vchiq_add_service_internal(VCHIQ_STATE_T *state, - const VCHIQ_SERVICE_PARAMS_T *params, int srvstate, - VCHIQ_INSTANCE_T instance, VCHIQ_USERDATA_TERM_T userdata_term); +extern struct vchiq_service * +vchiq_add_service_internal(struct vchiq_state *state, + const struct vchiq_service_params *params, + int srvstate, VCHIQ_INSTANCE_T instance, + VCHIQ_USERDATA_TERM_T userdata_term); extern VCHIQ_STATUS_T -vchiq_open_service_internal(VCHIQ_SERVICE_T *service, int client_id); +vchiq_open_service_internal(struct vchiq_service *service, int client_id); extern VCHIQ_STATUS_T -vchiq_close_service_internal(VCHIQ_SERVICE_T *service, int close_recvd); +vchiq_close_service_internal(struct vchiq_service *service, int close_recvd); extern void -vchiq_terminate_service_internal(VCHIQ_SERVICE_T *service); +vchiq_terminate_service_internal(struct vchiq_service *service); extern void -vchiq_free_service_internal(VCHIQ_SERVICE_T *service); +vchiq_free_service_internal(struct vchiq_service *service); extern VCHIQ_STATUS_T -vchiq_shutdown_internal(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance); +vchiq_shutdown_internal(struct vchiq_state *state, VCHIQ_INSTANCE_T instance); extern VCHIQ_STATUS_T -vchiq_pause_internal(VCHIQ_STATE_T *state); +vchiq_pause_internal(struct vchiq_state *state); extern VCHIQ_STATUS_T -vchiq_resume_internal(VCHIQ_STATE_T *state); +vchiq_resume_internal(struct vchiq_state *state); extern void -remote_event_pollall(VCHIQ_STATE_T *state); +remote_event_pollall(struct vchiq_state *state); extern VCHIQ_STATUS_T -vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, - VCHI_MEM_HANDLE_T memhandle, void *offset, int size, void *userdata, - VCHIQ_BULK_MODE_T mode, VCHIQ_BULK_DIR_T dir); +vchiq_bulk_transfer(VCHIQ_SERVICE_HANDLE_T handle, void *offset, int size, + void *userdata, VCHIQ_BULK_MODE_T mode, + VCHIQ_BULK_DIR_T dir); extern void -vchiq_dump_state(void *dump_context, VCHIQ_STATE_T *state); +vchiq_dump_state(void *dump_context, struct vchiq_state *state); extern void -vchiq_dump_service_state(void *dump_context, VCHIQ_SERVICE_T *service); +vchiq_dump_service_state(void *dump_context, struct vchiq_service *service); extern void vchiq_loud_error_header(void); @@ -583,12 +575,13 @@ extern void vchiq_loud_error_footer(void); extern void -request_poll(VCHIQ_STATE_T *state, VCHIQ_SERVICE_T *service, int poll_type); +request_poll(struct vchiq_state *state, struct vchiq_service *service, + int poll_type); -static inline VCHIQ_SERVICE_T * +static inline struct vchiq_service * handle_to_service(VCHIQ_SERVICE_HANDLE_T handle) { - VCHIQ_STATE_T *state = vchiq_states[(handle / VCHIQ_MAX_SERVICES) & + struct vchiq_state *state = vchiq_states[(handle / VCHIQ_MAX_SERVICES) & (VCHIQ_MAX_STATES - 1)]; if (!state) return NULL; @@ -596,57 +589,54 @@ handle_to_service(VCHIQ_SERVICE_HANDLE_T handle) return state->services[handle & (VCHIQ_MAX_SERVICES - 1)]; } -extern VCHIQ_SERVICE_T * +extern struct vchiq_service * find_service_by_handle(VCHIQ_SERVICE_HANDLE_T handle); -extern VCHIQ_SERVICE_T * -find_service_by_port(VCHIQ_STATE_T *state, int localport); +extern struct vchiq_service * +find_service_by_port(struct vchiq_state *state, int localport); -extern VCHIQ_SERVICE_T * +extern struct vchiq_service * find_service_for_instance(VCHIQ_INSTANCE_T instance, VCHIQ_SERVICE_HANDLE_T handle); -extern VCHIQ_SERVICE_T * +extern struct vchiq_service * find_closed_service_for_instance(VCHIQ_INSTANCE_T instance, VCHIQ_SERVICE_HANDLE_T handle); -extern VCHIQ_SERVICE_T * -next_service_by_instance(VCHIQ_STATE_T *state, VCHIQ_INSTANCE_T instance, - int *pidx); +extern struct vchiq_service * +next_service_by_instance(struct vchiq_state *state, VCHIQ_INSTANCE_T instance, + int *pidx); extern void -lock_service(VCHIQ_SERVICE_T *service); +lock_service(struct vchiq_service *service); extern void -unlock_service(VCHIQ_SERVICE_T *service); +unlock_service(struct vchiq_service *service); /* The following functions are called from vchiq_core, and external ** implementations must be provided. */ extern VCHIQ_STATUS_T -vchiq_prepare_bulk_data(VCHIQ_BULK_T *bulk, - VCHI_MEM_HANDLE_T memhandle, void *offset, int size, int dir); - -extern void -vchiq_transfer_bulk(VCHIQ_BULK_T *bulk); +vchiq_prepare_bulk_data(struct vchiq_bulk *bulk, void *offset, int size, + int dir); extern void -vchiq_complete_bulk(VCHIQ_BULK_T *bulk); +vchiq_complete_bulk(struct vchiq_bulk *bulk); extern void -remote_event_signal(REMOTE_EVENT_T *event); +remote_event_signal(struct remote_event *event); void -vchiq_platform_check_suspend(VCHIQ_STATE_T *state); +vchiq_platform_check_suspend(struct vchiq_state *state); extern void -vchiq_platform_paused(VCHIQ_STATE_T *state); +vchiq_platform_paused(struct vchiq_state *state); extern VCHIQ_STATUS_T -vchiq_platform_resume(VCHIQ_STATE_T *state); +vchiq_platform_resume(struct vchiq_state *state); extern void -vchiq_platform_resumed(VCHIQ_STATE_T *state); +vchiq_platform_resumed(struct vchiq_state *state); extern void vchiq_dump(void *dump_context, const char *str, int len); @@ -659,47 +649,48 @@ vchiq_dump_platform_instances(void *dump_context); extern void vchiq_dump_platform_service_state(void *dump_context, - VCHIQ_SERVICE_T *service); + struct vchiq_service *service); extern VCHIQ_STATUS_T -vchiq_use_service_internal(VCHIQ_SERVICE_T *service); +vchiq_use_service_internal(struct vchiq_service *service); extern VCHIQ_STATUS_T -vchiq_release_service_internal(VCHIQ_SERVICE_T *service); +vchiq_release_service_internal(struct vchiq_service *service); extern void -vchiq_on_remote_use(VCHIQ_STATE_T *state); +vchiq_on_remote_use(struct vchiq_state *state); extern void -vchiq_on_remote_release(VCHIQ_STATE_T *state); +vchiq_on_remote_release(struct vchiq_state *state); extern VCHIQ_STATUS_T -vchiq_platform_init_state(VCHIQ_STATE_T *state); +vchiq_platform_init_state(struct vchiq_state *state); extern VCHIQ_STATUS_T -vchiq_check_service(VCHIQ_SERVICE_T *service); +vchiq_check_service(struct vchiq_service *service); extern void -vchiq_on_remote_use_active(VCHIQ_STATE_T *state); +vchiq_on_remote_use_active(struct vchiq_state *state); extern VCHIQ_STATUS_T -vchiq_send_remote_use(VCHIQ_STATE_T *state); +vchiq_send_remote_use(struct vchiq_state *state); extern VCHIQ_STATUS_T -vchiq_send_remote_release(VCHIQ_STATE_T *state); +vchiq_send_remote_release(struct vchiq_state *state); extern VCHIQ_STATUS_T -vchiq_send_remote_use_active(VCHIQ_STATE_T *state); +vchiq_send_remote_use_active(struct vchiq_state *state); extern void -vchiq_platform_conn_state_changed(VCHIQ_STATE_T *state, - VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate); +vchiq_platform_conn_state_changed(struct vchiq_state *state, + VCHIQ_CONNSTATE_T oldstate, + VCHIQ_CONNSTATE_T newstate); extern void -vchiq_platform_handle_timeout(VCHIQ_STATE_T *state); +vchiq_platform_handle_timeout(struct vchiq_state *state); extern void -vchiq_set_conn_state(VCHIQ_STATE_T *state, VCHIQ_CONNSTATE_T newstate); +vchiq_set_conn_state(struct vchiq_state *state, VCHIQ_CONNSTATE_T newstate); extern void vchiq_log_dump_mem(const char *label, uint32_t addr, const void *voidMem, diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c index 6a9e71a61142..3928287cf5f7 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c @@ -153,19 +153,7 @@ static int debugfs_usecount_show(struct seq_file *f, void *offset) return 0; } - -static int debugfs_usecount_open(struct inode *inode, struct file *file) -{ - return single_open(file, debugfs_usecount_show, inode->i_private); -} - -static const struct file_operations debugfs_usecount_fops = { - .owner = THIS_MODULE, - .open = debugfs_usecount_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(debugfs_usecount); static int debugfs_trace_show(struct seq_file *f, void *offset) { @@ -243,7 +231,8 @@ void vchiq_debugfs_add_instance(VCHIQ_INSTANCE_T instance) void vchiq_debugfs_remove_instance(VCHIQ_INSTANCE_T instance) { - VCHIQ_DEBUGFS_NODE_T *node = vchiq_instance_get_debugfs_node(instance); + struct vchiq_debugfs_node *node = + vchiq_instance_get_debugfs_node(instance); debugfs_remove_recursive(node->dentry); } diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h index 3af6397ada19..5be1a5663f51 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h @@ -36,9 +36,9 @@ #include "vchiq_core.h" -typedef struct vchiq_debugfs_node_struct { +struct vchiq_debugfs_node { struct dentry *dentry; -} VCHIQ_DEBUGFS_NODE_T; +}; void vchiq_debugfs_init(void); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h index e4109a83e628..13ed23eacfae 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_if.h @@ -34,12 +34,10 @@ #ifndef VCHIQ_IF_H #define VCHIQ_IF_H -#include "interface/vchi/vchi_mh.h" - #define VCHIQ_SERVICE_HANDLE_INVALID 0 #define VCHIQ_SLOT_SIZE 4096 -#define VCHIQ_MAX_MSG_SIZE (VCHIQ_SLOT_SIZE - sizeof(VCHIQ_HEADER_T)) +#define VCHIQ_MAX_MSG_SIZE (VCHIQ_SLOT_SIZE - sizeof(struct vchiq_header)) #define VCHIQ_CHANNEL_SIZE VCHIQ_MAX_MSG_SIZE /* For backwards compatibility */ #define VCHIQ_MAKE_FOURCC(x0, x1, x2, x3) \ @@ -78,7 +76,7 @@ typedef enum { VCHIQ_SERVICE_OPTION_TRACE } VCHIQ_SERVICE_OPTION_T; -typedef struct vchiq_header_struct { +struct vchiq_header { /* The message identifier - opaque to applications. */ int msgid; @@ -86,33 +84,34 @@ typedef struct vchiq_header_struct { unsigned int size; char data[0]; /* message */ -} VCHIQ_HEADER_T; +}; struct vchiq_element { - const void *data; + const void __user *data; unsigned int size; }; typedef unsigned int VCHIQ_SERVICE_HANDLE_T; -typedef VCHIQ_STATUS_T (*VCHIQ_CALLBACK_T)(VCHIQ_REASON_T, VCHIQ_HEADER_T *, - VCHIQ_SERVICE_HANDLE_T, void *); +typedef VCHIQ_STATUS_T (*VCHIQ_CALLBACK_T)(VCHIQ_REASON_T, + struct vchiq_header *, + VCHIQ_SERVICE_HANDLE_T, void *); -typedef struct vchiq_service_base_struct { +struct vchiq_service_base { int fourcc; VCHIQ_CALLBACK_T callback; void *userdata; -} VCHIQ_SERVICE_BASE_T; +}; -typedef struct vchiq_service_params_struct { +struct vchiq_service_params { int fourcc; VCHIQ_CALLBACK_T callback; void *userdata; short version; /* Increment for non-trivial changes */ short version_min; /* Update for incompatible changes */ -} VCHIQ_SERVICE_PARAMS_T; +}; -typedef struct vchiq_config_struct { +struct vchiq_config { unsigned int max_msg_size; unsigned int bulk_threshold; /* The message size above which it is better to use a bulk transfer @@ -121,7 +120,7 @@ typedef struct vchiq_config_struct { unsigned int max_services; short version; /* The version of VCHIQ */ short version_min; /* The minimum compatible version of VCHIQ */ -} VCHIQ_CONFIG_T; +}; typedef struct vchiq_instance_struct *VCHIQ_INSTANCE_T; typedef void (*VCHIQ_REMOTE_USE_CALLBACK_T)(void *cb_arg); @@ -130,10 +129,10 @@ extern VCHIQ_STATUS_T vchiq_initialise(VCHIQ_INSTANCE_T *pinstance); extern VCHIQ_STATUS_T vchiq_shutdown(VCHIQ_INSTANCE_T instance); extern VCHIQ_STATUS_T vchiq_connect(VCHIQ_INSTANCE_T instance); extern VCHIQ_STATUS_T vchiq_add_service(VCHIQ_INSTANCE_T instance, - const VCHIQ_SERVICE_PARAMS_T *params, + const struct vchiq_service_params *params, VCHIQ_SERVICE_HANDLE_T *pservice); extern VCHIQ_STATUS_T vchiq_open_service(VCHIQ_INSTANCE_T instance, - const VCHIQ_SERVICE_PARAMS_T *params, + const struct vchiq_service_params *params, VCHIQ_SERVICE_HANDLE_T *pservice); extern VCHIQ_STATUS_T vchiq_close_service(VCHIQ_SERVICE_HANDLE_T service); extern VCHIQ_STATUS_T vchiq_remove_service(VCHIQ_SERVICE_HANDLE_T service); @@ -148,7 +147,7 @@ vchiq_queue_message(VCHIQ_SERVICE_HANDLE_T handle, void *context, size_t size); extern void vchiq_release_message(VCHIQ_SERVICE_HANDLE_T service, - VCHIQ_HEADER_T *header); + struct vchiq_header *header); extern VCHIQ_STATUS_T vchiq_bulk_transmit(VCHIQ_SERVICE_HANDLE_T service, const void *data, unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode); @@ -156,16 +155,15 @@ extern VCHIQ_STATUS_T vchiq_bulk_receive(VCHIQ_SERVICE_HANDLE_T service, void *data, unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode); extern VCHIQ_STATUS_T vchiq_bulk_transmit_handle(VCHIQ_SERVICE_HANDLE_T service, - VCHI_MEM_HANDLE_T handle, const void *offset, unsigned int size, + const void *offset, unsigned int size, void *userdata, VCHIQ_BULK_MODE_T mode); extern VCHIQ_STATUS_T vchiq_bulk_receive_handle(VCHIQ_SERVICE_HANDLE_T service, - VCHI_MEM_HANDLE_T handle, void *offset, unsigned int size, - void *userdata, VCHIQ_BULK_MODE_T mode); + void *offset, unsigned int size, void *userdata, + VCHIQ_BULK_MODE_T mode); extern int vchiq_get_client_id(VCHIQ_SERVICE_HANDLE_T service); extern void *vchiq_get_service_userdata(VCHIQ_SERVICE_HANDLE_T service); extern int vchiq_get_service_fourcc(VCHIQ_SERVICE_HANDLE_T service); -extern VCHIQ_STATUS_T vchiq_get_config(VCHIQ_INSTANCE_T instance, - int config_size, VCHIQ_CONFIG_T *pconfig); +extern void vchiq_get_config(struct vchiq_config *config); extern VCHIQ_STATUS_T vchiq_set_service_option(VCHIQ_SERVICE_HANDLE_T service, VCHIQ_SERVICE_OPTION_T option, int value); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h index 9f859953f45c..56aef490e870 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h @@ -40,90 +40,90 @@ #define VCHIQ_IOC_MAGIC 0xc4 #define VCHIQ_INVALID_HANDLE (~0) -typedef struct { - VCHIQ_SERVICE_PARAMS_T params; +struct vchiq_create_service { + struct vchiq_service_params params; int is_open; int is_vchi; unsigned int handle; /* OUT */ -} VCHIQ_CREATE_SERVICE_T; +}; -typedef struct { +struct vchiq_queue_message { unsigned int handle; unsigned int count; - const struct vchiq_element *elements; -} VCHIQ_QUEUE_MESSAGE_T; + const struct vchiq_element __user *elements; +}; -typedef struct { +struct vchiq_queue_bulk_transfer { unsigned int handle; void *data; unsigned int size; void *userdata; VCHIQ_BULK_MODE_T mode; -} VCHIQ_QUEUE_BULK_TRANSFER_T; +}; -typedef struct { +struct vchiq_completion_data { VCHIQ_REASON_T reason; - VCHIQ_HEADER_T *header; + struct vchiq_header *header; void *service_userdata; void *bulk_userdata; -} VCHIQ_COMPLETION_DATA_T; +}; -typedef struct { +struct vchiq_await_completion { unsigned int count; - VCHIQ_COMPLETION_DATA_T *buf; + struct vchiq_completion_data *buf; unsigned int msgbufsize; unsigned int msgbufcount; /* IN/OUT */ void **msgbufs; -} VCHIQ_AWAIT_COMPLETION_T; +}; -typedef struct { +struct vchiq_dequeue_message { unsigned int handle; int blocking; unsigned int bufsize; void *buf; -} VCHIQ_DEQUEUE_MESSAGE_T; +}; -typedef struct { +struct vchiq_get_config { unsigned int config_size; - VCHIQ_CONFIG_T *pconfig; -} VCHIQ_GET_CONFIG_T; + struct vchiq_config __user *pconfig; +}; -typedef struct { +struct vchiq_set_service_option { unsigned int handle; VCHIQ_SERVICE_OPTION_T option; int value; -} VCHIQ_SET_SERVICE_OPTION_T; +}; -typedef struct { +struct vchiq_dump_mem { void *virt_addr; size_t num_bytes; -} VCHIQ_DUMP_MEM_T; +}; #define VCHIQ_IOC_CONNECT _IO(VCHIQ_IOC_MAGIC, 0) #define VCHIQ_IOC_SHUTDOWN _IO(VCHIQ_IOC_MAGIC, 1) #define VCHIQ_IOC_CREATE_SERVICE \ - _IOWR(VCHIQ_IOC_MAGIC, 2, VCHIQ_CREATE_SERVICE_T) + _IOWR(VCHIQ_IOC_MAGIC, 2, struct vchiq_create_service) #define VCHIQ_IOC_REMOVE_SERVICE _IO(VCHIQ_IOC_MAGIC, 3) #define VCHIQ_IOC_QUEUE_MESSAGE \ - _IOW(VCHIQ_IOC_MAGIC, 4, VCHIQ_QUEUE_MESSAGE_T) + _IOW(VCHIQ_IOC_MAGIC, 4, struct vchiq_queue_message) #define VCHIQ_IOC_QUEUE_BULK_TRANSMIT \ - _IOWR(VCHIQ_IOC_MAGIC, 5, VCHIQ_QUEUE_BULK_TRANSFER_T) + _IOWR(VCHIQ_IOC_MAGIC, 5, struct vchiq_queue_bulk_transfer) #define VCHIQ_IOC_QUEUE_BULK_RECEIVE \ - _IOWR(VCHIQ_IOC_MAGIC, 6, VCHIQ_QUEUE_BULK_TRANSFER_T) + _IOWR(VCHIQ_IOC_MAGIC, 6, struct vchiq_queue_bulk_transfer) #define VCHIQ_IOC_AWAIT_COMPLETION \ - _IOWR(VCHIQ_IOC_MAGIC, 7, VCHIQ_AWAIT_COMPLETION_T) + _IOWR(VCHIQ_IOC_MAGIC, 7, struct vchiq_await_completion) #define VCHIQ_IOC_DEQUEUE_MESSAGE \ - _IOWR(VCHIQ_IOC_MAGIC, 8, VCHIQ_DEQUEUE_MESSAGE_T) + _IOWR(VCHIQ_IOC_MAGIC, 8, struct vchiq_dequeue_message) #define VCHIQ_IOC_GET_CLIENT_ID _IO(VCHIQ_IOC_MAGIC, 9) #define VCHIQ_IOC_GET_CONFIG \ - _IOWR(VCHIQ_IOC_MAGIC, 10, VCHIQ_GET_CONFIG_T) + _IOWR(VCHIQ_IOC_MAGIC, 10, struct vchiq_get_config) #define VCHIQ_IOC_CLOSE_SERVICE _IO(VCHIQ_IOC_MAGIC, 11) #define VCHIQ_IOC_USE_SERVICE _IO(VCHIQ_IOC_MAGIC, 12) #define VCHIQ_IOC_RELEASE_SERVICE _IO(VCHIQ_IOC_MAGIC, 13) #define VCHIQ_IOC_SET_SERVICE_OPTION \ - _IOW(VCHIQ_IOC_MAGIC, 14, VCHIQ_SET_SERVICE_OPTION_T) + _IOW(VCHIQ_IOC_MAGIC, 14, struct vchiq_set_service_option) #define VCHIQ_IOC_DUMP_PHYS_MEM \ - _IOW(VCHIQ_IOC_MAGIC, 15, VCHIQ_DUMP_MEM_T) + _IOW(VCHIQ_IOC_MAGIC, 15, struct vchiq_dump_mem) #define VCHIQ_IOC_LIB_VERSION _IO(VCHIQ_IOC_MAGIC, 16) #define VCHIQ_IOC_CLOSE_DELIVERED _IO(VCHIQ_IOC_MAGIC, 17) #define VCHIQ_IOC_MAX 17 diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_killable.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_killable.h deleted file mode 100644 index 778063ba312a..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_killable.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) 2010-2012 Broadcom. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the above-listed copyright holders may not be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * ALTERNATIVELY, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2, as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef VCHIQ_KILLABLE_H -#define VCHIQ_KILLABLE_H - -#include <linux/mutex.h> -#include <linux/semaphore.h> - -#define SHUTDOWN_SIGS (sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTRAP) | sigmask(SIGSTOP) | sigmask(SIGCONT)) - -static inline int __must_check down_interruptible_killable(struct semaphore *sem) -{ - /* Allow interception of killable signals only. We don't want to be interrupted by harmless signals like SIGALRM */ - int ret; - sigset_t blocked, oldset; - siginitsetinv(&blocked, SHUTDOWN_SIGS); - sigprocmask(SIG_SETMASK, &blocked, &oldset); - ret = down_interruptible(sem); - sigprocmask(SIG_SETMASK, &oldset, NULL); - return ret; -} -#define down_interruptible down_interruptible_killable - -#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h index bec411061554..4eaf7398cf2e 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h @@ -38,7 +38,7 @@ #define PAGELIST_READ 1 #define PAGELIST_READ_WITH_FRAGMENTS 2 -typedef struct pagelist_struct { +struct pagelist { u32 length; u16 type; u16 offset; @@ -46,6 +46,6 @@ typedef struct pagelist_struct { * of following pages at consecutive * addresses. */ -} PAGELIST_T; +}; #endif /* VCHIQ_PAGELIST_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c index c3223fcdaf87..ab6ca8fd6f14 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_shim.c @@ -44,7 +44,7 @@ struct shim_service { VCHIQ_SERVICE_HANDLE_T handle; - VCHIU_QUEUE_T queue; + struct vchiu_queue queue; VCHI_CALLBACK_T callback; void *callback_param; @@ -72,7 +72,7 @@ int32_t vchi_msg_peek(VCHI_SERVICE_HANDLE_T handle, VCHI_FLAGS_T flags) { struct shim_service *service = (struct shim_service *)handle; - VCHIQ_HEADER_T *header; + struct vchiq_header *header; WARN_ON((flags != VCHI_FLAGS_NONE) && (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); @@ -104,7 +104,7 @@ EXPORT_SYMBOL(vchi_msg_peek); int32_t vchi_msg_remove(VCHI_SERVICE_HANDLE_T handle) { struct shim_service *service = (struct shim_service *)handle; - VCHIQ_HEADER_T *header; + struct vchiq_header *header; header = vchiu_queue_pop(&service->queue); @@ -357,7 +357,7 @@ int32_t vchi_msg_dequeue(VCHI_SERVICE_HANDLE_T handle, VCHI_FLAGS_T flags) { struct shim_service *service = (struct shim_service *)handle; - VCHIQ_HEADER_T *header; + struct vchiq_header *header; WARN_ON((flags != VCHI_FLAGS_NONE) && (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); @@ -382,7 +382,7 @@ EXPORT_SYMBOL(vchi_msg_dequeue); /*********************************************************** * Name: vchi_held_msg_release * - * Arguments: VCHI_HELD_MSG_T *message + * Arguments: struct vchi_held_msg *message * * Description: Routine to release a held message (after it has been read with * vchi_msg_hold) @@ -390,7 +390,7 @@ EXPORT_SYMBOL(vchi_msg_dequeue); * Returns: int32_t - success == 0 * ***********************************************************/ -int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message) +int32_t vchi_held_msg_release(struct vchi_held_msg *message) { /* * Convert the service field pointer back to an @@ -401,7 +401,7 @@ int32_t vchi_held_msg_release(VCHI_HELD_MSG_T *message) */ vchiq_release_message((VCHIQ_SERVICE_HANDLE_T)(long)message->service, - (VCHIQ_HEADER_T *)message->message); + (struct vchiq_header *)message->message); return 0; } @@ -414,7 +414,7 @@ EXPORT_SYMBOL(vchi_held_msg_release); * void **data, * uint32_t *msg_size, * VCHI_FLAGS_T flags, - * VCHI_HELD_MSG_T *message_handle + * struct vchi_held_msg *message_handle * * Description: Routine to return a pointer to the current message (to allow * in place processing). The message is dequeued - don't forget @@ -428,10 +428,10 @@ int32_t vchi_msg_hold(VCHI_SERVICE_HANDLE_T handle, void **data, uint32_t *msg_size, VCHI_FLAGS_T flags, - VCHI_HELD_MSG_T *message_handle) + struct vchi_held_msg *message_handle) { struct shim_service *service = (struct shim_service *)handle; - VCHIQ_HEADER_T *header; + struct vchiq_header *header; WARN_ON((flags != VCHI_FLAGS_NONE) && (flags != VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE)); @@ -530,7 +530,7 @@ EXPORT_SYMBOL(vchi_disconnect); * Name: vchi_service_create * * Arguments: VCHI_INSTANCE_T *instance_handle - * SERVICE_CREATION_T *setup, + * struct service_creation *setup, * VCHI_SERVICE_HANDLE_T *handle * * Description: Routine to open a service @@ -540,7 +540,9 @@ EXPORT_SYMBOL(vchi_disconnect); ***********************************************************/ static VCHIQ_STATUS_T shim_callback(VCHIQ_REASON_T reason, - VCHIQ_HEADER_T *header, VCHIQ_SERVICE_HANDLE_T handle, void *bulk_user) + struct vchiq_header *header, + VCHIQ_SERVICE_HANDLE_T handle, + void *bulk_user) { struct shim_service *service = (struct shim_service *)VCHIQ_GET_SERVICE_USERDATA(handle); @@ -600,7 +602,7 @@ done: } static struct shim_service *service_alloc(VCHIQ_INSTANCE_T instance, - SERVICE_CREATION_T *setup) + struct service_creation *setup) { struct shim_service *service = kzalloc(sizeof(struct shim_service), GFP_KERNEL); @@ -628,7 +630,7 @@ static void service_free(struct shim_service *service) } int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle, - SERVICE_CREATION_T *setup, + struct service_creation *setup, VCHI_SERVICE_HANDLE_T *handle) { VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; @@ -637,7 +639,7 @@ int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle, *handle = (VCHI_SERVICE_HANDLE_T)service; if (service) { - VCHIQ_SERVICE_PARAMS_T params; + struct vchiq_service_params params; VCHIQ_STATUS_T status; memset(¶ms, 0, sizeof(params)); @@ -660,38 +662,6 @@ int32_t vchi_service_open(VCHI_INSTANCE_T instance_handle, } EXPORT_SYMBOL(vchi_service_open); -int32_t vchi_service_create(VCHI_INSTANCE_T instance_handle, - SERVICE_CREATION_T *setup, - VCHI_SERVICE_HANDLE_T *handle) -{ - VCHIQ_INSTANCE_T instance = (VCHIQ_INSTANCE_T)instance_handle; - struct shim_service *service = service_alloc(instance, setup); - - *handle = (VCHI_SERVICE_HANDLE_T)service; - - if (service) { - VCHIQ_SERVICE_PARAMS_T params; - VCHIQ_STATUS_T status; - - memset(¶ms, 0, sizeof(params)); - params.fourcc = setup->service_id; - params.callback = shim_callback; - params.userdata = service; - params.version = setup->version.version; - params.version_min = setup->version.version_min; - status = vchiq_add_service(instance, ¶ms, &service->handle); - - if (status != VCHIQ_SUCCESS) { - service_free(service); - service = NULL; - *handle = NULL; - } - } - - return (service != NULL) ? 0 : -1; -} -EXPORT_SYMBOL(vchi_service_create); - int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle) { int32_t ret = -1; diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c index 2e52f07bbaa9..55c5fd82b911 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.c @@ -32,14 +32,13 @@ */ #include "vchiq_util.h" -#include "vchiq_killable.h" static inline int is_pow2(int i) { return i && !(i & (i - 1)); } -int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size) +int vchiu_queue_init(struct vchiu_queue *queue, int size) { WARN_ON(!is_pow2(size)); @@ -48,10 +47,11 @@ int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size) queue->write = 0; queue->initialized = 1; - sema_init(&queue->pop, 0); - sema_init(&queue->push, 0); + init_completion(&queue->pop); + init_completion(&queue->push); - queue->storage = kcalloc(size, sizeof(VCHIQ_HEADER_T *), GFP_KERNEL); + queue->storage = kcalloc(size, sizeof(struct vchiq_header *), + GFP_KERNEL); if (!queue->storage) { vchiu_queue_delete(queue); return 0; @@ -59,94 +59,62 @@ int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size) return 1; } -void vchiu_queue_delete(VCHIU_QUEUE_T *queue) +void vchiu_queue_delete(struct vchiu_queue *queue) { kfree(queue->storage); } -int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue) +int vchiu_queue_is_empty(struct vchiu_queue *queue) { return queue->read == queue->write; } -int vchiu_queue_is_full(VCHIU_QUEUE_T *queue) +int vchiu_queue_is_full(struct vchiu_queue *queue) { return queue->write == queue->read + queue->size; } -void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header) +void vchiu_queue_push(struct vchiu_queue *queue, struct vchiq_header *header) { if (!queue->initialized) return; while (queue->write == queue->read + queue->size) { - if (down_interruptible(&queue->pop) != 0) + if (wait_for_completion_killable(&queue->pop)) flush_signals(current); } - /* - * Write to queue->storage must be visible after read from - * queue->read - */ - smp_mb(); - queue->storage[queue->write & (queue->size - 1)] = header; - - /* - * Write to queue->storage must be visible before write to - * queue->write - */ - smp_wmb(); - queue->write++; - up(&queue->push); + complete(&queue->push); } -VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue) +struct vchiq_header *vchiu_queue_peek(struct vchiu_queue *queue) { while (queue->write == queue->read) { - if (down_interruptible(&queue->push) != 0) + if (wait_for_completion_killable(&queue->push)) flush_signals(current); } - up(&queue->push); // We haven't removed anything from the queue. - - /* - * Read from queue->storage must be visible after read from - * queue->write - */ - smp_rmb(); + complete(&queue->push); // We haven't removed anything from the queue. return queue->storage[queue->read & (queue->size - 1)]; } -VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue) +struct vchiq_header *vchiu_queue_pop(struct vchiu_queue *queue) { - VCHIQ_HEADER_T *header; + struct vchiq_header *header; while (queue->write == queue->read) { - if (down_interruptible(&queue->push) != 0) + if (wait_for_completion_killable(&queue->push)) flush_signals(current); } - /* - * Read from queue->storage must be visible after read from - * queue->write - */ - smp_rmb(); - header = queue->storage[queue->read & (queue->size - 1)]; - - /* - * Read from queue->storage must be visible before write to - * queue->read - */ - smp_mb(); - queue->read++; - up(&queue->pop); + complete(&queue->pop); return header; } diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.h index 5a1540d349d3..d842194b4023 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.h +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_util.h @@ -35,7 +35,7 @@ #define VCHIQ_UTIL_H #include <linux/types.h> -#include <linux/semaphore.h> +#include <linux/completion.h> #include <linux/mutex.h> #include <linux/bitops.h> #include <linux/kthread.h> @@ -54,27 +54,28 @@ #include "vchiq_if.h" -typedef struct { +struct vchiu_queue { int size; int read; int write; int initialized; - struct semaphore pop; - struct semaphore push; + struct completion pop; + struct completion push; - VCHIQ_HEADER_T **storage; -} VCHIU_QUEUE_T; + struct vchiq_header **storage; +}; -extern int vchiu_queue_init(VCHIU_QUEUE_T *queue, int size); -extern void vchiu_queue_delete(VCHIU_QUEUE_T *queue); +extern int vchiu_queue_init(struct vchiu_queue *queue, int size); +extern void vchiu_queue_delete(struct vchiu_queue *queue); -extern int vchiu_queue_is_empty(VCHIU_QUEUE_T *queue); -extern int vchiu_queue_is_full(VCHIU_QUEUE_T *queue); +extern int vchiu_queue_is_empty(struct vchiu_queue *queue); +extern int vchiu_queue_is_full(struct vchiu_queue *queue); -extern void vchiu_queue_push(VCHIU_QUEUE_T *queue, VCHIQ_HEADER_T *header); +extern void vchiu_queue_push(struct vchiu_queue *queue, + struct vchiq_header *header); -extern VCHIQ_HEADER_T *vchiu_queue_peek(VCHIU_QUEUE_T *queue); -extern VCHIQ_HEADER_T *vchiu_queue_pop(VCHIU_QUEUE_T *queue); +extern struct vchiq_header *vchiu_queue_peek(struct vchiu_queue *queue); +extern struct vchiq_header *vchiu_queue_pop(struct vchiu_queue *queue); #endif |