void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
int ackcode)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&host->pending_packet_queue.lock, flags);
+
packet->ack_code = ackcode;
- if (packet->no_waiter) {
- /* must not have a tlabel allocated */
+ if (packet->no_waiter || packet->state == hpsb_complete) {
+ /* if packet->no_waiter, must not have a tlabel allocated */
+ spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
hpsb_free_packet(packet);
return;
}
+ atomic_dec(&packet->refcnt); /* drop HC's reference */
+ /* here the packet must be on the host->pending_packet_queue */
+
if (ackcode != ACK_PENDING || !packet->expect_response) {
- atomic_dec(&packet->refcnt);
- skb_unlink(packet->skb);
packet->state = hpsb_complete;
+ __skb_unlink(packet->skb, &host->pending_packet_queue);
+ spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
queue_packet_complete(packet);
return;
}
- if (packet->state == hpsb_complete) {
- hpsb_free_packet(packet);
- return;
- }
-
- atomic_dec(&packet->refcnt);
packet->state = hpsb_pending;
packet->sendtime = jiffies;
+ spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
+
mod_timer(&host->timeout, jiffies + host->timeout_interval);
}
}
if (!tcode_match) {
+ spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
HPSB_INFO("unsolicited response packet received - tcode mismatch");
dump_packet("contents:", data, 16);
- spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
return;
}
__skb_unlink(skb, skb->list);
- spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
if (packet->state == hpsb_queued) {
packet->sendtime = jiffies;
}
packet->state = hpsb_complete;
+ spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
+
queue_packet_complete(packet);
}
static void queue_packet_complete(struct hpsb_packet *packet)
{
+ if (packet->no_waiter) {
+ hpsb_free_packet(packet);
+ return;
+ }
if (packet->complete_routine != NULL) {
skb_queue_tail(&hpsbpkt_queue, packet->skb);
static int __init ieee1394_init(void)
{
- int i;
+ int i, ret;
skb_queue_head_init(&hpsbpkt_queue);
+ /* non-fatal error */
if (hpsb_init_config_roms()) {
HPSB_ERR("Failed to initialize some config rom entries.\n");
HPSB_ERR("Some features may not be available\n");
khpsbpkt_pid = kernel_thread(hpsbpkt_thread, NULL, CLONE_KERNEL);
if (khpsbpkt_pid < 0) {
HPSB_ERR("Failed to start hpsbpkt thread!\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto exit_cleanup_config_roms;
}
- devfs_mk_dir("ieee1394");
-
if (register_chrdev_region(IEEE1394_CORE_DEV, 256, "ieee1394")) {
HPSB_ERR("unable to register character device major %d!\n", IEEE1394_MAJOR);
- return -ENODEV;
+ ret = -ENODEV;
+ goto exit_release_kernel_thread;
}
- devfs_mk_dir("ieee1394");
+ /* actually this is a non-fatal error */
+ ret = devfs_mk_dir("ieee1394");
+ if (ret < 0) {
+ HPSB_ERR("unable to make devfs dir for device major %d!\n", IEEE1394_MAJOR);
+ goto release_chrdev;
+ }
- bus_register(&ieee1394_bus_type);
- for (i = 0; fw_bus_attrs[i]; i++)
- bus_create_file(&ieee1394_bus_type, fw_bus_attrs[i]);
- class_register(&hpsb_host_class);
+ ret = bus_register(&ieee1394_bus_type);
+ if (ret < 0) {
+ HPSB_INFO("bus register failed");
+ goto release_devfs;
+ }
- if (init_csr())
- return -ENOMEM;
+ for (i = 0; fw_bus_attrs[i]; i++) {
+ ret = bus_create_file(&ieee1394_bus_type, fw_bus_attrs[i]);
+ if (ret < 0) {
+ while (i >= 0) {
+ bus_remove_file(&ieee1394_bus_type,
+ fw_bus_attrs[i--]);
+ }
+ bus_unregister(&ieee1394_bus_type);
+ goto release_devfs;
+ }
+ }
- if (!disable_nodemgr)
- init_ieee1394_nodemgr();
- else
+ ret = class_register(&hpsb_host_class);
+ if (ret < 0)
+ goto release_all_bus;
+
+ ret = init_csr();
+ if (ret) {
+ HPSB_INFO("init csr failed");
+ ret = -ENOMEM;
+ goto release_class;
+ }
+
+ if (disable_nodemgr) {
HPSB_INFO("nodemgr functionality disabled");
+ return 0;
+ }
+
+ ret = init_ieee1394_nodemgr();
+ if (ret < 0) {
+ HPSB_INFO("init nodemgr failed");
+ goto cleanup_csr;
+ }
return 0;
+
+cleanup_csr:
+ cleanup_csr();
+release_class:
+ class_unregister(&hpsb_host_class);
+release_all_bus:
+ for (i = 0; fw_bus_attrs[i]; i++)
+ bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
+ bus_unregister(&ieee1394_bus_type);
+release_devfs:
+ devfs_remove("ieee1394");
+release_chrdev:
+ unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
+exit_release_kernel_thread:
+ if (khpsbpkt_pid >= 0) {
+ kill_proc(khpsbpkt_pid, SIGTERM, 1);
+ wait_for_completion(&khpsbpkt_complete);
+ }
+exit_cleanup_config_roms:
+ hpsb_cleanup_config_roms();
+ return ret;
}
static void __exit ieee1394_cleanup(void)