@@ -481,6 +481,20 @@ static int timed_wait_for_timeout(struct ishtp_device *dev, int condition,
481481 return ret ;
482482}
483483
484+ static void ish_send_reset_notify_ack (struct ishtp_device * dev )
485+ {
486+ /* Read reset ID */
487+ u32 reset_id = ish_reg_read (dev , IPC_REG_ISH2HOST_MSG ) & 0xFFFF ;
488+
489+ /*
490+ * Set HOST2ISH.ILUP. Apparently we need this BEFORE sending
491+ * RESET_NOTIFY_ACK - FW will be checking for it
492+ */
493+ ish_set_host_rdy (dev );
494+ /* Send RESET_NOTIFY_ACK (with reset_id) */
495+ ipc_send_mng_msg (dev , MNG_RESET_NOTIFY_ACK , & reset_id , sizeof (u32 ));
496+ }
497+
484498#define TIME_SLICE_FOR_FW_RDY_MS 100
485499#define TIME_SLICE_FOR_INPUT_RDY_MS 100
486500#define TIMEOUT_FOR_FW_RDY_MS 2000
@@ -496,13 +510,9 @@ static int timed_wait_for_timeout(struct ishtp_device *dev, int condition,
496510 */
497511static int ish_fw_reset_handler (struct ishtp_device * dev )
498512{
499- uint32_t reset_id ;
500513 unsigned long flags ;
501514 int ret ;
502515
503- /* Read reset ID */
504- reset_id = ish_reg_read (dev , IPC_REG_ISH2HOST_MSG ) & 0xFFFF ;
505-
506516 /* Clear IPC output queue */
507517 spin_lock_irqsave (& dev -> wr_processing_spinlock , flags );
508518 list_splice_init (& dev -> wr_processing_list , & dev -> wr_free_list );
@@ -521,15 +531,6 @@ static int ish_fw_reset_handler(struct ishtp_device *dev)
521531 /* Send clock sync at once after reset */
522532 ishtp_dev -> prev_sync = 0 ;
523533
524- /*
525- * Set HOST2ISH.ILUP. Apparently we need this BEFORE sending
526- * RESET_NOTIFY_ACK - FW will be checking for it
527- */
528- ish_set_host_rdy (dev );
529- /* Send RESET_NOTIFY_ACK (with reset_id) */
530- ipc_send_mng_msg (dev , MNG_RESET_NOTIFY_ACK , & reset_id ,
531- sizeof (uint32_t ));
532-
533534 /* Wait for ISH FW'es ILUP and ISHTP_READY */
534535 ret = timed_wait_for_timeout (dev , WAIT_FOR_FW_RDY ,
535536 TIME_SLICE_FOR_FW_RDY_MS ,
@@ -563,8 +564,6 @@ static void fw_reset_work_fn(struct work_struct *work)
563564 if (!rv ) {
564565 /* ISH is ILUP & ISHTP-ready. Restart ISHTP */
565566 msleep_interruptible (TIMEOUT_FOR_HW_RDY_MS );
566- ishtp_dev -> recvd_hw_ready = 1 ;
567- wake_up_interruptible (& ishtp_dev -> wait_hw_ready );
568567
569568 /* ISHTP notification in IPC_RESET sequence completion */
570569 if (!work_pending (work ))
@@ -625,15 +624,14 @@ static void recv_ipc(struct ishtp_device *dev, uint32_t doorbell_val)
625624 break ;
626625
627626 case MNG_RESET_NOTIFY :
628- if (!ishtp_dev ) {
629- ishtp_dev = dev ;
630- }
631- schedule_work (& fw_reset_work );
632- break ;
627+ ish_send_reset_notify_ack (ishtp_dev );
628+ fallthrough ;
633629
634630 case MNG_RESET_NOTIFY_ACK :
635631 dev -> recvd_hw_ready = 1 ;
636632 wake_up_interruptible (& dev -> wait_hw_ready );
633+ if (!work_pending (& fw_reset_work ))
634+ queue_work (dev -> unbound_wq , & fw_reset_work );
637635 break ;
638636 }
639637}
@@ -730,22 +728,28 @@ int ish_disable_dma(struct ishtp_device *dev)
730728 * ish_wakeup() - wakeup ishfw from waiting-for-host state
731729 * @dev: ishtp device pointer
732730 *
733- * Set the dma enable bit and send a void message to FW,
731+ * Set the dma enable bit and send a IPC RESET message to FW,
734732 * it wil wakeup FW from waiting-for-host state.
733+ *
734+ * Return: 0 for success else error code.
735735 */
736- static void ish_wakeup (struct ishtp_device * dev )
736+ static int ish_wakeup (struct ishtp_device * dev )
737737{
738+ int ret ;
739+
738740 /* Set dma enable bit */
739741 ish_reg_write (dev , IPC_REG_ISH_RMP2 , IPC_RMP2_DMA_ENABLED );
740742
741743 /*
742- * Send 0 IPC message so that ISH FW wakes up if it was already
744+ * Send IPC RESET message so that ISH FW wakes up if it was already
743745 * asleep.
744746 */
745- ish_reg_write ( dev , IPC_REG_HOST2ISH_DRBL , IPC_DRBL_BUSY_BIT );
747+ ret = ish_ipc_reset ( dev );
746748
747749 /* Flush writes to doorbell and REMAP2 */
748750 ish_reg_read (dev , IPC_REG_ISH_HOST_FWSTS );
751+
752+ return ret ;
749753}
750754
751755/**
@@ -794,11 +798,11 @@ static int _ish_hw_reset(struct ishtp_device *dev)
794798 pci_write_config_word (pdev , pdev -> pm_cap + PCI_PM_CTRL , csr );
795799
796800 /* Now we can enable ISH DMA operation and wakeup ISHFW */
797- ish_wakeup (dev );
798-
799- return 0 ;
801+ return ish_wakeup (dev );
800802}
801803
804+ #define RECVD_HW_READY_TIMEOUT (10 * HZ)
805+
802806/**
803807 * _ish_ipc_reset() - IPC reset
804808 * @dev: ishtp device pointer
@@ -833,7 +837,8 @@ static int _ish_ipc_reset(struct ishtp_device *dev)
833837 }
834838
835839 wait_event_interruptible_timeout (dev -> wait_hw_ready ,
836- dev -> recvd_hw_ready , 2 * HZ );
840+ dev -> recvd_hw_ready ,
841+ RECVD_HW_READY_TIMEOUT );
837842 if (!dev -> recvd_hw_ready ) {
838843 dev_err (dev -> devc , "Timed out waiting for HW ready\n" );
839844 rv = - ENODEV ;
@@ -857,21 +862,7 @@ int ish_hw_start(struct ishtp_device *dev)
857862 set_host_ready (dev );
858863
859864 /* After that we can enable ISH DMA operation and wakeup ISHFW */
860- ish_wakeup (dev );
861-
862- /* wait for FW-initiated reset flow */
863- if (!dev -> recvd_hw_ready )
864- wait_event_interruptible_timeout (dev -> wait_hw_ready ,
865- dev -> recvd_hw_ready ,
866- 10 * HZ );
867-
868- if (!dev -> recvd_hw_ready ) {
869- dev_err (dev -> devc ,
870- "[ishtp-ish]: Timed out waiting for FW-initiated reset\n" );
871- return - ENODEV ;
872- }
873-
874- return 0 ;
865+ return ish_wakeup (dev );
875866}
876867
877868/**
@@ -933,6 +924,25 @@ static const struct ishtp_hw_ops ish_hw_ops = {
933924 .dma_no_cache_snooping = _dma_no_cache_snooping
934925};
935926
927+ static void ishtp_free_workqueue (void * wq )
928+ {
929+ destroy_workqueue (wq );
930+ }
931+
932+ static struct workqueue_struct * devm_ishtp_alloc_workqueue (struct device * dev )
933+ {
934+ struct workqueue_struct * wq ;
935+
936+ wq = alloc_workqueue ("ishtp_unbound_%d" , WQ_UNBOUND , 0 , dev -> id );
937+ if (!wq )
938+ return NULL ;
939+
940+ if (devm_add_action_or_reset (dev , ishtp_free_workqueue , wq ))
941+ return NULL ;
942+
943+ return wq ;
944+ }
945+
936946/**
937947 * ish_dev_init() -Initialize ISH devoce
938948 * @pdev: PCI device
@@ -953,6 +963,10 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
953963 if (!dev )
954964 return NULL ;
955965
966+ dev -> unbound_wq = devm_ishtp_alloc_workqueue (& pdev -> dev );
967+ if (!dev -> unbound_wq )
968+ return NULL ;
969+
956970 dev -> devc = & pdev -> dev ;
957971 ishtp_device_init (dev );
958972
@@ -982,6 +996,7 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
982996 list_add_tail (& tx_buf -> link , & dev -> wr_free_list );
983997 }
984998
999+ ishtp_dev = dev ;
9851000 ret = devm_work_autocancel (& pdev -> dev , & fw_reset_work , fw_reset_work_fn );
9861001 if (ret ) {
9871002 dev_err (dev -> devc , "Failed to initialise FW reset work\n" );
0 commit comments