diff options
Diffstat (limited to 'drivers/firewire/ohci.c')
| -rw-r--r-- | drivers/firewire/ohci.c | 350 | 
1 files changed, 209 insertions, 141 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 7f5f0da726d..187b3f2e797 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -170,10 +170,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;  }; @@ -338,8 +340,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" @@ -349,7 +349,7 @@ 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 void log_irqs(struct fw_ohci *ohci, u32 evt)  {  	if (likely(!(param_debug &  			(OHCI_PARAM_DEBUG_IRQS | OHCI_PARAM_DEBUG_BUSRESETS)))) @@ -359,7 +359,8 @@ 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%s\n", evt, +	dev_notice(ohci->card.device, +	    "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"		: "", @@ -398,24 +399,29 @@ 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); +	dev_notice(ohci->card.device, +		   "%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] " +			dev_notice(ohci->card.device, +			    "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", +			dev_notice(ohci->card.device, +			    "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)); @@ -451,7 +457,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]; @@ -463,8 +470,9 @@ 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); +		dev_notice(ohci->card.device, +			   "A%c evt_bus_reset, generation %d\n", +			   dir, (header[2] >> 16) & 0xff);  		return;  	} @@ -483,39 +491,35 @@ 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]); +		dev_notice(ohci->card.device, +			   "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]); +		dev_notice(ohci->card.device, +			   "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); +		dev_notice(ohci->card.device, +			   "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); +		dev_notice(ohci->card.device, +			   "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); @@ -559,7 +563,7 @@ static int read_phy_reg(struct fw_ohci *ohci, int addr)  		if (i >= 3)  			msleep(1);  	} -	fw_error("failed to read phy reg\n"); +	dev_err(ohci->card.device, "failed to read phy reg\n");  	return -EBUSY;  } @@ -581,7 +585,7 @@ static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val)  		if (i >= 3)  			msleep(1);  	} -	fw_error("failed to write phy reg\n"); +	dev_err(ohci->card.device, "failed to write phy reg\n");  	return -EBUSY;  } @@ -680,11 +684,14 @@ 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; + +	if (reg_read(ohci, CONTROL_CLEAR(ctx->regs)) & CONTEXT_RUN) { +		reg_write(ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN); +		flush_writes(ohci); -		fw_error("AR error: %s; DMA stopped\n", error_msg); +		dev_err(ohci->card.device, "AR error: %s; DMA stopped\n", +			error_msg);  	}  	/* FIXME: restart? */  } @@ -854,7 +861,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 @@ -1226,21 +1233,22 @@ static void context_append(struct context *ctx,  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;  	for (i = 0; i < 1000; i++) { -		reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs)); +		reg = reg_read(ohci, CONTROL_SET(ctx->regs));  		if ((reg & CONTEXT_ACTIVE) == 0)  			return;  		if (i)  			udelay(10);  	} -	fw_error("Error: DMA context still active (0x%08x)\n", reg); +	dev_err(ohci->card.device, "DMA context still active (0x%08x)\n", reg);  }  struct driver_data { @@ -1420,7 +1428,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: @@ -1549,7 +1557,7 @@ static void handle_local_lock(struct fw_ohci *ohci,  			goto out;  		} -	fw_error("swap not done (CSR lock timeout)\n"); +	dev_err(ohci->card.device, "swap not done (CSR lock timeout)\n");  	fw_fill_response(&response, packet->header, RCODE_BUSY, NULL, 0);   out: @@ -1623,15 +1631,10 @@ static void detect_dead_context(struct fw_ohci *ohci,  	u32 ctl;  	ctl = reg_read(ohci, CONTROL_SET(regs)); -	if (ctl & CONTEXT_DEAD) { -#ifdef CONFIG_FIREWIRE_OHCI_DEBUG -		fw_error("DMA context %s has stopped, error code: %s\n", -			 name, evts[ctl & 0x1f]); -#else -		fw_error("DMA context %s has stopped, error code: %#x\n", -			 name, ctl & 0x1f); -#endif -	} +	if (ctl & CONTEXT_DEAD) +		dev_err(ohci->card.device, +			"DMA context %s has stopped, error code: %s\n", +			name, evts[ctl & 0x1f]);  }  static void handle_dead_contexts(struct fw_ohci *ohci) @@ -1781,7 +1784,8 @@ static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count)  	reg = reg_read(ohci, OHCI1394_NodeID);  	if (!(reg & OHCI1394_NodeID_idValid)) { -		fw_notify("node ID not valid, new bus reset in progress\n"); +		dev_notice(ohci->card.device, +			   "node ID not valid, new bus reset in progress\n");  		return -EBUSY;  	}  	self_id |= ((reg & 0x3f) << 24); /* phy ID */ @@ -1827,11 +1831,12 @@ static void bus_reset_work(struct work_struct *work)  	reg = reg_read(ohci, OHCI1394_NodeID);  	if (!(reg & OHCI1394_NodeID_idValid)) { -		fw_notify("node ID not valid, new bus reset in progress\n"); +		dev_notice(ohci->card.device, +			   "node ID not valid, new bus reset in progress\n");  		return;  	}  	if ((reg & OHCI1394_NodeID_nodeNumber) == 63) { -		fw_notify("malconfigured bus\n"); +		dev_notice(ohci->card.device, "malconfigured bus\n");  		return;  	}  	ohci->node_id = reg & (OHCI1394_NodeID_busNumber | @@ -1845,7 +1850,7 @@ static void bus_reset_work(struct work_struct *work)  	reg = reg_read(ohci, OHCI1394_SelfIDCount);  	if (reg & OHCI1394_SelfIDCount_selfIDError) { -		fw_notify("inconsistent self IDs\n"); +		dev_notice(ohci->card.device, "inconsistent self IDs\n");  		return;  	}  	/* @@ -1857,7 +1862,7 @@ static void bus_reset_work(struct work_struct *work)  	self_id_count = (reg >> 3) & 0xff;  	if (self_id_count > 252) { -		fw_notify("inconsistent self IDs\n"); +		dev_notice(ohci->card.device, "inconsistent self IDs\n");  		return;  	} @@ -1875,11 +1880,13 @@ static void bus_reset_work(struct work_struct *work)  			 */  			if (cond_le32_to_cpu(ohci->self_id_cpu[i])  							== 0xffff008f) { -				fw_notify("ignoring spurious self IDs\n"); +				dev_notice(ohci->card.device, +					   "ignoring spurious self IDs\n");  				self_id_count = j;  				break;  			} else { -				fw_notify("inconsistent self IDs\n"); +				dev_notice(ohci->card.device, +					   "inconsistent self IDs\n");  				return;  			}  		} @@ -1890,13 +1897,14 @@ static void bus_reset_work(struct work_struct *work)  	if (ohci->quirks & QUIRK_TI_SLLZ059) {  		self_id_count = find_and_insert_self_id(ohci, self_id_count);  		if (self_id_count < 0) { -			fw_notify("could not construct local self ID\n"); +			dev_notice(ohci->card.device, +				   "could not construct local self ID\n");  			return;  		}  	}  	if (self_id_count == 0) { -		fw_notify("inconsistent self IDs\n"); +		dev_notice(ohci->card.device, "inconsistent self IDs\n");  		return;  	}  	rmb(); @@ -1917,8 +1925,8 @@ static void bus_reset_work(struct work_struct *work)  	new_generation = (reg_read(ohci, OHCI1394_SelfIDCount) >> 16) & 0xff;  	if (new_generation != generation) { -		fw_notify("recursive bus reset detected, " -			  "discarding self ids\n"); +		dev_notice(ohci->card.device, +			   "new bus reset, discarding self ids\n");  		return;  	} @@ -1989,8 +1997,7 @@ static void bus_reset_work(struct work_struct *work)  		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, @@ -2015,7 +2022,7 @@ 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)  		queue_work(fw_workqueue, &ohci->bus_reset_work); @@ -2057,8 +2064,7 @@ 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"); +		dev_err(ohci->card.device, "register access failure\n");  	if (unlikely(event & OHCI1394_postedWriteErr)) {  		reg_read(ohci, OHCI1394_PostedWriteAddressHi); @@ -2066,12 +2072,13 @@ static irqreturn_t irq_handler(int irq, void *data)  		reg_write(ohci, OHCI1394_IntEventClear,  			  OHCI1394_postedWriteErr);  		if (printk_ratelimit()) -			fw_error("PCI posted write error\n"); +			dev_err(ohci->card.device, "PCI posted write error\n");  	}  	if (unlikely(event & OHCI1394_cycleTooLong)) {  		if (printk_ratelimit()) -			fw_notify("isochronous cycle too long\n"); +			dev_notice(ohci->card.device, +				   "isochronous cycle too long\n");  		reg_write(ohci, OHCI1394_LinkControlSet,  			  OHCI1394_LinkControl_cycleMaster);  	} @@ -2084,7 +2091,8 @@ 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"); +			dev_notice(ohci->card.device, +				   "isochronous cycle inconsistent\n");  	}  	if (unlikely(event & OHCI1394_unrecoverableError)) @@ -2211,7 +2219,7 @@ static int ohci_enable(struct fw_card *card,  	int i, ret;  	if (software_reset(ohci)) { -		fw_error("Failed to reset ohci card.\n"); +		dev_err(card->device, "failed to reset ohci card\n");  		return -EBUSY;  	} @@ -2235,7 +2243,7 @@ static int ohci_enable(struct fw_card *card,  	}  	if (!lps) { -		fw_error("Failed to set Link Power Status\n"); +		dev_err(card->device, "failed to set Link Power Status\n");  		return -EIO;  	} @@ -2244,7 +2252,7 @@ static int ohci_enable(struct fw_card *card,  		if (ret < 0)  			return ret;  		if (ret) -			fw_notify("local TSB41BA3D phy\n"); +			dev_notice(card->device, "local TSB41BA3D phy\n");  		else  			ohci->quirks &= ~QUIRK_TI_SLLZ059;  	} @@ -2344,7 +2352,8 @@ static int ohci_enable(struct fw_card *card,  	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); +		dev_err(card->device, "failed to allocate interrupt %d\n", +			dev->irq);  		pci_disable_msi(dev);  		if (config_rom) { @@ -2509,7 +2518,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); @@ -2674,25 +2683,35 @@ 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) +		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;  } @@ -2704,8 +2723,6 @@ static int handle_ir_packet_per_buffer(struct context *context,  		container_of(context, struct iso_context, context);  	struct descriptor *pd;  	u32 buffer_dma; -	__le32 *ir_header; -	void *p;  	for (pd = d; pd <= last; pd++)  		if (pd->transfer_status) @@ -2724,17 +2741,10 @@ static int handle_ir_packet_per_buffer(struct context *context,  					      DMA_FROM_DEVICE);  	} -	p = last + 1; -	copy_iso_headers(ctx, p); +	copy_iso_headers(ctx, (u32 *) (last + 1)); -	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; -	} +	if (last->control & cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS)) +		flush_iso_completions(ctx);  	return 1;  } @@ -2746,29 +2756,51 @@ 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; -	if (!last->transfer_status) +	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 (res_count != 0)  		/* Descriptor(s) not done yet, stop iteration */  		return 0; -	buffer_dma = le32_to_cpu(last->data_address);  	dma_sync_single_range_for_cpu(context->ohci->card.device,  				      buffer_dma & PAGE_MASK,  				      buffer_dma & ~PAGE_MASK, -				      le16_to_cpu(last->req_count), -				      DMA_FROM_DEVICE); +				      completed, DMA_FROM_DEVICE); -	if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) +	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)  { @@ -2812,8 +2844,8 @@ static int handle_it_packet(struct context *context,  {  	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) @@ -2824,20 +2856,19 @@ static int handle_it_packet(struct context *context,  	sync_it_packet_for_cpu(context, d); -	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; -	} +	if (ctx->header_length + 4 > PAGE_SIZE) +		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;  } @@ -2924,8 +2955,10 @@ 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; @@ -3387,6 +3420,39 @@ static void ohci_flush_queue_iso(struct fw_iso_context *base)  	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_clear_bit(); +	} + +	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, @@ -3404,6 +3470,7 @@ static const struct fw_card_driver ohci_driver = {  	.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,  }; @@ -3463,7 +3530,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;  	} @@ -3478,13 +3545,13 @@ static int __devinit pci_probe(struct pci_dev *dev,  	err = pci_request_region(dev, 0, ohci_driver_name);  	if (err) { -		fw_error("MMIO resource unavailable\n"); +		dev_err(&dev->dev, "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"); +		dev_err(&dev->dev, "failed to remap registers\n");  		err = -ENXIO;  		goto fail_iomem;  	} @@ -3573,9 +3640,10 @@ static int __devinit pci_probe(struct pci_dev *dev,  		goto fail_contexts;  	version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; -	fw_notify("Added fw-ohci device %s, OHCI v%x.%x, " +	dev_notice(&dev->dev, +		  "added OHCI v%x.%x device as card %d, "  		  "%d IR + %d IT contexts, quirks 0x%x\n", -		  dev_name(&dev->dev), version >> 16, version & 0xff, +		  version >> 16, version & 0xff, ohci->card.index,  		  ohci->n_ir, ohci->n_it, ohci->quirks);  	return 0; @@ -3604,7 +3672,7 @@ static int __devinit pci_probe(struct pci_dev *dev,  	pmac_ohci_off(dev);   fail:  	if (err == -ENOMEM) -		fw_error("Out of memory\n"); +		dev_err(&dev->dev, "out of memory\n");  	return err;  } @@ -3648,7 +3716,7 @@ static void pci_remove(struct pci_dev *dev)  	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 @@ -3662,12 +3730,12 @@ static int pci_suspend(struct pci_dev *dev, pm_message_t state)  	pci_disable_msi(dev);  	err = pci_save_state(dev);  	if (err) { -		fw_error("pci_save_state failed\n"); +		dev_err(&dev->dev, "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); +		dev_err(&dev->dev, "pci_set_power_state failed with %d\n", err);  	pmac_ohci_off(dev);  	return 0; @@ -3683,7 +3751,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"); +		dev_err(&dev->dev, "pci_enable_device failed\n");  		return err;  	}  |