struct fw_ohci {
struct fw_card card;
- u32 version;
__iomem char *registers;
dma_addr_t self_id_bus;
__le32 *self_id_cpu;
int generation;
int request_generation; /* for timestamping incoming requests */
u32 bus_seconds;
+
+ bool use_dualbuffer;
bool old_uninorth;
bool bus_reset_packet_quirk;
} else {
mask = &ohci->ir_context_mask;
list = ohci->ir_context_list;
- if (ohci->version >= OHCI_VERSION_1_1)
+ if (ohci->use_dualbuffer)
callback = handle_ir_dualbuffer_packet;
else
callback = handle_ir_packet_per_buffer;
} else {
index = ctx - ohci->ir_context_list;
control = IR_CONTEXT_ISOCH_HEADER;
- if (ohci->version >= OHCI_VERSION_1_1)
+ if (ohci->use_dualbuffer)
control |= IR_CONTEXT_DUAL_BUFFER_MODE;
match = (tags << 28) | (sync << 8) | ctx->base.channel;
if (cycle >= 0) {
spin_lock_irqsave(&ctx->context.ohci->lock, flags);
if (base->type == FW_ISO_CONTEXT_TRANSMIT)
retval = ohci_queue_iso_transmit(base, packet, buffer, payload);
- else if (ctx->context.ohci->version >= OHCI_VERSION_1_1)
+ else if (ctx->context.ohci->use_dualbuffer)
retval = ohci_queue_iso_receive_dualbuffer(base, packet,
buffer, payload);
else
pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
{
struct fw_ohci *ohci;
- u32 bus_options, max_receive, link_speed;
+ u32 bus_options, max_receive, link_speed, version;
u64 guid;
int err;
size_t size;
pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0);
pci_set_drvdata(dev, ohci);
-#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
- ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
- dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
-#endif
- ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
-
spin_lock_init(&ohci->lock);
tasklet_init(&ohci->bus_reset_tasklet,
goto fail_iomem;
}
+ version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
+ ohci->use_dualbuffer = version >= OHCI_VERSION_1_1;
+
+/* x86-32 currently doesn't use highmem for dma_alloc_coherent */
+#if !defined(CONFIG_X86_32)
+ /* dual-buffer mode is broken with descriptor addresses above 2G */
+ if (dev->vendor == PCI_VENDOR_ID_TI &&
+ dev->device == PCI_DEVICE_ID_TI_TSB43AB22)
+ ohci->use_dualbuffer = false;
+#endif
+
+#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
+ ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
+ dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
+#endif
+ ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
+
ar_context_init(&ohci->ar_request_ctx, ohci,
OHCI1394_AsReqRcvContextControlSet);
if (err < 0)
goto fail_self_id;
- ohci->version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n",
- dev->dev.bus_id, ohci->version >> 16, ohci->version & 0xff);
+ dev->dev.bus_id, version >> 16, version & 0xff);
return 0;
fail_self_id:
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
static void
fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
- int node_id, int source_id, int generation, int speed,
+ int destination_id, int source_id, int generation, int speed,
unsigned long long offset, void *payload, size_t length)
{
int ext_tcode;
HEADER_RETRY(RETRY_X) |
HEADER_TLABEL(tlabel) |
HEADER_TCODE(tcode) |
- HEADER_DESTINATION(node_id);
+ HEADER_DESTINATION(destination_id);
packet->header[1] =
HEADER_OFFSET_HIGH(offset >> 32) | HEADER_SOURCE(source_id);
packet->header[2] =
fw_transaction_callback_t callback, void *callback_data)
{
unsigned long flags;
- int tlabel, source;
+ int tlabel;
/*
* Bump the flush timer up 100ms first of all so we
spin_lock_irqsave(&card->lock, flags);
- source = card->node_id;
tlabel = card->current_tlabel;
if (card->tlabel_mask & (1 << tlabel)) {
spin_unlock_irqrestore(&card->lock, flags);
card->current_tlabel = (card->current_tlabel + 1) & 0x1f;
card->tlabel_mask |= (1 << tlabel);
- list_add_tail(&t->link, &card->transaction_list);
-
- spin_unlock_irqrestore(&card->lock, flags);
-
- /* Initialize rest of transaction, fill out packet and send it. */
t->node_id = node_id;
t->tlabel = tlabel;
t->callback = callback;
t->callback_data = callback_data;
- fw_fill_request(&t->packet, tcode, t->tlabel,
- node_id, source, generation,
- speed, offset, payload, length);
+ fw_fill_request(&t->packet, tcode, t->tlabel, node_id, card->node_id,
+ generation, speed, offset, payload, length);
t->packet.callback = transmit_complete_callback;
+ list_add_tail(&t->link, &card->transaction_list);
+
+ spin_unlock_irqrestore(&card->lock, flags);
+
card->driver->send_request(card, &t->packet);
}
EXPORT_SYMBOL(fw_send_request);
-struct fw_phy_packet {
- struct fw_packet packet;
- struct completion done;
- struct kref kref;
-};
-
-static void phy_packet_release(struct kref *kref)
-{
- struct fw_phy_packet *p =
- container_of(kref, struct fw_phy_packet, kref);
- kfree(p);
-}
+static DEFINE_MUTEX(phy_config_mutex);
+static DECLARE_COMPLETION(phy_config_done);
static void transmit_phy_packet_callback(struct fw_packet *packet,
struct fw_card *card, int status)
{
- struct fw_phy_packet *p =
- container_of(packet, struct fw_phy_packet, packet);
-
- complete(&p->done);
- kref_put(&p->kref, phy_packet_release);
+ complete(&phy_config_done);
}
+static struct fw_packet phy_config_packet = {
+ .header_length = 8,
+ .payload_length = 0,
+ .speed = SCODE_100,
+ .callback = transmit_phy_packet_callback,
+};
+
void fw_send_phy_config(struct fw_card *card,
int node_id, int generation, int gap_count)
{
- struct fw_phy_packet *p;
long timeout = DIV_ROUND_UP(HZ, 10);
u32 data = PHY_IDENTIFIER(PHY_PACKET_CONFIG) |
PHY_CONFIG_ROOT_ID(node_id) |
PHY_CONFIG_GAP_COUNT(gap_count);
- p = kmalloc(sizeof(*p), GFP_KERNEL);
- if (p == NULL)
- return;
+ mutex_lock(&phy_config_mutex);
+
+ phy_config_packet.header[0] = data;
+ phy_config_packet.header[1] = ~data;
+ phy_config_packet.generation = generation;
+ INIT_COMPLETION(phy_config_done);
+
+ card->driver->send_request(card, &phy_config_packet);
+ wait_for_completion_timeout(&phy_config_done, timeout);
- p->packet.header[0] = data;
- p->packet.header[1] = ~data;
- p->packet.header_length = 8;
- p->packet.payload_length = 0;
- p->packet.speed = SCODE_100;
- p->packet.generation = generation;
- p->packet.callback = transmit_phy_packet_callback;
- init_completion(&p->done);
- kref_set(&p->kref, 2);
-
- card->driver->send_request(card, &p->packet);
- timeout = wait_for_completion_timeout(&p->done, timeout);
- kref_put(&p->kref, phy_packet_release);
-
- /* will leak p if the callback is never executed */
- WARN_ON(timeout == 0);
+ mutex_unlock(&phy_config_mutex);
}
void fw_flush_transactions(struct fw_card *card)