pcmcia: soc_common: switch to a per-socket cpufreq notifier
authorRussell King <rmk+kernel@armlinux.org.uk>
Wed, 31 Aug 2016 07:49:46 +0000 (08:49 +0100)
committerRussell King <rmk+kernel@armlinux.org.uk>
Thu, 22 Sep 2016 08:39:03 +0000 (09:39 +0100)
Switch to a per-socket cpufreq notifier rather than a global notifier.
This allows each socket to be self-contained.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
drivers/pcmcia/soc_common.c
drivers/pcmcia/soc_common.h

index 15e332aca0f321b5f61ecbb675811d5898792fba..6138c14a55663f81c6991b4f3b7af1c3b4a7aaf6 100644 (file)
@@ -732,50 +732,15 @@ static struct pccard_operations soc_common_pcmcia_operations = {
 };
 
 
-static LIST_HEAD(soc_pcmcia_sockets);
-static DEFINE_MUTEX(soc_pcmcia_sockets_lock);
-
 #ifdef CONFIG_CPU_FREQ
-static int
-soc_pcmcia_notifier(struct notifier_block *nb, unsigned long val, void *data)
+static int soc_common_pcmcia_cpufreq_nb(struct notifier_block *nb,
+       unsigned long val, void *data)
 {
-       struct soc_pcmcia_socket *skt;
+       struct soc_pcmcia_socket *skt = container_of(nb, struct soc_pcmcia_socket, cpufreq_nb);
        struct cpufreq_freqs *freqs = data;
-       int ret = 0;
-
-       mutex_lock(&soc_pcmcia_sockets_lock);
-       list_for_each_entry(skt, &soc_pcmcia_sockets, node)
-               if (skt->ops->frequency_change)
-                       ret += skt->ops->frequency_change(skt, val, freqs);
-       mutex_unlock(&soc_pcmcia_sockets_lock);
-
-       return ret;
-}
-
-static struct notifier_block soc_pcmcia_notifier_block = {
-       .notifier_call  = soc_pcmcia_notifier
-};
-
-static int soc_pcmcia_cpufreq_register(void)
-{
-       int ret;
-
-       ret = cpufreq_register_notifier(&soc_pcmcia_notifier_block,
-                                       CPUFREQ_TRANSITION_NOTIFIER);
-       if (ret < 0)
-               printk(KERN_ERR "Unable to register CPU frequency change "
-                               "notifier for PCMCIA (%d)\n", ret);
-       return ret;
-}
-fs_initcall(soc_pcmcia_cpufreq_register);
 
-static void soc_pcmcia_cpufreq_unregister(void)
-{
-       cpufreq_unregister_notifier(&soc_pcmcia_notifier_block,
-               CPUFREQ_TRANSITION_NOTIFIER);
+       return skt->ops->frequency_change(skt, val, freqs);
 }
-module_exit(soc_pcmcia_cpufreq_unregister);
-
 #endif
 
 void soc_pcmcia_init_one(struct soc_pcmcia_socket *skt,
@@ -795,19 +760,21 @@ EXPORT_SYMBOL(soc_pcmcia_init_one);
 
 void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt)
 {
-       mutex_lock(&soc_pcmcia_sockets_lock);
        del_timer_sync(&skt->poll_timer);
 
        pcmcia_unregister_socket(&skt->socket);
 
+#ifdef CONFIG_CPU_FREQ
+       if (skt->ops->frequency_change)
+               cpufreq_unregister_notifier(&skt->cpufreq_nb,
+                                           CPUFREQ_TRANSITION_NOTIFIER);
+#endif
+
        soc_pcmcia_hw_shutdown(skt);
 
        /* should not be required; violates some lowlevel drivers */
        soc_common_pcmcia_config_skt(skt, &dead_socket);
 
-       list_del(&skt->node);
-       mutex_unlock(&soc_pcmcia_sockets_lock);
-
        iounmap(skt->virt_io);
        skt->virt_io = NULL;
        release_resource(&skt->res_attr);
@@ -849,10 +816,6 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
                goto out_err_5;
        }
 
-       mutex_lock(&soc_pcmcia_sockets_lock);
-
-       list_add(&skt->node, &soc_pcmcia_sockets);
-
        /*
         * We initialize default socket timing here, because
         * we are not guaranteed to see a SetIOMap operation at
@@ -873,14 +836,23 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
 
        skt->status = soc_common_pcmcia_skt_state(skt);
 
+#ifdef CONFIG_CPU_FREQ
+       if (skt->ops->frequency_change) {
+               skt->cpufreq_nb.notifier_call = soc_common_pcmcia_cpufreq_nb;
+
+               ret = cpufreq_register_notifier(&skt->cpufreq_nb,
+                                               CPUFREQ_TRANSITION_NOTIFIER);
+               if (ret < 0)
+                       dev_err(skt->socket.dev.parent,
+                               "unable to register CPU frequency change notifier for PCMCIA (%d)\n",
+                               ret);
+       }
+#endif
+
        ret = pcmcia_register_socket(&skt->socket);
        if (ret)
                goto out_err_7;
 
-       add_timer(&skt->poll_timer);
-
-       mutex_unlock(&soc_pcmcia_sockets_lock);
-
        ret = device_create_file(&skt->socket.dev, &dev_attr_status);
        if (ret)
                goto out_err_8;
@@ -888,15 +860,12 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
        return ret;
 
  out_err_8:
-       mutex_lock(&soc_pcmcia_sockets_lock);
        del_timer_sync(&skt->poll_timer);
        pcmcia_unregister_socket(&skt->socket);
 
  out_err_7:
        soc_pcmcia_hw_shutdown(skt);
  out_err_6:
-       list_del(&skt->node);
-       mutex_unlock(&soc_pcmcia_sockets_lock);
        iounmap(skt->virt_io);
  out_err_5:
        release_resource(&skt->res_attr);
index 18a6df5ca374fdf522381ae6188e0f59d569546c..f66e2fb1f33f864149730a49286579f8183c22ad 100644 (file)
@@ -75,6 +75,9 @@ struct soc_pcmcia_socket {
 
        unsigned int            irq_state;
 
+#ifdef CONFIG_CPU_FREQ
+       struct notifier_block   cpufreq_nb;
+#endif
        struct timer_list       poll_timer;
        struct list_head        node;
 };