hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/memstick/host/rtsx_usb_ms.c
....@@ -1,18 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /* Realtek USB Memstick Card Interface driver
23 *
34 * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
4
- *
5
- * This program is free software; you can redistribute it and/or modify it
6
- * under the terms of the GNU General Public License version 2
7
- * as published by the Free Software Foundation.
8
- *
9
- * This program is distributed in the hope that it will be useful, but
10
- * WITHOUT ANY WARRANTY; without even the implied warranty of
11
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
- * General Public License for more details.
13
- *
14
- * You should have received a copy of the GNU General Public License along
15
- * with this program; if not, see <http://www.gnu.org/licenses/>.
165 *
176 * Author:
187 * Roger Tseng <rogerable@realtek.com>
....@@ -40,15 +29,14 @@
4029
4130 struct mutex host_mutex;
4231 struct work_struct handle_req;
43
-
44
- struct task_struct *detect_ms;
45
- struct completion detect_ms_exit;
32
+ struct delayed_work poll_card;
4633
4734 u8 ssc_depth;
4835 unsigned int clock;
4936 int power_mode;
5037 unsigned char ifmode;
5138 bool eject;
39
+ bool system_suspending;
5240 };
5341
5442 static inline struct device *ms_dev(struct rtsx_usb_ms *host)
....@@ -545,7 +533,7 @@
545533 host->req->error);
546534 }
547535 } while (!rc);
548
- pm_runtime_put(ms_dev(host));
536
+ pm_runtime_put_sync(ms_dev(host));
549537 }
550538
551539 }
....@@ -585,14 +573,14 @@
585573 break;
586574
587575 if (value == MEMSTICK_POWER_ON) {
588
- pm_runtime_get_sync(ms_dev(host));
576
+ pm_runtime_get_noresume(ms_dev(host));
589577 err = ms_power_on(host);
578
+ if (err)
579
+ pm_runtime_put_noidle(ms_dev(host));
590580 } else if (value == MEMSTICK_POWER_OFF) {
591581 err = ms_power_off(host);
592
- if (host->msh->card)
582
+ if (!err)
593583 pm_runtime_put_noidle(ms_dev(host));
594
- else
595
- pm_runtime_put(ms_dev(host));
596584 } else
597585 err = -EINVAL;
598586 if (!err)
....@@ -638,11 +626,15 @@
638626 }
639627 out:
640628 mutex_unlock(&ucr->dev_mutex);
641
- pm_runtime_put(ms_dev(host));
629
+ pm_runtime_put_sync(ms_dev(host));
642630
643631 /* power-on delay */
644
- if (param == MEMSTICK_POWER && value == MEMSTICK_POWER_ON)
632
+ if (param == MEMSTICK_POWER && value == MEMSTICK_POWER_ON) {
645633 usleep_range(10000, 12000);
634
+
635
+ if (!host->eject)
636
+ schedule_delayed_work(&host->poll_card, 100);
637
+ }
646638
647639 dev_dbg(ms_dev(host), "%s: return = %d\n", __func__, err);
648640 return err;
....@@ -654,9 +646,24 @@
654646 struct rtsx_usb_ms *host = dev_get_drvdata(dev);
655647 struct memstick_host *msh = host->msh;
656648
657
- dev_dbg(ms_dev(host), "--> %s\n", __func__);
649
+ /* Since we use rtsx_usb's resume callback to runtime resume its
650
+ * children to implement remote wakeup signaling, this causes
651
+ * rtsx_usb_ms' runtime resume callback runs after its suspend
652
+ * callback:
653
+ * rtsx_usb_ms_suspend()
654
+ * rtsx_usb_resume()
655
+ * -> rtsx_usb_ms_runtime_resume()
656
+ * -> memstick_detect_change()
657
+ *
658
+ * rtsx_usb_suspend()
659
+ *
660
+ * To avoid this, skip runtime resume/suspend if system suspend is
661
+ * underway.
662
+ */
658663
664
+ host->system_suspending = true;
659665 memstick_suspend_host(msh);
666
+
660667 return 0;
661668 }
662669
....@@ -665,58 +672,85 @@
665672 struct rtsx_usb_ms *host = dev_get_drvdata(dev);
666673 struct memstick_host *msh = host->msh;
667674
668
- dev_dbg(ms_dev(host), "--> %s\n", __func__);
669
-
670675 memstick_resume_host(msh);
676
+ host->system_suspending = false;
677
+
671678 return 0;
672679 }
673680 #endif /* CONFIG_PM_SLEEP */
674681
675
-/*
676
- * Thread function of ms card slot detection. The thread starts right after
677
- * successful host addition. It stops while the driver removal function sets
678
- * host->eject true.
679
- */
680
-static int rtsx_usb_detect_ms_card(void *__host)
682
+#ifdef CONFIG_PM
683
+static int rtsx_usb_ms_runtime_suspend(struct device *dev)
681684 {
682
- struct rtsx_usb_ms *host = (struct rtsx_usb_ms *)__host;
685
+ struct rtsx_usb_ms *host = dev_get_drvdata(dev);
686
+
687
+ if (host->system_suspending)
688
+ return 0;
689
+
690
+ if (host->msh->card || host->power_mode != MEMSTICK_POWER_OFF)
691
+ return -EAGAIN;
692
+
693
+ return 0;
694
+}
695
+
696
+static int rtsx_usb_ms_runtime_resume(struct device *dev)
697
+{
698
+ struct rtsx_usb_ms *host = dev_get_drvdata(dev);
699
+
700
+
701
+ if (host->system_suspending)
702
+ return 0;
703
+
704
+ memstick_detect_change(host->msh);
705
+
706
+ return 0;
707
+}
708
+#endif /* CONFIG_PM */
709
+
710
+static const struct dev_pm_ops rtsx_usb_ms_pm_ops = {
711
+ SET_SYSTEM_SLEEP_PM_OPS(rtsx_usb_ms_suspend, rtsx_usb_ms_resume)
712
+ SET_RUNTIME_PM_OPS(rtsx_usb_ms_runtime_suspend, rtsx_usb_ms_runtime_resume, NULL)
713
+};
714
+
715
+
716
+static void rtsx_usb_ms_poll_card(struct work_struct *work)
717
+{
718
+ struct rtsx_usb_ms *host = container_of(work, struct rtsx_usb_ms,
719
+ poll_card.work);
683720 struct rtsx_ucr *ucr = host->ucr;
684
- u8 val = 0;
685721 int err;
722
+ u8 val;
686723
687
- for (;;) {
688
- pm_runtime_get_sync(ms_dev(host));
689
- mutex_lock(&ucr->dev_mutex);
724
+ if (host->eject || host->power_mode != MEMSTICK_POWER_ON)
725
+ return;
690726
691
- /* Check pending MS card changes */
692
- err = rtsx_usb_read_register(ucr, CARD_INT_PEND, &val);
693
- if (err) {
694
- mutex_unlock(&ucr->dev_mutex);
695
- goto poll_again;
696
- }
727
+ pm_runtime_get_sync(ms_dev(host));
728
+ mutex_lock(&ucr->dev_mutex);
697729
698
- /* Clear the pending */
699
- rtsx_usb_write_register(ucr, CARD_INT_PEND,
700
- XD_INT | MS_INT | SD_INT,
701
- XD_INT | MS_INT | SD_INT);
702
-
730
+ /* Check pending MS card changes */
731
+ err = rtsx_usb_read_register(ucr, CARD_INT_PEND, &val);
732
+ if (err) {
703733 mutex_unlock(&ucr->dev_mutex);
704
-
705
- if (val & MS_INT) {
706
- dev_dbg(ms_dev(host), "MS slot change detected\n");
707
- memstick_detect_change(host->msh);
708
- }
709
-
710
-poll_again:
711
- pm_runtime_put(ms_dev(host));
712
- if (host->eject)
713
- break;
714
-
715
- schedule_timeout_idle(HZ);
734
+ goto poll_again;
716735 }
717736
718
- complete(&host->detect_ms_exit);
719
- return 0;
737
+ /* Clear the pending */
738
+ rtsx_usb_write_register(ucr, CARD_INT_PEND,
739
+ XD_INT | MS_INT | SD_INT,
740
+ XD_INT | MS_INT | SD_INT);
741
+
742
+ mutex_unlock(&ucr->dev_mutex);
743
+
744
+ if (val & MS_INT) {
745
+ dev_dbg(ms_dev(host), "MS slot change detected\n");
746
+ memstick_detect_change(host->msh);
747
+ }
748
+
749
+poll_again:
750
+ pm_runtime_put_sync(ms_dev(host));
751
+
752
+ if (!host->eject && host->power_mode == MEMSTICK_POWER_ON)
753
+ schedule_delayed_work(&host->poll_card, 100);
720754 }
721755
722756 static int rtsx_usb_ms_drv_probe(struct platform_device *pdev)
....@@ -747,28 +781,26 @@
747781 mutex_init(&host->host_mutex);
748782 INIT_WORK(&host->handle_req, rtsx_usb_ms_handle_req);
749783
750
- init_completion(&host->detect_ms_exit);
751
- host->detect_ms = kthread_create(rtsx_usb_detect_ms_card, host,
752
- "rtsx_usb_ms_%d", pdev->id);
753
- if (IS_ERR(host->detect_ms)) {
754
- dev_dbg(&(pdev->dev),
755
- "Unable to create polling thread.\n");
756
- err = PTR_ERR(host->detect_ms);
757
- goto err_out;
758
- }
784
+ INIT_DELAYED_WORK(&host->poll_card, rtsx_usb_ms_poll_card);
759785
760786 msh->request = rtsx_usb_ms_request;
761787 msh->set_param = rtsx_usb_ms_set_param;
762788 msh->caps = MEMSTICK_CAP_PAR4;
763789
764
- pm_runtime_enable(&pdev->dev);
790
+ pm_runtime_get_noresume(ms_dev(host));
791
+ pm_runtime_set_active(ms_dev(host));
792
+ pm_runtime_enable(ms_dev(host));
793
+
765794 err = memstick_add_host(msh);
766795 if (err)
767796 goto err_out;
768797
769
- wake_up_process(host->detect_ms);
798
+ pm_runtime_put(ms_dev(host));
799
+
770800 return 0;
771801 err_out:
802
+ pm_runtime_disable(ms_dev(host));
803
+ pm_runtime_put_noidle(ms_dev(host));
772804 memstick_free_host(msh);
773805 return err;
774806 }
....@@ -776,16 +808,15 @@
776808 static int rtsx_usb_ms_drv_remove(struct platform_device *pdev)
777809 {
778810 struct rtsx_usb_ms *host = platform_get_drvdata(pdev);
779
- struct memstick_host *msh;
811
+ struct memstick_host *msh = host->msh;
780812 int err;
781813
782
- msh = host->msh;
783814 host->eject = true;
784815 cancel_work_sync(&host->handle_req);
785816
786817 mutex_lock(&host->host_mutex);
787818 if (host->req) {
788
- dev_dbg(&(pdev->dev),
819
+ dev_dbg(ms_dev(host),
789820 "%s: Controller removed during transfer\n",
790821 dev_name(&msh->dev));
791822 host->req->error = -ENOMEDIUM;
....@@ -797,27 +828,21 @@
797828 }
798829 mutex_unlock(&host->host_mutex);
799830
800
- wait_for_completion(&host->detect_ms_exit);
801
- memstick_remove_host(msh);
802
- memstick_free_host(msh);
803
-
804831 /* Balance possible unbalanced usage count
805832 * e.g. unconditional module removal
806833 */
807834 if (pm_runtime_active(ms_dev(host)))
808835 pm_runtime_put(ms_dev(host));
809836
810
- pm_runtime_disable(&pdev->dev);
811
- platform_set_drvdata(pdev, NULL);
812
-
813
- dev_dbg(&(pdev->dev),
837
+ pm_runtime_disable(ms_dev(host));
838
+ memstick_remove_host(msh);
839
+ dev_dbg(ms_dev(host),
814840 ": Realtek USB Memstick controller has been removed\n");
841
+ memstick_free_host(msh);
842
+ platform_set_drvdata(pdev, NULL);
815843
816844 return 0;
817845 }
818
-
819
-static SIMPLE_DEV_PM_OPS(rtsx_usb_ms_pm_ops,
820
- rtsx_usb_ms_suspend, rtsx_usb_ms_resume);
821846
822847 static struct platform_device_id rtsx_usb_ms_ids[] = {
823848 {