aboutsummaryrefslogtreecommitdiff
path: root/drivers/firewire/ohci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firewire/ohci.c')
-rw-r--r--drivers/firewire/ohci.c1045
1 files changed, 767 insertions, 278 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index bd3c61b6dd8..a66a3217f1d 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -42,10 +42,10 @@
#include <linux/string.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
#include <asm/byteorder.h>
#include <asm/page.h>
-#include <asm/system.h>
#ifdef CONFIG_PPC_PMAC
#include <asm/pmac_feature.h>
@@ -54,6 +54,10 @@
#include "core.h"
#include "ohci.h"
+#define ohci_info(ohci, f, args...) dev_info(ohci->card.device, f, ##args)
+#define ohci_notice(ohci, f, args...) dev_notice(ohci->card.device, f, ##args)
+#define ohci_err(ohci, f, args...) dev_err(ohci->card.device, f, ##args)
+
#define DESCRIPTOR_OUTPUT_MORE 0
#define DESCRIPTOR_OUTPUT_LAST (1 << 12)
#define DESCRIPTOR_INPUT_MORE (2 << 12)
@@ -68,6 +72,8 @@
#define DESCRIPTOR_BRANCH_ALWAYS (3 << 2)
#define DESCRIPTOR_WAIT (3 << 0)
+#define DESCRIPTOR_CMD (0xf << 12)
+
struct descriptor {
__le16 req_count;
__le16 control;
@@ -125,6 +131,7 @@ struct context {
struct fw_ohci *ohci;
u32 regs;
int total_allocation;
+ u32 current_bus;
bool running;
bool flushing;
@@ -148,10 +155,11 @@ struct context {
struct descriptor *last;
/*
- * The last descriptor in the DMA program. It contains the branch
+ * The last descriptor block in the DMA program. It contains the branch
* address that must be updated upon appending a new descriptor.
*/
struct descriptor *prev;
+ int prev_z;
descriptor_callback_t callback;
@@ -168,10 +176,12 @@ struct context {
struct iso_context {
struct fw_iso_context base;
struct context context;
- int excess_bytes;
void *header;
size_t header_length;
-
+ unsigned long flushing_completions;
+ u32 mc_buffer_bus;
+ u16 mc_completed;
+ u16 last_timestamp;
u8 sync;
u8 tags;
};
@@ -188,6 +198,7 @@ struct fw_ohci {
unsigned quirks;
unsigned int pri_req_max;
u32 bus_time;
+ bool bus_time_running;
bool is_root;
bool csr_state_setclear_abdicate;
int n_ir;
@@ -208,9 +219,11 @@ struct fw_ohci {
struct context at_request_ctx;
struct context at_response_ctx;
+ u32 it_context_support;
u32 it_context_mask; /* unoccupied IT contexts */
struct iso_context *it_context_list;
u64 ir_context_channels; /* unoccupied channels */
+ u32 ir_context_support;
u32 ir_context_mask; /* unoccupied IR contexts */
struct iso_context *ir_context_list;
u64 mc_channels; /* channels in use by the multichannel IR context */
@@ -222,13 +235,15 @@ struct fw_ohci {
dma_addr_t next_config_rom_bus;
__be32 next_header;
- __le32 *self_id_cpu;
+ __le32 *self_id;
dma_addr_t self_id_bus;
- struct tasklet_struct bus_reset_tasklet;
+ struct work_struct bus_reset_work;
u32 self_id_buffer[512];
};
+static struct workqueue_struct *selfid_workqueue;
+
static inline struct fw_ohci *fw_ohci(struct fw_card *card)
{
return container_of(card, struct fw_ohci, card);
@@ -251,7 +266,6 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
#define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8
#define OHCI1394_REGISTER_SIZE 0x800
-#define OHCI_LOOP_COUNT 500
#define OHCI1394_PCI_HCI_Control 0x40
#define SELF_ID_BUF_SIZE 0x800
#define OHCI_TCODE_PHY_PACKET 0x0e
@@ -259,15 +273,24 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
static char ohci_driver_name[] = KBUILD_MODNAME;
+#define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd
#define PCI_DEVICE_ID_AGERE_FW643 0x5901
+#define PCI_DEVICE_ID_CREATIVE_SB1394 0x4001
#define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380
#define PCI_DEVICE_ID_TI_TSB12LV22 0x8009
-
-#define QUIRK_CYCLE_TIMER 1
-#define QUIRK_RESET_PACKET 2
-#define QUIRK_BE_HEADERS 4
-#define QUIRK_NO_1394A 8
-#define QUIRK_NO_MSI 16
+#define PCI_DEVICE_ID_TI_TSB12LV26 0x8020
+#define PCI_DEVICE_ID_TI_TSB82AA2 0x8025
+#define PCI_DEVICE_ID_VIA_VT630X 0x3044
+#define PCI_REV_ID_VIA_VT6306 0x46
+#define PCI_DEVICE_ID_VIA_VT6315 0x3403
+
+#define QUIRK_CYCLE_TIMER 0x1
+#define QUIRK_RESET_PACKET 0x2
+#define QUIRK_BE_HEADERS 0x4
+#define QUIRK_NO_1394A 0x8
+#define QUIRK_NO_MSI 0x10
+#define QUIRK_TI_SLLZ059 0x20
+#define QUIRK_IR_WAKE 0x40
/* In case of multiple matches in ohci_quirks[], only the first one is used. */
static const struct {
@@ -282,21 +305,42 @@ static const struct {
{PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6,
QUIRK_NO_MSI},
+ {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_SB1394, PCI_ANY_ID,
+ QUIRK_RESET_PACKET},
+
{PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, PCI_ANY_ID,
QUIRK_NO_MSI},
{PCI_VENDOR_ID_NEC, PCI_ANY_ID, PCI_ANY_ID,
QUIRK_CYCLE_TIMER},
+ {PCI_VENDOR_ID_O2, PCI_ANY_ID, PCI_ANY_ID,
+ QUIRK_NO_MSI},
+
{PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID,
- QUIRK_CYCLE_TIMER},
+ QUIRK_CYCLE_TIMER | QUIRK_NO_MSI},
{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
+ {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV26, PCI_ANY_ID,
+ QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059},
+
+ {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB82AA2, PCI_ANY_ID,
+ QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059},
+
{PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID,
QUIRK_RESET_PACKET},
+ {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT630X, PCI_REV_ID_VIA_VT6306,
+ QUIRK_CYCLE_TIMER | QUIRK_IR_WAKE},
+
+ {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT6315, 0,
+ QUIRK_CYCLE_TIMER /* FIXME: necessary? */ | QUIRK_NO_MSI},
+
+ {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT6315, PCI_ANY_ID,
+ QUIRK_NO_MSI},
+
{PCI_VENDOR_ID_VIA, PCI_ANY_ID, PCI_ANY_ID,
QUIRK_CYCLE_TIMER | QUIRK_NO_MSI},
};
@@ -307,9 +351,11 @@ module_param_named(quirks, param_quirks, int, 0644);
MODULE_PARM_DESC(quirks, "Chip quirks (default = 0"
", nonatomic cycle timer = " __stringify(QUIRK_CYCLE_TIMER)
", reset packet generation = " __stringify(QUIRK_RESET_PACKET)
- ", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS)
+ ", AR/selfID endianness = " __stringify(QUIRK_BE_HEADERS)
", no 1394a enhancements = " __stringify(QUIRK_NO_1394A)
", disable MSI = " __stringify(QUIRK_NO_MSI)
+ ", TI SLLZ059 erratum = " __stringify(QUIRK_TI_SLLZ059)
+ ", IR wake unreliable = " __stringify(QUIRK_IR_WAKE)
")");
#define OHCI_PARAM_DEBUG_AT_AR 1
@@ -317,8 +363,6 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0"
#define OHCI_PARAM_DEBUG_IRQS 4
#define OHCI_PARAM_DEBUG_BUSRESETS 8 /* only effective before chip init */
-#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
-
static int param_debug;
module_param_named(debug, param_debug, int, 0644);
MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
@@ -328,7 +372,11 @@ MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
", busReset events = " __stringify(OHCI_PARAM_DEBUG_BUSRESETS)
", or a combination, or all = -1)");
-static void log_irqs(u32 evt)
+static bool param_remote_dma;
+module_param_named(remote_dma, param_remote_dma, bool, 0444);
+MODULE_PARM_DESC(remote_dma, "Enable unfiltered remote DMA (default = N)");
+
+static void log_irqs(struct fw_ohci *ohci, u32 evt)
{
if (likely(!(param_debug &
(OHCI_PARAM_DEBUG_IRQS | OHCI_PARAM_DEBUG_BUSRESETS))))
@@ -338,7 +386,7 @@ static void log_irqs(u32 evt)
!(evt & OHCI1394_busReset))
return;
- fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt,
+ ohci_notice(ohci, "IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt,
evt & OHCI1394_selfIDComplete ? " selfID" : "",
evt & OHCI1394_RQPkt ? " AR_req" : "",
evt & OHCI1394_RSPkt ? " AR_resp" : "",
@@ -351,6 +399,7 @@ static void log_irqs(u32 evt)
evt & OHCI1394_cycle64Seconds ? " cycle64Seconds" : "",
evt & OHCI1394_cycleInconsistent ? " cycleInconsistent" : "",
evt & OHCI1394_regAccessFail ? " regAccessFail" : "",
+ evt & OHCI1394_unrecoverableError ? " unrecoverableError" : "",
evt & OHCI1394_busReset ? " busReset" : "",
evt & ~(OHCI1394_selfIDComplete | OHCI1394_RQPkt |
OHCI1394_RSPkt | OHCI1394_reqTxComplete |
@@ -376,24 +425,27 @@ static char _p(u32 *s, int shift)
return port[*s >> shift & 3];
}
-static void log_selfids(int node_id, int generation, int self_id_count, u32 *s)
+static void log_selfids(struct fw_ohci *ohci, int generation, int self_id_count)
{
+ u32 *s;
+
if (likely(!(param_debug & OHCI_PARAM_DEBUG_SELFIDS)))
return;
- fw_notify("%d selfIDs, generation %d, local node ID %04x\n",
- self_id_count, generation, node_id);
+ ohci_notice(ohci, "%d selfIDs, generation %d, local node ID %04x\n",
+ self_id_count, generation, ohci->node_id);
- for (; self_id_count--; ++s)
+ for (s = ohci->self_id_buffer; self_id_count--; ++s)
if ((*s & 1 << 23) == 0)
- fw_notify("selfID 0: %08x, phy %d [%c%c%c] "
- "%s gc=%d %s %s%s%s\n",
+ ohci_notice(ohci,
+ "selfID 0: %08x, phy %d [%c%c%c] %s gc=%d %s %s%s%s\n",
*s, *s >> 24 & 63, _p(s, 6), _p(s, 4), _p(s, 2),
speed[*s >> 14 & 3], *s >> 16 & 63,
power[*s >> 8 & 7], *s >> 22 & 1 ? "L" : "",
*s >> 11 & 1 ? "c" : "", *s & 2 ? "i" : "");
else
- fw_notify("selfID n: %08x, phy %d [%c%c%c%c%c%c%c%c]\n",
+ ohci_notice(ohci,
+ "selfID n: %08x, phy %d [%c%c%c%c%c%c%c%c]\n",
*s, *s >> 24 & 63,
_p(s, 16), _p(s, 14), _p(s, 12), _p(s, 10),
_p(s, 8), _p(s, 6), _p(s, 4), _p(s, 2));
@@ -429,7 +481,8 @@ static const char *tcodes[] = {
[0xe] = "link internal", [0xf] = "-reserved-",
};
-static void log_ar_at_event(char dir, int speed, u32 *header, int evt)
+static void log_ar_at_event(struct fw_ohci *ohci,
+ char dir, int speed, u32 *header, int evt)
{
int tcode = header[0] >> 4 & 0xf;
char specific[12];
@@ -441,8 +494,8 @@ static void log_ar_at_event(char dir, int speed, u32 *header, int evt)
evt = 0x1f;
if (evt == OHCI1394_evt_bus_reset) {
- fw_notify("A%c evt_bus_reset, generation %d\n",
- dir, (header[2] >> 16) & 0xff);
+ ohci_notice(ohci, "A%c evt_bus_reset, generation %d\n",
+ dir, (header[2] >> 16) & 0xff);
return;
}
@@ -461,39 +514,29 @@ static void log_ar_at_event(char dir, int speed, u32 *header, int evt)
switch (tcode) {
case 0xa:
- fw_notify("A%c %s, %s\n", dir, evts[evt], tcodes[tcode]);
+ ohci_notice(ohci, "A%c %s, %s\n",
+ dir, evts[evt], tcodes[tcode]);
break;
case 0xe:
- fw_notify("A%c %s, PHY %08x %08x\n",
- dir, evts[evt], header[1], header[2]);
+ ohci_notice(ohci, "A%c %s, PHY %08x %08x\n",
+ dir, evts[evt], header[1], header[2]);
break;
case 0x0: case 0x1: case 0x4: case 0x5: case 0x9:
- fw_notify("A%c spd %x tl %02x, "
- "%04x -> %04x, %s, "
- "%s, %04x%08x%s\n",
- dir, speed, header[0] >> 10 & 0x3f,
- header[1] >> 16, header[0] >> 16, evts[evt],
- tcodes[tcode], header[1] & 0xffff, header[2], specific);
+ ohci_notice(ohci,
+ "A%c spd %x tl %02x, %04x -> %04x, %s, %s, %04x%08x%s\n",
+ dir, speed, header[0] >> 10 & 0x3f,
+ header[1] >> 16, header[0] >> 16, evts[evt],
+ tcodes[tcode], header[1] & 0xffff, header[2], specific);
break;
default:
- fw_notify("A%c spd %x tl %02x, "
- "%04x -> %04x, %s, "
- "%s%s\n",
- dir, speed, header[0] >> 10 & 0x3f,
- header[1] >> 16, header[0] >> 16, evts[evt],
- tcodes[tcode], specific);
+ ohci_notice(ohci,
+ "A%c spd %x tl %02x, %04x -> %04x, %s, %s%s\n",
+ dir, speed, header[0] >> 10 & 0x3f,
+ header[1] >> 16, header[0] >> 16, evts[evt],
+ tcodes[tcode], specific);
}
}
-#else
-
-#define param_debug 0
-static inline void log_irqs(u32 evt) {}
-static inline void log_selfids(int node_id, int generation, int self_id_count, u32 *s) {}
-static inline void log_ar_at_event(char dir, int speed, u32 *header, int evt) {}
-
-#endif /* CONFIG_FIREWIRE_OHCI_DEBUG */
-
static inline void reg_write(const struct fw_ohci *ohci, int offset, u32 data)
{
writel(data, ohci->registers + offset);
@@ -510,6 +553,12 @@ static inline void flush_writes(const struct fw_ohci *ohci)
reg_read(ohci, OHCI1394_Version);
}
+/*
+ * Beware! read_phy_reg(), write_phy_reg(), update_phy_reg(), and
+ * read_paged_phy_reg() require the caller to hold ohci->phy_reg_mutex.
+ * In other words, only use ohci_read_phy_reg() and ohci_update_phy_reg()
+ * directly. Exceptions are intrinsically serialized contexts like pci_probe.
+ */
static int read_phy_reg(struct fw_ohci *ohci, int addr)
{
u32 val;
@@ -518,6 +567,9 @@ static int read_phy_reg(struct fw_ohci *ohci, int addr)
reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr));
for (i = 0; i < 3 + 100; i++) {
val = reg_read(ohci, OHCI1394_PhyControl);
+ if (!~val)
+ return -ENODEV; /* Card was ejected. */
+
if (val & OHCI1394_PhyControl_ReadDone)
return OHCI1394_PhyControl_ReadData(val);
@@ -528,7 +580,8 @@ static int read_phy_reg(struct fw_ohci *ohci, int addr)
if (i >= 3)
msleep(1);
}
- fw_error("failed to read phy reg\n");
+ ohci_err(ohci, "failed to read phy reg %d\n", addr);
+ dump_stack();
return -EBUSY;
}
@@ -541,13 +594,17 @@ static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val)
OHCI1394_PhyControl_Write(addr, val));
for (i = 0; i < 3 + 100; i++) {
val = reg_read(ohci, OHCI1394_PhyControl);
+ if (!~val)
+ return -ENODEV; /* Card was ejected. */
+
if (!(val & OHCI1394_PhyControl_WritePending))
return 0;
if (i >= 3)
msleep(1);
}
- fw_error("failed to write phy reg\n");
+ ohci_err(ohci, "failed to write phy reg %d, val %u\n", addr, val);
+ dump_stack();
return -EBUSY;
}
@@ -626,7 +683,6 @@ static void ar_context_link_page(struct ar_context *ctx, unsigned int index)
ctx->last_buffer_index = index;
reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
- flush_writes(ctx->ohci);
}
static void ar_context_release(struct ar_context *ctx)
@@ -647,11 +703,13 @@ static void ar_context_release(struct ar_context *ctx)
static void ar_context_abort(struct ar_context *ctx, const char *error_msg)
{
- if (reg_read(ctx->ohci, CONTROL_CLEAR(ctx->regs)) & CONTEXT_RUN) {
- reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
- flush_writes(ctx->ohci);
+ struct fw_ohci *ohci = ctx->ohci;
- fw_error("AR error: %s; DMA stopped\n", error_msg);
+ if (reg_read(ohci, CONTROL_CLEAR(ctx->regs)) & CONTEXT_RUN) {
+ reg_write(ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
+ flush_writes(ohci);
+
+ ohci_err(ohci, "AR error: %s; DMA stopped\n", error_msg);
}
/* FIXME: restart? */
}
@@ -821,7 +879,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
p.timestamp = status & 0xffff;
p.generation = ohci->request_generation;
- log_ar_at_event('R', p.speed, p.header, evt);
+ log_ar_at_event(ohci, 'R', p.speed, p.header, evt);
/*
* Several controllers, notably from NEC and VIA, forget to
@@ -842,7 +900,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
*
* Alas some chips sometimes emit bus reset packets with a
* wrong generation. We set the correct generation for these
- * at a slightly incorrect time (in bus_reset_tasklet).
+ * at a slightly incorrect time (in bus_reset_work).
*/
if (evt == OHCI1394_evt_bus_reset) {
if (!(ohci->quirks & QUIRK_RESET_PACKET))
@@ -998,18 +1056,16 @@ static void ar_context_run(struct ar_context *ctx)
reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ctx->descriptors_bus | 1);
reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN);
- flush_writes(ctx->ohci);
}
static struct descriptor *find_branch_descriptor(struct descriptor *d, int z)
{
- int b, key;
+ __le16 branch;
- b = (le16_to_cpu(d->control) & DESCRIPTOR_BRANCH_ALWAYS) >> 2;
- key = (le16_to_cpu(d->control) & DESCRIPTOR_KEY_IMMEDIATE) >> 8;
+ branch = d->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS);
/* figure out which descriptor the branch address goes in */
- if (z == 2 && (b == 3 || key == 2))
+ if (z == 2 && branch == cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))
return d;
else
return d + z - 1;
@@ -1031,6 +1087,7 @@ static void context_tasklet(unsigned long data)
address = le32_to_cpu(last->branch_address);
z = address & 0xf;
address &= ~0xf;
+ ctx->current_bus = address;
/* If the branch address points to a buffer outside of the
* current buffer, advance to the next buffer. */
@@ -1118,6 +1175,7 @@ static int context_init(struct context *ctx, struct fw_ohci *ohci,
ctx->buffer_tail->used += sizeof(*ctx->buffer_tail->buffer);
ctx->last = ctx->buffer_tail->buffer;
ctx->prev = ctx->buffer_tail->buffer;
+ ctx->prev_z = 1;
return 0;
}
@@ -1182,39 +1240,59 @@ static void context_append(struct context *ctx,
{
dma_addr_t d_bus;
struct descriptor_buffer *desc = ctx->buffer_tail;
+ struct descriptor *d_branch;
d_bus = desc->buffer_bus + (d - desc->buffer) * sizeof(*d);
desc->used += (z + extra) * sizeof(*d);
wmb(); /* finish init of new descriptors before branch_address update */
- ctx->prev->branch_address = cpu_to_le32(d_bus | z);
- ctx->prev = find_branch_descriptor(d, z);
- reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
- flush_writes(ctx->ohci);
+ d_branch = find_branch_descriptor(ctx->prev, ctx->prev_z);
+ d_branch->branch_address = cpu_to_le32(d_bus | z);
+
+ /*
+ * VT6306 incorrectly checks only the single descriptor at the
+ * CommandPtr when the wake bit is written, so if it's a
+ * multi-descriptor block starting with an INPUT_MORE, put a copy of
+ * the branch address in the first descriptor.
+ *
+ * Not doing this for transmit contexts since not sure how it interacts
+ * with skip addresses.
+ */
+ if (unlikely(ctx->ohci->quirks & QUIRK_IR_WAKE) &&
+ d_branch != ctx->prev &&
+ (ctx->prev->control & cpu_to_le16(DESCRIPTOR_CMD)) ==
+ cpu_to_le16(DESCRIPTOR_INPUT_MORE)) {
+ ctx->prev->branch_address = cpu_to_le32(d_bus | z);
+ }
+
+ ctx->prev = d;
+ ctx->prev_z = z;
}
static void context_stop(struct context *ctx)
{
+ struct fw_ohci *ohci = ctx->ohci;
u32 reg;
int i;
- reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
+ reg_write(ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
ctx->running = false;
- flush_writes(ctx->ohci);
- for (i = 0; i < 10; i++) {
- reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs));
+ for (i = 0; i < 1000; i++) {
+ reg = reg_read(ohci, CONTROL_SET(ctx->regs));
if ((reg & CONTEXT_ACTIVE) == 0)
return;
- mdelay(1);
+ if (i)
+ udelay(10);
}
- fw_error("Error: DMA context still active (0x%08x)\n", reg);
+ ohci_err(ohci, "DMA context still active (0x%08x)\n", reg);
}
struct driver_data {
+ u8 inline_data[8];
struct fw_packet *packet;
};
@@ -1243,7 +1321,7 @@ static int at_context_queue_packet(struct context *ctx,
d[0].res_count = cpu_to_le16(packet->timestamp);
/*
- * The DMA format for asyncronous link packets is different
+ * The DMA format for asynchronous link packets is different
* from the IEEE1394 layout, so shift the fields around
* accordingly.
*/
@@ -1298,20 +1376,28 @@ static int at_context_queue_packet(struct context *ctx,
return -1;
}
+ BUILD_BUG_ON(sizeof(struct driver_data) > sizeof(struct descriptor));
driver_data = (struct driver_data *) &d[3];
driver_data->packet = packet;
packet->driver_data = driver_data;
if (packet->payload_length > 0) {
- payload_bus =
- dma_map_single(ohci->card.device, packet->payload,
- packet->payload_length, DMA_TO_DEVICE);
- if (dma_mapping_error(ohci->card.device, payload_bus)) {
- packet->ack = RCODE_SEND_ERROR;
- return -1;
+ if (packet->payload_length > sizeof(driver_data->inline_data)) {
+ payload_bus = dma_map_single(ohci->card.device,
+ packet->payload,
+ packet->payload_length,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(ohci->card.device, payload_bus)) {
+ packet->ack = RCODE_SEND_ERROR;
+ return -1;
+ }
+ packet->payload_bus = payload_bus;
+ packet->payload_mapped = true;
+ } else {
+ memcpy(driver_data->inline_data, packet->payload,
+ packet->payload_length);
+ payload_bus = d_bus + 3 * sizeof(*d);
}
- packet->payload_bus = payload_bus;
- packet->payload_mapped = true;
d[2].req_count = cpu_to_le16(packet->payload_length);
d[2].data_address = cpu_to_le32(payload_bus);
@@ -1326,21 +1412,8 @@ static int at_context_queue_packet(struct context *ctx,
DESCRIPTOR_IRQ_ALWAYS |
DESCRIPTOR_BRANCH_ALWAYS);
- /*
- * If the controller and packet generations don't match, we need to
- * bail out and try again. If IntEvent.busReset is set, the AT context
- * is halted, so appending to the context and trying to run it is
- * futile. Most controllers do the right thing and just flush the AT
- * queue (per section 7.2.3.2 of the OHCI 1.1 specification), but
- * some controllers (like a JMicron JMB381 PCI-e) misbehave and wind
- * up stalling out. So we just bail out in software and try again
- * later, and everyone is happy.
- * FIXME: Test of IntEvent.busReset may no longer be necessary since we
- * flush AT queues in bus_reset_tasklet.
- * FIXME: Document how the locking works.
- */
- if (ohci->generation != packet->generation ||
- reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
+ /* FIXME: Document how the locking works. */
+ if (ohci->generation != packet->generation) {
if (packet->payload_mapped)
dma_unmap_single(ohci->card.device, payload_bus,
packet->payload_length, DMA_TO_DEVICE);
@@ -1350,7 +1423,9 @@ static int at_context_queue_packet(struct context *ctx,
context_append(ctx, d, z, 4 - z);
- if (!ctx->running)
+ if (ctx->running)
+ reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
+ else
context_run(ctx, 0);
return 0;
@@ -1393,7 +1468,7 @@ static int handle_at_packet(struct context *context,
evt = le16_to_cpu(last->transfer_status) & 0x1f;
packet->timestamp = le16_to_cpu(last->res_count);
- log_ar_at_event('T', packet->speed, packet->header, evt);
+ log_ar_at_event(ohci, 'T', packet->speed, packet->header, evt);
switch (evt) {
case OHCI1394_evt_timeout:
@@ -1522,7 +1597,7 @@ static void handle_local_lock(struct fw_ohci *ohci,
goto out;
}
- fw_error("swap not done (CSR lock timeout)\n");
+ ohci_err(ohci, "swap not done (CSR lock timeout)\n");
fw_fill_response(&response, packet->header, RCODE_BUSY, NULL, 0);
out:
@@ -1590,6 +1665,41 @@ static void at_context_transmit(struct context *ctx, struct fw_packet *packet)
}
+static void detect_dead_context(struct fw_ohci *ohci,
+ const char *name, unsigned int regs)
+{
+ u32 ctl;
+
+ ctl = reg_read(ohci, CONTROL_SET(regs));
+ if (ctl & CONTEXT_DEAD)
+ ohci_err(ohci, "DMA context %s has stopped, error code: %s\n",
+ name, evts[ctl & 0x1f]);
+}
+
+static void handle_dead_contexts(struct fw_ohci *ohci)
+{
+ unsigned int i;
+ char name[8];
+
+ detect_dead_context(ohci, "ATReq", OHCI1394_AsReqTrContextBase);
+ detect_dead_context(ohci, "ATRsp", OHCI1394_AsRspTrContextBase);
+ detect_dead_context(ohci, "ARReq", OHCI1394_AsReqRcvContextBase);
+ detect_dead_context(ohci, "ARRsp", OHCI1394_AsRspRcvContextBase);
+ for (i = 0; i < 32; ++i) {
+ if (!(ohci->it_context_support & (1 << i)))
+ continue;
+ sprintf(name, "IT%u", i);
+ detect_dead_context(ohci, name, OHCI1394_IsoXmitContextBase(i));
+ }
+ for (i = 0; i < 32; ++i) {
+ if (!(ohci->ir_context_support & (1 << i)))
+ continue;
+ sprintf(name, "IR%u", i);
+ detect_dead_context(ohci, name, OHCI1394_IsoRcvContextBase(i));
+ }
+ /* TODO: maybe try to flush and restart the dead contexts */
+}
+
static u32 cycle_timer_ticks(u32 cycle_timer)
{
u32 ticks;
@@ -1656,29 +1766,148 @@ static u32 update_bus_time(struct fw_ohci *ohci)
{
u32 cycle_time_seconds = get_cycle_time(ohci) >> 25;
+ if (unlikely(!ohci->bus_time_running)) {
+ reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_cycle64Seconds);
+ ohci->bus_time = (lower_32_bits(get_seconds()) & ~0x7f) |
+ (cycle_time_seconds & 0x40);
+ ohci->bus_time_running = true;
+ }
+
if ((ohci->bus_time & 0x40) != (cycle_time_seconds & 0x40))
ohci->bus_time += 0x40;
return ohci->bus_time | cycle_time_seconds;
}
-static void bus_reset_tasklet(unsigned long data)
+static int get_status_for_port(struct fw_ohci *ohci, int port_index)
{
- struct fw_ohci *ohci = (struct fw_ohci *)data;
- int self_id_count, i, j, reg;
- int generation, new_generation;
- unsigned long flags;
+ int reg;
+
+ mutex_lock(&ohci->phy_reg_mutex);
+ reg = write_phy_reg(ohci, 7, port_index);
+ if (reg >= 0)
+ reg = read_phy_reg(ohci, 8);
+ mutex_unlock(&ohci->phy_reg_mutex);
+ if (reg < 0)
+ return reg;
+
+ switch (reg & 0x0f) {
+ case 0x06:
+ return 2; /* is child node (connected to parent node) */
+ case 0x0e:
+ return 3; /* is parent node (connected to child node) */
+ }
+ return 1; /* not connected */
+}
+
+static int get_self_id_pos(struct fw_ohci *ohci, u32 self_id,
+ int self_id_count)
+{
+ int i;
+ u32 entry;
+
+ for (i = 0; i < self_id_count; i++) {
+ entry = ohci->self_id_buffer[i];
+ if ((self_id & 0xff000000) == (entry & 0xff000000))
+ return -1;
+ if ((self_id & 0xff000000) < (entry & 0xff000000))
+ return i;
+ }
+ return i;
+}
+
+static int initiated_reset(struct fw_ohci *ohci)
+{
+ int reg;
+ int ret = 0;
+
+ mutex_lock(&ohci->phy_reg_mutex);
+ reg = write_phy_reg(ohci, 7, 0xe0); /* Select page 7 */
+ if (reg >= 0) {
+ reg = read_phy_reg(ohci, 8);
+ reg |= 0x40;
+ reg = write_phy_reg(ohci, 8, reg); /* set PMODE bit */
+ if (reg >= 0) {
+ reg = read_phy_reg(ohci, 12); /* read register 12 */
+ if (reg >= 0) {
+ if ((reg & 0x08) == 0x08) {
+ /* bit 3 indicates "initiated reset" */
+ ret = 0x2;
+ }
+ }
+ }
+ }
+ mutex_unlock(&ohci->phy_reg_mutex);
+ return ret;
+}
+
+/*
+ * TI TSB82AA2B and TSB12LV26 do not receive the selfID of a locally
+ * attached TSB41BA3D phy; see http://www.ti.com/litv/pdf/sllz059.
+ * Construct the selfID from phy register contents.
+ */
+static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count)
+{
+ int reg, i, pos, status;
+ /* link active 1, speed 3, bridge 0, contender 1, more packets 0 */
+ u32 self_id = 0x8040c800;
+
+ reg = reg_read(ohci, OHCI1394_NodeID);
+ if (!(reg & OHCI1394_NodeID_idValid)) {
+ ohci_notice(ohci,
+ "node ID not valid, new bus reset in progress\n");
+ return -EBUSY;
+ }
+ self_id |= ((reg & 0x3f) << 24); /* phy ID */
+
+ reg = ohci_read_phy_reg(&ohci->card, 4);
+ if (reg < 0)
+ return reg;
+ self_id |= ((reg & 0x07) << 8); /* power class */
+
+ reg = ohci_read_phy_reg(&ohci->card, 1);
+ if (reg < 0)
+ return reg;
+ self_id |= ((reg & 0x3f) << 16); /* gap count */
+
+ for (i = 0; i < 3; i++) {
+ status = get_status_for_port(ohci, i);
+ if (status < 0)
+ return status;
+ self_id |= ((status & 0x3) << (6 - (i * 2)));
+ }
+
+ self_id |= initiated_reset(ohci);
+
+ pos = get_self_id_pos(ohci, self_id, self_id_count);
+ if (pos >= 0) {
+ memmove(&(ohci->self_id_buffer[pos+1]),
+ &(ohci->self_id_buffer[pos]),
+ (self_id_count - pos) * sizeof(*ohci->self_id_buffer));
+ ohci->self_id_buffer[pos] = self_id;
+ self_id_count++;
+ }
+ return self_id_count;
+}
+
+static void bus_reset_work(struct work_struct *work)
+{
+ struct fw_ohci *ohci =
+ container_of(work, struct fw_ohci, bus_reset_work);
+ int self_id_count, generation, new_generation, i, j;
+ u32 reg;
void *free_rom = NULL;
dma_addr_t free_rom_bus = 0;
bool is_new_root;
reg = reg_read(ohci, OHCI1394_NodeID);
if (!(reg & OHCI1394_NodeID_idValid)) {
- fw_notify("node ID not valid, new bus reset in progress\n");
+ ohci_notice(ohci,
+ "node ID not valid, new bus reset in progress\n");
return;
}
if ((reg & OHCI1394_NodeID_nodeNumber) == 63) {
- fw_notify("malconfigured bus\n");
+ ohci_notice(ohci, "malconfigured bus\n");
return;
}
ohci->node_id = reg & (OHCI1394_NodeID_busNumber |
@@ -1692,7 +1921,7 @@ static void bus_reset_tasklet(unsigned long data)
reg = reg_read(ohci, OHCI1394_SelfIDCount);
if (reg & OHCI1394_SelfIDCount_selfIDError) {
- fw_notify("inconsistent self IDs\n");
+ ohci_notice(ohci, "self ID receive error\n");
return;
}
/*
@@ -1702,20 +1931,52 @@ static void bus_reset_tasklet(unsigned long data)
* bit extra to get the actual number of self IDs.
*/
self_id_count = (reg >> 3) & 0xff;
- if (self_id_count == 0 || self_id_count > 252) {
- fw_notify("inconsistent self IDs\n");
+
+ if (self_id_count > 252) {
+ ohci_notice(ohci, "bad selfIDSize (%08x)\n", reg);
return;
}
- generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
+
+ generation = (cond_le32_to_cpu(ohci->self_id[0]) >> 16) & 0xff;
rmb();
for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
- if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) {
- fw_notify("inconsistent self IDs\n");
+ u32 id = cond_le32_to_cpu(ohci->self_id[i]);
+ u32 id2 = cond_le32_to_cpu(ohci->self_id[i + 1]);
+
+ if (id != ~id2) {
+ /*
+ * If the invalid data looks like a cycle start packet,
+ * it's likely to be the result of the cycle master
+ * having a wrong gap count. In this case, the self IDs
+ * so far are valid and should be processed so that the
+ * bus manager can then correct the gap count.
+ */
+ if (id == 0xffff008f) {
+ ohci_notice(ohci, "ignoring spurious self IDs\n");
+ self_id_count = j;
+ break;
+ }
+
+ ohci_notice(ohci, "bad self ID %d/%d (%08x != ~%08x)\n",
+ j, self_id_count, id, id2);
+ return;
+ }
+ ohci->self_id_buffer[j] = id;
+ }
+
+ if (ohci->quirks & QUIRK_TI_SLLZ059) {
+ self_id_count = find_and_insert_self_id(ohci, self_id_count);
+ if (self_id_count < 0) {
+ ohci_notice(ohci,
+ "could not construct local self ID\n");
return;
}
- ohci->self_id_buffer[j] =
- cond_le32_to_cpu(ohci->self_id_cpu[i]);
+ }
+
+ if (self_id_count == 0) {
+ ohci_notice(ohci, "no self IDs\n");
+ return;
}
rmb();
@@ -1735,19 +1996,18 @@ static void bus_reset_tasklet(unsigned long data)
new_generation = (reg_read(ohci, OHCI1394_SelfIDCount) >> 16) & 0xff;
if (new_generation != generation) {
- fw_notify("recursive bus reset detected, "
- "discarding self ids\n");
+ ohci_notice(ohci, "new bus reset, discarding self ids\n");
return;
}
/* FIXME: Document how the locking works. */
- spin_lock_irqsave(&ohci->lock, flags);
+ spin_lock_irq(&ohci->lock);
ohci->generation = -1; /* prevent AT packet queueing */
context_stop(&ohci->at_request_ctx);
context_stop(&ohci->at_response_ctx);
- spin_unlock_irqrestore(&ohci->lock, flags);
+ spin_unlock_irq(&ohci->lock);
/*
* Per OHCI 1.2 draft, clause 7.2.3.3, hardware may leave unsent
@@ -1757,7 +2017,7 @@ static void bus_reset_tasklet(unsigned long data)
at_context_flush(&ohci->at_request_ctx);
at_context_flush(&ohci->at_response_ctx);
- spin_lock_irqsave(&ohci->lock, flags);
+ spin_lock_irq(&ohci->lock);
ohci->generation = generation;
reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
@@ -1796,19 +2056,18 @@ static void bus_reset_tasklet(unsigned long data)
be32_to_cpu(ohci->next_header));
}
-#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
- reg_write(ohci, OHCI1394_PhyReqFilterHiSet, ~0);
- reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0);
-#endif
+ if (param_remote_dma) {
+ reg_write(ohci, OHCI1394_PhyReqFilterHiSet, ~0);
+ reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0);
+ }
- spin_unlock_irqrestore(&ohci->lock, flags);
+ spin_unlock_irq(&ohci->lock);
if (free_rom)
dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
free_rom, free_rom_bus);
- log_selfids(ohci->node_id, generation,
- self_id_count, ohci->self_id_buffer);
+ log_selfids(ohci, generation, self_id_count);
fw_core_handle_bus_reset(&ohci->card, ohci->node_id, generation,
self_id_count, ohci->self_id_buffer,
@@ -1833,10 +2092,10 @@ static irqreturn_t irq_handler(int irq, void *data)
*/
reg_write(ohci, OHCI1394_IntEventClear,
event & ~(OHCI1394_busReset | OHCI1394_postedWriteErr));
- log_irqs(event);
+ log_irqs(ohci, event);
if (event & OHCI1394_selfIDComplete)
- tasklet_schedule(&ohci->bus_reset_tasklet);
+ queue_work(selfid_workqueue, &ohci->bus_reset_work);
if (event & OHCI1394_RQPkt)
tasklet_schedule(&ohci->ar_request_ctx.tasklet);
@@ -1875,20 +2134,20 @@ static irqreturn_t irq_handler(int irq, void *data)
}
if (unlikely(event & OHCI1394_regAccessFail))
- fw_error("Register access failure - "
- "please notify linux1394-devel@lists.sf.net\n");
+ ohci_err(ohci, "register access failure\n");
if (unlikely(event & OHCI1394_postedWriteErr)) {
reg_read(ohci, OHCI1394_PostedWriteAddressHi);
reg_read(ohci, OHCI1394_PostedWriteAddressLo);
reg_write(ohci, OHCI1394_IntEventClear,
OHCI1394_postedWriteErr);
- fw_error("PCI posted write error\n");
+ if (printk_ratelimit())
+ ohci_err(ohci, "PCI posted write error\n");
}
if (unlikely(event & OHCI1394_cycleTooLong)) {
if (printk_ratelimit())
- fw_notify("isochronous cycle too long\n");
+ ohci_notice(ohci, "isochronous cycle too long\n");
reg_write(ohci, OHCI1394_LinkControlSet,
OHCI1394_LinkControl_cycleMaster);
}
@@ -1901,9 +2160,12 @@ static irqreturn_t irq_handler(int irq, void *data)
* them at least two cycles later. (FIXME?)
*/
if (printk_ratelimit())
- fw_notify("isochronous cycle inconsistent\n");
+ ohci_notice(ohci, "isochronous cycle inconsistent\n");
}
+ if (unlikely(event & OHCI1394_unrecoverableError))
+ handle_dead_contexts(ohci);
+
if (event & OHCI1394_cycle64Seconds) {
spin_lock(&ohci->lock);
update_bus_time(ohci);
@@ -1916,14 +2178,18 @@ static irqreturn_t irq_handler(int irq, void *data)
static int software_reset(struct fw_ohci *ohci)
{
+ u32 val;
int i;
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
+ for (i = 0; i < 500; i++) {
+ val = reg_read(ohci, OHCI1394_HCControlSet);
+ if (!~val)
+ return -ENODEV; /* Card was ejected. */
- for (i = 0; i < OHCI_LOOP_COUNT; i++) {
- if ((reg_read(ohci, OHCI1394_HCControlSet) &
- OHCI1394_HCControl_softReset) == 0)
+ if (!(val & OHCI1394_HCControl_softReset))
return 0;
+
msleep(1);
}
@@ -1990,16 +2256,37 @@ static int configure_1394a_enhancements(struct fw_ohci *ohci)
return 0;
}
+static int probe_tsb41ba3d(struct fw_ohci *ohci)
+{
+ /* TI vendor ID = 0x080028, TSB41BA3D product ID = 0x833005 (sic) */
+ static const u8 id[] = { 0x08, 0x00, 0x28, 0x83, 0x30, 0x05, };
+ int reg, i;
+
+ reg = read_phy_reg(ohci, 2);
+ if (reg < 0)
+ return reg;
+ if ((reg & PHY_EXTENDED_REGISTERS) != PHY_EXTENDED_REGISTERS)
+ return 0;
+
+ for (i = ARRAY_SIZE(id) - 1; i >= 0; i--) {
+ reg = read_paged_phy_reg(ohci, 1, i + 10);
+ if (reg < 0)
+ return reg;
+ if (reg != id[i])
+ return 0;
+ }
+ return 1;
+}
+
static int ohci_enable(struct fw_card *card,
const __be32 *config_rom, size_t length)
{
struct fw_ohci *ohci = fw_ohci(card);
- struct pci_dev *dev = to_pci_dev(card->device);
- u32 lps, seconds, version, irqs;
+ u32 lps, version, irqs;
int i, ret;
if (software_reset(ohci)) {
- fw_error("Failed to reset ohci card.\n");
+ ohci_err(ohci, "failed to reset ohci card\n");
return -EBUSY;
}
@@ -2010,7 +2297,12 @@ static int ohci_enable(struct fw_card *card,
* will lock up the machine. Wait 50msec to make sure we have
* full link enabled. However, with some cards (well, at least
* a JMicron PCIe card), we have to try again sometimes.
+ *
+ * TI TSB82AA2 + TSB81BA3(A) cards signal LPS enabled early but
+ * cannot actually use the phy at that time. These need tens of
+ * millisecods pause between LPS write and first phy access too.
*/
+
reg_write(ohci, OHCI1394_HCControlSet,
OHCI1394_HCControl_LPS |
OHCI1394_HCControl_postedWriteEnable);
@@ -2023,17 +2315,25 @@ static int ohci_enable(struct fw_card *card,
}
if (!lps) {
- fw_error("Failed to set Link Power Status\n");
+ ohci_err(ohci, "failed to set Link Power Status\n");
return -EIO;
}
+ if (ohci->quirks & QUIRK_TI_SLLZ059) {
+ ret = probe_tsb41ba3d(ohci);
+ if (ret < 0)
+ return ret;
+ if (ret)
+ ohci_notice(ohci, "local TSB41BA3D phy\n");
+ else
+ ohci->quirks &= ~QUIRK_TI_SLLZ059;
+ }
+
reg_write(ohci, OHCI1394_HCControlClear,
OHCI1394_HCControl_noByteSwapData);
reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus);
reg_write(ohci, OHCI1394_LinkControlSet,
- OHCI1394_LinkControl_rcvSelfID |
- OHCI1394_LinkControl_rcvPhyPkt |
OHCI1394_LinkControl_cycleTimerEnable |
OHCI1394_LinkControl_cycleMaster);
@@ -2043,9 +2343,12 @@ static int ohci_enable(struct fw_card *card,
(OHCI1394_MAX_PHYS_RESP_RETRIES << 8) |
(200 << 16));
- seconds = lower_32_bits(get_seconds());
- reg_write(ohci, OHCI1394_IsochronousCycleTimer, seconds << 25);
- ohci->bus_time = seconds & ~0x3f;
+ ohci->bus_time_running = false;
+
+ for (i = 0; i < 32; i++)
+ if (ohci->ir_context_support & (1 << i))
+ reg_write(ohci, OHCI1394_IsoRcvContextControlClear(i),
+ IR_CONTEXT_MULTI_CHANNEL_MODE);
version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
if (version >= OHCI_VERSION_1_1) {
@@ -2060,10 +2363,7 @@ static int ohci_enable(struct fw_card *card,
reg_write(ohci, OHCI1394_FairnessControl, 0);
card->priority_budget_implemented = ohci->pri_req_max != 0;
- ar_context_run(&ohci->ar_request_ctx);
- ar_context_run(&ohci->ar_response_ctx);
-
- reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000);
+ reg_write(ohci, OHCI1394_PhyUpperBound, FW_MAX_PHYSICAL_RANGE >> 16);
reg_write(ohci, OHCI1394_IntEventClear, ~0);
reg_write(ohci, OHCI1394_IntMaskClear, ~0);
@@ -2122,26 +2422,15 @@ static int ohci_enable(struct fw_card *card,
reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
- if (!(ohci->quirks & QUIRK_NO_MSI))
- pci_enable_msi(dev);
- if (request_irq(dev->irq, irq_handler,
- pci_dev_msi_enabled(dev) ? 0 : IRQF_SHARED,
- ohci_driver_name, ohci)) {
- fw_error("Failed to allocate interrupt %d.\n", dev->irq);
- pci_disable_msi(dev);
- dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
- ohci->config_rom, ohci->config_rom_bus);
- return -EIO;
- }
-
irqs = OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
OHCI1394_RQPkt | OHCI1394_RSPkt |
OHCI1394_isochTx | OHCI1394_isochRx |
OHCI1394_postedWriteErr |
OHCI1394_selfIDComplete |
OHCI1394_regAccessFail |
- OHCI1394_cycle64Seconds |
- OHCI1394_cycleInconsistent | OHCI1394_cycleTooLong |
+ OHCI1394_cycleInconsistent |
+ OHCI1394_unrecoverableError |
+ OHCI1394_cycleTooLong |
OHCI1394_masterIntEnable;
if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
irqs |= OHCI1394_busReset;
@@ -2150,6 +2439,14 @@ static int ohci_enable(struct fw_card *card,
reg_write(ohci, OHCI1394_HCControlSet,
OHCI1394_HCControl_linkEnable |
OHCI1394_HCControl_BIBimageValid);
+
+ reg_write(ohci, OHCI1394_LinkControlSet,
+ OHCI1394_LinkControl_rcvSelfID |
+ OHCI1394_LinkControl_rcvPhyPkt);
+
+ ar_context_run(&ohci->ar_request_ctx);
+ ar_context_run(&ohci->ar_response_ctx);
+
flush_writes(ohci);
/* We are ready to go, reset bus to finish initialization. */
@@ -2162,8 +2459,6 @@ static int ohci_set_config_rom(struct fw_card *card,
const __be32 *config_rom, size_t length)
{
struct fw_ohci *ohci;
- unsigned long flags;
- int ret = -EBUSY;
__be32 *next_config_rom;
dma_addr_t uninitialized_var(next_config_rom_bus);
@@ -2193,7 +2488,7 @@ static int ohci_set_config_rom(struct fw_card *card,
* then set up the real values for the two registers.
*
* We use ohci->lock to avoid racing with the code that sets
- * ohci->next_config_rom to NULL (see bus_reset_tasklet).
+ * ohci->next_config_rom to NULL (see bus_reset_work).
*/
next_config_rom =
@@ -2202,23 +2497,38 @@ static int ohci_set_config_rom(struct fw_card *card,
if (next_config_rom == NULL)
return -ENOMEM;
- spin_lock_irqsave(&ohci->lock, flags);
+ spin_lock_irq(&ohci->lock);
+
+ /*
+ * If there is not an already pending config_rom update,
+ * push our new allocation into the ohci->next_config_rom
+ * and then mark the local variable as null so that we
+ * won't deallocate the new buffer.
+ *
+ * OTOH, if there is a pending config_rom update, just
+ * use that buffer with the new config_rom data, and
+ * let this routine free the unused DMA allocation.
+ */
if (ohci->next_config_rom == NULL) {
ohci->next_config_rom = next_config_rom;
ohci->next_config_rom_bus = next_config_rom_bus;
+ next_config_rom = NULL;
+ }
- copy_config_rom(ohci->next_config_rom, config_rom, length);
+ copy_config_rom(ohci->next_config_rom, config_rom, length);
- ohci->next_header = config_rom[0];
- ohci->next_config_rom[0] = 0;
+ ohci->next_header = config_rom[0];
+ ohci->next_config_rom[0] = 0;
- reg_write(ohci, OHCI1394_ConfigROMmap,
- ohci->next_config_rom_bus);
- ret = 0;
- }
+ reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus);
- spin_unlock_irqrestore(&ohci->lock, flags);
+ spin_unlock_irq(&ohci->lock);
+
+ /* If we didn't use the DMA allocation, delete it. */
+ if (next_config_rom != NULL)
+ dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+ next_config_rom, next_config_rom_bus);
/*
* Now initiate a bus reset to have the changes take
@@ -2227,13 +2537,10 @@ static int ohci_set_config_rom(struct fw_card *card,
* controller could need to access it before the bus reset
* takes effect.
*/
- if (ret == 0)
- fw_schedule_bus_reset(&ohci->card, true, true);
- else
- dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
- next_config_rom, next_config_rom_bus);
- return ret;
+ fw_schedule_bus_reset(&ohci->card, true, true);
+
+ return 0;
}
static void ohci_send_request(struct fw_card *card, struct fw_packet *packet)
@@ -2266,7 +2573,7 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
dma_unmap_single(ohci->card.device, packet->payload_bus,
packet->payload_length, DMA_TO_DEVICE);
- log_ar_at_event('T', packet->speed, packet->header, 0x20);
+ log_ar_at_event(ohci, 'T', packet->speed, packet->header, 0x20);
driver_data->packet = NULL;
packet->ack = RCODE_CANCELLED;
packet->callback(packet, &ohci->card, packet->ack);
@@ -2280,13 +2587,13 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
static int ohci_enable_phys_dma(struct fw_card *card,
int node_id, int generation)
{
-#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA
- return 0;
-#else
struct fw_ohci *ohci = fw_ohci(card);
unsigned long flags;
int n, ret = 0;
+ if (param_remote_dma)
+ return 0;
+
/*
* FIXME: Make sure this bitmask is cleared when we clear the busReset
* interrupt bit. Clear physReqResourceAllBuses on bus reset.
@@ -2315,7 +2622,6 @@ static int ohci_enable_phys_dma(struct fw_card *card,
spin_unlock_irqrestore(&ohci->lock, flags);
return ret;
-#endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */
}
static u32 ohci_read_csr(struct fw_card *card, int csr_offset)
@@ -2409,7 +2715,8 @@ static void ohci_write_csr(struct fw_card *card, int csr_offset, u32 value)
case CSR_BUS_TIME:
spin_lock_irqsave(&ohci->lock, flags);
- ohci->bus_time = (ohci->bus_time & 0x7f) | (value & ~0x7f);
+ ohci->bus_time = (update_bus_time(ohci) & 0x40) |
+ (value & ~0x7f);
spin_unlock_irqrestore(&ohci->lock, flags);
break;
@@ -2431,25 +2738,38 @@ static void ohci_write_csr(struct fw_card *card, int csr_offset, u32 value)
}
}
-static void copy_iso_headers(struct iso_context *ctx, void *p)
+static void flush_iso_completions(struct iso_context *ctx)
{
- int i = ctx->header_length;
+ ctx->base.callback.sc(&ctx->base, ctx->last_timestamp,
+ ctx->header_length, ctx->header,
+ ctx->base.callback_data);
+ ctx->header_length = 0;
+}
- if (i + ctx->base.header_size > PAGE_SIZE)
- return;
+static void copy_iso_headers(struct iso_context *ctx, const u32 *dma_hdr)
+{
+ u32 *ctx_hdr;
+
+ if (ctx->header_length + ctx->base.header_size > PAGE_SIZE) {
+ if (ctx->base.drop_overflow_headers)
+ return;
+ flush_iso_completions(ctx);
+ }
+
+ ctx_hdr = ctx->header + ctx->header_length;
+ ctx->last_timestamp = (u16)le32_to_cpu((__force __le32)dma_hdr[0]);
/*
- * The iso header is byteswapped to little endian by
- * the controller, but the remaining header quadlets
- * are big endian. We want to present all the headers
- * as big endian, so we have to swap the first quadlet.
+ * The two iso header quadlets are byteswapped to little
+ * endian by the controller, but we want to present them
+ * as big endian for consistency with the bus endianness.
*/
if (ctx->base.header_size > 0)
- *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4));
+ ctx_hdr[0] = swab32(dma_hdr[1]); /* iso packet header */
if (ctx->base.header_size > 4)
- *(u32 *) (ctx->header + i + 4) = __swab32(*(u32 *) p);
+ ctx_hdr[1] = swab32(dma_hdr[0]); /* timestamp */
if (ctx->base.header_size > 8)
- memcpy(ctx->header + i + 8, p + 8, ctx->base.header_size - 8);
+ memcpy(&ctx_hdr[2], &dma_hdr[2], ctx->base.header_size - 8);
ctx->header_length += ctx->base.header_size;
}
@@ -2460,8 +2780,7 @@ static int handle_ir_packet_per_buffer(struct context *context,
struct iso_context *ctx =
container_of(context, struct iso_context, context);
struct descriptor *pd;
- __le32 *ir_header;
- void *p;
+ u32 buffer_dma;
for (pd = d; pd <= last; pd++)
if (pd->transfer_status)
@@ -2470,18 +2789,21 @@ static int handle_ir_packet_per_buffer(struct context *context,
/* Descriptor(s) not done yet, stop iteration */
return 0;
- p = last + 1;
- copy_iso_headers(ctx, p);
-
- if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) {
- ir_header = (__le32 *) p;
- ctx->base.callback.sc(&ctx->base,
- le32_to_cpu(ir_header[0]) & 0xffff,
- ctx->header_length, ctx->header,
- ctx->base.callback_data);
- ctx->header_length = 0;
+ while (!(d->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))) {
+ d++;
+ buffer_dma = le32_to_cpu(d->data_address);
+ dma_sync_single_range_for_cpu(context->ohci->card.device,
+ buffer_dma & PAGE_MASK,
+ buffer_dma & ~PAGE_MASK,
+ le16_to_cpu(d->req_count),
+ DMA_FROM_DEVICE);
}
+ copy_iso_headers(ctx, (u32 *) (last + 1));
+
+ if (last->control & cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS))
+ flush_iso_completions(ctx);
+
return 1;
}
@@ -2492,29 +2814,96 @@ static int handle_ir_buffer_fill(struct context *context,
{
struct iso_context *ctx =
container_of(context, struct iso_context, context);
+ unsigned int req_count, res_count, completed;
+ u32 buffer_dma;
+
+ req_count = le16_to_cpu(last->req_count);
+ res_count = le16_to_cpu(ACCESS_ONCE(last->res_count));
+ completed = req_count - res_count;
+ buffer_dma = le32_to_cpu(last->data_address);
+
+ if (completed > 0) {
+ ctx->mc_buffer_bus = buffer_dma;
+ ctx->mc_completed = completed;
+ }
- if (!last->transfer_status)
+ if (res_count != 0)
/* Descriptor(s) not done yet, stop iteration */
return 0;
- if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS)
+ dma_sync_single_range_for_cpu(context->ohci->card.device,
+ buffer_dma & PAGE_MASK,
+ buffer_dma & ~PAGE_MASK,
+ completed, DMA_FROM_DEVICE);
+
+ if (last->control & cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS)) {
ctx->base.callback.mc(&ctx->base,
- le32_to_cpu(last->data_address) +
- le16_to_cpu(last->req_count) -
- le16_to_cpu(last->res_count),
+ buffer_dma + completed,
ctx->base.callback_data);
+ ctx->mc_completed = 0;
+ }
return 1;
}
+static void flush_ir_buffer_fill(struct iso_context *ctx)
+{
+ dma_sync_single_range_for_cpu(ctx->context.ohci->card.device,
+ ctx->mc_buffer_bus & PAGE_MASK,
+ ctx->mc_buffer_bus & ~PAGE_MASK,
+ ctx->mc_completed, DMA_FROM_DEVICE);
+
+ ctx->base.callback.mc(&ctx->base,
+ ctx->mc_buffer_bus + ctx->mc_completed,
+ ctx->base.callback_data);
+ ctx->mc_completed = 0;
+}
+
+static inline void sync_it_packet_for_cpu(struct context *context,
+ struct descriptor *pd)
+{
+ __le16 control;
+ u32 buffer_dma;
+
+ /* only packets beginning with OUTPUT_MORE* have data buffers */
+ if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))
+ return;
+
+ /* skip over the OUTPUT_MORE_IMMEDIATE descriptor */
+ pd += 2;
+
+ /*
+ * If the packet has a header, the first OUTPUT_MORE/LAST descriptor's
+ * data buffer is in the context program's coherent page and must not
+ * be synced.
+ */
+ if ((le32_to_cpu(pd->data_address) & PAGE_MASK) ==
+ (context->current_bus & PAGE_MASK)) {
+ if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))
+ return;
+ pd++;
+ }
+
+ do {
+ buffer_dma = le32_to_cpu(pd->data_address);
+ dma_sync_single_range_for_cpu(context->ohci->card.device,
+ buffer_dma & PAGE_MASK,
+ buffer_dma & ~PAGE_MASK,
+ le16_to_cpu(pd->req_count),
+ DMA_TO_DEVICE);
+ control = pd->control;
+ pd++;
+ } while (!(control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS)));
+}
+
static int handle_it_packet(struct context *context,
struct descriptor *d,
struct descriptor *last)
{
struct iso_context *ctx =
container_of(context, struct iso_context, context);
- int i;
struct descriptor *pd;
+ __be32 *ctx_hdr;
for (pd = d; pd <= last; pd++)
if (pd->transfer_status)
@@ -2523,20 +2912,24 @@ static int handle_it_packet(struct context *context,
/* Descriptor(s) not done yet, stop iteration */
return 0;
- i = ctx->header_length;
- if (i + 4 < PAGE_SIZE) {
- /* Present this value as big-endian to match the receive code */
- *(__be32 *)(ctx->header + i) = cpu_to_be32(
- ((u32)le16_to_cpu(pd->transfer_status) << 16) |
- le16_to_cpu(pd->res_count));
- ctx->header_length += 4;
- }
- if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) {
- ctx->base.callback.sc(&ctx->base, le16_to_cpu(last->res_count),
- ctx->header_length, ctx->header,
- ctx->base.callback_data);
- ctx->header_length = 0;
+ sync_it_packet_for_cpu(context, d);
+
+ if (ctx->header_length + 4 > PAGE_SIZE) {
+ if (ctx->base.drop_overflow_headers)
+ return 1;
+ flush_iso_completions(ctx);
}
+
+ ctx_hdr = ctx->header + ctx->header_length;
+ ctx->last_timestamp = le16_to_cpu(last->res_count);
+ /* Present this value as big-endian to match the receive code */
+ *ctx_hdr = cpu_to_be32((le16_to_cpu(pd->transfer_status) << 16) |
+ le16_to_cpu(pd->res_count));
+ ctx->header_length += 4;
+
+ if (last->control & cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS))
+ flush_iso_completions(ctx);
+
return 1;
}
@@ -2560,10 +2953,9 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
descriptor_callback_t uninitialized_var(callback);
u64 *uninitialized_var(channels);
u32 *uninitialized_var(mask), uninitialized_var(regs);
- unsigned long flags;
int index, ret = -EBUSY;
- spin_lock_irqsave(&ohci->lock, flags);
+ spin_lock_irq(&ohci->lock);
switch (type) {
case FW_ISO_CONTEXT_TRANSMIT:
@@ -2607,7 +2999,7 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
ret = -ENOSYS;
}
- spin_unlock_irqrestore(&ohci->lock, flags);
+ spin_unlock_irq(&ohci->lock);
if (index < 0)
return ERR_PTR(ret);
@@ -2623,15 +3015,17 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
if (ret < 0)
goto out_with_header;
- if (type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL)
+ if (type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL) {
set_multichannel_mask(ohci, 0);
+ ctx->mc_completed = 0;
+ }
return &ctx->base;
out_with_header:
free_page((unsigned long)ctx->header);
out:
- spin_lock_irqsave(&ohci->lock, flags);
+ spin_lock_irq(&ohci->lock);
switch (type) {
case FW_ISO_CONTEXT_RECEIVE:
@@ -2644,7 +3038,7 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
}
*mask |= 1 << index;
- spin_unlock_irqrestore(&ohci->lock, flags);
+ spin_unlock_irq(&ohci->lock);
return ERR_PTR(ret);
}
@@ -2657,6 +3051,10 @@ static int ohci_start_iso(struct fw_iso_context *base,
u32 control = IR_CONTEXT_ISOCH_HEADER, match;
int index;
+ /* the controller cannot start without any queued packets */
+ if (ctx->context.last->branch_address == 0)
+ return -ENODATA;
+
switch (ctx->base.type) {
case FW_ISO_CONTEXT_TRANSMIT:
index = ctx - ohci->it_context_list;
@@ -2715,6 +3113,7 @@ static int ohci_stop_iso(struct fw_iso_context *base)
}
flush_writes(ohci);
context_stop(&ctx->context);
+ tasklet_kill(&ctx->context.tasklet);
return 0;
}
@@ -2887,6 +3286,10 @@ static int queue_iso_transmit(struct iso_context *ctx,
page_bus = page_private(buffer->pages[page]);
pd[i].data_address = cpu_to_le32(page_bus + offset);
+ dma_sync_single_range_for_device(ctx->context.ohci->card.device,
+ page_bus, offset, length,
+ DMA_TO_DEVICE);
+
payload_index += length;
}
@@ -2911,6 +3314,7 @@ static int queue_iso_packet_per_buffer(struct iso_context *ctx,
struct fw_iso_buffer *buffer,
unsigned long payload)
{
+ struct device *device = ctx->context.ohci->card.device;
struct descriptor *d, *pd;
dma_addr_t d_bus, page_bus;
u32 z, header_z, rest;
@@ -2965,6 +3369,10 @@ static int queue_iso_packet_per_buffer(struct iso_context *ctx,
page_bus = page_private(buffer->pages[page]);
pd->data_address = cpu_to_le32(page_bus + offset);
+ dma_sync_single_range_for_device(device, page_bus,
+ offset, length,
+ DMA_FROM_DEVICE);
+
offset = (offset + length) & ~PAGE_MASK;
rest -= length;
if (offset == 0)
@@ -3024,6 +3432,10 @@ static int queue_iso_buffer_fill(struct iso_context *ctx,
page_bus = page_private(buffer->pages[page]);
d->data_address = cpu_to_le32(page_bus + offset);
+ dma_sync_single_range_for_device(ctx->context.ohci->card.device,
+ page_bus, offset, length,
+ DMA_FROM_DEVICE);
+
rest -= length;
offset = 0;
page++;
@@ -3060,6 +3472,47 @@ static int ohci_queue_iso(struct fw_iso_context *base,
return ret;
}
+static void ohci_flush_queue_iso(struct fw_iso_context *base)
+{
+ struct context *ctx =
+ &container_of(base, struct iso_context, base)->context;
+
+ reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
+}
+
+static int ohci_flush_iso_completions(struct fw_iso_context *base)
+{
+ struct iso_context *ctx = container_of(base, struct iso_context, base);
+ int ret = 0;
+
+ tasklet_disable(&ctx->context.tasklet);
+
+ if (!test_and_set_bit_lock(0, &ctx->flushing_completions)) {
+ context_tasklet((unsigned long)&ctx->context);
+
+ switch (base->type) {
+ case FW_ISO_CONTEXT_TRANSMIT:
+ case FW_ISO_CONTEXT_RECEIVE:
+ if (ctx->header_length != 0)
+ flush_iso_completions(ctx);
+ break;
+ case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
+ if (ctx->mc_completed != 0)
+ flush_ir_buffer_fill(ctx);
+ break;
+ default:
+ ret = -ENOSYS;
+ }
+
+ clear_bit_unlock(0, &ctx->flushing_completions);
+ smp_mb__after_atomic();
+ }
+
+ tasklet_enable(&ctx->context.tasklet);
+
+ return ret;
+}
+
static const struct fw_card_driver ohci_driver = {
.enable = ohci_enable,
.read_phy_reg = ohci_read_phy_reg,
@@ -3076,6 +3529,8 @@ static const struct fw_card_driver ohci_driver = {
.free_iso_context = ohci_free_iso_context,
.set_iso_channels = ohci_set_iso_channels,
.queue_iso = ohci_queue_iso,
+ .flush_queue_iso = ohci_flush_queue_iso,
+ .flush_iso_completions = ohci_flush_iso_completions,
.start_iso = ohci_start_iso,
.stop_iso = ohci_stop_iso,
};
@@ -3109,7 +3564,7 @@ static inline void pmac_ohci_on(struct pci_dev *dev) {}
static inline void pmac_ohci_off(struct pci_dev *dev) {}
#endif /* CONFIG_PPC_PMAC */
-static int __devinit pci_probe(struct pci_dev *dev,
+static int pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
struct fw_ohci *ohci;
@@ -3118,6 +3573,11 @@ static int __devinit pci_probe(struct pci_dev *dev,
int i, err;
size_t size;
+ if (dev->vendor == PCI_VENDOR_ID_PINNACLE_SYSTEMS) {
+ dev_err(&dev->dev, "Pinnacle MovieBoard is not yet supported\n");
+ return -ENOSYS;
+ }
+
ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
if (ohci == NULL) {
err = -ENOMEM;
@@ -3130,7 +3590,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
err = pci_enable_device(dev);
if (err) {
- fw_error("Failed to enable OHCI hardware\n");
+ dev_err(&dev->dev, "failed to enable OHCI hardware\n");
goto fail_free;
}
@@ -3141,18 +3601,24 @@ static int __devinit pci_probe(struct pci_dev *dev,
spin_lock_init(&ohci->lock);
mutex_init(&ohci->phy_reg_mutex);
- tasklet_init(&ohci->bus_reset_tasklet,
- bus_reset_tasklet, (unsigned long)ohci);
+ INIT_WORK(&ohci->bus_reset_work, bus_reset_work);
+
+ if (!(pci_resource_flags(dev, 0) & IORESOURCE_MEM) ||
+ pci_resource_len(dev, 0) < OHCI1394_REGISTER_SIZE) {
+ ohci_err(ohci, "invalid MMIO resource\n");
+ err = -ENXIO;
+ goto fail_disable;
+ }
err = pci_request_region(dev, 0, ohci_driver_name);
if (err) {
- fw_error("MMIO resource unavailable\n");
+ ohci_err(ohci, "MMIO resource unavailable\n");
goto fail_disable;
}
ohci->registers = pci_iomap(dev, 0, OHCI1394_REGISTER_SIZE);
if (ohci->registers == NULL) {
- fw_error("Failed to remap registers\n");
+ ohci_err(ohci, "failed to remap registers\n");
err = -ENXIO;
goto fail_iomem;
}
@@ -3207,15 +3673,17 @@ static int __devinit pci_probe(struct pci_dev *dev,
reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0);
ohci->ir_context_channels = ~0ULL;
- ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
+ ohci->ir_context_support = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0);
+ ohci->ir_context_mask = ohci->ir_context_support;
ohci->n_ir = hweight32(ohci->ir_context_mask);
size = sizeof(struct iso_context) * ohci->n_ir;
ohci->ir_context_list = kzalloc(size, GFP_KERNEL);
reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0);
- ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
+ ohci->it_context_support = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0);
+ ohci->it_context_mask = ohci->it_context_support;
ohci->n_it = hweight32(ohci->it_context_mask);
size = sizeof(struct iso_context) * ohci->n_it;
ohci->it_context_list = kzalloc(size, GFP_KERNEL);
@@ -3225,7 +3693,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
goto fail_contexts;
}
- ohci->self_id_cpu = ohci->misc_buffer + PAGE_SIZE/2;
+ ohci->self_id = ohci->misc_buffer + PAGE_SIZE/2;
ohci->self_id_bus = ohci->misc_buffer_bus + PAGE_SIZE/2;
bus_options = reg_read(ohci, OHCI1394_BusOptions);
@@ -3234,18 +3702,35 @@ static int __devinit pci_probe(struct pci_dev *dev,
guid = ((u64) reg_read(ohci, OHCI1394_GUIDHi) << 32) |
reg_read(ohci, OHCI1394_GUIDLo);
+ if (!(ohci->quirks & QUIRK_NO_MSI))
+ pci_enable_msi(dev);
+ if (request_irq(dev->irq, irq_handler,
+ pci_dev_msi_enabled(dev) ? 0 : IRQF_SHARED,
+ ohci_driver_name, ohci)) {
+ ohci_err(ohci, "failed to allocate interrupt %d\n", dev->irq);
+ err = -EIO;
+ goto fail_msi;
+ }
+
err = fw_card_add(&ohci->card, max_receive, link_speed, guid);
if (err)
- goto fail_contexts;
+ goto fail_irq;
version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
- fw_notify("Added fw-ohci device %s, OHCI v%x.%x, "
- "%d IR + %d IT contexts, quirks 0x%x\n",
- dev_name(&dev->dev), version >> 16, version & 0xff,
- ohci->n_ir, ohci->n_it, ohci->quirks);
+ ohci_notice(ohci,
+ "added OHCI v%x.%x device as card %d, "
+ "%d IR + %d IT contexts, quirks 0x%x%s\n",
+ version >> 16, version & 0xff, ohci->card.index,
+ ohci->n_ir, ohci->n_it, ohci->quirks,
+ reg_read(ohci, OHCI1394_PhyUpperBound) ?
+ ", physUB" : "");
return 0;
+ fail_irq:
+ free_irq(dev->irq, ohci);
+ fail_msi:
+ pci_disable_msi(dev);
fail_contexts:
kfree(ohci->ir_context_list);
kfree(ohci->it_context_list);
@@ -3266,22 +3751,25 @@ static int __devinit pci_probe(struct pci_dev *dev,
fail_disable:
pci_disable_device(dev);
fail_free:
- kfree(&ohci->card);
+ kfree(ohci);
pmac_ohci_off(dev);
fail:
- if (err == -ENOMEM)
- fw_error("Out of memory\n");
-
return err;
}
static void pci_remove(struct pci_dev *dev)
{
- struct fw_ohci *ohci;
+ struct fw_ohci *ohci = pci_get_drvdata(dev);
- ohci = pci_get_drvdata(dev);
- reg_write(ohci, OHCI1394_IntMaskClear, ~0);
- flush_writes(ohci);
+ /*
+ * If the removal is happening from the suspend state, LPS won't be
+ * enabled and host registers (eg., IntMaskClear) won't be accessible.
+ */
+ if (reg_read(ohci, OHCI1394_HCControlSet) & OHCI1394_HCControl_LPS) {
+ reg_write(ohci, OHCI1394_IntMaskClear, ~0);
+ flush_writes(ohci);
+ }
+ cancel_work_sync(&ohci->bus_reset_work);
fw_core_remove_card(&ohci->card);
/*
@@ -3310,10 +3798,10 @@ static void pci_remove(struct pci_dev *dev)
pci_iounmap(dev, ohci->registers);
pci_release_region(dev, 0);
pci_disable_device(dev);
- kfree(&ohci->card);
+ kfree(ohci);
pmac_ohci_off(dev);
- fw_notify("Removed fw-ohci device.\n");
+ dev_notice(&dev->dev, "removed fw-ohci device\n");
}
#ifdef CONFIG_PM
@@ -3323,16 +3811,14 @@ static int pci_suspend(struct pci_dev *dev, pm_message_t state)
int err;
software_reset(ohci);
- free_irq(dev->irq, ohci);
- pci_disable_msi(dev);
err = pci_save_state(dev);
if (err) {
- fw_error("pci_save_state failed\n");
+ ohci_err(ohci, "pci_save_state failed\n");
return err;
}
err = pci_set_power_state(dev, pci_choose_state(dev, state));
if (err)
- fw_error("pci_set_power_state failed with %d\n", err);
+ ohci_err(ohci, "pci_set_power_state failed with %d\n", err);
pmac_ohci_off(dev);
return 0;
@@ -3348,7 +3834,7 @@ static int pci_resume(struct pci_dev *dev)
pci_restore_state(dev);
err = pci_enable_device(dev);
if (err) {
- fw_error("pci_enable_device failed\n");
+ ohci_err(ohci, "pci_enable_device failed\n");
return err;
}
@@ -3387,24 +3873,27 @@ static struct pci_driver fw_ohci_pci_driver = {
#endif
};
-MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
-MODULE_DESCRIPTION("Driver for PCI OHCI IEEE1394 controllers");
-MODULE_LICENSE("GPL");
-
-/* Provide a module alias so root-on-sbp2 initrds don't break. */
-#ifndef CONFIG_IEEE1394_OHCI1394_MODULE
-MODULE_ALIAS("ohci1394");
-#endif
-
static int __init fw_ohci_init(void)
{
+ selfid_workqueue = alloc_workqueue(KBUILD_MODNAME, WQ_MEM_RECLAIM, 0);
+ if (!selfid_workqueue)
+ return -ENOMEM;
+
return pci_register_driver(&fw_ohci_pci_driver);
}
static void __exit fw_ohci_cleanup(void)
{
pci_unregister_driver(&fw_ohci_pci_driver);
+ destroy_workqueue(selfid_workqueue);
}
module_init(fw_ohci_init);
module_exit(fw_ohci_cleanup);
+
+MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
+MODULE_DESCRIPTION("Driver for PCI OHCI IEEE1394 controllers");
+MODULE_LICENSE("GPL");
+
+/* Provide a module alias so root-on-sbp2 initrds don't break. */
+MODULE_ALIAS("ohci1394");