aboutsummaryrefslogtreecommitdiff
path: root/drivers/firewire
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/fw-device.c14
-rw-r--r--drivers/firewire/fw-ohci.c52
-rw-r--r--drivers/firewire/fw-sbp2.c40
-rw-r--r--drivers/firewire/fw-topology.c6
-rw-r--r--drivers/firewire/fw-transaction.h2
5 files changed, 81 insertions, 33 deletions
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
index 3fccdd48410..6b9be42c7b9 100644
--- a/drivers/firewire/fw-device.c
+++ b/drivers/firewire/fw-device.c
@@ -587,8 +587,7 @@ static void create_units(struct fw_device *device)
unit->device.bus = &fw_bus_type;
unit->device.type = &fw_unit_type;
unit->device.parent = &device->device;
- snprintf(unit->device.bus_id, sizeof(unit->device.bus_id),
- "%s.%d", device->device.bus_id, i++);
+ dev_set_name(&unit->device, "%s.%d", dev_name(&device->device), i++);
init_fw_attribute_group(&unit->device,
fw_unit_attributes,
@@ -711,8 +710,7 @@ static void fw_device_init(struct work_struct *work)
device->device.type = &fw_device_type;
device->device.parent = device->card->device;
device->device.devt = MKDEV(fw_cdev_major, minor);
- snprintf(device->device.bus_id, sizeof(device->device.bus_id),
- "fw%d", minor);
+ dev_set_name(&device->device, "fw%d", minor);
init_fw_attribute_group(&device->device,
fw_device_attributes,
@@ -741,13 +739,13 @@ static void fw_device_init(struct work_struct *work)
if (device->config_rom_retries)
fw_notify("created device %s: GUID %08x%08x, S%d00, "
"%d config ROM retries\n",
- device->device.bus_id,
+ dev_name(&device->device),
device->config_rom[3], device->config_rom[4],
1 << device->max_speed,
device->config_rom_retries);
else
fw_notify("created device %s: GUID %08x%08x, S%d00\n",
- device->device.bus_id,
+ dev_name(&device->device),
device->config_rom[3], device->config_rom[4],
1 << device->max_speed);
device->config_rom_retries = 0;
@@ -883,12 +881,12 @@ static void fw_device_refresh(struct work_struct *work)
FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
goto gone;
- fw_notify("refreshed device %s\n", device->device.bus_id);
+ fw_notify("refreshed device %s\n", dev_name(&device->device));
device->config_rom_retries = 0;
goto out;
give_up:
- fw_notify("giving up on refresh of device %s\n", device->device.bus_id);
+ fw_notify("giving up on refresh of device %s\n", dev_name(&device->device));
gone:
atomic_set(&device->state, FW_DEVICE_SHUTDOWN);
fw_device_shutdown(work);
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
index 251416f2148..46610b09041 100644
--- a/drivers/firewire/fw-ohci.c
+++ b/drivers/firewire/fw-ohci.c
@@ -476,6 +476,7 @@ static int ar_context_add_page(struct ar_context *ctx)
if (ab == NULL)
return -ENOMEM;
+ ab->next = NULL;
memset(&ab->descriptor, 0, sizeof(ab->descriptor));
ab->descriptor.control = cpu_to_le16(DESCRIPTOR_INPUT_MORE |
DESCRIPTOR_STATUS |
@@ -496,6 +497,21 @@ static int ar_context_add_page(struct ar_context *ctx)
return 0;
}
+static void ar_context_release(struct ar_context *ctx)
+{
+ struct ar_buffer *ab, *ab_next;
+ size_t offset;
+ dma_addr_t ab_bus;
+
+ for (ab = ctx->current_buffer; ab; ab = ab_next) {
+ ab_next = ab->next;
+ offset = offsetof(struct ar_buffer, data);
+ ab_bus = le32_to_cpu(ab->descriptor.data_address) - offset;
+ dma_free_coherent(ctx->ohci->card.device, PAGE_SIZE,
+ ab, ab_bus);
+ }
+}
+
#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
#define cond_le32_to_cpu(v) \
(ohci->old_uninorth ? (__force __u32)(v) : le32_to_cpu(v))
@@ -2349,8 +2365,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
if (ohci == NULL) {
- fw_error("Could not malloc fw_ohci data.\n");
- return -ENOMEM;
+ err = -ENOMEM;
+ goto fail;
}
fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev);
@@ -2359,7 +2375,7 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
err = pci_enable_device(dev);
if (err) {
- fw_error("Failed to enable OHCI hardware.\n");
+ fw_error("Failed to enable OHCI hardware\n");
goto fail_free;
}
@@ -2427,9 +2443,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
ohci->ir_context_list = kzalloc(size, GFP_KERNEL);
if (ohci->it_context_list == NULL || ohci->ir_context_list == NULL) {
- fw_error("Out of memory for it/ir contexts.\n");
err = -ENOMEM;
- goto fail_registers;
+ goto fail_contexts;
}
/* self-id dma buffer allocation */
@@ -2438,9 +2453,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
&ohci->self_id_bus,
GFP_KERNEL);
if (ohci->self_id_cpu == NULL) {
- fw_error("Out of memory for self ID buffer.\n");
err = -ENOMEM;
- goto fail_registers;
+ goto fail_contexts;
}
bus_options = reg_read(ohci, OHCI1394_BusOptions);
@@ -2454,15 +2468,19 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
goto fail_self_id;
fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n",
- dev->dev.bus_id, version >> 16, version & 0xff);
+ dev_name(&dev->dev), version >> 16, version & 0xff);
return 0;
fail_self_id:
dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE,
ohci->self_id_cpu, ohci->self_id_bus);
- fail_registers:
- kfree(ohci->it_context_list);
+ fail_contexts:
kfree(ohci->ir_context_list);
+ kfree(ohci->it_context_list);
+ context_release(&ohci->at_response_ctx);
+ context_release(&ohci->at_request_ctx);
+ ar_context_release(&ohci->ar_response_ctx);
+ ar_context_release(&ohci->ar_request_ctx);
pci_iounmap(dev, ohci->registers);
fail_iomem:
pci_release_region(dev, 0);
@@ -2471,6 +2489,9 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
fail_free:
kfree(&ohci->card);
ohci_pmac_off(dev);
+ fail:
+ if (err == -ENOMEM)
+ fw_error("Out of memory\n");
return err;
}
@@ -2491,8 +2512,19 @@ static void pci_remove(struct pci_dev *dev)
software_reset(ohci);
free_irq(dev->irq, ohci);
+
+ if (ohci->next_config_rom && ohci->next_config_rom != ohci->config_rom)
+ dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+ ohci->next_config_rom, ohci->next_config_rom_bus);
+ if (ohci->config_rom)
+ dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+ ohci->config_rom, ohci->config_rom_bus);
dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE,
ohci->self_id_cpu, ohci->self_id_bus);
+ ar_context_release(&ohci->ar_request_ctx);
+ ar_context_release(&ohci->ar_response_ctx);
+ context_release(&ohci->at_request_ctx);
+ context_release(&ohci->at_response_ctx);
kfree(ohci->it_context_list);
kfree(ohci->ir_context_list);
pci_iounmap(dev, ohci->registers);
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
index ef0b9b419c2..97df6dac3a8 100644
--- a/drivers/firewire/fw-sbp2.c
+++ b/drivers/firewire/fw-sbp2.c
@@ -173,6 +173,9 @@ struct sbp2_target {
int blocked; /* ditto */
};
+/* Impossible login_id, to detect logout attempt before successful login */
+#define INVALID_LOGIN_ID 0x10000
+
/*
* Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be
* provided in the config rom. Most devices do provide a value, which
@@ -788,9 +791,20 @@ static void sbp2_release_target(struct kref *kref)
scsi_remove_device(sdev);
scsi_device_put(sdev);
}
- sbp2_send_management_orb(lu, tgt->node_id, lu->generation,
- SBP2_LOGOUT_REQUEST, lu->login_id, NULL);
-
+ if (lu->login_id != INVALID_LOGIN_ID) {
+ int generation, node_id;
+ /*
+ * tgt->node_id may be obsolete here if we failed
+ * during initial login or after a bus reset where
+ * the topology changed.
+ */
+ generation = device->generation;
+ smp_rmb(); /* node_id vs. generation */
+ node_id = device->node_id;
+ sbp2_send_management_orb(lu, node_id, generation,
+ SBP2_LOGOUT_REQUEST,
+ lu->login_id, NULL);
+ }
fw_core_remove_address_handler(&lu->address_handler);
list_del(&lu->link);
kfree(lu);
@@ -805,19 +819,20 @@ static void sbp2_release_target(struct kref *kref)
static struct workqueue_struct *sbp2_wq;
+static void sbp2_target_put(struct sbp2_target *tgt)
+{
+ kref_put(&tgt->kref, sbp2_release_target);
+}
+
/*
* Always get the target's kref when scheduling work on one its units.
* Each workqueue job is responsible to call sbp2_target_put() upon return.
*/
static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
{
- if (queue_delayed_work(sbp2_wq, &lu->work, delay))
- kref_get(&lu->tgt->kref);
-}
-
-static void sbp2_target_put(struct sbp2_target *tgt)
-{
- kref_put(&tgt->kref, sbp2_release_target);
+ kref_get(&lu->tgt->kref);
+ if (!queue_delayed_work(sbp2_wq, &lu->work, delay))
+ sbp2_target_put(lu->tgt);
}
/*
@@ -978,6 +993,7 @@ static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
lu->tgt = tgt;
lu->lun = lun_entry & 0xffff;
+ lu->login_id = INVALID_LOGIN_ID;
lu->retries = 0;
lu->has_sdev = false;
lu->blocked = false;
@@ -1119,7 +1135,7 @@ static int sbp2_probe(struct device *dev)
tgt->unit = unit;
kref_init(&tgt->kref);
INIT_LIST_HEAD(&tgt->lu_list);
- tgt->bus_id = unit->device.bus_id;
+ tgt->bus_id = dev_name(&unit->device);
tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
if (fw_device_enable_phys_dma(device) < 0)
@@ -1147,7 +1163,7 @@ static int sbp2_probe(struct device *dev)
/* Do the login in a workqueue so we can easily reschedule retries. */
list_for_each_entry(lu, &tgt->lu_list, link)
- sbp2_queue_work(lu, 0);
+ sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
return 0;
fail_tgt_put:
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
index c1b81077c4a..5e204713002 100644
--- a/drivers/firewire/fw-topology.c
+++ b/drivers/firewire/fw-topology.c
@@ -413,7 +413,7 @@ static void
update_tree(struct fw_card *card, struct fw_node *root)
{
struct list_head list0, list1;
- struct fw_node *node0, *node1;
+ struct fw_node *node0, *node1, *next1;
int i, event;
INIT_LIST_HEAD(&list0);
@@ -485,7 +485,9 @@ update_tree(struct fw_card *card, struct fw_node *root)
}
node0 = fw_node(node0->link.next);
- node1 = fw_node(node1->link.next);
+ next1 = fw_node(node1->link.next);
+ fw_node_put(node1);
+ node1 = next1;
}
}
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
index 027f58ce81a..aed7dbb17cd 100644
--- a/drivers/firewire/fw-transaction.h
+++ b/drivers/firewire/fw-transaction.h
@@ -248,7 +248,7 @@ struct fw_card {
struct fw_node *local_node;
struct fw_node *root_node;
struct fw_node *irm_node;
- int color;
+ u8 color; /* must be u8 to match the definition in struct fw_node */
int gap_count;
bool beta_repeaters_present;