aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ntfs/debug.c
blob: 807150e2c2b9871d640bf10b260f134f4430f46c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
 * debug.c - NTFS kernel debug support. Part of the Linux-NTFS project.
 *
 * Copyright (c) 2001-2004 Anton Altaparmakov
 *
 * This program/include file is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published
 * by the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program/include file is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program (in the main directory of the Linux-NTFS
 * distribution in the file COPYING); if not, write to the Free Software
 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "debug.h"

/*
 * A static buffer to hold the error string being displayed and a spinlock
 * to protect concurrent accesses to it.
 */
static char err_buf[1024];
static DEFINE_SPINLOCK(err_buf_lock);

/**
 * __ntfs_warning - output a warning to the syslog
 * @function:	name of function outputting the warning
 * @sb:		super block of mounted ntfs filesystem
 * @fmt:	warning string containing format specifications
 * @...:	a variable number of arguments specified in @fmt
 *
 * Outputs a warning to the syslog for the mounted ntfs filesystem described
 * by @sb.
 *
 * @fmt and the corresponding @... is printf style format string containing
 * the warning string and the corresponding format arguments, respectively.
 *
 * @function is the name of the function from which __ntfs_warning is being
 * called.
 *
 * Note, you should be using debug.h::ntfs_warning(@sb, @fmt, @...) instead
 * as this provides the @function parameter automatically.
 */
void __ntfs_warning(const char *function, const struct super_block *sb,
		const char *fmt, ...)
{
	va_list args;
	int flen = 0;

#ifndef DEBUG
	if (!printk_ratelimit())
		return;
#endif
	if (function)
		flen = strlen(function);
	spin_lock(&err_buf_lock);
	va_start(args, fmt);
	vsnprintf(err_buf, sizeof(err_buf), fmt, args);
	va_end(args);
	if (sb)
		printk(KERN_ERR "NTFS-fs warning (device %s): %s(): %s\n",
				sb->s_id, flen ? function : "", err_buf);
	else
		printk(KERN_ERR "NTFS-fs warning: %s(): %s\n",
				flen ? function : "", err_buf);
	spin_unlock(&err_buf_lock);
}

/**
 * __ntfs_error - output an error to the syslog
 * @function:	name of function outputting the error
 * @sb:		super block of mounted ntfs filesystem
 * @fmt:	error string containing format specifications
 * @...:	a variable number of arguments specified in @fmt
 *
 * Outputs an error to the syslog for the mounted ntfs filesystem described
 * by @sb.
 *
 * @fmt and the corresponding @... is printf style format string containing
 * the error string and the corresponding format arguments, respectively.
 *
 * @function is the name of the function from which __ntfs_error is being
 * called.
 *
 * Note, you should be using debug.h::ntfs_error(@sb, @fmt, @...) instead
 * as this provides the @function parameter automatically.
 */
void __ntfs_error(const char *function, const struct super_block *sb,
		const char *fmt, ...)
{
	va_list args;
	int flen = 0;

#ifndef DEBUG
	if (!printk_ratelimit())
		return;
#endif
	if (function)
		flen = strlen(function);
	spin_lock(&err_buf_lock);
	va_start(args, fmt);
	vsnprintf(err_buf, sizeof(err_buf), fmt, args);
	va_end(args);
	if (sb)
		printk(KERN_ERR "NTFS-fs error (device %s): %s(): %s\n",
				sb->s_id, flen ? function : "", err_buf);
	else
		printk(KERN_ERR "NTFS-fs error: %s(): %s\n",
				flen ? function : "", err_buf);
	spin_unlock(&err_buf_lock);
}

#ifdef DEBUG

/* If 1, output debug messages, and if 0, don't. */
int debug_msgs = 0;

void __ntfs_debug (const char *file, int line, const char *function,
		const char *fmt, ...)
{
	va_list args;
	int flen = 0;

	if (!debug_msgs)
		return;
	if (function)
		flen = strlen(function);
	spin_lock(&err_buf_lock);
	va_start(args, fmt);
	vsnprintf(err_buf, sizeof(err_buf), fmt, args);
	va_end(args);
	printk(KERN_DEBUG "NTFS-fs DEBUG (%s, %d): %s(): %s\n", file, line,
			flen ? function : "", err_buf);
	spin_unlock(&err_buf_lock);
}

/* Dump a runlist. Caller has to provide synchronisation for @rl. */
void ntfs_debug_dump_runlist(const runlist_element *rl)
{
	int i;
	const char *lcn_str[5] = { "LCN_HOLE         ", "LCN_RL_NOT_MAPPED",
				   "LCN_ENOENT       ", "LCN_unknown      " };

	if (!debug_msgs)
		return;
	printk(KERN_DEBUG "NTFS-fs DEBUG: Dumping runlist (values in hex):\n");
	if (!rl) {
		printk(KERN_DEBUG "Run list not present.\n");
		return;
	}
	printk(KERN_DEBUG "VCN              LCN               Run length\n");
	for (i = 0; ; i++) {
		LCN lcn = (rl + i)->lcn;

		if (lcn < (LCN)0) {
			int index = -lcn - 1;

			if (index > -LCN_ENOENT - 1)
				index = 3;
			printk(KERN_DEBUG "%-16Lx %s %-16Lx%s\n",
					(long long)(rl + i)->vcn, lcn_str[index],
					(long long)(rl + i)->length,
					(rl + i)->length ? "" :
						" (runlist end)");
		} else
			printk(KERN_DEBUG "%-16Lx %-16Lx  %-16Lx%s\n",
					(long long)(rl + i)->vcn,
					(long long)(rl + i)->lcn,
					(long long)(rl + i)->length,
					(rl + i)->length ? "" :
						" (runlist end)");
		if (!(rl + i)->length)
			break;
	}
}

#endif
span class="hl opt">(bus->mmio + offset); hi = readw(bus->mmio + offset + 2); return lo | (hi << 16); case SSB_BUSTYPE_SDIO: offset += current_coreidx * SSB_CORE_SIZE; return ssb_sdio_scan_read32(bus, offset); } return readl(bus->mmio + offset); } static int scan_switchcore(struct ssb_bus *bus, u8 coreidx) { switch (bus->bustype) { case SSB_BUSTYPE_SSB: break; case SSB_BUSTYPE_PCI: return ssb_pci_switch_coreidx(bus, coreidx); case SSB_BUSTYPE_PCMCIA: return ssb_pcmcia_switch_coreidx(bus, coreidx); case SSB_BUSTYPE_SDIO: return ssb_sdio_scan_switch_coreidx(bus, coreidx); } return 0; } void ssb_iounmap(struct ssb_bus *bus) { switch (bus->bustype) { case SSB_BUSTYPE_SSB: case SSB_BUSTYPE_PCMCIA: iounmap(bus->mmio); break; case SSB_BUSTYPE_PCI: #ifdef CONFIG_SSB_PCIHOST pci_iounmap(bus->host_pci, bus->mmio); #else WARN_ON(1); /* Can't reach this code. */ #endif break; case SSB_BUSTYPE_SDIO: break; } bus->mmio = NULL; bus->mapped_device = NULL; } static void __iomem *ssb_ioremap(struct ssb_bus *bus, unsigned long baseaddr) { void __iomem *mmio = NULL; switch (bus->bustype) { case SSB_BUSTYPE_SSB: /* Only map the first core for now. */ /* fallthrough... */ case SSB_BUSTYPE_PCMCIA: mmio = ioremap(baseaddr, SSB_CORE_SIZE); break; case SSB_BUSTYPE_PCI: #ifdef CONFIG_SSB_PCIHOST mmio = pci_iomap(bus->host_pci, 0, ~0UL); #else WARN_ON(1); /* Can't reach this code. */ #endif break; case SSB_BUSTYPE_SDIO: /* Nothing to ioremap in the SDIO case, just fake it */ mmio = (void __iomem *)baseaddr; break; } return mmio; } static int we_support_multiple_80211_cores(struct ssb_bus *bus) { /* More than one 802.11 core is only supported by special chips. * There are chips with two 802.11 cores, but with dangling * pins on the second core. Be careful and reject them here. */ #ifdef CONFIG_SSB_PCIHOST if (bus->bustype == SSB_BUSTYPE_PCI) { if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM && ((bus->host_pci->device == 0x4313) || (bus->host_pci->device == 0x431A) || (bus->host_pci->device == 0x4321) || (bus->host_pci->device == 0x4324))) return 1; } #endif /* CONFIG_SSB_PCIHOST */ return 0; } int ssb_bus_scan(struct ssb_bus *bus, unsigned long baseaddr) { int err = -ENOMEM; void __iomem *mmio; u32 idhi, cc, rev, tmp; int dev_i, i; struct ssb_device *dev; int nr_80211_cores = 0; mmio = ssb_ioremap(bus, baseaddr); if (!mmio) goto out; bus->mmio = mmio; err = scan_switchcore(bus, 0); /* Switch to first core */ if (err) goto err_unmap; idhi = scan_read32(bus, 0, SSB_IDHIGH); cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT; rev = (idhi & SSB_IDHIGH_RCLO); rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT; bus->nr_devices = 0; if (cc == SSB_DEV_CHIPCOMMON) { tmp = scan_read32(bus, 0, SSB_CHIPCO_CHIPID); bus->chip_id = (tmp & SSB_CHIPCO_IDMASK); bus->chip_rev = (tmp & SSB_CHIPCO_REVMASK) >> SSB_CHIPCO_REVSHIFT; bus->chip_package = (tmp & SSB_CHIPCO_PACKMASK) >> SSB_CHIPCO_PACKSHIFT; if (rev >= 4) { bus->nr_devices = (tmp & SSB_CHIPCO_NRCORESMASK) >> SSB_CHIPCO_NRCORESSHIFT; } tmp = scan_read32(bus, 0, SSB_CHIPCO_CAP); bus->chipco.capabilities = tmp; } else { if (bus->bustype == SSB_BUSTYPE_PCI) { bus->chip_id = pcidev_to_chipid(bus->host_pci); bus->chip_rev = bus->host_pci->revision; bus->chip_package = 0; } else { bus->chip_id = 0x4710; bus->chip_rev = 0; bus->chip_package = 0; } } pr_info("Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", bus->chip_id, bus->chip_rev, bus->chip_package); if (!bus->nr_devices) bus->nr_devices = chipid_to_nrcores(bus->chip_id); if (bus->nr_devices > ARRAY_SIZE(bus->devices)) { pr_err("More than %d ssb cores found (%d)\n", SSB_MAX_NR_CORES, bus->nr_devices); goto err_unmap; } if (bus->bustype == SSB_BUSTYPE_SSB) { /* Now that we know the number of cores, * remap the whole IO space for all cores. */ err = -ENOMEM; iounmap(mmio); mmio = ioremap(baseaddr, SSB_CORE_SIZE * bus->nr_devices); if (!mmio) goto out; bus->mmio = mmio; } /* Fetch basic information about each core/device */ for (i = 0, dev_i = 0; i < bus->nr_devices; i++) { err = scan_switchcore(bus, i); if (err) goto err_unmap; dev = &(bus->devices[dev_i]); idhi = scan_read32(bus, i, SSB_IDHIGH); dev->id.coreid = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT; dev->id.revision = (idhi & SSB_IDHIGH_RCLO); dev->id.revision |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT; dev->id.vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT; dev->core_index = i; dev->bus = bus; dev->ops = bus->ops; pr_debug("Core %d found: %s (cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n", i, ssb_core_name(dev->id.coreid), dev->id.coreid, dev->id.revision, dev->id.vendor); switch (dev->id.coreid) { case SSB_DEV_80211: nr_80211_cores++; if (nr_80211_cores > 1) { if (!we_support_multiple_80211_cores(bus)) { pr_debug("Ignoring additional 802.11 core\n"); continue; } } break; case SSB_DEV_EXTIF: #ifdef CONFIG_SSB_DRIVER_EXTIF if (bus->extif.dev) { pr_warn("WARNING: Multiple EXTIFs found\n"); break; } bus->extif.dev = dev; #endif /* CONFIG_SSB_DRIVER_EXTIF */ break; case SSB_DEV_CHIPCOMMON: if (bus->chipco.dev) { pr_warn("WARNING: Multiple ChipCommon found\n"); break; } bus->chipco.dev = dev; break; case SSB_DEV_MIPS: case SSB_DEV_MIPS_3302: #ifdef CONFIG_SSB_DRIVER_MIPS if (bus->mipscore.dev) { pr_warn("WARNING: Multiple MIPS cores found\n"); break; } bus->mipscore.dev = dev; #endif /* CONFIG_SSB_DRIVER_MIPS */ break; case SSB_DEV_PCI: case SSB_DEV_PCIE: #ifdef CONFIG_SSB_DRIVER_PCICORE if (bus->bustype == SSB_BUSTYPE_PCI) { /* Ignore PCI cores on PCI-E cards. * Ignore PCI-E cores on PCI cards. */ if (dev->id.coreid == SSB_DEV_PCI) { if (pci_is_pcie(bus->host_pci)) continue; } else { if (!pci_is_pcie(bus->host_pci)) continue; } } if (bus->pcicore.dev) { pr_warn("WARNING: Multiple PCI(E) cores found\n"); break; } bus->pcicore.dev = dev; #endif /* CONFIG_SSB_DRIVER_PCICORE */ break; case SSB_DEV_ETHERNET: if (bus->bustype == SSB_BUSTYPE_PCI) { if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM && (bus->host_pci->device & 0xFF00) == 0x4300) { /* This is a dangling ethernet core on a * wireless device. Ignore it. */ continue; } } break; default: break; } dev_i++; } bus->nr_devices = dev_i; err = 0; out: return err; err_unmap: ssb_iounmap(bus); goto out; }