diff options
| -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) |
