diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/firewire/fw-transaction.c | 58 |
1 files changed, 21 insertions, 37 deletions
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 861dd60de7d9..e5d1a0b64fcf 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/kref.h> | 23 | #include <linux/kref.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/mutex.h> | ||
25 | #include <linux/init.h> | 26 | #include <linux/init.h> |
26 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
27 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
@@ -295,58 +296,41 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t, | |||
295 | } | 296 | } |
296 | EXPORT_SYMBOL(fw_send_request); | 297 | EXPORT_SYMBOL(fw_send_request); |
297 | 298 | ||
298 | struct fw_phy_packet { | 299 | static DEFINE_MUTEX(phy_config_mutex); |
299 | struct fw_packet packet; | 300 | static DECLARE_COMPLETION(phy_config_done); |
300 | struct completion done; | ||
301 | struct kref kref; | ||
302 | }; | ||
303 | |||
304 | static void phy_packet_release(struct kref *kref) | ||
305 | { | ||
306 | struct fw_phy_packet *p = | ||
307 | container_of(kref, struct fw_phy_packet, kref); | ||
308 | kfree(p); | ||
309 | } | ||
310 | 301 | ||
311 | static void transmit_phy_packet_callback(struct fw_packet *packet, | 302 | static void transmit_phy_packet_callback(struct fw_packet *packet, |
312 | struct fw_card *card, int status) | 303 | struct fw_card *card, int status) |
313 | { | 304 | { |
314 | struct fw_phy_packet *p = | 305 | complete(&phy_config_done); |
315 | container_of(packet, struct fw_phy_packet, packet); | ||
316 | |||
317 | complete(&p->done); | ||
318 | kref_put(&p->kref, phy_packet_release); | ||
319 | } | 306 | } |
320 | 307 | ||
308 | static struct fw_packet phy_config_packet = { | ||
309 | .header_length = 8, | ||
310 | .payload_length = 0, | ||
311 | .speed = SCODE_100, | ||
312 | .callback = transmit_phy_packet_callback, | ||
313 | }; | ||
314 | |||
321 | void fw_send_phy_config(struct fw_card *card, | 315 | void fw_send_phy_config(struct fw_card *card, |
322 | int node_id, int generation, int gap_count) | 316 | int node_id, int generation, int gap_count) |
323 | { | 317 | { |
324 | struct fw_phy_packet *p; | ||
325 | long timeout = DIV_ROUND_UP(HZ, 10); | 318 | long timeout = DIV_ROUND_UP(HZ, 10); |
326 | u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG) | | 319 | u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG) | |
327 | PHY_CONFIG_ROOT_ID(node_id) | | 320 | PHY_CONFIG_ROOT_ID(node_id) | |
328 | PHY_CONFIG_GAP_COUNT(gap_count); | 321 | PHY_CONFIG_GAP_COUNT(gap_count); |
329 | 322 | ||
330 | p = kmalloc(sizeof(*p), GFP_KERNEL); | 323 | mutex_lock(&phy_config_mutex); |
331 | if (p == NULL) | 324 | |
332 | return; | 325 | phy_config_packet.header[0] = data; |
326 | phy_config_packet.header[1] = ~data; | ||
327 | phy_config_packet.generation = generation; | ||
328 | INIT_COMPLETION(phy_config_done); | ||
329 | |||
330 | card->driver->send_request(card, &phy_config_packet); | ||
331 | wait_for_completion_timeout(&phy_config_done, timeout); | ||
333 | 332 | ||
334 | p->packet.header[0] = data; | 333 | mutex_unlock(&phy_config_mutex); |
335 | p->packet.header[1] = ~data; | ||
336 | p->packet.header_length = 8; | ||
337 | p->packet.payload_length = 0; | ||
338 | p->packet.speed = SCODE_100; | ||
339 | p->packet.generation = generation; | ||
340 | p->packet.callback = transmit_phy_packet_callback; | ||
341 | init_completion(&p->done); | ||
342 | kref_set(&p->kref, 2); | ||
343 | |||
344 | card->driver->send_request(card, &p->packet); | ||
345 | timeout = wait_for_completion_timeout(&p->done, timeout); | ||
346 | kref_put(&p->kref, phy_packet_release); | ||
347 | |||
348 | /* will leak p if the callback is never executed */ | ||
349 | WARN_ON(timeout == 0); | ||
350 | } | 334 | } |
351 | 335 | ||
352 | void fw_flush_transactions(struct fw_card *card) | 336 | void fw_flush_transactions(struct fw_card *card) |