@@ -119,12 +119,22 @@ static const struct wiimod_ops wiimod_keys = {
119119 * the rumble motor, this flag shouldn't be set.
120120 */
121121
122+ /* used by wiimod_rumble and wiipro_rumble */
123+ static void wiimod_rumble_worker (struct work_struct * work )
124+ {
125+ struct wiimote_data * wdata = container_of (work , struct wiimote_data ,
126+ rumble_worker );
127+
128+ spin_lock_irq (& wdata -> state .lock );
129+ wiiproto_req_rumble (wdata , wdata -> state .cache_rumble );
130+ spin_unlock_irq (& wdata -> state .lock );
131+ }
132+
122133static int wiimod_rumble_play (struct input_dev * dev , void * data ,
123134 struct ff_effect * eff )
124135{
125136 struct wiimote_data * wdata = input_get_drvdata (dev );
126137 __u8 value ;
127- unsigned long flags ;
128138
129139 /*
130140 * The wiimote supports only a single rumble motor so if any magnitude
@@ -137,16 +147,19 @@ static int wiimod_rumble_play(struct input_dev *dev, void *data,
137147 else
138148 value = 0 ;
139149
140- spin_lock_irqsave (& wdata -> state .lock , flags );
141- wiiproto_req_rumble (wdata , value );
142- spin_unlock_irqrestore (& wdata -> state .lock , flags );
150+ /* Locking state.lock here might deadlock with input_event() calls.
151+ * schedule_work acts as barrier. Merging multiple changes is fine. */
152+ wdata -> state .cache_rumble = value ;
153+ schedule_work (& wdata -> rumble_worker );
143154
144155 return 0 ;
145156}
146157
147158static int wiimod_rumble_probe (const struct wiimod_ops * ops ,
148159 struct wiimote_data * wdata )
149160{
161+ INIT_WORK (& wdata -> rumble_worker , wiimod_rumble_worker );
162+
150163 set_bit (FF_RUMBLE , wdata -> input -> ffbit );
151164 if (input_ff_create_memless (wdata -> input , NULL , wiimod_rumble_play ))
152165 return - ENOMEM ;
@@ -159,6 +172,8 @@ static void wiimod_rumble_remove(const struct wiimod_ops *ops,
159172{
160173 unsigned long flags ;
161174
175+ cancel_work_sync (& wdata -> rumble_worker );
176+
162177 spin_lock_irqsave (& wdata -> state .lock , flags );
163178 wiiproto_req_rumble (wdata , 0 );
164179 spin_unlock_irqrestore (& wdata -> state .lock , flags );
@@ -1731,7 +1746,6 @@ static int wiimod_pro_play(struct input_dev *dev, void *data,
17311746{
17321747 struct wiimote_data * wdata = input_get_drvdata (dev );
17331748 __u8 value ;
1734- unsigned long flags ;
17351749
17361750 /*
17371751 * The wiimote supports only a single rumble motor so if any magnitude
@@ -1744,9 +1758,10 @@ static int wiimod_pro_play(struct input_dev *dev, void *data,
17441758 else
17451759 value = 0 ;
17461760
1747- spin_lock_irqsave (& wdata -> state .lock , flags );
1748- wiiproto_req_rumble (wdata , value );
1749- spin_unlock_irqrestore (& wdata -> state .lock , flags );
1761+ /* Locking state.lock here might deadlock with input_event() calls.
1762+ * schedule_work acts as barrier. Merging multiple changes is fine. */
1763+ wdata -> state .cache_rumble = value ;
1764+ schedule_work (& wdata -> rumble_worker );
17501765
17511766 return 0 ;
17521767}
@@ -1756,6 +1771,8 @@ static int wiimod_pro_probe(const struct wiimod_ops *ops,
17561771{
17571772 int ret , i ;
17581773
1774+ INIT_WORK (& wdata -> rumble_worker , wiimod_rumble_worker );
1775+
17591776 wdata -> extension .input = input_allocate_device ();
17601777 if (!wdata -> extension .input )
17611778 return - ENOMEM ;
@@ -1817,12 +1834,13 @@ static void wiimod_pro_remove(const struct wiimod_ops *ops,
18171834 if (!wdata -> extension .input )
18181835 return ;
18191836
1837+ input_unregister_device (wdata -> extension .input );
1838+ wdata -> extension .input = NULL ;
1839+ cancel_work_sync (& wdata -> rumble_worker );
1840+
18201841 spin_lock_irqsave (& wdata -> state .lock , flags );
18211842 wiiproto_req_rumble (wdata , 0 );
18221843 spin_unlock_irqrestore (& wdata -> state .lock , flags );
1823-
1824- input_unregister_device (wdata -> extension .input );
1825- wdata -> extension .input = NULL ;
18261844}
18271845
18281846static const struct wiimod_ops wiimod_pro = {
0 commit comments