diff options
Diffstat (limited to 'drivers/usb/host/ehci-dbg.c')
| -rw-r--r-- | drivers/usb/host/ehci-dbg.c | 113 | 
1 files changed, 109 insertions, 4 deletions
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index aa5b603f3933..4a9c2edbcb2b 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -334,6 +334,7 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { }  /* troubleshooting help: expose state in debugfs */  static int debug_async_open(struct inode *, struct file *); +static int debug_bandwidth_open(struct inode *, struct file *);  static int debug_periodic_open(struct inode *, struct file *);  static int debug_registers_open(struct inode *, struct file *); @@ -347,6 +348,13 @@ static const struct file_operations debug_async_fops = {  	.release	= debug_close,  	.llseek		= default_llseek,  }; +static const struct file_operations debug_bandwidth_fops = { +	.owner		= THIS_MODULE, +	.open		= debug_bandwidth_open, +	.read		= debug_output, +	.release	= debug_close, +	.llseek		= default_llseek, +};  static const struct file_operations debug_periodic_fops = {  	.owner		= THIS_MODULE,  	.open		= debug_periodic_open, @@ -379,7 +387,7 @@ struct debug_buffer {  		case QH_LOW_SPEED:  tmp = 'l'; break; \  		case QH_HIGH_SPEED: tmp = 'h'; break; \  		default: tmp = '?'; break; \ -		}; tmp; }) +		} tmp; })  static inline char token_mark(struct ehci_hcd *ehci, __hc32 token)  { @@ -525,6 +533,89 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)  	return strlen(buf->output_buf);  } +static ssize_t fill_bandwidth_buffer(struct debug_buffer *buf) +{ +	struct ehci_hcd		*ehci; +	struct ehci_tt		*tt; +	struct ehci_per_sched	*ps; +	unsigned		temp, size; +	char			*next; +	unsigned		i; +	u8			*bw; +	u16			*bf; +	u8			budget[EHCI_BANDWIDTH_SIZE]; + +	ehci = hcd_to_ehci(bus_to_hcd(buf->bus)); +	next = buf->output_buf; +	size = buf->alloc_size; + +	*next = 0; + +	spin_lock_irq(&ehci->lock); + +	/* Dump the HS bandwidth table */ +	temp = scnprintf(next, size, +			"HS bandwidth allocation (us per microframe)\n"); +	size -= temp; +	next += temp; +	for (i = 0; i < EHCI_BANDWIDTH_SIZE; i += 8) { +		bw = &ehci->bandwidth[i]; +		temp = scnprintf(next, size, +				"%2u: %4u%4u%4u%4u%4u%4u%4u%4u\n", +				i, bw[0], bw[1], bw[2], bw[3], +					bw[4], bw[5], bw[6], bw[7]); +		size -= temp; +		next += temp; +	} + +	/* Dump all the FS/LS tables */ +	list_for_each_entry(tt, &ehci->tt_list, tt_list) { +		temp = scnprintf(next, size, +				"\nTT %s port %d  FS/LS bandwidth allocation (us per frame)\n", +				dev_name(&tt->usb_tt->hub->dev), +				tt->tt_port + !!tt->usb_tt->multi); +		size -= temp; +		next += temp; + +		bf = tt->bandwidth; +		temp = scnprintf(next, size, +				"  %5u%5u%5u%5u%5u%5u%5u%5u\n", +				bf[0], bf[1], bf[2], bf[3], +					bf[4], bf[5], bf[6], bf[7]); +		size -= temp; +		next += temp; + +		temp = scnprintf(next, size, +				"FS/LS budget (us per microframe)\n"); +		size -= temp; +		next += temp; +		compute_tt_budget(budget, tt); +		for (i = 0; i < EHCI_BANDWIDTH_SIZE; i += 8) { +			bw = &budget[i]; +			temp = scnprintf(next, size, +					"%2u: %4u%4u%4u%4u%4u%4u%4u%4u\n", +					i, bw[0], bw[1], bw[2], bw[3], +						bw[4], bw[5], bw[6], bw[7]); +			size -= temp; +			next += temp; +		} +		list_for_each_entry(ps, &tt->ps_list, ps_list) { +			temp = scnprintf(next, size, +					"%s ep %02x:  %4u @ %2u.%u+%u mask %04x\n", +					dev_name(&ps->udev->dev), +					ps->ep->desc.bEndpointAddress, +					ps->tt_usecs, +					ps->bw_phase, ps->phase_uf, +					ps->bw_period, ps->cs_mask); +			size -= temp; +			next += temp; +		} +	} +	spin_unlock_irq(&ehci->lock); + +	return next - buf->output_buf; +} +  #define DBG_SCHED_LIMIT 64  static ssize_t fill_periodic_buffer(struct debug_buffer *buf)  { @@ -571,7 +662,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)  			case Q_TYPE_QH:  				hw = p.qh->hw;  				temp = scnprintf (next, size, " qh%d-%04x/%p", -						p.qh->period, +						p.qh->ps.period,  						hc32_to_cpup(ehci,  							&hw->hw_info2)  							/* uframe masks */ @@ -618,7 +709,8 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)  						speed_char (scratch),  						scratch & 0x007f,  						(scratch >> 8) & 0x000f, type, -						p.qh->usecs, p.qh->c_usecs, +						p.qh->ps.usecs, +						p.qh->ps.c_usecs,  						temp,  						0x7ff & (scratch >> 16)); @@ -645,7 +737,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)  			case Q_TYPE_SITD:  				temp = scnprintf (next, size,  					" sitd%d-%04x/%p", -					p.sitd->stream->interval, +					p.sitd->stream->ps.period,  					hc32_to_cpup(ehci, &p.sitd->hw_uframe)  						& 0x0000ffff,  					p.sitd); @@ -918,6 +1010,7 @@ static int debug_close(struct inode *inode, struct file *file)  	return 0;  } +  static int debug_async_open(struct inode *inode, struct file *file)  {  	file->private_data = alloc_buffer(inode->i_private, fill_async_buffer); @@ -925,6 +1018,14 @@ static int debug_async_open(struct inode *inode, struct file *file)  	return file->private_data ? 0 : -ENOMEM;  } +static int debug_bandwidth_open(struct inode *inode, struct file *file) +{ +	file->private_data = alloc_buffer(inode->i_private, +			fill_bandwidth_buffer); + +	return file->private_data ? 0 : -ENOMEM; +} +  static int debug_periodic_open(struct inode *inode, struct file *file)  {  	struct debug_buffer *buf; @@ -957,6 +1058,10 @@ static inline void create_debug_files (struct ehci_hcd *ehci)  						&debug_async_fops))  		goto file_error; +	if (!debugfs_create_file("bandwidth", S_IRUGO, ehci->debug_dir, bus, +						&debug_bandwidth_fops)) +		goto file_error; +  	if (!debugfs_create_file("periodic", S_IRUGO, ehci->debug_dir, bus,  						&debug_periodic_fops))  		goto file_error;  |