aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2018-07-18 14:03:36 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2018-07-25 15:04:15 -0400
commit34dad2cf1104869ce2db2bddb34f8e6780c2ddaa (patch)
treebb117a473c186aa8263dc44a0459cf4ae9b7defc /drivers/input
parent9730f60888d4b35be0f2d7316cb9e227d071cdda (diff)
Input: pxrc - fix freeing URB on device teardown
URB is the only resource that is not managed, and thus is destroyed too early, before we unregister input device and stop URB in pxrc_close(). To fix it let's install custom devm handler to free the URB at the right time in devm unwind sequence. Reviewed-by: Marcus Folkesson <marcus.folkesson@gmail.com> Tested-by: Marcus Folkesson <marcus.folkesson@gmail.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/joystick/pxrc.c66
1 files changed, 30 insertions, 36 deletions
diff --git a/drivers/input/joystick/pxrc.c b/drivers/input/joystick/pxrc.c
index 000b9b7da744..1560f0e39c34 100644
--- a/drivers/input/joystick/pxrc.c
+++ b/drivers/input/joystick/pxrc.c
@@ -119,49 +119,52 @@ static void pxrc_close(struct input_dev *input)
119 mutex_unlock(&pxrc->pm_mutex); 119 mutex_unlock(&pxrc->pm_mutex);
120} 120}
121 121
122static void pxrc_free_urb(void *_pxrc)
123{
124 struct pxrc *pxrc = _pxrc;
125
126 usb_free_urb(pxrc->urb);
127}
128
122static int pxrc_usb_init(struct pxrc *pxrc) 129static int pxrc_usb_init(struct pxrc *pxrc)
123{ 130{
124 struct usb_device *udev = interface_to_usbdev(pxrc->intf); 131 struct usb_device *udev = interface_to_usbdev(pxrc->intf);
125 struct usb_endpoint_descriptor *epirq; 132 struct usb_endpoint_descriptor *epirq;
126 unsigned int pipe; 133 unsigned int pipe;
127 int retval; 134 int error;
128 135
129 /* Set up the endpoint information */ 136 /* Set up the endpoint information */
130 /* This device only has an interrupt endpoint */ 137 /* This device only has an interrupt endpoint */
131 retval = usb_find_common_endpoints(pxrc->intf->cur_altsetting, 138 error = usb_find_common_endpoints(pxrc->intf->cur_altsetting,
132 NULL, NULL, &epirq, NULL); 139 NULL, NULL, &epirq, NULL);
133 if (retval) { 140 if (error) {
134 dev_err(&pxrc->intf->dev, 141 dev_err(&pxrc->intf->dev, "Could not find endpoint\n");
135 "Could not find endpoint\n"); 142 return error;
136 goto error;
137 } 143 }
138 144
139 pxrc->bsize = usb_endpoint_maxp(epirq); 145 pxrc->bsize = usb_endpoint_maxp(epirq);
140 pxrc->epaddr = epirq->bEndpointAddress; 146 pxrc->epaddr = epirq->bEndpointAddress;
141 pxrc->data = devm_kmalloc(&pxrc->intf->dev, pxrc->bsize, GFP_KERNEL); 147 pxrc->data = devm_kmalloc(&pxrc->intf->dev, pxrc->bsize, GFP_KERNEL);
142 if (!pxrc->data) { 148 if (!pxrc->data)
143 retval = -ENOMEM; 149 return -ENOMEM;
144 goto error;
145 }
146 150
147 usb_set_intfdata(pxrc->intf, pxrc); 151 usb_set_intfdata(pxrc->intf, pxrc);
148 usb_make_path(udev, pxrc->phys, sizeof(pxrc->phys)); 152 usb_make_path(udev, pxrc->phys, sizeof(pxrc->phys));
149 strlcat(pxrc->phys, "/input0", sizeof(pxrc->phys)); 153 strlcat(pxrc->phys, "/input0", sizeof(pxrc->phys));
150 154
151 pxrc->urb = usb_alloc_urb(0, GFP_KERNEL); 155 pxrc->urb = usb_alloc_urb(0, GFP_KERNEL);
152 if (!pxrc->urb) { 156 if (!pxrc->urb)
153 retval = -ENOMEM; 157 return -ENOMEM;
154 goto error; 158
155 } 159 error = devm_add_action_or_reset(&pxrc->intf->dev, pxrc_free_urb, pxrc);
160 if (error)
161 return error;
156 162
157 pipe = usb_rcvintpipe(udev, pxrc->epaddr), 163 pipe = usb_rcvintpipe(udev, pxrc->epaddr),
158 usb_fill_int_urb(pxrc->urb, udev, pipe, pxrc->data, pxrc->bsize, 164 usb_fill_int_urb(pxrc->urb, udev, pipe, pxrc->data, pxrc->bsize,
159 pxrc_usb_irq, pxrc, 1); 165 pxrc_usb_irq, pxrc, 1);
160 166
161error: 167 return 0;
162 return retval;
163
164
165} 168}
166 169
167static int pxrc_input_init(struct pxrc *pxrc) 170static int pxrc_input_init(struct pxrc *pxrc)
@@ -197,7 +200,7 @@ static int pxrc_probe(struct usb_interface *intf,
197 const struct usb_device_id *id) 200 const struct usb_device_id *id)
198{ 201{
199 struct pxrc *pxrc; 202 struct pxrc *pxrc;
200 int retval; 203 int error;
201 204
202 pxrc = devm_kzalloc(&intf->dev, sizeof(*pxrc), GFP_KERNEL); 205 pxrc = devm_kzalloc(&intf->dev, sizeof(*pxrc), GFP_KERNEL);
203 if (!pxrc) 206 if (!pxrc)
@@ -206,29 +209,20 @@ static int pxrc_probe(struct usb_interface *intf,
206 mutex_init(&pxrc->pm_mutex); 209 mutex_init(&pxrc->pm_mutex);
207 pxrc->intf = intf; 210 pxrc->intf = intf;
208 211
209 retval = pxrc_usb_init(pxrc); 212 error = pxrc_usb_init(pxrc);
210 if (retval) 213 if (error)
211 goto error; 214 return error;
212 215
213 retval = pxrc_input_init(pxrc); 216 error = pxrc_input_init(pxrc);
214 if (retval) 217 if (error)
215 goto err_free_urb; 218 return error;
216 219
217 return 0; 220 return 0;
218
219err_free_urb:
220 usb_free_urb(pxrc->urb);
221
222error:
223 return retval;
224} 221}
225 222
226static void pxrc_disconnect(struct usb_interface *intf) 223static void pxrc_disconnect(struct usb_interface *intf)
227{ 224{
228 struct pxrc *pxrc = usb_get_intfdata(intf); 225 /* All driver resources are devm-managed. */
229
230 usb_free_urb(pxrc->urb);
231 usb_set_intfdata(intf, NULL);
232} 226}
233 227
234static int pxrc_suspend(struct usb_interface *intf, pm_message_t message) 228static int pxrc_suspend(struct usb_interface *intf, pm_message_t message)