Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6

This commit is contained in:
Steve French 2008-03-11 19:15:41 +00:00
commit 5b4d4771e2
108 changed files with 3291 additions and 983 deletions

View file

@ -486,9 +486,12 @@ static void concat(char *dst, char *args[])
unsigned int i, len = 0;
for (i = 0; args[i]; i++) {
if (i) {
strcat(dst+len, " ");
len++;
}
strcpy(dst+len, args[i]);
strcat(dst+len, " ");
len += strlen(args[i]) + 1;
len += strlen(args[i]);
}
/* In case it's empty. */
dst[len] = '\0';

View file

@ -123,7 +123,7 @@ initialization with a pointer to a structure describing the driver
The ID table is an array of struct pci_device_id entries ending with an
all-zero entry; use of the macro DECLARE_PCI_DEVICE_TABLE is the preferred
all-zero entry; use of the macro DEFINE_PCI_DEVICE_TABLE is the preferred
method of declaring the table. Each entry consists of:
vendor,device Vendor and device ID to match (or PCI_ANY_ID)
@ -193,7 +193,7 @@ Tips on when/where to use the above attributes:
o Do not mark the struct pci_driver.
o The ID table array should be marked __devinitconst; this is done
automatically if the table is declared with DECLARE_PCI_DEVICE_TABLE().
automatically if the table is declared with DEFINE_PCI_DEVICE_TABLE().
o The probe() and remove() functions should be marked __devinit
and __devexit respectively. All initialization functions

View file

@ -142,7 +142,7 @@ of idleness (idle, busy, and newly idle):
/proc/<pid>/schedstat
----------------
schedstats also adds a new /proc/<pid/schedstat file to include some of
schedstats also adds a new /proc/<pid>/schedstat file to include some of
the same information on a per-process level. There are three fields in
this file correlating for that process to:
1) time spent on the cpu

View file

@ -1,5 +1,5 @@
usb-help.txt
2000-July-12
2008-Mar-7
For USB help other than the readme files that are located in
Documentation/usb/*, see the following:
@ -10,9 +10,7 @@ Linux-USB project: http://www.linux-usb.org
Linux USB Guide: http://linux-usb.sourceforge.net
Linux-USB device overview (working devices and drivers):
http://www.qbik.ch/usb/devices/
The Linux-USB mailing lists are:
linux-usb-users@lists.sourceforge.net for general user help
linux-usb-devel@lists.sourceforge.net for developer discussions
The Linux-USB mailing list is at linux-usb@vger.kernel.org
###

View file

@ -2156,7 +2156,7 @@ L: netdev@vger.kernel.org
S: Maintained
IPATH DRIVER:
P: Arthur Jones
P: Ralph Campbell
M: infinipath@qlogic.com
L: general@lists.openfabrics.org
T: git git://git.qlogic.com/ipath-linux-2.6

View file

@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 25
EXTRAVERSION = -rc4
EXTRAVERSION = -rc5
NAME = Funky Weasel is Jiggy wit it
# *DOCUMENTATION*

View file

@ -144,15 +144,14 @@ iommu_arena_find_pages(struct device *dev, struct pci_iommu_arena *arena,
unsigned long base;
unsigned long boundary_size;
BUG_ON(arena->dma_base & ~PAGE_MASK);
base = arena->dma_base >> PAGE_SHIFT;
if (dev)
boundary_size = ALIGN(dma_get_max_seg_size(dev) + 1, PAGE_SIZE)
>> PAGE_SHIFT;
else
boundary_size = ALIGN(1UL << 32, PAGE_SIZE) >> PAGE_SHIFT;
BUG_ON(!is_power_of_2(boundary_size));
if (dev) {
boundary_size = dma_get_seg_boundary(dev) + 1;
BUG_ON(!is_power_of_2(boundary_size));
boundary_size >>= PAGE_SHIFT;
} else {
boundary_size = 1UL << (32 - PAGE_SHIFT);
}
/* Search forward for the first mask-aligned sequence of N free ptes */
ptes = arena->ptes;

View file

@ -66,9 +66,6 @@ config MMU
config ZONE_DMA
def_bool y
config QUICKLIST
def_bool X86_32
config SBUS
bool

View file

@ -1055,10 +1055,17 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 value)
R32(esi, si);
R32(ebp, bp);
R32(eax, ax);
R32(orig_eax, orig_ax);
R32(eip, ip);
R32(esp, sp);
case offsetof(struct user32, regs.orig_eax):
/*
* Sign-extend the value so that orig_eax = -1
* causes (long)orig_ax < 0 tests to fire correctly.
*/
regs->orig_ax = (long) (s32) value;
break;
case offsetof(struct user32, regs.eflags):
return set_flags(child, value);

View file

@ -310,6 +310,35 @@ give_sigsegv:
return -EFAULT;
}
/*
* Return -1L or the syscall number that @regs is executing.
*/
static long current_syscall(struct pt_regs *regs)
{
/*
* We always sign-extend a -1 value being set here,
* so this is always either -1L or a syscall number.
*/
return regs->orig_ax;
}
/*
* Return a value that is -EFOO if the system call in @regs->orig_ax
* returned an error. This only works for @regs from @current.
*/
static long current_syscall_ret(struct pt_regs *regs)
{
#ifdef CONFIG_IA32_EMULATION
if (test_thread_flag(TIF_IA32))
/*
* Sign-extend the value so (int)-EFOO becomes (long)-EFOO
* and will match correctly in comparisons.
*/
return (int) regs->ax;
#endif
return regs->ax;
}
/*
* OK, we're invoking a handler
*/
@ -327,9 +356,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
#endif
/* Are we from a system call? */
if ((long)regs->orig_ax >= 0) {
if (current_syscall(regs) >= 0) {
/* If so, check system call restarting.. */
switch (regs->ax) {
switch (current_syscall_ret(regs)) {
case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND:
regs->ax = -EINTR;
@ -426,10 +455,9 @@ static void do_signal(struct pt_regs *regs)
}
/* Did we come from a system call? */
if ((long)regs->orig_ax >= 0) {
if (current_syscall(regs) >= 0) {
/* Restart the system call - no handlers present */
long res = regs->ax;
switch (res) {
switch (current_syscall_ret(regs)) {
case -ERESTARTNOHAND:
case -ERESTARTSYS:
case -ERESTARTNOINTR:

View file

@ -84,7 +84,6 @@ struct lguest_data lguest_data = {
.blocked_interrupts = { 1 }, /* Block timer interrupts */
.syscall_vec = SYSCALL_VECTOR,
};
static cycle_t clock_base;
/*G:037 async_hcall() is pretty simple: I'm quite proud of it really. We have a
* ring buffer of stored hypercalls which the Host will run though next time we
@ -327,8 +326,8 @@ static void lguest_cpuid(unsigned int *ax, unsigned int *bx,
case 1: /* Basic feature request. */
/* We only allow kernel to see SSE3, CMPXCHG16B and SSSE3 */
*cx &= 0x00002201;
/* SSE, SSE2, FXSR, MMX, CMOV, CMPXCHG8B, FPU. */
*dx &= 0x07808101;
/* SSE, SSE2, FXSR, MMX, CMOV, CMPXCHG8B, TSC, FPU. */
*dx &= 0x07808111;
/* The Host can do a nice optimization if it knows that the
* kernel mappings (addresses above 0xC0000000 or whatever
* PAGE_OFFSET is set to) haven't changed. But Linux calls
@ -481,7 +480,7 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)
{
*pmdp = pmdval;
lazy_hcall(LHCALL_SET_PMD, __pa(pmdp)&PAGE_MASK,
(__pa(pmdp)&(PAGE_SIZE-1)), 0);
(__pa(pmdp)&(PAGE_SIZE-1))/4, 0);
}
/* There are a couple of legacy places where the kernel sets a PTE, but we
@ -595,19 +594,25 @@ static unsigned long lguest_get_wallclock(void)
return lguest_data.time.tv_sec;
}
/* The TSC is a Time Stamp Counter. The Host tells us what speed it runs at,
* or 0 if it's unusable as a reliable clock source. This matches what we want
* here: if we return 0 from this function, the x86 TSC clock will not register
* itself. */
static unsigned long lguest_cpu_khz(void)
{
return lguest_data.tsc_khz;
}
/* If we can't use the TSC, the kernel falls back to our "lguest_clock", where
* we read the time value given to us by the Host. */
static cycle_t lguest_clock_read(void)
{
unsigned long sec, nsec;
/* If the Host tells the TSC speed, we can trust that. */
if (lguest_data.tsc_khz)
return native_read_tsc();
/* If we can't use the TSC, we read the time value written by the Host.
* Since it's in two parts (seconds and nanoseconds), we risk reading
* it just as it's changing from 99 & 0.999999999 to 100 and 0, and
* getting 99 and 0. As Linux tends to come apart under the stress of
* time travel, we must be careful: */
/* Since the time is in two parts (seconds and nanoseconds), we risk
* reading it just as it's changing from 99 & 0.999999999 to 100 and 0,
* and getting 99 and 0. As Linux tends to come apart under the stress
* of time travel, we must be careful: */
do {
/* First we read the seconds part. */
sec = lguest_data.time.tv_sec;
@ -622,14 +627,14 @@ static cycle_t lguest_clock_read(void)
/* Now if the seconds part has changed, try again. */
} while (unlikely(lguest_data.time.tv_sec != sec));
/* Our non-TSC clock is in real nanoseconds. */
/* Our lguest clock is in real nanoseconds. */
return sec*1000000000ULL + nsec;
}
/* This is what we tell the kernel is our clocksource. */
/* This is the fallback clocksource: lower priority than the TSC clocksource. */
static struct clocksource lguest_clock = {
.name = "lguest",
.rating = 400,
.rating = 200,
.read = lguest_clock_read,
.mask = CLOCKSOURCE_MASK(64),
.mult = 1 << 22,
@ -637,12 +642,6 @@ static struct clocksource lguest_clock = {
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
/* The "scheduler clock" is just our real clock, adjusted to start at zero */
static unsigned long long lguest_sched_clock(void)
{
return cyc2ns(&lguest_clock, lguest_clock_read() - clock_base);
}
/* We also need a "struct clock_event_device": Linux asks us to set it to go
* off some time in the future. Actually, James Morris figured all this out, I
* just applied the patch. */
@ -712,19 +711,8 @@ static void lguest_time_init(void)
/* Set up the timer interrupt (0) to go to our simple timer routine */
set_irq_handler(0, lguest_time_irq);
/* Our clock structure looks like arch/x86/kernel/tsc_32.c if we can
* use the TSC, otherwise it's a dumb nanosecond-resolution clock.
* Either way, the "rating" is set so high that it's always chosen over
* any other clocksource. */
if (lguest_data.tsc_khz)
lguest_clock.mult = clocksource_khz2mult(lguest_data.tsc_khz,
lguest_clock.shift);
clock_base = lguest_clock_read();
clocksource_register(&lguest_clock);
/* Now we've set up our clock, we can use it as the scheduler clock */
pv_time_ops.sched_clock = lguest_sched_clock;
/* We can't set cpumask in the initializer: damn C limitations! Set it
* here and register our timer device. */
lguest_clockevent.cpumask = cpumask_of_cpu(0);
@ -995,6 +983,7 @@ __init void lguest_init(void)
/* time operations */
pv_time_ops.get_wallclock = lguest_get_wallclock;
pv_time_ops.time_init = lguest_time_init;
pv_time_ops.get_cpu_khz = lguest_cpu_khz;
/* Now is a good time to look at the implementations of these functions
* before returning to the rest of lguest_init(). */

View file

@ -134,8 +134,6 @@ static void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
return NULL;
}
WARN_ON_ONCE(page_is_ram(pfn));
switch (mode) {
case IOR_MODE_UNCACHED:
default:

View file

@ -342,12 +342,16 @@ static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
pgd_t *pgd_alloc(struct mm_struct *mm)
{
pgd_t *pgd = quicklist_alloc(0, GFP_KERNEL, pgd_ctor);
pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
mm->pgd = pgd; /* so that alloc_pd can use it */
/* so that alloc_pd can use it */
mm->pgd = pgd;
if (pgd)
pgd_ctor(pgd);
if (pgd && !pgd_prepopulate_pmd(mm, pgd)) {
quicklist_free(0, pgd_dtor, pgd);
pgd_dtor(pgd);
free_page((unsigned long)pgd);
pgd = NULL;
}
@ -357,12 +361,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
void pgd_free(struct mm_struct *mm, pgd_t *pgd)
{
pgd_mop_up_pmds(mm, pgd);
quicklist_free(0, pgd_dtor, pgd);
}
void check_pgt_cache(void)
{
quicklist_trim(0, pgd_dtor, 25, 16);
pgd_dtor(pgd);
free_page((unsigned long)pgd);
}
void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte)

View file

@ -198,6 +198,11 @@ static int pci_bios_read(unsigned int seg, unsigned int bus,
"b" (bx),
"D" ((long)reg),
"S" (&pci_indirect));
/*
* Zero-extend the result beyond 8 bits, do not trust the
* BIOS having done it:
*/
*value &= 0xff;
break;
case 2:
__asm__("lcall *(%%esi); cld\n\t"
@ -210,6 +215,11 @@ static int pci_bios_read(unsigned int seg, unsigned int bus,
"b" (bx),
"D" ((long)reg),
"S" (&pci_indirect));
/*
* Zero-extend the result beyond 16 bits, do not trust the
* BIOS having done it:
*/
*value &= 0xffff;
break;
case 4:
__asm__("lcall *(%%esi); cld\n\t"

View file

@ -318,10 +318,8 @@ int __init chainiv_module_init(void)
{
return crypto_register_template(&chainiv_tmpl);
}
EXPORT_SYMBOL_GPL(chainiv_module_init);
void __exit chainiv_module_exit(void)
void chainiv_module_exit(void)
{
crypto_unregister_template(&chainiv_tmpl);
}
EXPORT_SYMBOL_GPL(chainiv_module_exit);

View file

@ -251,10 +251,8 @@ int __init eseqiv_module_init(void)
{
return crypto_register_template(&eseqiv_tmpl);
}
EXPORT_SYMBOL_GPL(eseqiv_module_init);
void __exit eseqiv_module_exit(void)
{
crypto_unregister_template(&eseqiv_tmpl);
}
EXPORT_SYMBOL_GPL(eseqiv_module_exit);

View file

@ -538,6 +538,15 @@ config PATA_RADISYS
If unsure, say N.
config PATA_RB500
tristate "RouterBoard 500 PATA CompactFlash support"
depends on MIKROTIK_RB500
help
This option enables support for the RouterBoard 500
PATA CompactFlash controller.
If unsure, say N.
config PATA_RZ1000
tristate "PC Tech RZ1000 PATA support"
depends on PCI

View file

@ -55,6 +55,7 @@ obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o
obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o
obj-$(CONFIG_PATA_QDI) += pata_qdi.o
obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o
obj-$(CONFIG_PATA_RB500) += pata_rb500_cf.o
obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o
obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o

View file

@ -567,6 +567,18 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci }, /* MCP79 */
{ PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci }, /* MCP79 */
{ PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci }, /* MCP79 */
{ PCI_VDEVICE(NVIDIA, 0x0bc8), board_ahci }, /* MCP7B */
{ PCI_VDEVICE(NVIDIA, 0x0bc9), board_ahci }, /* MCP7B */
{ PCI_VDEVICE(NVIDIA, 0x0bca), board_ahci }, /* MCP7B */
{ PCI_VDEVICE(NVIDIA, 0x0bcb), board_ahci }, /* MCP7B */
{ PCI_VDEVICE(NVIDIA, 0x0bcc), board_ahci }, /* MCP7B */
{ PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci }, /* MCP7B */
{ PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci }, /* MCP7B */
{ PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci }, /* MCP7B */
{ PCI_VDEVICE(NVIDIA, 0x0bd0), board_ahci }, /* MCP7B */
{ PCI_VDEVICE(NVIDIA, 0x0bd1), board_ahci }, /* MCP7B */
{ PCI_VDEVICE(NVIDIA, 0x0bd2), board_ahci }, /* MCP7B */
{ PCI_VDEVICE(NVIDIA, 0x0bd3), board_ahci }, /* MCP7B */
/* SiS */
{ PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
@ -672,7 +684,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
cap &= ~HOST_CAP_NCQ;
}
if ((cap && HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
dev_printk(KERN_INFO, &pdev->dev,
"controller can't do PMP, turning off CAP_PMP\n");
cap &= ~HOST_CAP_PMP;

View file

@ -382,7 +382,7 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER: port#: %d\n",
__FUNCTION__, ap->port_no);
__func__, ap->port_no);
/* _GTF has no input parameters */
status = acpi_evaluate_object(dev->acpi_handle, "_GTF", NULL, &output);
@ -402,7 +402,7 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: Run _GTF: "
"length or ptr is NULL (0x%llx, 0x%p)\n",
__FUNCTION__,
__func__,
(unsigned long long)output.length,
output.pointer);
rc = -EINVAL;
@ -432,7 +432,7 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG,
"%s: returning gtf=%p, gtf_count=%d\n",
__FUNCTION__, *gtf, rc);
__func__, *gtf, rc);
}
return rc;
@ -725,7 +725,7 @@ static int ata_acpi_push_id(struct ata_device *dev)
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: ix = %d, port#: %d\n",
__FUNCTION__, dev->devno, ap->port_no);
__func__, dev->devno, ap->port_no);
/* Give the drive Identify data to the drive via the _SDD method */
/* _SDD: set up input parameters */

View file

@ -106,7 +106,8 @@ static struct ata_force_ent *ata_force_tbl;
static int ata_force_tbl_size;
static char ata_force_param_buf[PAGE_SIZE] __initdata;
module_param_string(force, ata_force_param_buf, sizeof(ata_force_param_buf), 0444);
/* param_buf is thrown away after initialization, disallow read */
module_param_string(force, ata_force_param_buf, sizeof(ata_force_param_buf), 0);
MODULE_PARM_DESC(force, "Force ATA configurations including cable type, link speed and transfer mode (see Documentation/kernel-parameters.txt for details)");
int atapi_enabled = 1;
@ -1719,7 +1720,7 @@ void ata_port_flush_task(struct ata_port *ap)
cancel_rearming_delayed_work(&ap->port_task);
if (ata_msg_ctl(ap))
ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__);
ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __func__);
}
static void ata_qc_complete_internal(struct ata_queued_cmd *qc)
@ -2056,7 +2057,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
int rc;
if (ata_msg_ctl(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);
ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__);
ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
retry:
@ -2253,12 +2254,12 @@ int ata_dev_configure(struct ata_device *dev)
if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
ata_dev_printk(dev, KERN_INFO, "%s: ENTER/EXIT -- nodev\n",
__FUNCTION__);
__func__);
return 0;
}
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__);
ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __func__);
/* set horkage */
dev->horkage |= ata_dev_blacklisted(dev);
@ -2279,7 +2280,7 @@ int ata_dev_configure(struct ata_device *dev)
ata_dev_printk(dev, KERN_DEBUG,
"%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x "
"85:%04x 86:%04x 87:%04x 88:%04x\n",
__FUNCTION__,
__func__,
id[49], id[82], id[83], id[84],
id[85], id[86], id[87], id[88]);
@ -2511,13 +2512,13 @@ int ata_dev_configure(struct ata_device *dev)
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n",
__FUNCTION__, ata_chk_status(ap));
__func__, ata_chk_status(ap));
return 0;
err_out_nosup:
if (ata_msg_probe(ap))
ata_dev_printk(dev, KERN_DEBUG,
"%s: EXIT, err\n", __FUNCTION__);
"%s: EXIT, err\n", __func__);
return rc;
}

View file

@ -2150,6 +2150,15 @@ int ata_eh_reset(struct ata_link *link, int classify,
ap->ops->set_piomode(ap, dev);
}
if (!softreset && !hardreset) {
if (verbose)
ata_link_printk(link, KERN_INFO, "no reset method "
"available, skipping reset\n");
if (!(lflags & ATA_LFLAG_ASSUME_CLASS))
lflags |= ATA_LFLAG_ASSUME_ATA;
goto done;
}
/* Determine which reset to use and record in ehc->i.action.
* prereset() may examine and modify it.
*/
@ -2254,6 +2263,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
lflags |= ATA_LFLAG_ASSUME_ATA;
}
done:
ata_link_for_each_dev(dev, link) {
/* After the reset, the device state is PIO 0 and the
* controller state is undefined. Reset also wakes up

View file

@ -56,7 +56,8 @@ u8 ata_irq_on(struct ata_port *ap)
ap->ctl &= ~ATA_NIEN;
ap->last_ctl = ap->ctl;
iowrite8(ap->ctl, ioaddr->ctl_addr);
if (ioaddr->ctl_addr)
iowrite8(ap->ctl, ioaddr->ctl_addr);
tmp = ata_wait_idle(ap);
ap->ops->irq_clear(ap);
@ -81,12 +82,14 @@ void ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
if (tf->ctl != ap->last_ctl) {
iowrite8(tf->ctl, ioaddr->ctl_addr);
if (ioaddr->ctl_addr)
iowrite8(tf->ctl, ioaddr->ctl_addr);
ap->last_ctl = tf->ctl;
ata_wait_idle(ap);
}
if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
WARN_ON(!ioaddr->ctl_addr);
iowrite8(tf->hob_feature, ioaddr->feature_addr);
iowrite8(tf->hob_nsect, ioaddr->nsect_addr);
iowrite8(tf->hob_lbal, ioaddr->lbal_addr);
@ -167,14 +170,17 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
tf->device = ioread8(ioaddr->device_addr);
if (tf->flags & ATA_TFLAG_LBA48) {
iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
tf->hob_feature = ioread8(ioaddr->error_addr);
tf->hob_nsect = ioread8(ioaddr->nsect_addr);
tf->hob_lbal = ioread8(ioaddr->lbal_addr);
tf->hob_lbam = ioread8(ioaddr->lbam_addr);
tf->hob_lbah = ioread8(ioaddr->lbah_addr);
iowrite8(tf->ctl, ioaddr->ctl_addr);
ap->last_ctl = tf->ctl;
if (likely(ioaddr->ctl_addr)) {
iowrite8(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
tf->hob_feature = ioread8(ioaddr->error_addr);
tf->hob_nsect = ioread8(ioaddr->nsect_addr);
tf->hob_lbal = ioread8(ioaddr->lbal_addr);
tf->hob_lbam = ioread8(ioaddr->lbam_addr);
tf->hob_lbah = ioread8(ioaddr->lbah_addr);
iowrite8(tf->ctl, ioaddr->ctl_addr);
ap->last_ctl = tf->ctl;
} else
WARN_ON(1);
}
}
@ -352,7 +358,8 @@ void ata_bmdma_freeze(struct ata_port *ap)
ap->ctl |= ATA_NIEN;
ap->last_ctl = ap->ctl;
iowrite8(ap->ctl, ioaddr->ctl_addr);
if (ioaddr->ctl_addr)
iowrite8(ap->ctl, ioaddr->ctl_addr);
/* Under certain circumstances, some controllers raise IRQ on
* ATA_NIEN manipulation. Also, many controllers fail to mask
@ -459,13 +466,14 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
*/
void ata_bmdma_error_handler(struct ata_port *ap)
{
ata_reset_fn_t hardreset;
ata_reset_fn_t softreset = NULL, hardreset = NULL;
hardreset = NULL;
if (ap->ioaddr.ctl_addr)
softreset = ata_std_softreset;
if (sata_scr_valid(&ap->link))
hardreset = sata_std_hardreset;
ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
ata_bmdma_drive_eh(ap, ata_std_prereset, softreset, hardreset,
ata_std_postreset);
}

View file

@ -39,7 +39,7 @@
#undef PDC_DEBUG
#ifdef PDC_DEBUG
#define PDPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
#define PDPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
#else
#define PDPRINTK(fmt, args...)
#endif

314
drivers/ata/pata_rb500_cf.c Normal file
View file

@ -0,0 +1,314 @@
/*
* A low-level PATA driver to handle a Compact Flash connected on the
* Mikrotik's RouterBoard 532 board.
*
* Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org>
* Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
*
* This file was based on: drivers/ata/pata_ixp4xx_cf.c
* Copyright (C) 2006-07 Tower Technologies
* Author: Alessandro Zummo <a.zummo@towertech.it>
*
* Also was based on the driver for Linux 2.4.xx published by Mikrotik for
* their RouterBoard 1xx and 5xx series devices. The original Mikrotik code
* seems not to have a license.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/libata.h>
#include <scsi/scsi_host.h>
#include <asm/gpio.h>
#define DRV_NAME "pata-rb500-cf"
#define DRV_VERSION "0.1.0"
#define DRV_DESC "PATA driver for RouterBOARD 532 Compact Flash"
#define RB500_CF_MAXPORTS 1
#define RB500_CF_IO_DELAY 400
#define RB500_CF_REG_CMD 0x0800
#define RB500_CF_REG_CTRL 0x080E
#define RB500_CF_REG_DATA 0x0C00
struct rb500_cf_info {
void __iomem *iobase;
unsigned int gpio_line;
int frozen;
unsigned int irq;
};
/* ------------------------------------------------------------------------ */
static inline void rb500_pata_finish_io(struct ata_port *ap)
{
struct ata_host *ah = ap->host;
struct rb500_cf_info *info = ah->private_data;
ata_altstatus(ap);
ndelay(RB500_CF_IO_DELAY);
set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
}
static void rb500_pata_exec_command(struct ata_port *ap,
const struct ata_taskfile *tf)
{
writeb(tf->command, ap->ioaddr.command_addr);
rb500_pata_finish_io(ap);
}
static void rb500_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data)
{
struct ata_port *ap = adev->link->ap;
void __iomem *ioaddr = ap->ioaddr.data_addr;
if (write_data) {
for (; buflen > 0; buflen--, buf++)
writeb(*buf, ioaddr);
} else {
for (; buflen > 0; buflen--, buf++)
*buf = readb(ioaddr);
}
rb500_pata_finish_io(adev->link->ap);
}
static void rb500_pata_freeze(struct ata_port *ap)
{
struct rb500_cf_info *info = ap->host->private_data;
info->frozen = 1;
}
static void rb500_pata_thaw(struct ata_port *ap)
{
struct rb500_cf_info *info = ap->host->private_data;
info->frozen = 0;
}
static irqreturn_t rb500_pata_irq_handler(int irq, void *dev_instance)
{
struct ata_host *ah = dev_instance;
struct rb500_cf_info *info = ah->private_data;
if (gpio_get_value(info->gpio_line)) {
set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
if (!info->frozen)
ata_interrupt(info->irq, dev_instance);
} else {
set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
}
return IRQ_HANDLED;
}
static void rb500_pata_irq_clear(struct ata_port *ap)
{
}
static int rb500_pata_port_start(struct ata_port *ap)
{
return 0;
}
static struct ata_port_operations rb500_pata_port_ops = {
.tf_load = ata_tf_load,
.tf_read = ata_tf_read,
.exec_command = rb500_pata_exec_command,
.check_status = ata_check_status,
.dev_select = ata_std_dev_select,
.data_xfer = rb500_pata_data_xfer,
.qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot,
.freeze = rb500_pata_freeze,
.thaw = rb500_pata_thaw,
.error_handler = ata_bmdma_error_handler,
.irq_handler = rb500_pata_irq_handler,
.irq_clear = rb500_pata_irq_clear,
.irq_on = ata_irq_on,
.port_start = rb500_pata_port_start,
};
/* ------------------------------------------------------------------------ */
static struct scsi_host_template rb500_pata_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.queuecommand = ata_scsi_queuecmd,
.slave_configure = ata_scsi_slave_config,
.slave_destroy = ata_scsi_slave_destroy,
.bios_param = ata_std_bios_param,
.proc_name = DRV_NAME,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
.sg_tablesize = LIBATA_MAX_PRD,
.dma_boundary = ATA_DMA_BOUNDARY,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING,
};
/* ------------------------------------------------------------------------ */
static void rb500_pata_setup_ports(struct ata_host *ah)
{
struct rb500_cf_info *info = ah->private_data;
struct ata_port *ap;
ap = ah->ports[0];
ap->ops = &rb500_pata_port_ops;
ap->pio_mask = 0x1f; /* PIO4 */
ap->flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
ap->ioaddr.cmd_addr = info->iobase + RB500_CF_REG_CMD;
ap->ioaddr.ctl_addr = info->iobase + RB500_CF_REG_CTRL;
ap->ioaddr.altstatus_addr = info->iobase + RB500_CF_REG_CTRL;
ata_std_ports(&ap->ioaddr);
ap->ioaddr.data_addr = info->iobase + RB500_CF_REG_DATA;
}
static __devinit int rb500_pata_driver_probe(struct platform_device *pdev)
{
unsigned int irq;
int gpio;
struct resource *res;
struct ata_host *ah;
struct rb500_cf_info *info;
int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "no IOMEM resource found\n");
return -EINVAL;
}
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
dev_err(&pdev->dev, "no IRQ resource found\n");
return -ENOENT;
}
gpio = irq_to_gpio(irq);
if (gpio < 0) {
dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq);
return -ENOENT;
}
ret = gpio_request(gpio, DRV_NAME);
if (ret) {
dev_err(&pdev->dev, "GPIO request failed\n");
return ret;
}
/* allocate host */
ah = ata_host_alloc(&pdev->dev, RB500_CF_MAXPORTS);
if (!ah)
return -ENOMEM;
platform_set_drvdata(pdev, ah);
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
ah->private_data = info;
info->gpio_line = gpio;
info->irq = irq;
info->iobase = devm_ioremap_nocache(&pdev->dev, res->start,
res->end - res->start + 1);
if (!info->iobase)
return -ENOMEM;
ret = gpio_direction_input(gpio);
if (ret) {
dev_err(&pdev->dev, "unable to set GPIO direction, err=%d\n",
ret);
goto err_free_gpio;
}
rb500_pata_setup_ports(ah);
ret = ata_host_activate(ah, irq, rb500_pata_irq_handler,
IRQF_TRIGGER_LOW, &rb500_pata_sht);
if (ret)
goto err_free_gpio;
return 0;
err_free_gpio:
gpio_free(gpio);
return ret;
}
static __devexit int rb500_pata_driver_remove(struct platform_device *pdev)
{
struct ata_host *ah = platform_get_drvdata(pdev);
struct rb500_cf_info *info = ah->private_data;
ata_host_detach(ah);
gpio_free(info->gpio_line);
return 0;
}
static struct platform_driver rb500_pata_platform_driver = {
.probe = rb500_pata_driver_probe,
.remove = __devexit_p(rb500_pata_driver_remove),
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
};
/* ------------------------------------------------------------------------ */
#define DRV_INFO DRV_DESC " version " DRV_VERSION
static int __init rb500_pata_module_init(void)
{
printk(KERN_INFO DRV_INFO "\n");
return platform_driver_register(&rb500_pata_platform_driver);
}
static void __exit rb500_pata_module_exit(void)
{
platform_driver_unregister(&rb500_pata_platform_driver);
}
MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
MODULE_DESCRIPTION(DRV_DESC);
MODULE_VERSION(DRV_VERSION);
MODULE_LICENSE("GPL");
module_init(rb500_pata_module_init);
module_exit(rb500_pata_module_exit);

View file

@ -648,7 +648,7 @@ u64 dma_get_required_mask(struct device *dev)
high_totalram += high_totalram - 1;
mask = (((u64)high_totalram) << 32) + 0xffffffff;
}
return mask & *dev->dma_mask;
return mask;
}
EXPORT_SYMBOL_GPL(dma_get_required_mask);
#endif

View file

@ -133,6 +133,7 @@ int sysdev_class_register(struct sysdev_class * cls)
pr_debug("Registering sysdev class '%s'\n",
kobject_name(&cls->kset.kobj));
INIT_LIST_HEAD(&cls->drivers);
memset(&cls->kset.kobj, 0x00, sizeof(struct kobject));
cls->kset.kobj.parent = &system_kset->kobj;
cls->kset.kobj.ktype = &ktype_sysdev_class;
cls->kset.kobj.kset = system_kset;
@ -227,6 +228,9 @@ int sysdev_register(struct sys_device * sysdev)
pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj));
/* initialize the kobject to 0, in case it had previously been used */
memset(&sysdev->kobj, 0x00, sizeof(struct kobject));
/* Make sure the kset is set */
sysdev->kobj.kset = &cls->kset;

View file

@ -190,6 +190,14 @@ enum card_type {
F32_8 = 8192, /* 3072 bytes downl. + 1024 bytes uplink * 2 -> 8192 */
};
/* Initialization states a card can be in */
enum card_state {
NOZOMI_STATE_UKNOWN = 0,
NOZOMI_STATE_ENABLED = 1, /* pci device enabled */
NOZOMI_STATE_ALLOCATED = 2, /* config setup done */
NOZOMI_STATE_READY = 3, /* flowcontrols received */
};
/* Two different toggle channels exist */
enum channel_type {
CH_A = 0,
@ -385,6 +393,7 @@ struct nozomi {
spinlock_t spin_mutex; /* secures access to registers and tty */
unsigned int index_start;
enum card_state state;
u32 open_ttys;
};
@ -686,6 +695,7 @@ static int nozomi_read_config_table(struct nozomi *dc)
dc->last_ier = dc->last_ier | CTRL_DL;
writew(dc->last_ier, dc->reg_ier);
dc->state = NOZOMI_STATE_ALLOCATED;
dev_info(&dc->pdev->dev, "Initialization OK!\n");
return 1;
}
@ -944,6 +954,14 @@ static int receive_flow_control(struct nozomi *dc)
case CTRL_APP2:
port = PORT_APP2;
enable_ier = APP2_DL;
if (dc->state == NOZOMI_STATE_ALLOCATED) {
/*
* After card initialization the flow control
* received for APP2 is always the last
*/
dc->state = NOZOMI_STATE_READY;
dev_info(&dc->pdev->dev, "Device READY!\n");
}
break;
default:
dev_err(&dc->pdev->dev,
@ -1366,22 +1384,12 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
dc->pdev = pdev;
/* Find out what card type it is */
nozomi_get_card_type(dc);
ret = pci_enable_device(dc->pdev);
if (ret) {
dev_err(&pdev->dev, "Failed to enable PCI Device\n");
goto err_free;
}
start = pci_resource_start(dc->pdev, 0);
if (start == 0) {
dev_err(&pdev->dev, "No I/O address for card detected\n");
ret = -ENODEV;
goto err_disable_device;
}
ret = pci_request_regions(dc->pdev, NOZOMI_NAME);
if (ret) {
dev_err(&pdev->dev, "I/O address 0x%04x already in use\n",
@ -1389,6 +1397,16 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
goto err_disable_device;
}
start = pci_resource_start(dc->pdev, 0);
if (start == 0) {
dev_err(&pdev->dev, "No I/O address for card detected\n");
ret = -ENODEV;
goto err_rel_regs;
}
/* Find out what card type it is */
nozomi_get_card_type(dc);
dc->base_addr = ioremap(start, dc->card_type);
if (!dc->base_addr) {
dev_err(&pdev->dev, "Unable to map card MMIO\n");
@ -1425,6 +1443,14 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
dc->index_start = ndev_idx * MAX_PORT;
ndevs[ndev_idx] = dc;
pci_set_drvdata(pdev, dc);
/* Enable RESET interrupt */
dc->last_ier = RESET;
iowrite16(dc->last_ier, dc->reg_ier);
dc->state = NOZOMI_STATE_ENABLED;
for (i = 0; i < MAX_PORT; i++) {
mutex_init(&dc->port[i].tty_sem);
dc->port[i].tty_open_count = 0;
@ -1433,12 +1459,6 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
&pdev->dev);
}
/* Enable RESET interrupt. */
dc->last_ier = RESET;
writew(dc->last_ier, dc->reg_ier);
pci_set_drvdata(pdev, dc);
return 0;
err_free_sbuf:
@ -1553,7 +1573,7 @@ static int ntty_open(struct tty_struct *tty, struct file *file)
struct nozomi *dc = get_dc_by_tty(tty);
unsigned long flags;
if (!port || !dc)
if (!port || !dc || dc->state != NOZOMI_STATE_READY)
return -ENODEV;
if (mutex_lock_interruptible(&port->tty_sem))
@ -1716,6 +1736,10 @@ static int ntty_tiocmget(struct tty_struct *tty, struct file *file)
static int ntty_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear)
{
struct nozomi *dc = get_dc_by_tty(tty);
unsigned long flags;
spin_lock_irqsave(&dc->spin_mutex, flags);
if (set & TIOCM_RTS)
set_rts(tty, 1);
else if (clear & TIOCM_RTS)
@ -1725,6 +1749,7 @@ static int ntty_tiocmset(struct tty_struct *tty, struct file *file,
set_dtr(tty, 1);
else if (clear & TIOCM_DTR)
set_dtr(tty, 0);
spin_unlock_irqrestore(&dc->spin_mutex, flags);
return 0;
}
@ -1762,7 +1787,7 @@ static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp)
icount.brk = cnow.brk;
icount.buf_overrun = cnow.buf_overrun;
return copy_to_user(argp, &icount, sizeof(icount));
return copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0;
}
static int ntty_ioctl(struct tty_struct *tty, struct file *file,

View file

@ -1620,14 +1620,8 @@ static int __init rc_init_drivers(void)
static void rc_release_drivers(void)
{
unsigned long flags;
spin_lock_irqsave(&riscom_lock, flags);
tty_unregister_driver(riscom_driver);
put_tty_driver(riscom_driver);
spin_unlock_irqrestore(&riscom_lock, flags);
}
#ifndef MODULE

View file

@ -184,6 +184,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
gc->direction_output = pca953x_gpio_direction_output;
gc->get = pca953x_gpio_get_value;
gc->set = pca953x_gpio_set_value;
gc->can_sleep = 1;
gc->base = chip->gpio_start;
gc->ngpio = gpios;

View file

@ -3759,6 +3759,7 @@ static void cm_remove_one(struct ib_device *device)
port = cm_dev->port[i-1];
ib_modify_port(device, port->port_num, 0, &port_modify);
ib_unregister_mad_agent(port->mad_agent);
flush_workqueue(cm.wq);
cm_remove_port_fs(port);
}
kobject_put(&cm_dev->dev_obj);
@ -3813,6 +3814,7 @@ static void __exit ib_cm_cleanup(void)
cancel_delayed_work(&timewait_info->work.work);
spin_unlock_irq(&cm.lock);
ib_unregister_client(&cm_client);
destroy_workqueue(cm.wq);
list_for_each_entry_safe(timewait_info, tmp, &cm.timewait_list, list) {
@ -3820,7 +3822,6 @@ static void __exit ib_cm_cleanup(void)
kfree(timewait_info);
}
ib_unregister_client(&cm_client);
class_unregister(&cm_class);
idr_destroy(&cm.local_id_table);
}

View file

@ -139,7 +139,7 @@ static inline struct ib_pool_fmr *ib_fmr_cache_lookup(struct ib_fmr_pool *pool,
static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
{
int ret;
struct ib_pool_fmr *fmr, *next;
struct ib_pool_fmr *fmr;
LIST_HEAD(unmap_list);
LIST_HEAD(fmr_list);
@ -158,20 +158,6 @@ static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
#endif
}
/*
* The free_list may hold FMRs that have been put there
* because they haven't reached the max_remap count.
* Invalidate their mapping as well.
*/
list_for_each_entry_safe(fmr, next, &pool->free_list, list) {
if (fmr->remap_count == 0)
continue;
hlist_del_init(&fmr->cache_node);
fmr->remap_count = 0;
list_add_tail(&fmr->fmr->list, &fmr_list);
list_move(&fmr->list, &unmap_list);
}
list_splice(&pool->dirty_list, &unmap_list);
INIT_LIST_HEAD(&pool->dirty_list);
pool->dirty_len = 0;
@ -384,6 +370,11 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
i = 0;
list_for_each_entry_safe(fmr, tmp, &pool->free_list, list) {
if (fmr->remap_count) {
INIT_LIST_HEAD(&fmr_list);
list_add_tail(&fmr->fmr->list, &fmr_list);
ib_unmap_fmr(&fmr_list);
}
ib_dealloc_fmr(fmr->fmr);
list_del(&fmr->list);
kfree(fmr);
@ -407,8 +398,23 @@ EXPORT_SYMBOL(ib_destroy_fmr_pool);
*/
int ib_flush_fmr_pool(struct ib_fmr_pool *pool)
{
int serial = atomic_inc_return(&pool->req_ser);
int serial;
struct ib_pool_fmr *fmr, *next;
/*
* The free_list holds FMRs that may have been used
* but have not been remapped enough times to be dirty.
* Put them on the dirty list now so that the cleanup
* thread will reap them too.
*/
spin_lock_irq(&pool->pool_lock);
list_for_each_entry_safe(fmr, next, &pool->free_list, list) {
if (fmr->remap_count > 0)
list_move(&fmr->list, &pool->dirty_list);
}
spin_unlock_irq(&pool->pool_lock);
serial = atomic_inc_return(&pool->req_ser);
wake_up_process(pool->thread);
if (wait_event_interruptible(pool->force_wait,

View file

@ -839,6 +839,7 @@ static void cm_work_handler(struct work_struct *_work)
unsigned long flags;
int empty;
int ret = 0;
int destroy_id;
spin_lock_irqsave(&cm_id_priv->lock, flags);
empty = list_empty(&cm_id_priv->work_list);
@ -857,9 +858,9 @@ static void cm_work_handler(struct work_struct *_work)
destroy_cm_id(&cm_id_priv->id);
}
BUG_ON(atomic_read(&cm_id_priv->refcount)==0);
destroy_id = test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags);
if (iwcm_deref_id(cm_id_priv)) {
if (test_bit(IWCM_F_CALLBACK_DESTROY,
&cm_id_priv->flags)) {
if (destroy_id) {
BUG_ON(!list_empty(&cm_id_priv->work_list));
free_cm_id(cm_id_priv);
}

View file

@ -189,7 +189,7 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve
return ERR_PTR(-ENOMEM);
}
chp->rhp = rhp;
chp->ibcq.cqe = (1 << chp->cq.size_log2) - 1;
chp->ibcq.cqe = 1 << chp->cq.size_log2;
spin_lock_init(&chp->lock);
atomic_set(&chp->refcnt, 1);
init_waitqueue_head(&chp->wait);
@ -819,8 +819,11 @@ static struct ib_qp *iwch_create_qp(struct ib_pd *pd,
kfree(qhp);
return ERR_PTR(-ENOMEM);
}
attrs->cap.max_recv_wr = rqsize - 1;
attrs->cap.max_send_wr = sqsize;
attrs->cap.max_inline_data = T3_MAX_INLINE;
qhp->rhp = rhp;
qhp->attr.pd = php->pdid;
qhp->attr.scq = ((struct iwch_cq *) attrs->send_cq)->cq.cqid;

View file

@ -237,36 +237,32 @@ static int iser_free_ib_conn_res(struct iser_conn *ib_conn)
static
struct iser_device *iser_device_find_by_ib_device(struct rdma_cm_id *cma_id)
{
struct list_head *p_list;
struct iser_device *device = NULL;
struct iser_device *device;
mutex_lock(&ig.device_list_mutex);
p_list = ig.device_list.next;
while (p_list != &ig.device_list) {
device = list_entry(p_list, struct iser_device, ig_list);
list_for_each_entry(device, &ig.device_list, ig_list)
/* find if there's a match using the node GUID */
if (device->ib_device->node_guid == cma_id->device->node_guid)
break;
}
goto inc_refcnt;
if (device == NULL) {
device = kzalloc(sizeof *device, GFP_KERNEL);
if (device == NULL)
goto out;
/* assign this device to the device */
device->ib_device = cma_id->device;
/* init the device and link it into ig device list */
if (iser_create_device_ib_res(device)) {
kfree(device);
device = NULL;
goto out;
}
list_add(&device->ig_list, &ig.device_list);
device = kzalloc(sizeof *device, GFP_KERNEL);
if (device == NULL)
goto out;
/* assign this device to the device */
device->ib_device = cma_id->device;
/* init the device and link it into ig device list */
if (iser_create_device_ib_res(device)) {
kfree(device);
device = NULL;
goto out;
}
out:
BUG_ON(device == NULL);
list_add(&device->ig_list, &ig.device_list);
inc_refcnt:
device->refcount++;
out:
mutex_unlock(&ig.device_list_mutex);
return device;
}
@ -372,6 +368,12 @@ static void iser_addr_handler(struct rdma_cm_id *cma_id)
int ret;
device = iser_device_find_by_ib_device(cma_id);
if (!device) {
iser_err("device lookup/creation failed\n");
iser_connect_error(cma_id);
return;
}
ib_conn = (struct iser_conn *)cma_id->context;
ib_conn->device = device;
@ -380,7 +382,6 @@ static void iser_addr_handler(struct rdma_cm_id *cma_id)
iser_err("resolve route failed: %d\n", ret);
iser_connect_error(cma_id);
}
return;
}
static void iser_route_handler(struct rdma_cm_id *cma_id)

View file

@ -16,7 +16,7 @@
#if defined(CONFIG_MACH_JAZZ)
#include "i8042-jazzio.h"
#elif defined(CONFIG_SGI_IP22)
#elif defined(CONFIG_SGI_HAS_I8042)
#include "i8042-ip22io.h"
#elif defined(CONFIG_PPC)
#include "i8042-ppcio.h"

View file

@ -69,11 +69,22 @@ static __init int map_switcher(void)
switcher_page[i] = virt_to_page(addr);
}
/* First we check that the Switcher won't overlap the fixmap area at
* the top of memory. It's currently nowhere near, but it could have
* very strange effects if it ever happened. */
if (SWITCHER_ADDR + (TOTAL_SWITCHER_PAGES+1)*PAGE_SIZE > FIXADDR_START){
err = -ENOMEM;
printk("lguest: mapping switcher would thwack fixmap\n");
goto free_pages;
}
/* Now we reserve the "virtual memory area" we want: 0xFFC00000
* (SWITCHER_ADDR). We might not get it in theory, but in practice
* it's worked so far. */
* it's worked so far. The end address needs +1 because __get_vm_area
* allocates an extra guard page, so we need space for that. */
switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE,
VM_ALLOC, SWITCHER_ADDR, VMALLOC_END);
VM_ALLOC, SWITCHER_ADDR, SWITCHER_ADDR
+ (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE);
if (!switcher_vma) {
err = -ENOMEM;
printk("lguest: could not map switcher pages high\n");

View file

@ -241,16 +241,17 @@ static ssize_t write(struct file *file, const char __user *in,
cpu = &lg->cpus[cpu_id];
if (!cpu)
return -EINVAL;
/* Once the Guest is dead, you can only read() why it died. */
if (lg->dead)
return -ENOENT;
/* If you're not the task which owns the Guest, all you can do
* is break the Launcher out of running the Guest. */
if (current != cpu->tsk && req != LHREQ_BREAK)
return -EPERM;
}
/* Once the Guest is dead, all you can do is read() why it died. */
if (lg && lg->dead)
return -ENOENT;
/* If you're not the task which owns the Guest, you can only break */
if (lg && current != cpu->tsk && req != LHREQ_BREAK)
return -EPERM;
switch (req) {
case LHREQ_INITIALIZE:
return initialize(file, input);

View file

@ -391,7 +391,7 @@ static unsigned int find_pgdir(struct lguest *lg, unsigned long pgtable)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(lg->pgdirs); i++)
if (lg->pgdirs[i].gpgdir == pgtable)
if (lg->pgdirs[i].pgdir && lg->pgdirs[i].gpgdir == pgtable)
break;
return i;
}

View file

@ -1045,7 +1045,8 @@ void bitmap_daemon_work(struct bitmap *bitmap)
if (bitmap == NULL)
return;
if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ))
return;
goto done;
bitmap->daemon_lastrun = jiffies;
if (bitmap->allclean) {
bitmap->mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
@ -1142,6 +1143,7 @@ void bitmap_daemon_work(struct bitmap *bitmap)
}
}
done:
if (bitmap->allclean == 0)
bitmap->mddev->thread->timeout = bitmap->daemon_sleep * HZ;
}

View file

@ -5149,7 +5149,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
if (mddev->ro==1)
seq_printf(seq, " (read-only)");
if (mddev->ro==2)
seq_printf(seq, "(auto-read-only)");
seq_printf(seq, " (auto-read-only)");
seq_printf(seq, " %s", mddev->pers->name);
}

View file

@ -8,7 +8,7 @@ menuconfig MEMSTICK
Sony MemoryStick is a proprietary storage/extension card protocol.
If you want MemoryStick support, you should say Y here and also
to the specific driver for your MMC interface.
to the specific driver for your MemoryStick interface.
if MEMSTICK

View file

@ -18,7 +18,6 @@
#include <linux/delay.h>
#define DRIVER_NAME "memstick"
#define DRIVER_VERSION "0.2"
static unsigned int cmd_retries = 3;
module_param(cmd_retries, uint, 0644);
@ -236,7 +235,7 @@ int memstick_next_req(struct memstick_host *host, struct memstick_request **mrq)
rc = host->card->next_request(host->card, mrq);
if (!rc)
host->retries = cmd_retries;
host->retries = cmd_retries > 1 ? cmd_retries - 1 : 1;
else
*mrq = NULL;
@ -271,7 +270,7 @@ void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc,
mrq->data_dir = READ;
mrq->sg = *sg;
mrq->io_type = MEMSTICK_IO_SG;
mrq->long_data = 1;
if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD)
mrq->need_card_int = 1;
@ -306,7 +305,7 @@ void memstick_init_req(struct memstick_request *mrq, unsigned char tpc,
if (mrq->data_dir == WRITE)
memcpy(mrq->data, buf, mrq->data_len);
mrq->io_type = MEMSTICK_IO_VAL;
mrq->long_data = 0;
if (tpc == MS_TPC_SET_CMD || tpc == MS_TPC_EX_SET_CMD)
mrq->need_card_int = 1;
@ -561,6 +560,31 @@ void memstick_free_host(struct memstick_host *host)
}
EXPORT_SYMBOL(memstick_free_host);
/**
* memstick_suspend_host - notify bus driver of host suspension
* @host - host to use
*/
void memstick_suspend_host(struct memstick_host *host)
{
mutex_lock(&host->lock);
host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
mutex_unlock(&host->lock);
}
EXPORT_SYMBOL(memstick_suspend_host);
/**
* memstick_resume_host - notify bus driver of host resumption
* @host - host to use
*/
void memstick_resume_host(struct memstick_host *host)
{
mutex_lock(&host->lock);
host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON);
mutex_unlock(&host->lock);
memstick_detect_change(host);
}
EXPORT_SYMBOL(memstick_resume_host);
int memstick_register_driver(struct memstick_driver *drv)
{
drv->driver.bus = &memstick_bus_type;
@ -611,4 +635,3 @@ module_exit(memstick_exit);
MODULE_AUTHOR("Alex Dubov");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Sony MemoryStick core driver");
MODULE_VERSION(DRIVER_VERSION);

View file

@ -16,10 +16,10 @@
#include <linux/idr.h>
#include <linux/hdreg.h>
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/memstick.h>
#define DRIVER_NAME "mspro_block"
#define DRIVER_VERSION "0.2"
static int major;
module_param(major, int, 0644);
@ -110,6 +110,17 @@ struct mspro_mbr {
unsigned int sectors_per_partition;
} __attribute__((packed));
struct mspro_specfile {
char name[8];
char ext[3];
unsigned char attr;
unsigned char reserved[10];
unsigned short time;
unsigned short date;
unsigned short cluster;
unsigned int size;
} __attribute__((packed));
struct mspro_devinfo {
unsigned short cylinders;
unsigned short heads;
@ -293,6 +304,20 @@ static ssize_t mspro_block_attr_show_sysinfo(struct device *dev,
dev_attr);
struct mspro_sys_info *x_sys = x_attr->data;
ssize_t rc = 0;
int date_tz = 0, date_tz_f = 0;
if (x_sys->assembly_date[0] > 0x80U) {
date_tz = (~x_sys->assembly_date[0]) + 1;
date_tz_f = date_tz & 3;
date_tz >>= 2;
date_tz = -date_tz;
date_tz_f *= 15;
} else if (x_sys->assembly_date[0] < 0x80U) {
date_tz = x_sys->assembly_date[0];
date_tz_f = date_tz & 3;
date_tz >>= 2;
date_tz_f *= 15;
}
rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "class: %x\n",
x_sys->class);
@ -305,8 +330,8 @@ static ssize_t mspro_block_attr_show_sysinfo(struct device *dev,
rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "page size: %x\n",
be16_to_cpu(x_sys->page_size));
rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "assembly date: "
"%d %04u-%02u-%02u %02u:%02u:%02u\n",
x_sys->assembly_date[0],
"GMT%+d:%d %04u-%02u-%02u %02u:%02u:%02u\n",
date_tz, date_tz_f,
be16_to_cpu(*(unsigned short *)
&x_sys->assembly_date[1]),
x_sys->assembly_date[3], x_sys->assembly_date[4],
@ -398,6 +423,41 @@ static ssize_t mspro_block_attr_show_mbr(struct device *dev,
return rc;
}
static ssize_t mspro_block_attr_show_specfile(struct device *dev,
struct device_attribute *attr,
char *buffer)
{
struct mspro_sys_attr *x_attr = container_of(attr,
struct mspro_sys_attr,
dev_attr);
struct mspro_specfile *x_spfile = x_attr->data;
char name[9], ext[4];
ssize_t rc = 0;
memcpy(name, x_spfile->name, 8);
name[8] = 0;
memcpy(ext, x_spfile->ext, 3);
ext[3] = 0;
rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "name: %s\n", name);
rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "ext: %s\n", ext);
rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "attribute: %x\n",
x_spfile->attr);
rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "time: %d:%d:%d\n",
x_spfile->time >> 11,
(x_spfile->time >> 5) & 0x3f,
(x_spfile->time & 0x1f) * 2);
rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "date: %d-%d-%d\n",
(x_spfile->date >> 9) + 1980,
(x_spfile->date >> 5) & 0xf,
x_spfile->date & 0x1f);
rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "start cluster: %x\n",
x_spfile->cluster);
rc += scnprintf(buffer + rc, PAGE_SIZE - rc, "size: %x\n",
x_spfile->size);
return rc;
}
static ssize_t mspro_block_attr_show_devinfo(struct device *dev,
struct device_attribute *attr,
char *buffer)
@ -430,6 +490,9 @@ static sysfs_show_t mspro_block_attr_show(unsigned char tag)
return mspro_block_attr_show_modelname;
case MSPRO_BLOCK_ID_MBR:
return mspro_block_attr_show_mbr;
case MSPRO_BLOCK_ID_SPECFILEVALUES1:
case MSPRO_BLOCK_ID_SPECFILEVALUES2:
return mspro_block_attr_show_specfile;
case MSPRO_BLOCK_ID_DEVINFO:
return mspro_block_attr_show_devinfo;
default:
@ -629,7 +692,7 @@ static void mspro_block_process_request(struct memstick_dev *card,
param.system = msb->system;
param.data_count = cpu_to_be16(page_count);
param.data_address = cpu_to_be32((uint32_t)t_sec);
param.cmd_param = 0;
param.tpc_param = 0;
msb->data_dir = rq_data_dir(req);
msb->transfer_cmd = msb->data_dir == READ
@ -758,10 +821,10 @@ static int mspro_block_switch_to_parallel(struct memstick_dev *card)
struct memstick_host *host = card->host;
struct mspro_block_data *msb = memstick_get_drvdata(card);
struct mspro_param_register param = {
.system = 0,
.system = MEMSTICK_SYS_PAR4,
.data_count = 0,
.data_address = 0,
.cmd_param = 0
.tpc_param = 0
};
card->next_request = h_mspro_block_req_init;
@ -773,8 +836,8 @@ static int mspro_block_switch_to_parallel(struct memstick_dev *card)
if (card->current_mrq.error)
return card->current_mrq.error;
msb->system = 0;
host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PARALLEL);
msb->system = MEMSTICK_SYS_PAR4;
host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4);
card->next_request = h_mspro_block_req_init;
msb->mrq_handler = h_mspro_block_default;
@ -783,8 +846,24 @@ static int mspro_block_switch_to_parallel(struct memstick_dev *card)
wait_for_completion(&card->mrq_complete);
if (card->current_mrq.error) {
msb->system = 0x80;
msb->system = MEMSTICK_SYS_SERIAL;
host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
msleep(1000);
host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON);
host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL);
if (memstick_set_rw_addr(card))
return card->current_mrq.error;
param.system = msb->system;
card->next_request = h_mspro_block_req_init;
msb->mrq_handler = h_mspro_block_default;
memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, &param,
sizeof(param));
memstick_new_req(host);
wait_for_completion(&card->mrq_complete);
return -EFAULT;
}
@ -802,7 +881,7 @@ static int mspro_block_read_attributes(struct memstick_dev *card)
.system = msb->system,
.data_count = cpu_to_be16(1),
.data_address = 0,
.cmd_param = 0
.tpc_param = 0
};
struct mspro_attribute *attr = NULL;
struct mspro_sys_attr *s_attr = NULL;
@ -922,7 +1001,7 @@ static int mspro_block_read_attributes(struct memstick_dev *card)
param.system = msb->system;
param.data_count = cpu_to_be16((rc / msb->page_size) + 1);
param.data_address = cpu_to_be32(addr / msb->page_size);
param.cmd_param = 0;
param.tpc_param = 0;
sg_init_one(&msb->req_sg[0], buffer,
be16_to_cpu(param.data_count) * msb->page_size);
@ -964,7 +1043,7 @@ static int mspro_block_init_card(struct memstick_dev *card)
struct memstick_host *host = card->host;
int rc = 0;
msb->system = 0x80;
msb->system = MEMSTICK_SYS_SERIAL;
card->reg_addr.r_offset = offsetof(struct mspro_register, status);
card->reg_addr.r_length = sizeof(struct ms_status_register);
card->reg_addr.w_offset = offsetof(struct mspro_register, param);
@ -973,7 +1052,7 @@ static int mspro_block_init_card(struct memstick_dev *card)
if (memstick_set_rw_addr(card))
return -EIO;
if (host->caps & MEMSTICK_CAP_PARALLEL) {
if (host->caps & MEMSTICK_CAP_PAR4) {
if (mspro_block_switch_to_parallel(card))
printk(KERN_WARNING "%s: could not switch to "
"parallel interface\n", card->dev.bus_id);
@ -1348,4 +1427,3 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alex Dubov");
MODULE_DESCRIPTION("Sony MemoryStickPro block device driver");
MODULE_DEVICE_TABLE(memstick, mspro_block_id_tbl);
MODULE_VERSION(DRIVER_VERSION);

View file

@ -20,3 +20,13 @@ config MEMSTICK_TIFM_MS
To compile this driver as a module, choose M here: the
module will be called tifm_ms.
config MEMSTICK_JMICRON_38X
tristate "JMicron JMB38X MemoryStick interface support (EXPERIMENTAL)"
depends on EXPERIMENTAL && PCI
help
Say Y here if you want to be able to access MemoryStick cards with
the JMicron(R) JMB38X MemoryStick card reader.
To compile this driver as a module, choose M here: the
module will be called jmb38x_ms.

View file

@ -3,8 +3,8 @@
#
ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
EXTRA_CFLAGS += -DDEBUG
endif
obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o
obj-$(CONFIG_MEMSTICK_TIFM_MS) += tifm_ms.o
obj-$(CONFIG_MEMSTICK_JMICRON_38X) += jmb38x_ms.o

View file

@ -0,0 +1,945 @@
/*
* jmb38x_ms.c - JMicron jmb38x MemoryStick card reader
*
* Copyright (C) 2008 Alex Dubov <oakad@yahoo.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/highmem.h>
#include <linux/memstick.h>
#define DRIVER_NAME "jmb38x_ms"
static int no_dma;
module_param(no_dma, bool, 0644);
enum {
DMA_ADDRESS = 0x00,
BLOCK = 0x04,
DMA_CONTROL = 0x08,
TPC_P0 = 0x0c,
TPC_P1 = 0x10,
TPC = 0x14,
HOST_CONTROL = 0x18,
DATA = 0x1c,
STATUS = 0x20,
INT_STATUS = 0x24,
INT_STATUS_ENABLE = 0x28,
INT_SIGNAL_ENABLE = 0x2c,
TIMER = 0x30,
TIMER_CONTROL = 0x34,
PAD_OUTPUT_ENABLE = 0x38,
PAD_PU_PD = 0x3c,
CLOCK_DELAY = 0x40,
ADMA_ADDRESS = 0x44,
CLOCK_CONTROL = 0x48,
LED_CONTROL = 0x4c,
VERSION = 0x50
};
struct jmb38x_ms_host {
struct jmb38x_ms *chip;
void __iomem *addr;
spinlock_t lock;
int id;
char host_id[DEVICE_ID_SIZE];
int irq;
unsigned int block_pos;
unsigned long timeout_jiffies;
struct timer_list timer;
struct memstick_request *req;
unsigned char eject:1,
use_dma:1;
unsigned char cmd_flags;
unsigned char io_pos;
unsigned int io_word[2];
};
struct jmb38x_ms {
struct pci_dev *pdev;
int host_cnt;
struct memstick_host *hosts[];
};
#define BLOCK_COUNT_MASK 0xffff0000
#define BLOCK_SIZE_MASK 0x00000fff
#define DMA_CONTROL_ENABLE 0x00000001
#define TPC_DATA_SEL 0x00008000
#define TPC_DIR 0x00004000
#define TPC_WAIT_INT 0x00002000
#define TPC_GET_INT 0x00000800
#define TPC_CODE_SZ_MASK 0x00000700
#define TPC_DATA_SZ_MASK 0x00000007
#define HOST_CONTROL_RESET_REQ 0x00008000
#define HOST_CONTROL_REI 0x00004000
#define HOST_CONTROL_LED 0x00000400
#define HOST_CONTROL_FAST_CLK 0x00000200
#define HOST_CONTROL_RESET 0x00000100
#define HOST_CONTROL_POWER_EN 0x00000080
#define HOST_CONTROL_CLOCK_EN 0x00000040
#define HOST_CONTROL_IF_SHIFT 4
#define HOST_CONTROL_IF_SERIAL 0x0
#define HOST_CONTROL_IF_PAR4 0x1
#define HOST_CONTROL_IF_PAR8 0x3
#define STATUS_HAS_MEDIA 0x00000400
#define STATUS_FIFO_EMPTY 0x00000200
#define STATUS_FIFO_FULL 0x00000100
#define INT_STATUS_TPC_ERR 0x00080000
#define INT_STATUS_CRC_ERR 0x00040000
#define INT_STATUS_TIMER_TO 0x00020000
#define INT_STATUS_HSK_TO 0x00010000
#define INT_STATUS_ANY_ERR 0x00008000
#define INT_STATUS_FIFO_WRDY 0x00000080
#define INT_STATUS_FIFO_RRDY 0x00000040
#define INT_STATUS_MEDIA_OUT 0x00000010
#define INT_STATUS_MEDIA_IN 0x00000008
#define INT_STATUS_DMA_BOUNDARY 0x00000004
#define INT_STATUS_EOTRAN 0x00000002
#define INT_STATUS_EOTPC 0x00000001
#define INT_STATUS_ALL 0x000f801f
#define PAD_OUTPUT_ENABLE_MS 0x0F3F
#define PAD_PU_PD_OFF 0x7FFF0000
#define PAD_PU_PD_ON_MS_SOCK0 0x5f8f0000
#define PAD_PU_PD_ON_MS_SOCK1 0x0f0f0000
enum {
CMD_READY = 0x01,
FIFO_READY = 0x02,
REG_DATA = 0x04,
AUTO_GET_INT = 0x08
};
static unsigned int jmb38x_ms_read_data(struct jmb38x_ms_host *host,
unsigned char *buf, unsigned int length)
{
unsigned int off = 0;
while (host->io_pos && length) {
buf[off++] = host->io_word[0] & 0xff;
host->io_word[0] >>= 8;
length--;
host->io_pos--;
}
if (!length)
return off;
while (!(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {
if (length < 4)
break;
*(unsigned int *)(buf + off) = __raw_readl(host->addr + DATA);
length -= 4;
off += 4;
}
if (length
&& !(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {
host->io_word[0] = readl(host->addr + DATA);
for (host->io_pos = 4; host->io_pos; --host->io_pos) {
buf[off++] = host->io_word[0] & 0xff;
host->io_word[0] >>= 8;
length--;
if (!length)
break;
}
}
return off;
}
static unsigned int jmb38x_ms_read_reg_data(struct jmb38x_ms_host *host,
unsigned char *buf,
unsigned int length)
{
unsigned int off = 0;
while (host->io_pos > 4 && length) {
buf[off++] = host->io_word[0] & 0xff;
host->io_word[0] >>= 8;
length--;
host->io_pos--;
}
if (!length)
return off;
while (host->io_pos && length) {
buf[off++] = host->io_word[1] & 0xff;
host->io_word[1] >>= 8;
length--;
host->io_pos--;
}
return off;
}
static unsigned int jmb38x_ms_write_data(struct jmb38x_ms_host *host,
unsigned char *buf,
unsigned int length)
{
unsigned int off = 0;
if (host->io_pos) {
while (host->io_pos < 4 && length) {
host->io_word[0] |= buf[off++] << (host->io_pos * 8);
host->io_pos++;
length--;
}
}
if (host->io_pos == 4
&& !(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {
writel(host->io_word[0], host->addr + DATA);
host->io_pos = 0;
host->io_word[0] = 0;
} else if (host->io_pos) {
return off;
}
if (!length)
return off;
while (!(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {
if (length < 4)
break;
__raw_writel(*(unsigned int *)(buf + off),
host->addr + DATA);
length -= 4;
off += 4;
}
switch (length) {
case 3:
host->io_word[0] |= buf[off + 2] << 16;
host->io_pos++;
case 2:
host->io_word[0] |= buf[off + 1] << 8;
host->io_pos++;
case 1:
host->io_word[0] |= buf[off];
host->io_pos++;
}
off += host->io_pos;
return off;
}
static unsigned int jmb38x_ms_write_reg_data(struct jmb38x_ms_host *host,
unsigned char *buf,
unsigned int length)
{
unsigned int off = 0;
while (host->io_pos < 4 && length) {
host->io_word[0] &= ~(0xff << (host->io_pos * 8));
host->io_word[0] |= buf[off++] << (host->io_pos * 8);
host->io_pos++;
length--;
}
if (!length)
return off;
while (host->io_pos < 8 && length) {
host->io_word[1] &= ~(0xff << (host->io_pos * 8));
host->io_word[1] |= buf[off++] << (host->io_pos * 8);
host->io_pos++;
length--;
}
return off;
}
static int jmb38x_ms_transfer_data(struct jmb38x_ms_host *host)
{
unsigned int length;
unsigned int off;
unsigned int t_size, p_off, p_cnt;
unsigned char *buf;
struct page *pg;
unsigned long flags = 0;
if (host->req->long_data) {
length = host->req->sg.length - host->block_pos;
off = host->req->sg.offset + host->block_pos;
} else {
length = host->req->data_len - host->block_pos;
off = 0;
}
while (length) {
if (host->req->long_data) {
pg = nth_page(sg_page(&host->req->sg),
off >> PAGE_SHIFT);
p_off = offset_in_page(off);
p_cnt = PAGE_SIZE - p_off;
p_cnt = min(p_cnt, length);
local_irq_save(flags);
buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off;
} else {
buf = host->req->data + host->block_pos;
p_cnt = host->req->data_len - host->block_pos;
}
if (host->req->data_dir == WRITE)
t_size = !(host->cmd_flags & REG_DATA)
? jmb38x_ms_write_data(host, buf, p_cnt)
: jmb38x_ms_write_reg_data(host, buf, p_cnt);
else
t_size = !(host->cmd_flags & REG_DATA)
? jmb38x_ms_read_data(host, buf, p_cnt)
: jmb38x_ms_read_reg_data(host, buf, p_cnt);
if (host->req->long_data) {
kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ);
local_irq_restore(flags);
}
if (!t_size)
break;
host->block_pos += t_size;
length -= t_size;
off += t_size;
}
if (!length && host->req->data_dir == WRITE) {
if (host->cmd_flags & REG_DATA) {
writel(host->io_word[0], host->addr + TPC_P0);
writel(host->io_word[1], host->addr + TPC_P1);
} else if (host->io_pos) {
writel(host->io_word[0], host->addr + DATA);
}
}
return length;
}
static int jmb38x_ms_issue_cmd(struct memstick_host *msh)
{
struct jmb38x_ms_host *host = memstick_priv(msh);
unsigned char *data;
unsigned int data_len, cmd, t_val;
if (!(STATUS_HAS_MEDIA & readl(host->addr + STATUS))) {
dev_dbg(msh->cdev.dev, "no media status\n");
host->req->error = -ETIME;
return host->req->error;
}
dev_dbg(msh->cdev.dev, "control %08x\n",
readl(host->addr + HOST_CONTROL));
dev_dbg(msh->cdev.dev, "status %08x\n", readl(host->addr + INT_STATUS));
dev_dbg(msh->cdev.dev, "hstatus %08x\n", readl(host->addr + STATUS));
host->cmd_flags = 0;
host->block_pos = 0;
host->io_pos = 0;
host->io_word[0] = 0;
host->io_word[1] = 0;
cmd = host->req->tpc << 16;
cmd |= TPC_DATA_SEL;
if (host->req->data_dir == READ)
cmd |= TPC_DIR;
if (host->req->need_card_int)
cmd |= TPC_WAIT_INT;
if (host->req->get_int_reg)
cmd |= TPC_GET_INT;
data = host->req->data;
host->use_dma = !no_dma;
if (host->req->long_data) {
data_len = host->req->sg.length;
} else {
data_len = host->req->data_len;
host->use_dma = 0;
}
if (data_len <= 8) {
cmd &= ~(TPC_DATA_SEL | 0xf);
host->cmd_flags |= REG_DATA;
cmd |= data_len & 0xf;
host->use_dma = 0;
}
if (host->use_dma) {
if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1,
host->req->data_dir == READ
? PCI_DMA_FROMDEVICE
: PCI_DMA_TODEVICE)) {
host->req->error = -ENOMEM;
return host->req->error;
}
data_len = sg_dma_len(&host->req->sg);
writel(sg_dma_address(&host->req->sg),
host->addr + DMA_ADDRESS);
writel(((1 << 16) & BLOCK_COUNT_MASK)
| (data_len & BLOCK_SIZE_MASK),
host->addr + BLOCK);
writel(DMA_CONTROL_ENABLE, host->addr + DMA_CONTROL);
} else if (!(host->cmd_flags & REG_DATA)) {
writel(((1 << 16) & BLOCK_COUNT_MASK)
| (data_len & BLOCK_SIZE_MASK),
host->addr + BLOCK);
t_val = readl(host->addr + INT_STATUS_ENABLE);
t_val |= host->req->data_dir == READ
? INT_STATUS_FIFO_RRDY
: INT_STATUS_FIFO_WRDY;
writel(t_val, host->addr + INT_STATUS_ENABLE);
writel(t_val, host->addr + INT_SIGNAL_ENABLE);
} else {
cmd &= ~(TPC_DATA_SEL | 0xf);
host->cmd_flags |= REG_DATA;
cmd |= data_len & 0xf;
if (host->req->data_dir == WRITE) {
jmb38x_ms_transfer_data(host);
writel(host->io_word[0], host->addr + TPC_P0);
writel(host->io_word[1], host->addr + TPC_P1);
}
}
mod_timer(&host->timer, jiffies + host->timeout_jiffies);
writel(HOST_CONTROL_LED | readl(host->addr + HOST_CONTROL),
host->addr + HOST_CONTROL);
host->req->error = 0;
writel(cmd, host->addr + TPC);
dev_dbg(msh->cdev.dev, "executing TPC %08x, len %x\n", cmd, data_len);
return 0;
}
static void jmb38x_ms_complete_cmd(struct memstick_host *msh, int last)
{
struct jmb38x_ms_host *host = memstick_priv(msh);
unsigned int t_val = 0;
int rc;
del_timer(&host->timer);
dev_dbg(msh->cdev.dev, "c control %08x\n",
readl(host->addr + HOST_CONTROL));
dev_dbg(msh->cdev.dev, "c status %08x\n",
readl(host->addr + INT_STATUS));
dev_dbg(msh->cdev.dev, "c hstatus %08x\n", readl(host->addr + STATUS));
if (host->req->get_int_reg) {
t_val = readl(host->addr + TPC_P0);
host->req->int_reg = (t_val & 0xff);
}
if (host->use_dma) {
writel(0, host->addr + DMA_CONTROL);
pci_unmap_sg(host->chip->pdev, &host->req->sg, 1,
host->req->data_dir == READ
? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
} else {
t_val = readl(host->addr + INT_STATUS_ENABLE);
if (host->req->data_dir == READ)
t_val &= ~INT_STATUS_FIFO_RRDY;
else
t_val &= ~INT_STATUS_FIFO_WRDY;
writel(t_val, host->addr + INT_STATUS_ENABLE);
writel(t_val, host->addr + INT_SIGNAL_ENABLE);
}
writel((~HOST_CONTROL_LED) & readl(host->addr + HOST_CONTROL),
host->addr + HOST_CONTROL);
if (!last) {
do {
rc = memstick_next_req(msh, &host->req);
} while (!rc && jmb38x_ms_issue_cmd(msh));
} else {
do {
rc = memstick_next_req(msh, &host->req);
if (!rc)
host->req->error = -ETIME;
} while (!rc);
}
}
static irqreturn_t jmb38x_ms_isr(int irq, void *dev_id)
{
struct memstick_host *msh = dev_id;
struct jmb38x_ms_host *host = memstick_priv(msh);
unsigned int irq_status;
spin_lock(&host->lock);
irq_status = readl(host->addr + INT_STATUS);
dev_dbg(&host->chip->pdev->dev, "irq_status = %08x\n", irq_status);
if (irq_status == 0 || irq_status == (~0)) {
spin_unlock(&host->lock);
return IRQ_NONE;
}
if (host->req) {
if (irq_status & INT_STATUS_ANY_ERR) {
if (irq_status & INT_STATUS_CRC_ERR)
host->req->error = -EILSEQ;
else
host->req->error = -ETIME;
} else {
if (host->use_dma) {
if (irq_status & INT_STATUS_EOTRAN)
host->cmd_flags |= FIFO_READY;
} else {
if (irq_status & (INT_STATUS_FIFO_RRDY
| INT_STATUS_FIFO_WRDY))
jmb38x_ms_transfer_data(host);
if (irq_status & INT_STATUS_EOTRAN) {
jmb38x_ms_transfer_data(host);
host->cmd_flags |= FIFO_READY;
}
}
if (irq_status & INT_STATUS_EOTPC) {
host->cmd_flags |= CMD_READY;
if (host->cmd_flags & REG_DATA) {
if (host->req->data_dir == READ) {
host->io_word[0]
= readl(host->addr
+ TPC_P0);
host->io_word[1]
= readl(host->addr
+ TPC_P1);
host->io_pos = 8;
jmb38x_ms_transfer_data(host);
}
host->cmd_flags |= FIFO_READY;
}
}
}
}
if (irq_status & (INT_STATUS_MEDIA_IN | INT_STATUS_MEDIA_OUT)) {
dev_dbg(&host->chip->pdev->dev, "media changed\n");
memstick_detect_change(msh);
}
writel(irq_status, host->addr + INT_STATUS);
if (host->req
&& (((host->cmd_flags & CMD_READY)
&& (host->cmd_flags & FIFO_READY))
|| host->req->error))
jmb38x_ms_complete_cmd(msh, 0);
spin_unlock(&host->lock);
return IRQ_HANDLED;
}
static void jmb38x_ms_abort(unsigned long data)
{
struct memstick_host *msh = (struct memstick_host *)data;
struct jmb38x_ms_host *host = memstick_priv(msh);
unsigned long flags;
dev_dbg(&host->chip->pdev->dev, "abort\n");
spin_lock_irqsave(&host->lock, flags);
if (host->req) {
host->req->error = -ETIME;
jmb38x_ms_complete_cmd(msh, 0);
}
spin_unlock_irqrestore(&host->lock, flags);
}
static void jmb38x_ms_request(struct memstick_host *msh)
{
struct jmb38x_ms_host *host = memstick_priv(msh);
unsigned long flags;
int rc;
spin_lock_irqsave(&host->lock, flags);
if (host->req) {
spin_unlock_irqrestore(&host->lock, flags);
BUG();
return;
}
do {
rc = memstick_next_req(msh, &host->req);
} while (!rc && jmb38x_ms_issue_cmd(msh));
spin_unlock_irqrestore(&host->lock, flags);
}
static void jmb38x_ms_reset(struct jmb38x_ms_host *host)
{
unsigned int host_ctl = readl(host->addr + HOST_CONTROL);
writel(host_ctl | HOST_CONTROL_RESET_REQ | HOST_CONTROL_RESET,
host->addr + HOST_CONTROL);
while (HOST_CONTROL_RESET_REQ
& (host_ctl = readl(host->addr + HOST_CONTROL))) {
ndelay(100);
dev_dbg(&host->chip->pdev->dev, "reset\n");
}
writel(INT_STATUS_ALL, host->addr + INT_STATUS_ENABLE);
writel(INT_STATUS_ALL, host->addr + INT_SIGNAL_ENABLE);
dev_dbg(&host->chip->pdev->dev, "reset\n");
}
static void jmb38x_ms_set_param(struct memstick_host *msh,
enum memstick_param param,
int value)
{
struct jmb38x_ms_host *host = memstick_priv(msh);
unsigned int host_ctl;
unsigned long flags;
spin_lock_irqsave(&host->lock, flags);
switch (param) {
case MEMSTICK_POWER:
if (value == MEMSTICK_POWER_ON) {
jmb38x_ms_reset(host);
writel(host->id ? PAD_PU_PD_ON_MS_SOCK1
: PAD_PU_PD_ON_MS_SOCK0,
host->addr + PAD_PU_PD);
writel(PAD_OUTPUT_ENABLE_MS,
host->addr + PAD_OUTPUT_ENABLE);
host_ctl = readl(host->addr + HOST_CONTROL);
host_ctl |= 7;
writel(host_ctl | (HOST_CONTROL_POWER_EN
| HOST_CONTROL_CLOCK_EN),
host->addr + HOST_CONTROL);
dev_dbg(&host->chip->pdev->dev, "power on\n");
} else if (value == MEMSTICK_POWER_OFF) {
writel(readl(host->addr + HOST_CONTROL)
& ~(HOST_CONTROL_POWER_EN
| HOST_CONTROL_CLOCK_EN),
host->addr + HOST_CONTROL);
writel(0, host->addr + PAD_OUTPUT_ENABLE);
writel(PAD_PU_PD_OFF, host->addr + PAD_PU_PD);
dev_dbg(&host->chip->pdev->dev, "power off\n");
}
break;
case MEMSTICK_INTERFACE:
/* jmb38x_ms_reset(host); */
host_ctl = readl(host->addr + HOST_CONTROL);
host_ctl &= ~(3 << HOST_CONTROL_IF_SHIFT);
/* host_ctl |= 7; */
if (value == MEMSTICK_SERIAL) {
host_ctl &= ~HOST_CONTROL_FAST_CLK;
host_ctl |= HOST_CONTROL_IF_SERIAL
<< HOST_CONTROL_IF_SHIFT;
host_ctl |= HOST_CONTROL_REI;
writel(0, host->addr + CLOCK_DELAY);
} else if (value == MEMSTICK_PAR4) {
host_ctl |= HOST_CONTROL_FAST_CLK;
host_ctl |= HOST_CONTROL_IF_PAR4
<< HOST_CONTROL_IF_SHIFT;
host_ctl &= ~HOST_CONTROL_REI;
writel(4, host->addr + CLOCK_DELAY);
} else if (value == MEMSTICK_PAR8) {
host_ctl |= HOST_CONTROL_FAST_CLK;
host_ctl |= HOST_CONTROL_IF_PAR8
<< HOST_CONTROL_IF_SHIFT;
host_ctl &= ~HOST_CONTROL_REI;
writel(4, host->addr + CLOCK_DELAY);
}
writel(host_ctl, host->addr + HOST_CONTROL);
break;
};
spin_unlock_irqrestore(&host->lock, flags);
}
#ifdef CONFIG_PM
static int jmb38x_ms_suspend(struct pci_dev *dev, pm_message_t state)
{
struct jmb38x_ms *jm = pci_get_drvdata(dev);
int cnt;
for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
if (!jm->hosts[cnt])
break;
memstick_suspend_host(jm->hosts[cnt]);
}
pci_save_state(dev);
pci_enable_wake(dev, pci_choose_state(dev, state), 0);
pci_disable_device(dev);
pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
}
static int jmb38x_ms_resume(struct pci_dev *dev)
{
struct jmb38x_ms *jm = pci_get_drvdata(dev);
int rc;
pci_set_power_state(dev, PCI_D0);
pci_restore_state(dev);
rc = pci_enable_device(dev);
if (rc)
return rc;
pci_set_master(dev);
pci_read_config_dword(dev, 0xac, &rc);
pci_write_config_dword(dev, 0xac, rc | 0x00470000);
for (rc = 0; rc < jm->host_cnt; ++rc) {
if (!jm->hosts[rc])
break;
memstick_resume_host(jm->hosts[rc]);
memstick_detect_change(jm->hosts[rc]);
}
return 0;
}
#else
#define jmb38x_ms_suspend NULL
#define jmb38x_ms_resume NULL
#endif /* CONFIG_PM */
static int jmb38x_ms_count_slots(struct pci_dev *pdev)
{
int cnt, rc = 0;
for (cnt = 0; cnt < PCI_ROM_RESOURCE; ++cnt) {
if (!(IORESOURCE_MEM & pci_resource_flags(pdev, cnt)))
break;
if (256 != pci_resource_len(pdev, cnt))
break;
++rc;
}
return rc;
}
static struct memstick_host *jmb38x_ms_alloc_host(struct jmb38x_ms *jm, int cnt)
{
struct memstick_host *msh;
struct jmb38x_ms_host *host;
msh = memstick_alloc_host(sizeof(struct jmb38x_ms_host),
&jm->pdev->dev);
if (!msh)
return NULL;
host = memstick_priv(msh);
host->chip = jm;
host->addr = ioremap(pci_resource_start(jm->pdev, cnt),
pci_resource_len(jm->pdev, cnt));
if (!host->addr)
goto err_out_free;
spin_lock_init(&host->lock);
host->id = cnt;
snprintf(host->host_id, DEVICE_ID_SIZE, DRIVER_NAME ":slot%d",
host->id);
host->irq = jm->pdev->irq;
host->timeout_jiffies = msecs_to_jiffies(4000);
msh->request = jmb38x_ms_request;
msh->set_param = jmb38x_ms_set_param;
/*
msh->caps = MEMSTICK_CAP_AUTO_GET_INT | MEMSTICK_CAP_PAR4
| MEMSTICK_CAP_PAR8;
*/
msh->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8;
setup_timer(&host->timer, jmb38x_ms_abort, (unsigned long)msh);
if (!request_irq(host->irq, jmb38x_ms_isr, IRQF_SHARED, host->host_id,
msh))
return msh;
iounmap(host->addr);
err_out_free:
kfree(msh);
return NULL;
}
static void jmb38x_ms_free_host(struct memstick_host *msh)
{
struct jmb38x_ms_host *host = memstick_priv(msh);
free_irq(host->irq, msh);
iounmap(host->addr);
memstick_free_host(msh);
}
static int jmb38x_ms_probe(struct pci_dev *pdev,
const struct pci_device_id *dev_id)
{
struct jmb38x_ms *jm;
int pci_dev_busy = 0;
int rc, cnt;
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc)
return rc;
rc = pci_enable_device(pdev);
if (rc)
return rc;
pci_set_master(pdev);
rc = pci_request_regions(pdev, DRIVER_NAME);
if (rc) {
pci_dev_busy = 1;
goto err_out;
}
pci_read_config_dword(pdev, 0xac, &rc);
pci_write_config_dword(pdev, 0xac, rc | 0x00470000);
cnt = jmb38x_ms_count_slots(pdev);
if (!cnt) {
rc = -ENODEV;
pci_dev_busy = 1;
goto err_out;
}
jm = kzalloc(sizeof(struct jmb38x_ms)
+ cnt * sizeof(struct memstick_host *), GFP_KERNEL);
if (!jm) {
rc = -ENOMEM;
goto err_out_int;
}
jm->pdev = pdev;
jm->host_cnt = cnt;
pci_set_drvdata(pdev, jm);
for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
jm->hosts[cnt] = jmb38x_ms_alloc_host(jm, cnt);
if (!jm->hosts[cnt])
break;
rc = memstick_add_host(jm->hosts[cnt]);
if (rc) {
jmb38x_ms_free_host(jm->hosts[cnt]);
jm->hosts[cnt] = NULL;
break;
}
}
if (cnt)
return 0;
rc = -ENODEV;
pci_set_drvdata(pdev, NULL);
kfree(jm);
err_out_int:
pci_release_regions(pdev);
err_out:
if (!pci_dev_busy)
pci_disable_device(pdev);
return rc;
}
static void jmb38x_ms_remove(struct pci_dev *dev)
{
struct jmb38x_ms *jm = pci_get_drvdata(dev);
struct jmb38x_ms_host *host;
int cnt;
unsigned long flags;
for (cnt = 0; cnt < jm->host_cnt; ++cnt) {
if (!jm->hosts[cnt])
break;
host = memstick_priv(jm->hosts[cnt]);
writel(0, host->addr + INT_SIGNAL_ENABLE);
writel(0, host->addr + INT_STATUS_ENABLE);
mmiowb();
dev_dbg(&jm->pdev->dev, "interrupts off\n");
spin_lock_irqsave(&host->lock, flags);
if (host->req) {
host->req->error = -ETIME;
jmb38x_ms_complete_cmd(jm->hosts[cnt], 1);
}
spin_unlock_irqrestore(&host->lock, flags);
memstick_remove_host(jm->hosts[cnt]);
dev_dbg(&jm->pdev->dev, "host removed\n");
jmb38x_ms_free_host(jm->hosts[cnt]);
}
pci_set_drvdata(dev, NULL);
pci_release_regions(dev);
pci_disable_device(dev);
kfree(jm);
}
static struct pci_device_id jmb38x_ms_id_tbl [] = {
{ PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_MS, PCI_ANY_ID,
PCI_ANY_ID, 0, 0, 0 },
{ }
};
static struct pci_driver jmb38x_ms_driver = {
.name = DRIVER_NAME,
.id_table = jmb38x_ms_id_tbl,
.probe = jmb38x_ms_probe,
.remove = jmb38x_ms_remove,
.suspend = jmb38x_ms_suspend,
.resume = jmb38x_ms_resume
};
static int __init jmb38x_ms_init(void)
{
return pci_register_driver(&jmb38x_ms_driver);
}
static void __exit jmb38x_ms_exit(void)
{
pci_unregister_driver(&jmb38x_ms_driver);
}
MODULE_AUTHOR("Alex Dubov");
MODULE_DESCRIPTION("JMicron jmb38x MemoryStick driver");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, jmb38x_ms_id_tbl);
module_init(jmb38x_ms_init);
module_exit(jmb38x_ms_exit);

View file

@ -20,293 +20,315 @@
#include <asm/io.h>
#define DRIVER_NAME "tifm_ms"
#define DRIVER_VERSION "0.1"
static int no_dma;
module_param(no_dma, bool, 0644);
#define TIFM_MS_TIMEOUT 0x00100
#define TIFM_MS_BADCRC 0x00200
#define TIFM_MS_EOTPC 0x01000
#define TIFM_MS_INT 0x02000
/*
* Some control bits of TIFM appear to conform to Sony's reference design,
* so I'm just assuming they all are.
*/
/* The meaning of the bit majority in this constant is unknown. */
#define TIFM_MS_SERIAL 0x04010
#define TIFM_MS_STAT_DRQ 0x04000
#define TIFM_MS_STAT_MSINT 0x02000
#define TIFM_MS_STAT_RDY 0x01000
#define TIFM_MS_STAT_CRC 0x00200
#define TIFM_MS_STAT_TOE 0x00100
#define TIFM_MS_STAT_EMP 0x00020
#define TIFM_MS_STAT_FUL 0x00010
#define TIFM_MS_STAT_CED 0x00008
#define TIFM_MS_STAT_ERR 0x00004
#define TIFM_MS_STAT_BRQ 0x00002
#define TIFM_MS_STAT_CNK 0x00001
#define TIFM_MS_SYS_LATCH 0x00100
#define TIFM_MS_SYS_NOT_RDY 0x00800
#define TIFM_MS_SYS_DATA 0x10000
#define TIFM_MS_SYS_DMA 0x10000
#define TIFM_MS_SYS_RESET 0x08000
#define TIFM_MS_SYS_SRAC 0x04000
#define TIFM_MS_SYS_INTEN 0x02000
#define TIFM_MS_SYS_NOCRC 0x01000
#define TIFM_MS_SYS_INTCLR 0x00800
#define TIFM_MS_SYS_MSIEN 0x00400
#define TIFM_MS_SYS_FCLR 0x00200
#define TIFM_MS_SYS_FDIR 0x00100
#define TIFM_MS_SYS_DAM 0x00080
#define TIFM_MS_SYS_DRM 0x00040
#define TIFM_MS_SYS_DRQSL 0x00020
#define TIFM_MS_SYS_REI 0x00010
#define TIFM_MS_SYS_REO 0x00008
#define TIFM_MS_SYS_BSY_MASK 0x00007
#define TIFM_MS_SYS_FIFO (TIFM_MS_SYS_INTEN | TIFM_MS_SYS_MSIEN \
| TIFM_MS_SYS_FCLR | TIFM_MS_SYS_BSY_MASK)
/* Hardware flags */
enum {
CMD_READY = 0x0001,
FIFO_READY = 0x0002,
CARD_READY = 0x0004,
DATA_CARRY = 0x0008
CMD_READY = 0x01,
FIFO_READY = 0x02,
CARD_INT = 0x04
};
struct tifm_ms {
struct tifm_dev *dev;
unsigned short eject:1,
no_dma:1;
unsigned short cmd_flags;
struct timer_list timer;
struct memstick_request *req;
unsigned int mode_mask;
unsigned int block_pos;
unsigned long timeout_jiffies;
struct timer_list timer;
struct memstick_request *req;
unsigned char eject:1,
use_dma:1;
unsigned char cmd_flags;
unsigned char io_pos;
unsigned int io_word;
};
static void tifm_ms_read_fifo(struct tifm_ms *host, unsigned int fifo_offset,
struct page *pg, unsigned int page_off,
unsigned int length)
static unsigned int tifm_ms_read_data(struct tifm_ms *host,
unsigned char *buf, unsigned int length)
{
struct tifm_dev *sock = host->dev;
unsigned int cnt = 0, off = 0;
unsigned char *buf = kmap_atomic(pg, KM_BIO_DST_IRQ) + page_off;
unsigned int off = 0;
if (host->cmd_flags & DATA_CARRY) {
while ((fifo_offset & 3) && length) {
while (host->io_pos && length) {
buf[off++] = host->io_word & 0xff;
host->io_word >>= 8;
length--;
host->io_pos--;
}
if (!length)
return off;
while (!(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) {
if (length < 4)
break;
*(unsigned int *)(buf + off) = __raw_readl(sock->addr
+ SOCK_MS_DATA);
length -= 4;
off += 4;
}
if (length
&& !(TIFM_MS_STAT_EMP & readl(sock->addr + SOCK_MS_STATUS))) {
host->io_word = readl(sock->addr + SOCK_MS_DATA);
for (host->io_pos = 4; host->io_pos; --host->io_pos) {
buf[off++] = host->io_word & 0xff;
host->io_word >>= 8;
length--;
fifo_offset++;
if (!length)
break;
}
if (!(fifo_offset & 3))
host->cmd_flags &= ~DATA_CARRY;
if (!length)
return;
}
do {
host->io_word = readl(sock->addr + SOCK_FIFO_ACCESS
+ fifo_offset);
cnt = 4;
while (length && cnt) {
buf[off++] = (host->io_word >> 8) & 0xff;
cnt--;
length--;
}
fifo_offset += 4 - cnt;
} while (length);
if (cnt)
host->cmd_flags |= DATA_CARRY;
kunmap_atomic(buf - page_off, KM_BIO_DST_IRQ);
return off;
}
static void tifm_ms_write_fifo(struct tifm_ms *host, unsigned int fifo_offset,
struct page *pg, unsigned int page_off,
unsigned int length)
static unsigned int tifm_ms_write_data(struct tifm_ms *host,
unsigned char *buf, unsigned int length)
{
struct tifm_dev *sock = host->dev;
unsigned int cnt = 0, off = 0;
unsigned char *buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + page_off;
unsigned int off = 0;
if (host->cmd_flags & DATA_CARRY) {
while (fifo_offset & 3) {
host->io_word |= buf[off++] << (8 * (fifo_offset & 3));
if (host->io_pos) {
while (host->io_pos < 4 && length) {
host->io_word |= buf[off++] << (host->io_pos * 8);
host->io_pos++;
length--;
fifo_offset++;
}
if (!(fifo_offset & 3)) {
writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS
+ fifo_offset - 4);
host->cmd_flags &= ~DATA_CARRY;
}
if (!length)
return;
}
do {
cnt = 4;
if (host->io_pos == 4
&& !(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) {
writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM),
sock->addr + SOCK_MS_SYSTEM);
writel(host->io_word, sock->addr + SOCK_MS_DATA);
host->io_pos = 0;
host->io_word = 0;
while (length && cnt) {
host->io_word |= buf[off++] << (4 - cnt);
cnt--;
length--;
}
fifo_offset += 4 - cnt;
if (!cnt)
writel(host->io_word, sock->addr + SOCK_FIFO_ACCESS
+ fifo_offset - 4);
} while (length);
if (cnt)
host->cmd_flags |= DATA_CARRY;
kunmap_atomic(buf - page_off, KM_BIO_SRC_IRQ);
}
static void tifm_ms_move_block(struct tifm_ms *host, unsigned int length)
{
unsigned int t_size;
unsigned int off = host->req->sg.offset + host->block_pos;
unsigned int p_off, p_cnt;
struct page *pg;
unsigned long flags;
dev_dbg(&host->dev->dev, "moving block\n");
local_irq_save(flags);
t_size = length;
while (t_size) {
pg = nth_page(sg_page(&host->req->sg), off >> PAGE_SHIFT);
p_off = offset_in_page(off);
p_cnt = PAGE_SIZE - p_off;
p_cnt = min(p_cnt, t_size);
if (host->req->data_dir == WRITE)
tifm_ms_write_fifo(host, length - t_size,
pg, p_off, p_cnt);
else
tifm_ms_read_fifo(host, length - t_size,
pg, p_off, p_cnt);
t_size -= p_cnt;
} else if (host->io_pos) {
return off;
}
local_irq_restore(flags);
}
static int tifm_ms_transfer_data(struct tifm_ms *host, int skip)
{
struct tifm_dev *sock = host->dev;
unsigned int length = host->req->sg.length - host->block_pos;
if (!length)
return 1;
return off;
if (length > TIFM_FIFO_SIZE)
length = TIFM_FIFO_SIZE;
if (!skip) {
tifm_ms_move_block(host, length);
host->block_pos += length;
while (!(TIFM_MS_STAT_FUL & readl(sock->addr + SOCK_MS_STATUS))) {
if (length < 4)
break;
writel(TIFM_MS_SYS_FDIR | readl(sock->addr + SOCK_MS_SYSTEM),
sock->addr + SOCK_MS_SYSTEM);
__raw_writel(*(unsigned int *)(buf + off),
sock->addr + SOCK_MS_DATA);
length -= 4;
off += 4;
}
if ((host->req->data_dir == READ)
&& (host->block_pos == host->req->sg.length))
return 1;
switch (length) {
case 3:
host->io_word |= buf[off + 2] << 16;
host->io_pos++;
case 2:
host->io_word |= buf[off + 1] << 8;
host->io_pos++;
case 1:
host->io_word |= buf[off];
host->io_pos++;
}
writel(ilog2(length) - 2, sock->addr + SOCK_FIFO_PAGE_SIZE);
if (host->req->data_dir == WRITE)
writel((1 << 8) | TIFM_DMA_TX, sock->addr + SOCK_DMA_CONTROL);
else
writel((1 << 8), sock->addr + SOCK_DMA_CONTROL);
off += host->io_pos;
return 0;
return off;
}
static unsigned int tifm_ms_transfer_data(struct tifm_ms *host)
{
struct tifm_dev *sock = host->dev;
unsigned int length;
unsigned int off;
unsigned int t_size, p_off, p_cnt;
unsigned char *buf;
struct page *pg;
unsigned long flags = 0;
if (host->req->long_data) {
length = host->req->sg.length - host->block_pos;
off = host->req->sg.offset + host->block_pos;
} else {
length = host->req->data_len - host->block_pos;
off = 0;
}
dev_dbg(&sock->dev, "fifo data transfer, %d, %d\n", length,
host->block_pos);
while (length) {
if (host->req->long_data) {
pg = nth_page(sg_page(&host->req->sg),
off >> PAGE_SHIFT);
p_off = offset_in_page(off);
p_cnt = PAGE_SIZE - p_off;
p_cnt = min(p_cnt, length);
local_irq_save(flags);
buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off;
} else {
buf = host->req->data + host->block_pos;
p_cnt = host->req->data_len - host->block_pos;
}
t_size = host->req->data_dir == WRITE
? tifm_ms_write_data(host, buf, p_cnt)
: tifm_ms_read_data(host, buf, p_cnt);
if (host->req->long_data) {
kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ);
local_irq_restore(flags);
}
if (!t_size)
break;
host->block_pos += t_size;
length -= t_size;
off += t_size;
}
dev_dbg(&sock->dev, "fifo data transfer, %d remaining\n", length);
if (!length && (host->req->data_dir == WRITE)) {
if (host->io_pos) {
writel(TIFM_MS_SYS_FDIR
| readl(sock->addr + SOCK_MS_SYSTEM),
sock->addr + SOCK_MS_SYSTEM);
writel(host->io_word, sock->addr + SOCK_MS_DATA);
}
writel(TIFM_MS_SYS_FDIR
| readl(sock->addr + SOCK_MS_SYSTEM),
sock->addr + SOCK_MS_SYSTEM);
writel(0, sock->addr + SOCK_MS_DATA);
} else {
readl(sock->addr + SOCK_MS_DATA);
}
return length;
}
static int tifm_ms_issue_cmd(struct tifm_ms *host)
{
struct tifm_dev *sock = host->dev;
unsigned char *data;
unsigned int data_len = 0, cmd = 0, cmd_mask = 0, cnt, tval = 0;
unsigned int data_len, cmd, sys_param;
host->cmd_flags = 0;
host->block_pos = 0;
host->io_pos = 0;
host->io_word = 0;
host->cmd_flags = 0;
if (host->req->io_type == MEMSTICK_IO_SG) {
if (!host->no_dma) {
if (1 != tifm_map_sg(sock, &host->req->sg, 1,
host->req->data_dir == READ
? PCI_DMA_FROMDEVICE
: PCI_DMA_TODEVICE)) {
host->req->error = -ENOMEM;
return host->req->error;
}
data_len = sg_dma_len(&host->req->sg);
} else
data_len = host->req->sg.length;
data = host->req->data;
host->use_dma = !no_dma;
if (host->req->long_data) {
data_len = host->req->sg.length;
if (!is_power_of_2(data_len))
host->use_dma = 0;
} else {
data_len = host->req->data_len;
host->use_dma = 0;
}
writel(TIFM_FIFO_INT_SETALL,
sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
writel(TIFM_FIFO_ENABLE,
sock->addr + SOCK_FIFO_CONTROL);
if (host->use_dma) {
if (1 != tifm_map_sg(sock, &host->req->sg, 1,
host->req->data_dir == READ
? PCI_DMA_FROMDEVICE
: PCI_DMA_TODEVICE)) {
host->req->error = -ENOMEM;
return host->req->error;
}
data_len = sg_dma_len(&host->req->sg);
writel(ilog2(data_len) - 2,
sock->addr + SOCK_FIFO_PAGE_SIZE);
writel(TIFM_FIFO_INTMASK,
sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
sys_param = TIFM_DMA_EN | (1 << 8);
if (host->req->data_dir == WRITE)
sys_param |= TIFM_DMA_TX;
writel(TIFM_FIFO_INT_SETALL,
sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
writel(TIFM_FIFO_ENABLE,
sock->addr + SOCK_FIFO_CONTROL);
writel(TIFM_FIFO_INTMASK,
sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
if (!host->no_dma) {
writel(ilog2(data_len) - 2,
sock->addr + SOCK_FIFO_PAGE_SIZE);
writel(sg_dma_address(&host->req->sg),
sock->addr + SOCK_DMA_ADDRESS);
if (host->req->data_dir == WRITE)
writel((1 << 8) | TIFM_DMA_TX | TIFM_DMA_EN,
sock->addr + SOCK_DMA_CONTROL);
else
writel((1 << 8) | TIFM_DMA_EN,
sock->addr + SOCK_DMA_CONTROL);
} else {
tifm_ms_transfer_data(host,
host->req->data_dir == READ);
}
writel(sg_dma_address(&host->req->sg),
sock->addr + SOCK_DMA_ADDRESS);
writel(sys_param, sock->addr + SOCK_DMA_CONTROL);
} else {
writel(host->mode_mask | TIFM_MS_SYS_FIFO,
sock->addr + SOCK_MS_SYSTEM);
cmd_mask = readl(sock->addr + SOCK_MS_SYSTEM);
cmd_mask |= TIFM_MS_SYS_DATA | TIFM_MS_SYS_NOT_RDY;
writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
} else if (host->req->io_type == MEMSTICK_IO_VAL) {
data = host->req->data;
data_len = host->req->data_len;
cmd_mask = host->mode_mask | 0x2607; /* unknown constant */
if (host->req->data_dir == WRITE) {
cmd_mask |= TIFM_MS_SYS_LATCH;
writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
for (cnt = 0; (data_len - cnt) >= 4; cnt += 4) {
writel(TIFM_MS_SYS_LATCH
| readl(sock->addr + SOCK_MS_SYSTEM),
sock->addr + SOCK_MS_SYSTEM);
__raw_writel(*(unsigned int *)(data + cnt),
sock->addr + SOCK_MS_DATA);
dev_dbg(&sock->dev, "writing %x\n",
*(int *)(data + cnt));
}
switch (data_len - cnt) {
case 3:
tval |= data[cnt + 2] << 16;
case 2:
tval |= data[cnt + 1] << 8;
case 1:
tval |= data[cnt];
writel(TIFM_MS_SYS_LATCH
| readl(sock->addr + SOCK_MS_SYSTEM),
sock->addr + SOCK_MS_SYSTEM);
writel(tval, sock->addr + SOCK_MS_DATA);
dev_dbg(&sock->dev, "writing %x\n", tval);
}
writel(TIFM_MS_SYS_LATCH
| readl(sock->addr + SOCK_MS_SYSTEM),
sock->addr + SOCK_MS_SYSTEM);
writel(0, sock->addr + SOCK_MS_DATA);
dev_dbg(&sock->dev, "writing %x\n", 0);
} else
writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
cmd_mask = readl(sock->addr + SOCK_MS_SYSTEM);
cmd_mask &= ~TIFM_MS_SYS_DATA;
cmd_mask |= TIFM_MS_SYS_NOT_RDY;
dev_dbg(&sock->dev, "mask %x\n", cmd_mask);
writel(cmd_mask, sock->addr + SOCK_MS_SYSTEM);
} else
BUG();
writel(TIFM_FIFO_MORE,
sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
}
mod_timer(&host->timer, jiffies + host->timeout_jiffies);
writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
sock->addr + SOCK_CONTROL);
host->req->error = 0;
sys_param = readl(sock->addr + SOCK_MS_SYSTEM);
sys_param |= TIFM_MS_SYS_INTCLR;
if (host->use_dma)
sys_param |= TIFM_MS_SYS_DMA;
else
sys_param &= ~TIFM_MS_SYS_DMA;
writel(sys_param, sock->addr + SOCK_MS_SYSTEM);
cmd = (host->req->tpc & 0xf) << 12;
cmd |= data_len;
writel(cmd, sock->addr + SOCK_MS_COMMAND);
dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, cmd_mask);
dev_dbg(&sock->dev, "executing TPC %x, %x\n", cmd, sys_param);
return 0;
}
@ -314,47 +336,20 @@ static void tifm_ms_complete_cmd(struct tifm_ms *host)
{
struct tifm_dev *sock = host->dev;
struct memstick_host *msh = tifm_get_drvdata(sock);
unsigned int tval = 0, data_len;
unsigned char *data;
int rc;
del_timer(&host->timer);
if (host->req->io_type == MEMSTICK_IO_SG) {
if (!host->no_dma)
tifm_unmap_sg(sock, &host->req->sg, 1,
host->req->data_dir == READ
? PCI_DMA_FROMDEVICE
: PCI_DMA_TODEVICE);
} else if (host->req->io_type == MEMSTICK_IO_VAL) {
writel(~TIFM_MS_SYS_DATA & readl(sock->addr + SOCK_MS_SYSTEM),
sock->addr + SOCK_MS_SYSTEM);
data = host->req->data;
data_len = host->req->data_len;
if (host->req->data_dir == READ) {
for (rc = 0; (data_len - rc) >= 4; rc += 4)
*(int *)(data + rc)
= __raw_readl(sock->addr
+ SOCK_MS_DATA);
if (data_len - rc)
tval = readl(sock->addr + SOCK_MS_DATA);
switch (data_len - rc) {
case 3:
data[rc + 2] = (tval >> 16) & 0xff;
case 2:
data[rc + 1] = (tval >> 8) & 0xff;
case 1:
data[rc] = tval & 0xff;
}
readl(sock->addr + SOCK_MS_DATA);
}
}
if (host->use_dma)
tifm_unmap_sg(sock, &host->req->sg, 1,
host->req->data_dir == READ
? PCI_DMA_FROMDEVICE
: PCI_DMA_TODEVICE);
writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
sock->addr + SOCK_CONTROL);
dev_dbg(&sock->dev, "TPC complete\n");
do {
rc = memstick_next_req(msh, &host->req);
} while (!rc && tifm_ms_issue_cmd(host));
@ -365,11 +360,10 @@ static int tifm_ms_check_status(struct tifm_ms *host)
if (!host->req->error) {
if (!(host->cmd_flags & CMD_READY))
return 1;
if ((host->req->io_type == MEMSTICK_IO_SG)
&& !(host->cmd_flags & FIFO_READY))
if (!(host->cmd_flags & FIFO_READY))
return 1;
if (host->req->need_card_int
&& !(host->cmd_flags & CARD_READY))
&& !(host->cmd_flags & CARD_INT))
return 1;
}
return 0;
@ -379,18 +373,24 @@ static int tifm_ms_check_status(struct tifm_ms *host)
static void tifm_ms_data_event(struct tifm_dev *sock)
{
struct tifm_ms *host;
unsigned int fifo_status = 0;
unsigned int fifo_status = 0, host_status = 0;
int rc = 1;
spin_lock(&sock->lock);
host = memstick_priv((struct memstick_host *)tifm_get_drvdata(sock));
fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
dev_dbg(&sock->dev, "data event: fifo_status %x, flags %x\n",
fifo_status, host->cmd_flags);
host_status = readl(sock->addr + SOCK_MS_STATUS);
dev_dbg(&sock->dev,
"data event: fifo_status %x, host_status %x, flags %x\n",
fifo_status, host_status, host->cmd_flags);
if (host->req) {
if (fifo_status & TIFM_FIFO_READY) {
if (!host->no_dma || tifm_ms_transfer_data(host, 0)) {
if (host->use_dma && (fifo_status & 1)) {
host->cmd_flags |= FIFO_READY;
rc = tifm_ms_check_status(host);
}
if (!host->use_dma && (fifo_status & TIFM_FIFO_MORE)) {
if (!tifm_ms_transfer_data(host)) {
host->cmd_flags |= FIFO_READY;
rc = tifm_ms_check_status(host);
}
@ -419,9 +419,9 @@ static void tifm_ms_card_event(struct tifm_dev *sock)
host_status, host->cmd_flags);
if (host->req) {
if (host_status & TIFM_MS_TIMEOUT)
if (host_status & TIFM_MS_STAT_TOE)
host->req->error = -ETIME;
else if (host_status & TIFM_MS_BADCRC)
else if (host_status & TIFM_MS_STAT_CRC)
host->req->error = -EILSEQ;
if (host->req->error) {
@ -430,18 +430,17 @@ static void tifm_ms_card_event(struct tifm_dev *sock)
writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
}
if (host_status & TIFM_MS_EOTPC)
if (host_status & TIFM_MS_STAT_RDY)
host->cmd_flags |= CMD_READY;
if (host_status & TIFM_MS_INT)
host->cmd_flags |= CARD_READY;
if (host_status & TIFM_MS_STAT_MSINT)
host->cmd_flags |= CARD_INT;
rc = tifm_ms_check_status(host);
}
writel(TIFM_MS_SYS_NOT_RDY | readl(sock->addr + SOCK_MS_SYSTEM),
sock->addr + SOCK_MS_SYSTEM);
writel((~TIFM_MS_SYS_DATA) & readl(sock->addr + SOCK_MS_SYSTEM),
writel(TIFM_MS_SYS_INTCLR | readl(sock->addr + SOCK_MS_SYSTEM),
sock->addr + SOCK_MS_SYSTEM);
if (!rc)
@ -497,15 +496,26 @@ static void tifm_ms_set_param(struct memstick_host *msh,
switch (param) {
case MEMSTICK_POWER:
/* this is set by card detection mechanism */
/* also affected by media detection mechanism */
if (value == MEMSTICK_POWER_ON) {
host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI;
writel(TIFM_MS_SYS_RESET, sock->addr + SOCK_MS_SYSTEM);
writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR,
sock->addr + SOCK_MS_SYSTEM);
writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
} else if (value == MEMSTICK_POWER_OFF) {
writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR,
sock->addr + SOCK_MS_SYSTEM);
writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
}
break;
case MEMSTICK_INTERFACE:
if (value == MEMSTICK_SERIAL) {
host->mode_mask = TIFM_MS_SERIAL;
host->mode_mask = TIFM_MS_SYS_SRAC | TIFM_MS_SYS_REI;
writel((~TIFM_CTRL_FAST_CLK)
& readl(sock->addr + SOCK_CONTROL),
sock->addr + SOCK_CONTROL);
} else if (value == MEMSTICK_PARALLEL) {
} else if (value == MEMSTICK_PAR4) {
host->mode_mask = 0;
writel(TIFM_CTRL_FAST_CLK
| readl(sock->addr + SOCK_CONTROL),
@ -532,21 +542,6 @@ static void tifm_ms_abort(unsigned long data)
tifm_eject(host->dev);
}
static int tifm_ms_initialize_host(struct tifm_ms *host)
{
struct tifm_dev *sock = host->dev;
struct memstick_host *msh = tifm_get_drvdata(sock);
host->mode_mask = TIFM_MS_SERIAL;
writel(0x8000, sock->addr + SOCK_MS_SYSTEM);
writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM);
writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
if (tifm_has_ms_pif(sock))
msh->caps |= MEMSTICK_CAP_PARALLEL;
return 0;
}
static int tifm_ms_probe(struct tifm_dev *sock)
{
struct memstick_host *msh;
@ -568,7 +563,6 @@ static int tifm_ms_probe(struct tifm_dev *sock)
tifm_set_drvdata(sock, msh);
host->dev = sock;
host->timeout_jiffies = msecs_to_jiffies(1000);
host->no_dma = no_dma;
setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host);
@ -576,10 +570,10 @@ static int tifm_ms_probe(struct tifm_dev *sock)
msh->set_param = tifm_ms_set_param;
sock->card_event = tifm_ms_card_event;
sock->data_event = tifm_ms_data_event;
rc = tifm_ms_initialize_host(host);
if (tifm_has_ms_pif(sock))
msh->caps |= MEMSTICK_CAP_PAR4;
if (!rc)
rc = memstick_add_host(msh);
rc = memstick_add_host(msh);
if (!rc)
return 0;
@ -601,7 +595,7 @@ static void tifm_ms_remove(struct tifm_dev *sock)
writel(TIFM_FIFO_INT_SETALL,
sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL);
if ((host->req->io_type == MEMSTICK_IO_SG) && !host->no_dma)
if (host->use_dma)
tifm_unmap_sg(sock, &host->req->sg, 1,
host->req->data_dir == READ
? PCI_DMA_TODEVICE
@ -617,10 +611,6 @@ static void tifm_ms_remove(struct tifm_dev *sock)
spin_unlock_irqrestore(&sock->lock, flags);
memstick_remove_host(msh);
writel(0x0200 | TIFM_MS_SYS_NOT_RDY, sock->addr + SOCK_MS_SYSTEM);
writel(0xffffffff, sock->addr + SOCK_MS_STATUS);
memstick_free_host(msh);
}
@ -628,17 +618,17 @@ static void tifm_ms_remove(struct tifm_dev *sock)
static int tifm_ms_suspend(struct tifm_dev *sock, pm_message_t state)
{
struct memstick_host *msh = tifm_get_drvdata(sock);
memstick_suspend_host(msh);
return 0;
}
static int tifm_ms_resume(struct tifm_dev *sock)
{
struct memstick_host *msh = tifm_get_drvdata(sock);
struct tifm_ms *host = memstick_priv(msh);
tifm_ms_initialize_host(host);
memstick_detect_change(msh);
memstick_resume_host(msh);
return 0;
}
@ -679,7 +669,6 @@ MODULE_AUTHOR("Alex Dubov");
MODULE_DESCRIPTION("TI FlashMedia MemoryStick driver");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(tifm, tifm_ms_id_tbl);
MODULE_VERSION(DRIVER_VERSION);
module_init(tifm_ms_init);
module_exit(tifm_ms_exit);

View file

@ -367,6 +367,8 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
if (rc)
goto err_out_irq;
writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
fm->addr + FM_SET_INTERRUPT_ENABLE);
return 0;

View file

@ -963,6 +963,7 @@ static int __init ebda_rsrc_controller (void)
bus_info_ptr1 = ibmphp_find_same_bus_num (hpc_ptr->slots[index].slot_bus_num);
if (!bus_info_ptr1) {
kfree(tmp_slot);
rc = -ENODEV;
goto error;
}

View file

@ -138,7 +138,7 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = {
{ /* end of list */ },
};
static struct of_platform_driver __devinitdata of_platform_serial_driver = {
static struct of_platform_driver of_platform_serial_driver = {
.owner = THIS_MODULE,
.name = "of_serial",
.probe = of_platform_serial_probe,

View file

@ -131,7 +131,7 @@ config USB_ATMEL_USBA
config USB_GADGET_FSL_USB2
boolean "Freescale Highspeed USB DR Peripheral Controller"
depends on MPC834x || PPC_MPC831x
depends on FSL_SOC
select USB_GADGET_DUALSPEED
help
Some of Freescale PowerPC processors have a High Speed

View file

@ -281,23 +281,44 @@ static void ehci_iaa_watchdog(unsigned long param)
{
struct ehci_hcd *ehci = (struct ehci_hcd *) param;
unsigned long flags;
u32 status, cmd;
spin_lock_irqsave (&ehci->lock, flags);
WARN_ON(!ehci->reclaim);
status = ehci_readl(ehci, &ehci->regs->status);
cmd = ehci_readl(ehci, &ehci->regs->command);
ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd);
/* Lost IAA irqs wedge things badly; seen first with a vt8235.
* So we need this watchdog, but must protect it against both
* (a) SMP races against real IAA firing and retriggering, and
* (b) clean HC shutdown, when IAA watchdog was pending.
*/
if (ehci->reclaim
&& !timer_pending(&ehci->iaa_watchdog)
&& HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
u32 cmd, status;
/* lost IAA irqs wedge things badly; seen first with a vt8235 */
if (ehci->reclaim) {
if (status & STS_IAA) {
ehci_vdbg (ehci, "lost IAA\n");
/* If we get here, IAA is *REALLY* late. It's barely
* conceivable that the system is so busy that CMD_IAAD
* is still legitimately set, so let's be sure it's
* clear before we read STS_IAA. (The HC should clear
* CMD_IAAD when it sets STS_IAA.)
*/
cmd = ehci_readl(ehci, &ehci->regs->command);
if (cmd & CMD_IAAD)
ehci_writel(ehci, cmd & ~CMD_IAAD,
&ehci->regs->command);
/* If IAA is set here it either legitimately triggered
* before we cleared IAAD above (but _way_ late, so we'll
* still count it as lost) ... or a silicon erratum:
* - VIA seems to set IAA without triggering the IRQ;
* - IAAD potentially cleared without setting IAA.
*/
status = ehci_readl(ehci, &ehci->regs->status);
if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
COUNT (ehci->stats.lost_iaa);
ehci_writel(ehci, STS_IAA, &ehci->regs->status);
}
ehci_writel(ehci, cmd & ~CMD_IAAD, &ehci->regs->command);
ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n",
status, cmd);
end_unlink_async(ehci);
}
@ -631,7 +652,7 @@ static int ehci_run (struct usb_hcd *hcd)
static irqreturn_t ehci_irq (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 status, pcd_status = 0;
u32 status, pcd_status = 0, cmd;
int bh;
spin_lock (&ehci->lock);
@ -652,7 +673,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
/* clear (just) interrupts */
ehci_writel(ehci, status, &ehci->regs->status);
ehci_readl(ehci, &ehci->regs->command); /* unblock posted write */
cmd = ehci_readl(ehci, &ehci->regs->command);
bh = 0;
#ifdef EHCI_VERBOSE_DEBUG
@ -673,8 +694,17 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
/* complete the unlinking of some qh [4.15.2.3] */
if (status & STS_IAA) {
COUNT (ehci->stats.reclaim);
end_unlink_async(ehci);
/* guard against (alleged) silicon errata */
if (cmd & CMD_IAAD) {
ehci_writel(ehci, cmd & ~CMD_IAAD,
&ehci->regs->command);
ehci_dbg(ehci, "IAA with IAAD still set?\n");
}
if (ehci->reclaim) {
COUNT(ehci->stats.reclaim);
end_unlink_async(ehci);
} else
ehci_dbg(ehci, "IAA with nothing to reclaim?\n");
}
/* remote wakeup [4.3.1] */
@ -781,7 +811,7 @@ static int ehci_urb_enqueue (
static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
/* failfast */
if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))
if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state) && ehci->reclaim)
end_unlink_async(ehci);
/* if it's not linked then there's nothing to do */

View file

@ -94,6 +94,7 @@ static struct usb_device_id id_table_earthmate [] = {
static struct usb_device_id id_table_cyphidcomrs232 [] = {
{ USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
{ USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
{ } /* Terminating entry */
};
@ -106,6 +107,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
{ USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
{ USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
{ USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
{ } /* Terminating entry */
};

View file

@ -19,6 +19,10 @@
#define VENDOR_ID_CYPRESS 0x04b4
#define PRODUCT_ID_CYPHIDCOM 0x5500
/* Powercom UPS, chip CY7C63723 */
#define VENDOR_ID_POWERCOM 0x0d9f
#define PRODUCT_ID_UPS 0x0002
/* Nokia CA-42 USB to serial cable */
#define VENDOR_ID_DAZZLE 0x07d0
#define PRODUCT_ID_CA42 0x4101

View file

@ -359,6 +359,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
{ USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) },
{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID),

View file

@ -557,6 +557,9 @@
#define TML_VID 0x1B91 /* Vendor ID */
#define TML_USB_SERIAL_PID 0x0064 /* USB - Serial Converter */
/* Propox devices */
#define FTDI_PROPOX_JTAGCABLEII_PID 0xD738
/* Commands */
#define FTDI_SIO_RESET 0 /* Reset the port */
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */

View file

@ -323,7 +323,7 @@ static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
room = tty_buffer_request_room(tty, urb->actual_length);
if (room) {
tty_insert_flip_string(tty, urb->transfer_buffer, room);
tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
tty_flip_buffer_push(tty);
}
}
@ -349,10 +349,12 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb)
/* Throttle the device if requested by tty */
spin_lock_irqsave(&port->lock, flags);
if (!(port->throttled = port->throttle_req))
/* Handle data and continue reading from device */
if (!(port->throttled = port->throttle_req)) {
spin_unlock_irqrestore(&port->lock, flags);
flush_and_resubmit_read_urb(port);
spin_unlock_irqrestore(&port->lock, flags);
} else {
spin_unlock_irqrestore(&port->lock, flags);
}
}
EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);

View file

@ -111,6 +111,42 @@ static int option_send_setup(struct usb_serial_port *port);
#define HUAWEI_PRODUCT_E220BIS 0x1004
#define NOVATELWIRELESS_VENDOR_ID 0x1410
/* MERLIN EVDO PRODUCTS */
#define NOVATELWIRELESS_PRODUCT_V640 0x1100
#define NOVATELWIRELESS_PRODUCT_V620 0x1110
#define NOVATELWIRELESS_PRODUCT_V740 0x1120
#define NOVATELWIRELESS_PRODUCT_V720 0x1130
/* MERLIN HSDPA/HSPA PRODUCTS */
#define NOVATELWIRELESS_PRODUCT_U730 0x1400
#define NOVATELWIRELESS_PRODUCT_U740 0x1410
#define NOVATELWIRELESS_PRODUCT_U870 0x1420
#define NOVATELWIRELESS_PRODUCT_XU870 0x1430
#define NOVATELWIRELESS_PRODUCT_X950D 0x1450
/* EXPEDITE PRODUCTS */
#define NOVATELWIRELESS_PRODUCT_EV620 0x2100
#define NOVATELWIRELESS_PRODUCT_ES720 0x2110
#define NOVATELWIRELESS_PRODUCT_E725 0x2120
#define NOVATELWIRELESS_PRODUCT_EU730 0x2400
#define NOVATELWIRELESS_PRODUCT_EU740 0x2410
#define NOVATELWIRELESS_PRODUCT_EU870D 0x2420
/* OVATION PRODUCTS */
#define NOVATELWIRELESS_PRODUCT_MC727 0x4100
#define NOVATELWIRELESS_PRODUCT_MC950D 0x4400
/* FUTURE NOVATEL PRODUCTS */
#define NOVATELWIRELESS_PRODUCT_EVDO_1 0x6000
#define NOVATELWIRELESS_PRODUCT_HSPA_1 0x7000
#define NOVATELWIRELESS_PRODUCT_EMBEDDED_1 0x8000
#define NOVATELWIRELESS_PRODUCT_GLOBAL_1 0x9000
#define NOVATELWIRELESS_PRODUCT_EVDO_2 0x6001
#define NOVATELWIRELESS_PRODUCT_HSPA_2 0x7001
#define NOVATELWIRELESS_PRODUCT_EMBEDDED_2 0x8001
#define NOVATELWIRELESS_PRODUCT_GLOBAL_2 0x9001
#define DELL_VENDOR_ID 0x413C
#define KYOCERA_VENDOR_ID 0x0c88
@ -168,21 +204,34 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1100) }, /* Novatel Merlin XS620/S640 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1110) }, /* Novatel Merlin S620 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1120) }, /* Novatel Merlin EX720 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1130) }, /* Novatel Merlin S720 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1400) }, /* Novatel U730 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1410) }, /* Novatel U740 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1420) }, /* Novatel EU870 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2100) }, /* Novatel EV620 CDMA/EV-DO */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2110) }, /* Novatel Merlin ES620 / Merlin ES720 / Ovation U720 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, /* Novatel Merlin EX720/V740/X720 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V720) }, /* Novatel Merlin V720/S720/PC720 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U730) }, /* Novatel U730/U740 (VF version) */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U740) }, /* Novatel U740 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U870) }, /* Novatel U870 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_XU870) }, /* Novatel Merlin XU870 HSDPA/3G */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_X950D) }, /* Novatel X950D */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EV620) }, /* Novatel EV620/ES620 CDMA/EV-DO */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES720) }, /* Novatel ES620/ES720/U720/USB720 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E725) }, /* Novatel E725/E726 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2130) }, /* Novatel Merlin ES620 SM Bus */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x2410) }, /* Novatel EU740 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x4100) }, /* Novatel U727 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x4400) }, /* Novatel MC950 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU730) }, /* Novatel EU730 and Vodafone EU740 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU740) }, /* Novatel non-Vodafone EU740 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x5010) }, /* Novatel U727 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_1) }, /* Novatel EVDO product */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_1) }, /* Novatel HSPA product */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EMBEDDED_1) }, /* Novatel Embedded product */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_GLOBAL_1) }, /* Novatel Global product */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_2) }, /* Novatel EVDO product */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_2) }, /* Novatel HSPA product */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EMBEDDED_2) }, /* Novatel Embedded product */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_GLOBAL_2) }, /* Novatel Global product */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8114) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite EV620 CDMA/EV-DO */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8115) }, /* Dell Wireless 5500 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
{ USB_DEVICE(DELL_VENDOR_ID, 0x8116) }, /* Dell Wireless 5505 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */

View file

@ -522,8 +522,8 @@ int sddr55_reset(struct us_data *us) {
static unsigned long sddr55_get_capacity(struct us_data *us) {
unsigned char manufacturerID;
unsigned char deviceID;
unsigned char uninitialized_var(manufacturerID);
unsigned char uninitialized_var(deviceID);
int result;
struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;

View file

@ -553,6 +553,19 @@ config FB_BF54X_LQ043
help
This is the framebuffer device driver for a SHARP LQ043T1DG01 TFT LCD
config FB_BFIN_T350MCQB
tristate "Varitronix COG-T350MCQB TFT LCD display (BF527 EZKIT)"
depends on FB && BLACKFIN
select BFIN_GPTIMERS
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
help
This is the framebuffer device driver for a Varitronix VL-PS-COG-T350MCQB-01 display TFT LCD
This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI
It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK.
config FB_STI
tristate "HP STI frame buffer device support"
depends on FB && PARISC

View file

@ -122,6 +122,7 @@ obj-$(CONFIG_FB_EFI) += efifb.o
obj-$(CONFIG_FB_VGA16) += vga16fb.o
obj-$(CONFIG_FB_OF) += offb.o
obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o
obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o
# the test framebuffer is last
obj-$(CONFIG_FB_VIRTUAL) += vfb.o

View file

@ -8,7 +8,7 @@
*
*
* Modified:
* Copyright 2004-2007 Analog Devices Inc.
* Copyright 2007-2008 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
@ -241,7 +241,7 @@ static int request_ports(struct bfin_bf54xfb_info *fbi)
u16 eppi_req_18[] = EPPI0_18;
u16 disp = fbi->mach_info->disp;
if (gpio_request(disp, NULL)) {
if (gpio_request(disp, DRIVER_NAME)) {
printk(KERN_ERR "Requesting GPIO %d faild\n", disp);
return -EFAULT;
}
@ -672,7 +672,7 @@ static int __init bfin_bf54x_probe(struct platform_device *pdev)
&bfin_lq043fb_bl_ops);
bl_dev->props.max_brightness = 255;
lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops);
lcd_dev = lcd_device_register(DRIVER_NAME, &pdev->dev, NULL, &bfin_lcd_ops);
lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n");
#endif

View file

@ -0,0 +1,685 @@
/*
* File: drivers/video/bfin-t350mcqb-fb.c
* Based on:
* Author: Michael Hennerich <hennerich@blackfin.uclinux.org>
*
* Created:
* Description: Blackfin LCD Framebufer driver
*
*
* Modified:
* Copyright 2004-2007 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
* This program 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 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; if not, see the file COPYING, or write
* to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/backlight.h>
#include <linux/lcd.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <asm/blackfin.h>
#include <asm/irq.h>
#include <asm/dma-mapping.h>
#include <asm/dma.h>
#include <asm/portmux.h>
#include <asm/gptimers.h>
#define NO_BL_SUPPORT
#define LCD_X_RES 320 /* Horizontal Resolution */
#define LCD_Y_RES 240 /* Vertical Resolution */
#define LCD_BPP 24 /* Bit Per Pixel */
#define DMA_BUS_SIZE 16
#define LCD_CLK (12*1000*1000) /* 12MHz */
#define CLOCKS_PER_PIX 3
/*
* HS and VS timing parameters (all in number of PPI clk ticks)
*/
#define U_LINE 1 /* Blanking Lines */
#define H_ACTPIX (LCD_X_RES * CLOCKS_PER_PIX) /* active horizontal pixel */
#define H_PERIOD (408 * CLOCKS_PER_PIX) /* HS period */
#define H_PULSE 90 /* HS pulse width */
#define H_START 204 /* first valid pixel */
#define V_LINES (LCD_Y_RES + U_LINE) /* total vertical lines */
#define V_PULSE (3 * H_PERIOD) /* VS pulse width (1-5 H_PERIODs) */
#define V_PERIOD (H_PERIOD * V_LINES) /* VS period */
#define ACTIVE_VIDEO_MEM_OFFSET (U_LINE * H_ACTPIX)
#define BFIN_LCD_NBR_PALETTE_ENTRIES 256
#define DRIVER_NAME "bfin-t350mcqb"
static char driver_name[] = DRIVER_NAME;
struct bfin_t350mcqbfb_info {
struct fb_info *fb;
struct device *dev;
unsigned char *fb_buffer; /* RGB Buffer */
dma_addr_t dma_handle;
int lq043_mmap;
int lq043_open_cnt;
int irq;
spinlock_t lock; /* lock */
};
static int nocursor;
module_param(nocursor, int, 0644);
MODULE_PARM_DESC(nocursor, "cursor enable/disable");
#define PPI_TX_MODE 0x2
#define PPI_XFER_TYPE_11 0xC
#define PPI_PORT_CFG_01 0x10
#define PPI_PACK_EN 0x80
#define PPI_POLS_1 0x8000
static void bfin_t350mcqb_config_ppi(struct bfin_t350mcqbfb_info *fbi)
{
bfin_write_PPI_DELAY(H_START);
bfin_write_PPI_COUNT(H_ACTPIX-1);
bfin_write_PPI_FRAME(V_LINES);
bfin_write_PPI_CONTROL(PPI_TX_MODE | /* output mode , PORT_DIR */
PPI_XFER_TYPE_11 | /* sync mode XFR_TYPE */
PPI_PORT_CFG_01 | /* two frame sync PORT_CFG */
PPI_PACK_EN | /* packing enabled PACK_EN */
PPI_POLS_1); /* faling edge syncs POLS */
}
static inline void bfin_t350mcqb_disable_ppi(void)
{
bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() & ~PORT_EN);
}
static inline void bfin_t350mcqb_enable_ppi(void)
{
bfin_write_PPI_CONTROL(bfin_read_PPI_CONTROL() | PORT_EN);
}
static void bfin_t350mcqb_start_timers(void)
{
unsigned long flags;
local_irq_save(flags);
enable_gptimers(TIMER1bit);
enable_gptimers(TIMER0bit);
local_irq_restore(flags);
}
static void bfin_t350mcqb_stop_timers(void)
{
disable_gptimers(TIMER0bit | TIMER1bit);
set_gptimer_status(0, TIMER_STATUS_TRUN0 | TIMER_STATUS_TRUN1 |
TIMER_STATUS_TIMIL0 | TIMER_STATUS_TIMIL1 |
TIMER_STATUS_TOVF0 | TIMER_STATUS_TOVF1);
}
static void bfin_t350mcqb_init_timers(void)
{
bfin_t350mcqb_stop_timers();
set_gptimer_period(TIMER0_id, H_PERIOD);
set_gptimer_pwidth(TIMER0_id, H_PULSE);
set_gptimer_config(TIMER0_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
TIMER_TIN_SEL | TIMER_CLK_SEL|
TIMER_EMU_RUN);
set_gptimer_period(TIMER1_id, V_PERIOD);
set_gptimer_pwidth(TIMER1_id, V_PULSE);
set_gptimer_config(TIMER1_id, TIMER_MODE_PWM | TIMER_PERIOD_CNT |
TIMER_TIN_SEL | TIMER_CLK_SEL |
TIMER_EMU_RUN);
}
static void bfin_t350mcqb_config_dma(struct bfin_t350mcqbfb_info *fbi)
{
set_dma_config(CH_PPI,
set_bfin_dma_config(DIR_READ, DMA_FLOW_AUTO,
INTR_DISABLE, DIMENSION_2D,
DATA_SIZE_16,
DMA_NOSYNC_KEEP_DMA_BUF));
set_dma_x_count(CH_PPI, (LCD_X_RES * LCD_BPP) / DMA_BUS_SIZE);
set_dma_x_modify(CH_PPI, DMA_BUS_SIZE / 8);
set_dma_y_count(CH_PPI, V_LINES);
set_dma_y_modify(CH_PPI, DMA_BUS_SIZE / 8);
set_dma_start_addr(CH_PPI, (unsigned long)fbi->fb_buffer);
}
static int bfin_t350mcqb_request_ports(int action)
{
u16 ppi0_req_8[] = {P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
P_PPI0_D0, P_PPI0_D1, P_PPI0_D2,
P_PPI0_D3, P_PPI0_D4, P_PPI0_D5,
P_PPI0_D6, P_PPI0_D7, 0};
if (action) {
if (peripheral_request_list(ppi0_req_8, DRIVER_NAME)) {
printk(KERN_ERR "Requesting Peripherals faild\n");
return -EFAULT;
}
} else
peripheral_free_list(ppi0_req_8);
return 0;
}
static int bfin_t350mcqb_fb_open(struct fb_info *info, int user)
{
struct bfin_t350mcqbfb_info *fbi = info->par;
spin_lock(&fbi->lock);
fbi->lq043_open_cnt++;
if (fbi->lq043_open_cnt <= 1) {
bfin_t350mcqb_disable_ppi();
SSYNC();
bfin_t350mcqb_config_dma(fbi);
bfin_t350mcqb_config_ppi(fbi);
bfin_t350mcqb_init_timers();
/* start dma */
enable_dma(CH_PPI);
bfin_t350mcqb_enable_ppi();
bfin_t350mcqb_start_timers();
}
spin_unlock(&fbi->lock);
return 0;
}
static int bfin_t350mcqb_fb_release(struct fb_info *info, int user)
{
struct bfin_t350mcqbfb_info *fbi = info->par;
spin_lock(&fbi->lock);
fbi->lq043_open_cnt--;
fbi->lq043_mmap = 0;
if (fbi->lq043_open_cnt <= 0) {
bfin_t350mcqb_disable_ppi();
SSYNC();
disable_dma(CH_PPI);
bfin_t350mcqb_stop_timers();
memset(fbi->fb_buffer, 0, info->fix.smem_len);
}
spin_unlock(&fbi->lock);
return 0;
}
static int bfin_t350mcqb_fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
if (var->bits_per_pixel != LCD_BPP) {
pr_debug("%s: depth not supported: %u BPP\n", __FUNCTION__,
var->bits_per_pixel);
return -EINVAL;
}
if (info->var.xres != var->xres || info->var.yres != var->yres ||
info->var.xres_virtual != var->xres_virtual ||
info->var.yres_virtual != var->yres_virtual) {
pr_debug("%s: Resolution not supported: X%u x Y%u \n",
__FUNCTION__, var->xres, var->yres);
return -EINVAL;
}
/*
* Memory limit
*/
if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
pr_debug("%s: Memory Limit requested yres_virtual = %u\n",
__FUNCTION__, var->yres_virtual);
return -ENOMEM;
}
return 0;
}
static int bfin_t350mcqb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct bfin_t350mcqbfb_info *fbi = info->par;
if (fbi->lq043_mmap)
return -1;
spin_lock(&fbi->lock);
fbi->lq043_mmap = 1;
spin_unlock(&fbi->lock);
vma->vm_start = (unsigned long)(fbi->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET);
vma->vm_end = vma->vm_start + info->fix.smem_len;
/* For those who don't understand how mmap works, go read
* Documentation/nommu-mmap.txt.
* For those that do, you will know that the VM_MAYSHARE flag
* must be set in the vma->vm_flags structure on noMMU
* Other flags can be set, and are documented in
* include/linux/mm.h
*/
vma->vm_flags |= VM_MAYSHARE;
return 0;
}
int bfin_t350mcqb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
if (nocursor)
return 0;
else
return -EINVAL; /* just to force soft_cursor() call */
}
static int bfin_t350mcqb_fb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp,
struct fb_info *info)
{
if (regno >= BFIN_LCD_NBR_PALETTE_ENTRIES)
return -EINVAL;
if (info->var.grayscale) {
/* grayscale = 0.30*R + 0.59*G + 0.11*B */
red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
}
if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
u32 value;
/* Place color in the pseudopalette */
if (regno > 16)
return -EINVAL;
red >>= (16 - info->var.red.length);
green >>= (16 - info->var.green.length);
blue >>= (16 - info->var.blue.length);
value = (red << info->var.red.offset) |
(green << info->var.green.offset) |
(blue << info->var.blue.offset);
value &= 0xFFFFFF;
((u32 *) (info->pseudo_palette))[regno] = value;
}
return 0;
}
static struct fb_ops bfin_t350mcqb_fb_ops = {
.owner = THIS_MODULE,
.fb_open = bfin_t350mcqb_fb_open,
.fb_release = bfin_t350mcqb_fb_release,
.fb_check_var = bfin_t350mcqb_fb_check_var,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_mmap = bfin_t350mcqb_fb_mmap,
.fb_cursor = bfin_t350mcqb_fb_cursor,
.fb_setcolreg = bfin_t350mcqb_fb_setcolreg,
};
#ifndef NO_BL_SUPPORT
static int bl_get_brightness(struct backlight_device *bd)
{
return 0;
}
static struct backlight_ops bfin_lq043fb_bl_ops = {
.get_brightness = bl_get_brightness,
};
static struct backlight_device *bl_dev;
static int bfin_lcd_get_power(struct lcd_device *dev)
{
return 0;
}
static int bfin_lcd_set_power(struct lcd_device *dev, int power)
{
return 0;
}
static int bfin_lcd_get_contrast(struct lcd_device *dev)
{
return 0;
}
static int bfin_lcd_set_contrast(struct lcd_device *dev, int contrast)
{
return 0;
}
static int bfin_lcd_check_fb(struct fb_info *fi)
{
if (!fi || (fi == &bfin_t350mcqb_fb))
return 1;
return 0;
}
static struct lcd_ops bfin_lcd_ops = {
.get_power = bfin_lcd_get_power,
.set_power = bfin_lcd_set_power,
.get_contrast = bfin_lcd_get_contrast,
.set_contrast = bfin_lcd_set_contrast,
.check_fb = bfin_lcd_check_fb,
};
static struct lcd_device *lcd_dev;
#endif
static irqreturn_t bfin_t350mcqb_irq_error(int irq, void *dev_id)
{
/*struct bfin_t350mcqbfb_info *info = (struct bfin_t350mcqbfb_info *)dev_id;*/
u16 status = bfin_read_PPI_STATUS();
bfin_write_PPI_STATUS(0xFFFF);
if (status) {
bfin_t350mcqb_disable_ppi();
disable_dma(CH_PPI);
/* start dma */
enable_dma(CH_PPI);
bfin_t350mcqb_enable_ppi();
bfin_write_PPI_STATUS(0xFFFF);
}
return IRQ_HANDLED;
}
static int __init bfin_t350mcqb_probe(struct platform_device *pdev)
{
struct bfin_t350mcqbfb_info *info;
struct fb_info *fbinfo;
int ret;
printk(KERN_INFO DRIVER_NAME ": %dx%d %d-bit RGB FrameBuffer initializing...\n",
LCD_X_RES, LCD_Y_RES, LCD_BPP);
if (request_dma(CH_PPI, "CH_PPI") < 0) {
printk(KERN_ERR DRIVER_NAME
": couldn't request CH_PPI DMA\n");
ret = -EFAULT;
goto out1;
}
fbinfo =
framebuffer_alloc(sizeof(struct bfin_t350mcqbfb_info), &pdev->dev);
if (!fbinfo) {
ret = -ENOMEM;
goto out2;
}
info = fbinfo->par;
info->fb = fbinfo;
info->dev = &pdev->dev;
platform_set_drvdata(pdev, fbinfo);
strcpy(fbinfo->fix.id, driver_name);
fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
fbinfo->fix.type_aux = 0;
fbinfo->fix.xpanstep = 0;
fbinfo->fix.ypanstep = 0;
fbinfo->fix.ywrapstep = 0;
fbinfo->fix.accel = FB_ACCEL_NONE;
fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
fbinfo->var.nonstd = 0;
fbinfo->var.activate = FB_ACTIVATE_NOW;
fbinfo->var.height = -1;
fbinfo->var.width = -1;
fbinfo->var.accel_flags = 0;
fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
fbinfo->var.xres = LCD_X_RES;
fbinfo->var.xres_virtual = LCD_X_RES;
fbinfo->var.yres = LCD_Y_RES;
fbinfo->var.yres_virtual = LCD_Y_RES;
fbinfo->var.bits_per_pixel = LCD_BPP;
fbinfo->var.red.offset = 0;
fbinfo->var.green.offset = 8;
fbinfo->var.blue.offset = 16;
fbinfo->var.transp.offset = 0;
fbinfo->var.red.length = 8;
fbinfo->var.green.length = 8;
fbinfo->var.blue.length = 8;
fbinfo->var.transp.length = 0;
fbinfo->fix.smem_len = LCD_X_RES * LCD_Y_RES * LCD_BPP / 8;
fbinfo->fix.line_length = fbinfo->var.xres_virtual *
fbinfo->var.bits_per_pixel / 8;
fbinfo->fbops = &bfin_t350mcqb_fb_ops;
fbinfo->flags = FBINFO_FLAG_DEFAULT;
info->fb_buffer =
dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle,
GFP_KERNEL);
if (NULL == info->fb_buffer) {
printk(KERN_ERR DRIVER_NAME
": couldn't allocate dma buffer.\n");
ret = -ENOMEM;
goto out3;
}
memset(info->fb_buffer, 0, fbinfo->fix.smem_len);
fbinfo->screen_base = (void *)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
fbinfo->fix.smem_start = (int)info->fb_buffer + ACTIVE_VIDEO_MEM_OFFSET;
fbinfo->fbops = &bfin_t350mcqb_fb_ops;
fbinfo->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
if (!fbinfo->pseudo_palette) {
printk(KERN_ERR DRIVER_NAME
"Fail to allocate pseudo_palette\n");
ret = -ENOMEM;
goto out4;
}
memset(fbinfo->pseudo_palette, 0, sizeof(u32) * 16);
if (fb_alloc_cmap(&fbinfo->cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0)
< 0) {
printk(KERN_ERR DRIVER_NAME
"Fail to allocate colormap (%d entries)\n",
BFIN_LCD_NBR_PALETTE_ENTRIES);
ret = -EFAULT;
goto out5;
}
if (bfin_t350mcqb_request_ports(1)) {
printk(KERN_ERR DRIVER_NAME ": couldn't request gpio port.\n");
ret = -EFAULT;
goto out6;
}
info->irq = platform_get_irq(pdev, 0);
if (info->irq < 0) {
ret = -EINVAL;
goto out7;
}
if (request_irq(info->irq, (void *)bfin_t350mcqb_irq_error, IRQF_DISABLED,
"PPI ERROR", info) < 0) {
printk(KERN_ERR DRIVER_NAME
": unable to request PPI ERROR IRQ\n");
ret = -EFAULT;
goto out7;
}
if (register_framebuffer(fbinfo) < 0) {
printk(KERN_ERR DRIVER_NAME
": unable to register framebuffer.\n");
ret = -EINVAL;
goto out8;
}
#ifndef NO_BL_SUPPORT
bl_dev =
backlight_device_register("bf52x-bl", NULL, NULL,
&bfin_lq043fb_bl_ops);
bl_dev->props.max_brightness = 255;
lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops);
lcd_dev->props.max_contrast = 255, printk(KERN_INFO "Done.\n");
#endif
return 0;
out8:
free_irq(info->irq, info);
out7:
bfin_t350mcqb_request_ports(0);
out6:
fb_dealloc_cmap(&fbinfo->cmap);
out5:
kfree(fbinfo->pseudo_palette);
out4:
dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
info->dma_handle);
out3:
framebuffer_release(fbinfo);
out2:
free_dma(CH_PPI);
out1:
platform_set_drvdata(pdev, NULL);
return ret;
}
static int bfin_t350mcqb_remove(struct platform_device *pdev)
{
struct fb_info *fbinfo = platform_get_drvdata(pdev);
struct bfin_t350mcqbfb_info *info = fbinfo->par;
free_dma(CH_PPI);
free_irq(info->irq, info);
if (info->fb_buffer != NULL)
dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
info->dma_handle);
kfree(fbinfo->pseudo_palette);
fb_dealloc_cmap(&fbinfo->cmap);
#ifndef NO_BL_SUPPORT
lcd_device_unregister(lcd_dev);
backlight_device_unregister(bl_dev);
#endif
unregister_framebuffer(fbinfo);
bfin_t350mcqb_request_ports(0);
printk(KERN_INFO DRIVER_NAME ": Unregister LCD driver.\n");
return 0;
}
#ifdef CONFIG_PM
static int bfin_t350mcqb_suspend(struct platform_device *pdev, pm_message_t state)
{
struct fb_info *fbinfo = platform_get_drvdata(pdev);
struct bfin_t350mcqbfb_info *info = fbinfo->par;
bfin_t350mcqb_disable_ppi();
disable_dma(CH_PPI);
bfin_write_PPI_STATUS(0xFFFF);
return 0;
}
static int bfin_t350mcqb_resume(struct platform_device *pdev)
{
struct fb_info *fbinfo = platform_get_drvdata(pdev);
struct bfin_t350mcqbfb_info *info = fbinfo->par;
enable_dma(CH_PPI);
bfin_t350mcqb_enable_ppi();
return 0;
}
#else
#define bfin_t350mcqb_suspend NULL
#define bfin_t350mcqb_resume NULL
#endif
static struct platform_driver bfin_t350mcqb_driver = {
.probe = bfin_t350mcqb_probe,
.remove = bfin_t350mcqb_remove,
.suspend = bfin_t350mcqb_suspend,
.resume = bfin_t350mcqb_resume,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
};
static int __devinit bfin_t350mcqb_driver_init(void)
{
return platform_driver_register(&bfin_t350mcqb_driver);
}
static void __exit bfin_t350mcqb_driver_cleanup(void)
{
platform_driver_unregister(&bfin_t350mcqb_driver);
}
MODULE_DESCRIPTION("Blackfin TFT LCD Driver");
MODULE_LICENSE("GPL");
module_init(bfin_t350mcqb_driver_init);
module_exit(bfin_t350mcqb_driver_cleanup);

View file

@ -889,7 +889,7 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
struct mbxfb_info *mfbi;
struct mbxfb_platform_data *pdata;
dev_dbg(dev, "mbxfb_probe\n");
dev_dbg(&dev->dev, "mbxfb_probe\n");
pdata = dev->dev.platform_data;
if (!pdata) {

View file

@ -505,16 +505,24 @@ ngleSetupAttrPlanes(struct stifb_info *fb, int BufferNumber)
static void
rattlerSetupPlanes(struct stifb_info *fb)
{
int saved_id, y;
/* Write RAMDAC pixel read mask register so all overlay
* planes are display-enabled. (CRX24 uses Bt462 pixel
* read mask register for overlay planes, not image planes).
*/
CRX24_SETUP_RAMDAC(fb);
/* replacement for: SETUP_FB(fb, CRX24_OVERLAY_PLANES); */
WRITE_WORD(0x83000300, fb, REG_14);
SETUP_HW(fb);
WRITE_BYTE(1, fb, REG_16b1);
/* change fb->id temporarily to fool SETUP_FB() */
saved_id = fb->id;
fb->id = CRX24_OVERLAY_PLANES;
SETUP_FB(fb);
fb->id = saved_id;
for (y = 0; y < fb->info.var.yres; ++y)
memset(fb->info.screen_base + y * fb->info.fix.line_length,
0xff, fb->info.var.xres * fb->info.var.bits_per_pixel/8);
fb_memset((void*)fb->info.fix.smem_start, 0xff,
fb->info.var.yres*fb->info.fix.line_length);
CRX24_SET_OVLY_MASK(fb);
SETUP_FB(fb);
}

View file

@ -566,44 +566,32 @@ static inline void write3CE(int reg, unsigned char val)
static void enable_mmio(void)
{
unsigned char tmp;
/* Goto New Mode */
outb(0x0B, 0x3C4);
inb(0x3C5);
/* Unprotect registers */
outb(NewMode1, 0x3C4);
tmp = inb(0x3C5);
outb(0x80, 0x3C5);
/* Enable MMIO */
outb(PCIReg, 0x3D4);
outb(inb(0x3D5) | 0x01, 0x3D5);
t_outb(NewMode1, 0x3C4);
t_outb(tmp, 0x3C5);
}
static void disable_mmio(void)
{
unsigned char tmp;
/* Goto New Mode */
t_outb(0x0B, 0x3C4);
t_inb(0x3C5);
/* Unprotect registers */
t_outb(NewMode1, 0x3C4);
tmp = t_inb(0x3C5);
t_outb(0x80, 0x3C5);
/* Disable MMIO */
t_outb(PCIReg, 0x3D4);
t_outb(t_inb(0x3D5) & ~0x01, 0x3D5);
outb(NewMode1, 0x3C4);
outb(tmp, 0x3C5);
}
#define crtc_unlock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F)
@ -757,7 +745,7 @@ static unsigned int __devinit get_memsize(void)
switch (tmp) {
case 0x01:
k = 512;
k = 512 * Kb;
break;
case 0x02:
k = 6 * Mb; /* XP */

View file

@ -59,9 +59,9 @@ static int ticks = 10000;
static struct {
struct completion stop;
volatile int running;
int running;
struct timer_list timer;
volatile int queue;
int queue;
int default_ticks;
unsigned long inuse;
} cpu5wdt_device;

View file

@ -58,41 +58,6 @@ struct bios32_service_dir {
u8 reserved[5];
};
/*
* smbios_entry_point - defines SMBIOS entry point structure
*
* anchor[4] - anchor string (_SM_)
* checksum - checksum of the entry point structure
* length - length of the entry point structure
* major_ver - major version (02h for revision 2.1)
* minor_ver - minor version (01h for revision 2.1)
* max_struct_size - size of the largest SMBIOS structure
* revision - entry point structure revision implemented
* formatted_area[5] - reserved
* intermediate_anchor[5] - intermediate anchor string (_DMI_)
* intermediate_checksum - intermediate checksum
* table_length - structure table length
* table_address - structure table address
* table_num_structs - number of SMBIOS structures present
* bcd_revision - BCD revision
*/
struct smbios_entry_point {
u8 anchor[4];
u8 checksum;
u8 length;
u8 major_ver;
u8 minor_ver;
u16 max_struct_size;
u8 revision;
u8 formatted_area[5];
u8 intermediate_anchor[5];
u8 intermediate_checksum;
u16 table_length;
u64 table_address;
u16 table_num_structs;
u8 bcd_revision;
};
/* type 212 */
struct smbios_cru64_info {
u8 type;
@ -175,31 +140,13 @@ static struct pci_device_id hpwdt_devices[] = {
};
MODULE_DEVICE_TABLE(pci, hpwdt_devices);
/*
* bios_checksum
*/
static int __devinit bios_checksum(const char __iomem *ptr, int len)
{
char sum = 0;
int i;
/*
* calculate checksum of size bytes. This should add up
* to zero if we have a valid header.
*/
for (i = 0; i < len; i++)
sum += ptr[i];
return ((sum == 0) && (len > 0));
}
#ifndef CONFIG_X86_64
/* --32 Bit Bios------------------------------------------------------------ */
#define HPWDT_ARCH 32
asmlinkage void asminline_call(struct cmn_registers *pi86Regs,
unsigned long *pRomEntry)
static void asminline_call(struct cmn_registers *pi86Regs,
unsigned long *pRomEntry)
{
asm("pushl %ebp \n\t"
"movl %esp, %ebp \n\t"
@ -302,6 +249,24 @@ static int __devinit cru_detect(unsigned long map_entry,
return retval;
}
/*
* bios_checksum
*/
static int __devinit bios_checksum(const char __iomem *ptr, int len)
{
char sum = 0;
int i;
/*
* calculate checksum of size bytes. This should add up
* to zero if we have a valid header.
*/
for (i = 0; i < len; i++)
sum += ptr[i];
return ((sum == 0) && (len > 0));
}
/*
* bios32_present
*
@ -368,8 +333,8 @@ static int __devinit detect_cru_service(void)
#define HPWDT_ARCH 64
asmlinkage void asminline_call(struct cmn_registers *pi86Regs,
unsigned long *pRomEntry)
static void asminline_call(struct cmn_registers *pi86Regs,
unsigned long *pRomEntry)
{
asm("pushq %rbp \n\t"
"movq %rsp, %rbp \n\t"
@ -410,12 +375,8 @@ asmlinkage void asminline_call(struct cmn_registers *pi86Regs,
* dmi_find_cru
*
* Routine Description:
* This function checks wether or not a SMBIOS/DMI record is
* This function checks whether or not a SMBIOS/DMI record is
* the 64bit CRU info or not
*
* Return Value:
* 0 : SUCCESS - if record found
* <0 : FAILURE - if record not found
*/
static void __devinit dmi_find_cru(const struct dmi_header *dm)
{
@ -434,138 +395,11 @@ static void __devinit dmi_find_cru(const struct dmi_header *dm)
}
}
/*
* dmi_table
*
* Routine Description:
* Decode the SMBIOS/DMI table and check if we have a 64bit CRU record
* or not.
*
* We have to be cautious here. We have seen BIOSes with DMI pointers
* pointing to completely the wrong place for example
*/
static void __devinit dmi_table(u8 *buf, int len, int num,
void (*decode)(const struct dmi_header *))
{
u8 *data = buf;
int i = 0;
/*
* Stop when we see all the items the table claimed to have
* OR we run off the end of the table (also happens)
*/
while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
const struct dmi_header *dm = (const struct dmi_header *)data;
/*
* We want to know the total length (formated area and strings)
* before decoding to make sure we won't run off the table in
* dmi_decode or dmi_string
*/
data += dm->length;
while ((data - buf < len - 1) && (data[0] || data[1]))
data++;
if (data - buf < len - 1)
decode(dm);
data += 2;
i++;
}
}
/*
* smbios_present
*
* Routine Description:
* This function parses the SMBIOS entry point table to retrieve
* the 64 bit CRU Service.
*
* Return Value:
* 0 : SUCCESS
* <0 : FAILURE
*/
static int __devinit smbios_present(const char __iomem *p)
{
struct smbios_entry_point *eps =
(struct smbios_entry_point *) p;
int length;
u8 *buf;
/* check if we have indeed the SMBIOS table entry point */
if ((strncmp((char *)eps->anchor, "_SM_",
sizeof(eps->anchor))) == 0) {
length = eps->length;
/* SMBIOS v2.1 implementation might use 0x1e */
if ((length == 0x1e) &&
(eps->major_ver == 2) &&
(eps->minor_ver == 1))
length = 0x1f;
/*
* Now we will check:
* - SMBIOS checksum must be 0
* - intermediate anchor should be _DMI_
* - intermediate checksum should be 0
*/
if ((bios_checksum(p, length)) &&
(strncmp((char *)eps->intermediate_anchor, "_DMI_",
sizeof(eps->intermediate_anchor)) == 0) &&
(bios_checksum(p+0x10, 15))) {
buf = ioremap(eps->table_address, eps->table_length);
if (buf == NULL)
return -ENODEV;
/* Scan the DMI table for the 64 bit CRU service */
dmi_table(buf, eps->table_length,
eps->table_num_structs, dmi_find_cru);
iounmap(buf);
return 0;
}
}
return -ENODEV;
}
static int __devinit smbios_scan_machine(void)
{
char __iomem *p, *q;
int rc;
if (efi_enabled) {
if (efi.smbios == EFI_INVALID_TABLE_ADDR)
return -ENODEV;
p = ioremap(efi.smbios, 32);
if (p == NULL)
return -ENOMEM;
rc = smbios_present(p);
iounmap(p);
} else {
/*
* Search from 0x0f0000 through 0x0fffff, inclusive.
*/
p = ioremap(PCI_ROM_BASE1, ROM_SIZE);
if (p == NULL)
return -ENOMEM;
for (q = p; q < p + ROM_SIZE; q += 16) {
rc = smbios_present(q);
if (!rc) {
break;
}
}
iounmap(p);
}
}
static int __devinit detect_cru_service(void)
{
cru_rom_addr = NULL;
smbios_scan_machine(); /* will become dmi_walk(dmi_find_cru); */
dmi_walk(dmi_find_cru);
/* if cru_rom_addr has been set then we found a CRU service */
return ((cru_rom_addr != NULL)? 0: -ENODEV);

View file

@ -7,7 +7,8 @@
*
* drivers/char/watchdog/scx200_wdt.c
* drivers/hwmon/it87.c
* IT8712F EC-LPC I/O Preliminary Specification 0.9.2.pdf
* IT8712F EC-LPC I/O Preliminary Specification 0.8.2
* IT8712F EC-LPC I/O Preliminary Specification 0.9.3
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -40,6 +41,7 @@ MODULE_DESCRIPTION("IT8712F Watchdog Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
static int max_units = 255;
static int margin = 60; /* in seconds */
module_param(margin, int, 0);
MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
@ -51,6 +53,7 @@ MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
static struct semaphore it8712f_wdt_sem;
static unsigned expect_close;
static spinlock_t io_lock;
static unsigned char revision;
/* Dog Food address - We use the game port address */
static unsigned short address;
@ -108,6 +111,15 @@ superio_inw(int reg)
return val;
}
static void
superio_outw(int val, int reg)
{
outb(reg++, REG);
outb((val >> 8) & 0xff, VAL);
outb(reg, REG);
outb(val & 0xff, VAL);
}
static inline void
superio_select(int ldn)
{
@ -143,15 +155,33 @@ static void
it8712f_wdt_update_margin(void)
{
int config = WDT_OUT_KRST | WDT_OUT_PWROK;
int units = margin;
printk(KERN_INFO NAME ": timer margin %d seconds\n", margin);
/* The timeout register only has 8bits wide */
if (margin < 256)
config |= WDT_UNIT_SEC; /* else UNIT are MINUTES */
/* Switch to minutes precision if the configured margin
* value does not fit within the register width.
*/
if (units <= max_units) {
config |= WDT_UNIT_SEC; /* else UNIT is MINUTES */
printk(KERN_INFO NAME ": timer margin %d seconds\n", units);
} else {
units /= 60;
printk(KERN_INFO NAME ": timer margin %d minutes\n", units);
}
superio_outb(config, WDT_CONFIG);
superio_outb((margin > 255) ? (margin / 60) : margin, WDT_TIMEOUT);
if (revision >= 0x08)
superio_outw(units, WDT_TIMEOUT);
else
superio_outb(units, WDT_TIMEOUT);
}
static int
it8712f_wdt_get_status(void)
{
if (superio_inb(WDT_CONTROL) & 0x01)
return WDIOF_CARDRESET;
else
return 0;
}
static void
@ -234,7 +264,7 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file,
.firmware_version = 1,
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
};
int new_margin;
int value;
switch (cmd) {
default:
@ -244,17 +274,27 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
return 0;
case WDIOC_GETSTATUS:
superio_enter();
superio_select(LDN_GPIO);
value = it8712f_wdt_get_status();
superio_exit();
return put_user(value, p);
case WDIOC_GETBOOTSTATUS:
return put_user(0, p);
case WDIOC_KEEPALIVE:
it8712f_wdt_ping();
return 0;
case WDIOC_SETTIMEOUT:
if (get_user(new_margin, p))
if (get_user(value, p))
return -EFAULT;
if (new_margin < 1)
if (value < 1)
return -EINVAL;
margin = new_margin;
if (value > (max_units * 60))
return -EINVAL;
margin = value;
superio_enter();
superio_select(LDN_GPIO);
@ -262,6 +302,7 @@ it8712f_wdt_ioctl(struct inode *inode, struct file *file,
superio_exit();
it8712f_wdt_ping();
/* Fall through */
case WDIOC_GETTIMEOUT:
if (put_user(margin, p))
return -EFAULT;
@ -336,9 +377,18 @@ it8712f_wdt_find(unsigned short *address)
}
err = 0;
printk(KERN_DEBUG NAME ": Found IT%04xF chip revision %d - "
revision = superio_inb(DEVREV) & 0x0f;
/* Later revisions have 16-bit values per datasheet 0.9.1 */
if (revision >= 0x08)
max_units = 65535;
if (margin > (max_units * 60))
margin = (max_units * 60);
printk(KERN_INFO NAME ": Found IT%04xF chip revision %d - "
"using DogFood address 0x%x\n",
chip_type, superio_inb(DEVREV) & 0x0f, *address);
chip_type, revision, *address);
exit:
superio_exit();

View file

@ -141,7 +141,7 @@ static unsigned long next_heartbeat = 0;
#ifndef ZF_DEBUG
# define dprintk(format, args...)
#else
# define dprintk(format, args...) printk(KERN_DEBUG PFX ":%s:%d: " format, __FUNCTION__, __LINE__ , ## args)
# define dprintk(format, args...) printk(KERN_DEBUG PFX ":%s:%d: " format, __func__, __LINE__ , ## args)
#endif

View file

@ -59,9 +59,9 @@ static int ticks = 100 * HZ;
static struct {
struct completion stop;
volatile int running;
int running;
struct timer_list timer;
volatile int queue;
int queue;
int default_ticks;
unsigned long inuse;
unsigned gpio;

View file

@ -179,11 +179,11 @@ static void usb_pcwd_intr_done(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
dbg("%s - urb shutting down with status: %d", __func__, urb->status);
return;
/* -EPIPE: should clear the halt */
default: /* error */
dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
dbg("%s - nonzero urb status received: %d", __func__, urb->status);
goto resubmit;
}

View file

@ -144,7 +144,7 @@ static int s3c2410wdt_start(void)
}
DBG("%s: wdt_count=0x%08x, wtcon=%08lx\n",
__FUNCTION__, wdt_count, wtcon);
__func__, wdt_count, wtcon);
writel(wdt_count, wdt_base + S3C2410_WTDAT);
writel(wdt_count, wdt_base + S3C2410_WTCNT);
@ -167,7 +167,7 @@ static int s3c2410wdt_set_heartbeat(int timeout)
count = timeout * freq;
DBG("%s: count=%d, timeout=%d, freq=%d\n",
__FUNCTION__, count, timeout, freq);
__func__, count, timeout, freq);
/* if the count is bigger than the watchdog register,
then work out what we need to do (and if) we can
@ -189,7 +189,7 @@ static int s3c2410wdt_set_heartbeat(int timeout)
tmr_margin = timeout;
DBG("%s: timeout=%d, divisor=%d, count=%d (%08x)\n",
__FUNCTION__, timeout, divisor, count, count/divisor);
__func__, timeout, divisor, count, count/divisor);
count /= divisor;
wdt_count = count;
@ -355,7 +355,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
int ret;
int size;
DBG("%s: probe=%p\n", __FUNCTION__, pdev);
DBG("%s: probe=%p\n", __func__, pdev);
dev = &pdev->dev;
wdt_dev = &pdev->dev;

View file

@ -298,7 +298,7 @@ static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
PAGE_SIZE, vma->vm_page_prot)) {
printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n",
__FUNCTION__);
__func__);
return -EAGAIN;
}

View file

@ -451,9 +451,9 @@ static void o2net_set_nn_state(struct o2net_node *nn,
/* delay if we're withing a RECONNECT_DELAY of the
* last attempt */
delay = (nn->nn_last_connect_attempt +
msecs_to_jiffies(o2net_reconnect_delay(sc->sc_node)))
msecs_to_jiffies(o2net_reconnect_delay(NULL)))
- jiffies;
if (delay > msecs_to_jiffies(o2net_reconnect_delay(sc->sc_node)))
if (delay > msecs_to_jiffies(o2net_reconnect_delay(NULL)))
delay = 0;
mlog(ML_CONN, "queueing conn attempt in %lu jiffies\n", delay);
queue_delayed_work(o2net_wq, &nn->nn_connect_work, delay);
@ -1552,12 +1552,11 @@ static void o2net_connect_expired(struct work_struct *work)
spin_lock(&nn->nn_lock);
if (!nn->nn_sc_valid) {
struct o2nm_node *node = nn->nn_sc->sc_node;
mlog(ML_ERROR, "no connection established with node %u after "
"%u.%u seconds, giving up and returning errors.\n",
o2net_num_from_nn(nn),
o2net_idle_timeout(node) / 1000,
o2net_idle_timeout(node) % 1000);
o2net_idle_timeout(NULL) / 1000,
o2net_idle_timeout(NULL) % 1000);
o2net_set_nn_state(nn, NULL, 0, -ENOTCONN);
}

View file

@ -176,6 +176,7 @@ struct dlm_mig_lockres_priv
{
struct dlm_lock_resource *lockres;
u8 real_master;
u8 extra_ref;
};
struct dlm_assert_master_priv
@ -602,17 +603,19 @@ enum dlm_query_join_response_code {
JOIN_PROTOCOL_MISMATCH,
};
struct dlm_query_join_packet {
u8 code; /* Response code. dlm_minor and fs_minor
are only valid if this is JOIN_OK */
u8 dlm_minor; /* The minor version of the protocol the
dlm is speaking. */
u8 fs_minor; /* The minor version of the protocol the
filesystem is speaking. */
u8 reserved;
};
union dlm_query_join_response {
u32 intval;
struct {
u8 code; /* Response code. dlm_minor and fs_minor
are only valid if this is JOIN_OK */
u8 dlm_minor; /* The minor version of the protocol the
dlm is speaking. */
u8 fs_minor; /* The minor version of the protocol the
filesystem is speaking. */
u8 reserved;
} packet;
struct dlm_query_join_packet packet;
};
struct dlm_lock_request

View file

@ -487,7 +487,7 @@ int dlm_convert_lock_handler(struct o2net_msg *msg, u32 len, void *data,
"cookie=%u:%llu\n",
dlm_get_lock_cookie_node(be64_to_cpu(cnv->cookie)),
dlm_get_lock_cookie_seq(be64_to_cpu(cnv->cookie)));
__dlm_print_one_lock_resource(res);
dlm_print_one_lock_resource(res);
goto leave;
}

View file

@ -713,14 +713,46 @@ static int dlm_query_join_proto_check(char *proto_type, int node,
return rc;
}
/*
* struct dlm_query_join_packet is made up of four one-byte fields. They
* are effectively in big-endian order already. However, little-endian
* machines swap them before putting the packet on the wire (because
* query_join's response is a status, and that status is treated as a u32
* on the wire). Thus, a big-endian and little-endian machines will treat
* this structure differently.
*
* The solution is to have little-endian machines swap the structure when
* converting from the structure to the u32 representation. This will
* result in the structure having the correct format on the wire no matter
* the host endian format.
*/
static void dlm_query_join_packet_to_wire(struct dlm_query_join_packet *packet,
u32 *wire)
{
union dlm_query_join_response response;
response.packet = *packet;
*wire = cpu_to_be32(response.intval);
}
static void dlm_query_join_wire_to_packet(u32 wire,
struct dlm_query_join_packet *packet)
{
union dlm_query_join_response response;
response.intval = cpu_to_be32(wire);
*packet = response.packet;
}
static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
void **ret_data)
{
struct dlm_query_join_request *query;
union dlm_query_join_response response = {
.packet.code = JOIN_DISALLOW,
struct dlm_query_join_packet packet = {
.code = JOIN_DISALLOW,
};
struct dlm_ctxt *dlm = NULL;
u32 response;
u8 nodenum;
query = (struct dlm_query_join_request *) msg->buf;
@ -737,11 +769,11 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
mlog(0, "node %u is not in our live map yet\n",
query->node_idx);
response.packet.code = JOIN_DISALLOW;
packet.code = JOIN_DISALLOW;
goto respond;
}
response.packet.code = JOIN_OK_NO_MAP;
packet.code = JOIN_OK_NO_MAP;
spin_lock(&dlm_domain_lock);
dlm = __dlm_lookup_domain_full(query->domain, query->name_len);
@ -760,7 +792,7 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
mlog(0, "disallow join as node %u does not "
"have node %u in its nodemap\n",
query->node_idx, nodenum);
response.packet.code = JOIN_DISALLOW;
packet.code = JOIN_DISALLOW;
goto unlock_respond;
}
}
@ -780,23 +812,23 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
/*If this is a brand new context and we
* haven't started our join process yet, then
* the other node won the race. */
response.packet.code = JOIN_OK_NO_MAP;
packet.code = JOIN_OK_NO_MAP;
} else if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) {
/* Disallow parallel joins. */
response.packet.code = JOIN_DISALLOW;
packet.code = JOIN_DISALLOW;
} else if (dlm->reco.state & DLM_RECO_STATE_ACTIVE) {
mlog(0, "node %u trying to join, but recovery "
"is ongoing.\n", bit);
response.packet.code = JOIN_DISALLOW;
packet.code = JOIN_DISALLOW;
} else if (test_bit(bit, dlm->recovery_map)) {
mlog(0, "node %u trying to join, but it "
"still needs recovery.\n", bit);
response.packet.code = JOIN_DISALLOW;
packet.code = JOIN_DISALLOW;
} else if (test_bit(bit, dlm->domain_map)) {
mlog(0, "node %u trying to join, but it "
"is still in the domain! needs recovery?\n",
bit);
response.packet.code = JOIN_DISALLOW;
packet.code = JOIN_DISALLOW;
} else {
/* Alright we're fully a part of this domain
* so we keep some state as to who's joining
@ -807,19 +839,15 @@ static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,
if (dlm_query_join_proto_check("DLM", bit,
&dlm->dlm_locking_proto,
&query->dlm_proto)) {
response.packet.code =
JOIN_PROTOCOL_MISMATCH;
packet.code = JOIN_PROTOCOL_MISMATCH;
} else if (dlm_query_join_proto_check("fs", bit,
&dlm->fs_locking_proto,
&query->fs_proto)) {
response.packet.code =
JOIN_PROTOCOL_MISMATCH;
packet.code = JOIN_PROTOCOL_MISMATCH;
} else {
response.packet.dlm_minor =
query->dlm_proto.pv_minor;
response.packet.fs_minor =
query->fs_proto.pv_minor;
response.packet.code = JOIN_OK;
packet.dlm_minor = query->dlm_proto.pv_minor;
packet.fs_minor = query->fs_proto.pv_minor;
packet.code = JOIN_OK;
__dlm_set_joining_node(dlm, query->node_idx);
}
}
@ -830,9 +858,10 @@ unlock_respond:
spin_unlock(&dlm_domain_lock);
respond:
mlog(0, "We respond with %u\n", response.packet.code);
mlog(0, "We respond with %u\n", packet.code);
return response.intval;
dlm_query_join_packet_to_wire(&packet, &response);
return response;
}
static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data,
@ -937,7 +966,7 @@ static int dlm_send_join_cancels(struct dlm_ctxt *dlm,
sizeof(unsigned long))) {
mlog(ML_ERROR,
"map_size %u != BITS_TO_LONGS(O2NM_MAX_NODES) %u\n",
map_size, BITS_TO_LONGS(O2NM_MAX_NODES));
map_size, (unsigned)BITS_TO_LONGS(O2NM_MAX_NODES));
return -EINVAL;
}
@ -968,7 +997,8 @@ static int dlm_request_join(struct dlm_ctxt *dlm,
{
int status;
struct dlm_query_join_request join_msg;
union dlm_query_join_response join_resp;
struct dlm_query_join_packet packet;
u32 join_resp;
mlog(0, "querying node %d\n", node);
@ -984,11 +1014,12 @@ static int dlm_request_join(struct dlm_ctxt *dlm,
status = o2net_send_message(DLM_QUERY_JOIN_MSG, DLM_MOD_KEY, &join_msg,
sizeof(join_msg), node,
&join_resp.intval);
&join_resp);
if (status < 0 && status != -ENOPROTOOPT) {
mlog_errno(status);
goto bail;
}
dlm_query_join_wire_to_packet(join_resp, &packet);
/* -ENOPROTOOPT from the net code means the other side isn't
listening for our message type -- that's fine, it means
@ -997,10 +1028,10 @@ static int dlm_request_join(struct dlm_ctxt *dlm,
if (status == -ENOPROTOOPT) {
status = 0;
*response = JOIN_OK_NO_MAP;
} else if (join_resp.packet.code == JOIN_DISALLOW ||
join_resp.packet.code == JOIN_OK_NO_MAP) {
*response = join_resp.packet.code;
} else if (join_resp.packet.code == JOIN_PROTOCOL_MISMATCH) {
} else if (packet.code == JOIN_DISALLOW ||
packet.code == JOIN_OK_NO_MAP) {
*response = packet.code;
} else if (packet.code == JOIN_PROTOCOL_MISMATCH) {
mlog(ML_NOTICE,
"This node requested DLM locking protocol %u.%u and "
"filesystem locking protocol %u.%u. At least one of "
@ -1012,14 +1043,12 @@ static int dlm_request_join(struct dlm_ctxt *dlm,
dlm->fs_locking_proto.pv_minor,
node);
status = -EPROTO;
*response = join_resp.packet.code;
} else if (join_resp.packet.code == JOIN_OK) {
*response = join_resp.packet.code;
*response = packet.code;
} else if (packet.code == JOIN_OK) {
*response = packet.code;
/* Use the same locking protocol as the remote node */
dlm->dlm_locking_proto.pv_minor =
join_resp.packet.dlm_minor;
dlm->fs_locking_proto.pv_minor =
join_resp.packet.fs_minor;
dlm->dlm_locking_proto.pv_minor = packet.dlm_minor;
dlm->fs_locking_proto.pv_minor = packet.fs_minor;
mlog(0,
"Node %d responds JOIN_OK with DLM locking protocol "
"%u.%u and fs locking protocol %u.%u\n",
@ -1031,11 +1060,11 @@ static int dlm_request_join(struct dlm_ctxt *dlm,
} else {
status = -EINVAL;
mlog(ML_ERROR, "invalid response %d from node %u\n",
join_resp.packet.code, node);
packet.code, node);
}
mlog(0, "status %d, node %d response is %d\n", status, node,
*response);
*response);
bail:
return status;

View file

@ -1663,7 +1663,12 @@ way_up_top:
dlm_put_mle(tmpmle);
}
send_response:
/*
* __dlm_lookup_lockres() grabbed a reference to this lockres.
* The reference is released by dlm_assert_master_worker() under
* the call to dlm_dispatch_assert_master(). If
* dlm_assert_master_worker() isn't called, we drop it here.
*/
if (dispatch_assert) {
if (response != DLM_MASTER_RESP_YES)
mlog(ML_ERROR, "invalid response %d\n", response);
@ -1678,7 +1683,11 @@ send_response:
if (ret < 0) {
mlog(ML_ERROR, "failed to dispatch assert master work\n");
response = DLM_MASTER_RESP_ERROR;
dlm_lockres_put(res);
}
} else {
if (res)
dlm_lockres_put(res);
}
dlm_put(dlm);
@ -2348,7 +2357,7 @@ int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
mlog(ML_ERROR, "%s:%.*s: node %u trying to drop ref "
"but it is already dropped!\n", dlm->name,
res->lockname.len, res->lockname.name, node);
__dlm_print_one_lock_resource(res);
dlm_print_one_lock_resource(res);
}
ret = 0;
goto done;
@ -2408,7 +2417,7 @@ static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data)
mlog(ML_ERROR, "%s:%.*s: node %u trying to drop ref "
"but it is already dropped!\n", dlm->name,
res->lockname.len, res->lockname.name, node);
__dlm_print_one_lock_resource(res);
dlm_print_one_lock_resource(res);
}
dlm_lockres_put(res);
@ -2933,6 +2942,9 @@ static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm,
dlm_lockres_clear_refmap_bit(lock->ml.node, res);
list_del_init(&lock->list);
dlm_lock_put(lock);
/* In a normal unlock, we would have added a
* DLM_UNLOCK_FREE_LOCK action. Force it. */
dlm_lock_put(lock);
}
}
queue++;

View file

@ -519,9 +519,9 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm)
return 0;
master_here:
mlog(0, "(%d) mastering recovery of %s:%u here(this=%u)!\n",
task_pid_nr(dlm->dlm_reco_thread_task),
dlm->name, dlm->reco.dead_node, dlm->node_num);
mlog(ML_NOTICE, "(%d) Node %u is the Recovery Master for the Dead Node "
"%u for Domain %s\n", task_pid_nr(dlm->dlm_reco_thread_task),
dlm->node_num, dlm->reco.dead_node, dlm->name);
status = dlm_remaster_locks(dlm, dlm->reco.dead_node);
if (status < 0) {
@ -1191,7 +1191,7 @@ static int dlm_add_lock_to_array(struct dlm_lock *lock,
(ml->type == LKM_EXMODE ||
memcmp(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN))) {
mlog(ML_ERROR, "mismatched lvbs!\n");
__dlm_print_one_lock_resource(lock->lockres);
dlm_print_one_lock_resource(lock->lockres);
BUG();
}
memcpy(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN);
@ -1327,6 +1327,7 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
(struct dlm_migratable_lockres *)msg->buf;
int ret = 0;
u8 real_master;
u8 extra_refs = 0;
char *buf = NULL;
struct dlm_work_item *item = NULL;
struct dlm_lock_resource *res = NULL;
@ -1404,16 +1405,28 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
__dlm_insert_lockres(dlm, res);
spin_unlock(&dlm->spinlock);
/* Add an extra ref for this lock-less lockres lest the
* dlm_thread purges it before we get the chance to add
* locks to it */
dlm_lockres_get(res);
/* There are three refs that need to be put.
* 1. Taken above.
* 2. kref_init in dlm_new_lockres()->dlm_init_lockres().
* 3. dlm_lookup_lockres()
* The first one is handled at the end of this function. The
* other two are handled in the worker thread after locks have
* been attached. Yes, we don't wait for purge time to match
* kref_init. The lockres will still have atleast one ref
* added because it is in the hash __dlm_insert_lockres() */
extra_refs++;
/* now that the new lockres is inserted,
* make it usable by other processes */
spin_lock(&res->spinlock);
res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
spin_unlock(&res->spinlock);
wake_up(&res->wq);
/* add an extra ref for just-allocated lockres
* otherwise the lockres will be purged immediately */
dlm_lockres_get(res);
}
/* at this point we have allocated everything we need,
@ -1443,12 +1456,17 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
dlm_init_work_item(dlm, item, dlm_mig_lockres_worker, buf);
item->u.ml.lockres = res; /* already have a ref */
item->u.ml.real_master = real_master;
item->u.ml.extra_ref = extra_refs;
spin_lock(&dlm->work_lock);
list_add_tail(&item->list, &dlm->work_list);
spin_unlock(&dlm->work_lock);
queue_work(dlm->dlm_worker, &dlm->dispatched_work);
leave:
/* One extra ref taken needs to be put here */
if (extra_refs)
dlm_lockres_put(res);
dlm_put(dlm);
if (ret < 0) {
if (buf)
@ -1464,17 +1482,19 @@ leave:
static void dlm_mig_lockres_worker(struct dlm_work_item *item, void *data)
{
struct dlm_ctxt *dlm = data;
struct dlm_ctxt *dlm;
struct dlm_migratable_lockres *mres;
int ret = 0;
struct dlm_lock_resource *res;
u8 real_master;
u8 extra_ref;
dlm = item->dlm;
mres = (struct dlm_migratable_lockres *)data;
res = item->u.ml.lockres;
real_master = item->u.ml.real_master;
extra_ref = item->u.ml.extra_ref;
if (real_master == DLM_LOCK_RES_OWNER_UNKNOWN) {
/* this case is super-rare. only occurs if
@ -1517,6 +1537,12 @@ again:
}
leave:
/* See comment in dlm_mig_lockres_handler() */
if (res) {
if (extra_ref)
dlm_lockres_put(res);
dlm_lockres_put(res);
}
kfree(data);
mlog_exit(ret);
}
@ -1644,7 +1670,8 @@ int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data,
/* retry!? */
BUG();
}
}
} else /* put.. incase we are not the master */
dlm_lockres_put(res);
spin_unlock(&res->spinlock);
}
spin_unlock(&dlm->spinlock);
@ -1921,6 +1948,7 @@ void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm,
"Recovering res %s:%.*s, is already on recovery list!\n",
dlm->name, res->lockname.len, res->lockname.name);
list_del_init(&res->recovering);
dlm_lockres_put(res);
}
/* We need to hold a reference while on the recovery list */
dlm_lockres_get(res);
@ -2130,11 +2158,16 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
assert_spin_locked(&dlm->spinlock);
assert_spin_locked(&res->spinlock);
/* We do two dlm_lock_put(). One for removing from list and the other is
* to force the DLM_UNLOCK_FREE_LOCK action so as to free the locks */
/* TODO: check pending_asts, pending_basts here */
list_for_each_entry_safe(lock, next, &res->granted, list) {
if (lock->ml.node == dead_node) {
list_del_init(&lock->list);
dlm_lock_put(lock);
/* Can't schedule DLM_UNLOCK_FREE_LOCK - do manually */
dlm_lock_put(lock);
freed++;
}
}
@ -2142,6 +2175,8 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
if (lock->ml.node == dead_node) {
list_del_init(&lock->list);
dlm_lock_put(lock);
/* Can't schedule DLM_UNLOCK_FREE_LOCK - do manually */
dlm_lock_put(lock);
freed++;
}
}
@ -2149,6 +2184,8 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
if (lock->ml.node == dead_node) {
list_del_init(&lock->list);
dlm_lock_put(lock);
/* Can't schedule DLM_UNLOCK_FREE_LOCK - do manually */
dlm_lock_put(lock);
freed++;
}
}

View file

@ -176,12 +176,14 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm,
res->lockname.name, master);
if (!master) {
/* drop spinlock... retake below */
spin_unlock(&dlm->spinlock);
spin_lock(&res->spinlock);
/* This ensures that clear refmap is sent after the set */
__dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG);
spin_unlock(&res->spinlock);
/* drop spinlock to do messaging, retake below */
spin_unlock(&dlm->spinlock);
/* clear our bit from the master's refmap, ignore errors */
ret = dlm_drop_lockres_ref(dlm, res);
if (ret < 0) {

View file

@ -2409,7 +2409,7 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v)
return 0;
}
static struct seq_operations ocfs2_dlm_seq_ops = {
static const struct seq_operations ocfs2_dlm_seq_ops = {
.start = ocfs2_dlm_seq_start,
.stop = ocfs2_dlm_seq_stop,
.next = ocfs2_dlm_seq_next,

View file

@ -597,7 +597,7 @@ int ocfs2_group_add(struct inode *inode, struct ocfs2_new_group_input *input)
memset(cr, 0, sizeof(struct ocfs2_chain_rec));
}
cr->c_blkno = le64_to_cpu(input->group);
cr->c_blkno = cpu_to_le64(input->group);
le32_add_cpu(&cr->c_total, input->clusters * cl_bpc);
le32_add_cpu(&cr->c_free, input->frees * cl_bpc);

View file

@ -26,10 +26,9 @@ struct mm_struct;
struct vm_area_struct;
extern pgd_t swapper_pg_dir[1024];
extern struct kmem_cache *pmd_cache;
void check_pgt_cache(void);
static inline void pgtable_cache_init(void) {}
static inline void pgtable_cache_init(void) { }
static inline void check_pgt_cache(void) { }
void paging_init(void);

View file

@ -68,7 +68,7 @@ void skcipher_geniv_exit(struct crypto_tfm *tfm);
int __init eseqiv_module_init(void);
void __exit eseqiv_module_exit(void);
int __init chainiv_module_init(void);
void __exit chainiv_module_exit(void);
void chainiv_module_exit(void);
static inline struct crypto_ablkcipher *skcipher_geniv_cipher(
struct crypto_ablkcipher *geniv)

View file

@ -10,7 +10,10 @@ struct firmware {
size_t size;
u8 *data;
};
struct device;
#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
int request_firmware(const struct firmware **fw, const char *name,
struct device *device);
int request_firmware_nowait(
@ -19,4 +22,24 @@ int request_firmware_nowait(
void (*cont)(const struct firmware *fw, void *context));
void release_firmware(const struct firmware *fw);
#else
static inline int request_firmware(const struct firmware **fw,
const char *name,
struct device *device)
{
return -EINVAL;
}
static inline int request_firmware_nowait(
struct module *module, int uevent,
const char *name, struct device *device, void *context,
void (*cont)(const struct firmware *fw, void *context))
{
return -EINVAL;
}
static inline void release_firmware(const struct firmware *fw)
{
}
#endif
#endif

View file

@ -22,6 +22,8 @@ struct ms_status_register {
unsigned char reserved;
unsigned char interrupt;
#define MEMSTICK_INT_CMDNAK 0x0001
#define MEMSTICK_INT_IOREQ 0x0008
#define MEMSTICK_INT_IOBREQ 0x0010
#define MEMSTICK_INT_BREQ 0x0020
#define MEMSTICK_INT_ERR 0x0040
#define MEMSTICK_INT_CED 0x0080
@ -47,13 +49,17 @@ struct ms_status_register {
struct ms_id_register {
unsigned char type;
unsigned char reserved;
unsigned char if_mode;
unsigned char category;
unsigned char class;
} __attribute__((packed));
struct ms_param_register {
unsigned char system;
#define MEMSTICK_SYS_ATEN 0xc0
#define MEMSTICK_SYS_BAMD 0x80
#define MEMSTICK_SYS_PAM 0x08
unsigned char block_address_msb;
unsigned short block_address;
unsigned char cp;
@ -90,16 +96,48 @@ struct ms_register {
struct mspro_param_register {
unsigned char system;
#define MEMSTICK_SYS_SERIAL 0x80
#define MEMSTICK_SYS_PAR4 0x00
#define MEMSTICK_SYS_PAR8 0x40
unsigned short data_count;
unsigned int data_address;
unsigned char tpc_param;
} __attribute__((packed));
struct mspro_io_info_register {
unsigned char version;
unsigned char io_category;
unsigned char current_req;
unsigned char card_opt_info;
unsigned char rdy_wait_time;
} __attribute__((packed));
struct mspro_io_func_register {
unsigned char func_enable;
unsigned char func_select;
unsigned char func_intmask;
unsigned char transfer_mode;
} __attribute__((packed));
struct mspro_io_cmd_register {
unsigned short tpc_param;
unsigned short data_count;
unsigned int data_address;
unsigned char cmd_param;
} __attribute__((packed));
struct mspro_register {
struct ms_status_register status;
struct ms_id_register id;
unsigned char reserved[8];
struct mspro_param_register param;
struct ms_status_register status;
struct ms_id_register id;
unsigned char reserved0[8];
struct mspro_param_register param;
unsigned char reserved1[8];
struct mspro_io_info_register io_info;
struct mspro_io_func_register io_func;
unsigned char reserved2[7];
struct mspro_io_cmd_register io_cmd;
unsigned char io_int;
unsigned char io_int_func;
} __attribute__((packed));
struct ms_register_addr {
@ -110,49 +148,55 @@ struct ms_register_addr {
} __attribute__((packed));
enum {
MS_TPC_READ_MG_STATUS = 0x01,
MS_TPC_READ_LONG_DATA = 0x02,
MS_TPC_READ_SHORT_DATA = 0x03,
MS_TPC_READ_MG_DATA = 0x03,
MS_TPC_READ_REG = 0x04,
MS_TPC_READ_IO_DATA = 0x05, /* unverified */
MS_TPC_READ_QUAD_DATA = 0x05,
MS_TPC_READ_IO_DATA = 0x05,
MS_TPC_GET_INT = 0x07,
MS_TPC_SET_RW_REG_ADRS = 0x08,
MS_TPC_EX_SET_CMD = 0x09,
MS_TPC_WRITE_IO_DATA = 0x0a, /* unverified */
MS_TPC_WRITE_QUAD_DATA = 0x0a,
MS_TPC_WRITE_IO_DATA = 0x0a,
MS_TPC_WRITE_REG = 0x0b,
MS_TPC_WRITE_SHORT_DATA = 0x0c,
MS_TPC_WRITE_MG_DATA = 0x0c,
MS_TPC_WRITE_LONG_DATA = 0x0d,
MS_TPC_SET_CMD = 0x0e
};
enum {
MS_CMD_BLOCK_END = 0x33,
MS_CMD_RESET = 0x3c,
MS_CMD_BLOCK_WRITE = 0x55,
MS_CMD_SLEEP = 0x5a,
MS_CMD_BLOCK_ERASE = 0x99,
MS_CMD_BLOCK_READ = 0xaa,
MS_CMD_CLEAR_BUF = 0xc3,
MS_CMD_FLASH_STOP = 0xcc,
MSPRO_CMD_FORMAT = 0x10,
MSPRO_CMD_SLEEP = 0x11,
MSPRO_CMD_READ_DATA = 0x20,
MSPRO_CMD_WRITE_DATA = 0x21,
MSPRO_CMD_READ_ATRB = 0x24,
MSPRO_CMD_STOP = 0x25,
MSPRO_CMD_ERASE = 0x26,
MSPRO_CMD_SET_IBA = 0x46,
MSPRO_CMD_SET_IBD = 0x47
/*
MSPRO_CMD_RESET
MSPRO_CMD_WAKEUP
MSPRO_CMD_IN_IO_DATA
MSPRO_CMD_OUT_IO_DATA
MSPRO_CMD_READ_IO_ATRB
MSPRO_CMD_IN_IO_FIFO
MSPRO_CMD_OUT_IO_FIFO
MSPRO_CMD_IN_IOM
MSPRO_CMD_OUT_IOM
*/
MS_CMD_BLOCK_END = 0x33,
MS_CMD_RESET = 0x3c,
MS_CMD_BLOCK_WRITE = 0x55,
MS_CMD_SLEEP = 0x5a,
MS_CMD_BLOCK_ERASE = 0x99,
MS_CMD_BLOCK_READ = 0xaa,
MS_CMD_CLEAR_BUF = 0xc3,
MS_CMD_FLASH_STOP = 0xcc,
MS_CMD_LOAD_ID = 0x60,
MS_CMD_CMP_ICV = 0x7f,
MSPRO_CMD_FORMAT = 0x10,
MSPRO_CMD_SLEEP = 0x11,
MSPRO_CMD_WAKEUP = 0x12,
MSPRO_CMD_READ_DATA = 0x20,
MSPRO_CMD_WRITE_DATA = 0x21,
MSPRO_CMD_READ_ATRB = 0x24,
MSPRO_CMD_STOP = 0x25,
MSPRO_CMD_ERASE = 0x26,
MSPRO_CMD_READ_QUAD = 0x27,
MSPRO_CMD_WRITE_QUAD = 0x28,
MSPRO_CMD_SET_IBD = 0x46,
MSPRO_CMD_GET_IBD = 0x47,
MSPRO_CMD_IN_IO_DATA = 0xb0,
MSPRO_CMD_OUT_IO_DATA = 0xb1,
MSPRO_CMD_READ_IO_ATRB = 0xb2,
MSPRO_CMD_IN_IO_FIFO = 0xb3,
MSPRO_CMD_OUT_IO_FIFO = 0xb4,
MSPRO_CMD_IN_IOM = 0xb5,
MSPRO_CMD_OUT_IOM = 0xb6,
};
/*** Driver structures and functions ***/
@ -165,7 +209,8 @@ enum memstick_param { MEMSTICK_POWER = 1, MEMSTICK_INTERFACE };
#define MEMSTICK_POWER_ON 1
#define MEMSTICK_SERIAL 0
#define MEMSTICK_PARALLEL 1
#define MEMSTICK_PAR4 1
#define MEMSTICK_PAR8 2
struct memstick_host;
struct memstick_driver;
@ -195,11 +240,7 @@ struct memstick_request {
unsigned char data_dir:1,
need_card_int:1,
get_int_reg:1,
io_type:2;
#define MEMSTICK_IO_NONE 0
#define MEMSTICK_IO_VAL 1
#define MEMSTICK_IO_SG 2
long_data:1;
unsigned char int_reg;
int error;
union {
@ -231,8 +272,9 @@ struct memstick_host {
struct mutex lock;
unsigned int id;
unsigned int caps;
#define MEMSTICK_CAP_PARALLEL 1
#define MEMSTICK_CAP_AUTO_GET_INT 2
#define MEMSTICK_CAP_AUTO_GET_INT 1
#define MEMSTICK_CAP_PAR4 2
#define MEMSTICK_CAP_PAR8 4
struct work_struct media_checker;
struct class_device cdev;
@ -270,6 +312,8 @@ int memstick_add_host(struct memstick_host *host);
void memstick_remove_host(struct memstick_host *host);
void memstick_free_host(struct memstick_host *host);
void memstick_detect_change(struct memstick_host *host);
void memstick_suspend_host(struct memstick_host *host);
void memstick_resume_host(struct memstick_host *host);
void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc,
struct scatterlist *sg);

View file

@ -389,13 +389,13 @@ struct pci_driver {
#define to_pci_driver(drv) container_of(drv, struct pci_driver, driver)
/**
* DECLARE_PCI_DEVICE_TABLE - macro used to describe a pci device table
* DEFINE_PCI_DEVICE_TABLE - macro used to describe a pci device table
* @_table: device table name
*
* This macro is used to create a struct pci_device_id array (a device table)
* in a generic manner.
*/
#define DECLARE_PCI_DEVICE_TABLE(_table) \
#define DEFINE_PCI_DEVICE_TABLE(_table) \
const struct pci_device_id _table[] __devinitconst
/**

View file

@ -2184,6 +2184,7 @@
#define PCI_DEVICE_ID_JMICRON_JMB366 0x2366
#define PCI_DEVICE_ID_JMICRON_JMB368 0x2368
#define PCI_DEVICE_ID_JMICRON_JMB38X_SD 0x2381
#define PCI_DEVICE_ID_JMICRON_JMB38X_MS 0x2383
#define PCI_VENDOR_ID_KORENIX 0x1982
#define PCI_DEVICE_ID_KORENIX_JETCARDF0 0x1600

View file

@ -70,9 +70,9 @@ enum {
#define TIFM_FIFO_ENABLE 0x00000001
#define TIFM_FIFO_READY 0x00000001
#define TIFM_FIFO_MORE 0x00000008
#define TIFM_FIFO_INT_SETALL 0x0000ffff
#define TIFM_FIFO_INTMASK 0x00000005
#define TIFM_FIFO_SIZE 0x00000200
#define TIFM_DMA_RESET 0x00000002
#define TIFM_DMA_TX 0x00008000

View file

@ -174,6 +174,10 @@ static inline void timespec_add_ns(struct timespec *a, u64 ns)
{
ns += a->tv_nsec;
while(unlikely(ns >= NSEC_PER_SEC)) {
/* The following asm() prevents the compiler from
* optimising this loop into a modulo operation. */
asm("" : "+r"(ns));
ns -= NSEC_PER_SEC;
a->tv_sec++;
}

View file

@ -232,14 +232,7 @@ static inline int ntp_synced(void)
#else
#define NTP_INTERVAL_FREQ (HZ)
#endif
#define CLOCK_TICK_OVERFLOW (LATCH * HZ - CLOCK_TICK_RATE)
#define CLOCK_TICK_ADJUST (((s64)CLOCK_TICK_OVERFLOW * NSEC_PER_SEC) / \
(s64)CLOCK_TICK_RATE)
/* Because using NSEC_PER_SEC would be too easy */
#define NTP_INTERVAL_LENGTH ((((s64)TICK_USEC * NSEC_PER_USEC * USER_HZ) + \
CLOCK_TICK_ADJUST) / NTP_INTERVAL_FREQ)
#define NTP_INTERVAL_LENGTH (NSEC_PER_SEC/NTP_INTERVAL_FREQ)
/* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */
extern u64 current_tick_length(void);

View file

@ -3,5 +3,5 @@ header-y += cdc.h
header-y += ch9.h
header-y += gadgetfs.h
header-y += midi.h
unifdef-y += g_printer.h
header-y += g_printer.h

View file

@ -15,8 +15,6 @@
#ifndef __LINUX_USB_GADGET_H
#define __LINUX_USB_GADGET_H
#ifdef __KERNEL__
struct usb_ep;
/**
@ -848,6 +846,4 @@ extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *,
extern void usb_ep_autoconfig_reset(struct usb_gadget *) __devinit;
#endif /* __KERNEL__ */
#endif /* __LINUX_USB_GADGET_H */

View file

@ -865,38 +865,10 @@ source "block/Kconfig"
config PREEMPT_NOTIFIERS
bool
choice
prompt "RCU implementation type:"
default CLASSIC_RCU
help
This allows you to choose either the classic RCU implementation
that is designed for best read-side performance on non-realtime
systems, or the preemptible RCU implementation for best latency
on realtime systems. Note that some kernel preemption modes
will restrict your choice.
Select the default if you are unsure.
config CLASSIC_RCU
bool "Classic RCU"
def_bool !PREEMPT_RCU
help
This option selects the classic RCU implementation that is
designed for best read-side performance on non-realtime
systems.
Say Y if you are unsure.
config PREEMPT_RCU
bool "Preemptible RCU"
depends on PREEMPT
help
This option reduces the latency of the kernel by making certain
RCU sections preemptible. Normally RCU code is non-preemptible, if
this option is selected then read-only RCU sections become
preemptible. This helps latency, but may expose bugs due to
now-naive assumptions about each RCU read-side critical section
remaining on a given CPU through its execution.
Say N if you are unsure.
endchoice
systems. Classic RCU is the default. Note that the
PREEMPT_RCU symbol is used to select/deselect this option.

View file

@ -271,9 +271,10 @@ static struct mempolicy *shm_get_policy(struct vm_area_struct *vma,
if (sfd->vm_ops->get_policy)
pol = sfd->vm_ops->get_policy(vma, addr);
else if (vma->vm_policy)
else if (vma->vm_policy) {
pol = vma->vm_policy;
else
mpol_get(pol); /* get_vma_policy() expects this */
} else
pol = current->mempolicy;
return pol;
}

View file

@ -52,8 +52,23 @@ config PREEMPT
endchoice
config PREEMPT_RCU
bool "Preemptible RCU"
depends on PREEMPT
default n
help
This option reduces the latency of the kernel by making certain
RCU sections preemptible. Normally RCU code is non-preemptible, if
this option is selected then read-only RCU sections become
preemptible. This helps latency, but may expose bugs due to
now-naive assumptions about each RCU read-side critical section
remaining on a given CPU through its execution.
Say N if you are unsure.
config RCU_TRACE
bool "Enable tracing for RCU - currently stats in debugfs"
depends on PREEMPT_RCU
select DEBUG_FS
default y
help

View file

@ -1378,7 +1378,7 @@ unlock_sig:
if (!retval && infop)
retval = put_user(0, &infop->si_errno);
if (!retval && infop)
retval = put_user(why, &infop->si_code);
retval = put_user((short)why, &infop->si_code);
if (!retval && infop)
retval = put_user(exit_code, &infop->si_status);
if (!retval && infop)

View file

@ -2178,10 +2178,20 @@ sys_init_module(void __user *umod,
wake_up(&module_wq);
return ret;
}
if (ret > 0) {
printk(KERN_WARNING "%s: '%s'->init suspiciously returned %d, "
"it should follow 0/-E convention\n"
KERN_WARNING "%s: loading module anyway...\n",
__func__, mod->name, ret,
__func__);
dump_stack();
}
/* Now it's a first class citizen! */
mutex_lock(&module_mutex);
/* Now it's a first class citizen! Wake up anyone waiting for it. */
mod->state = MODULE_STATE_LIVE;
wake_up(&module_wq);
mutex_lock(&module_mutex);
/* Drop initial reference. */
module_put(mod);
unwind_remove_table(mod->unwind_info, 1);
@ -2190,7 +2200,6 @@ sys_init_module(void __user *umod,
mod->init_size = 0;
mod->init_text_size = 0;
mutex_unlock(&module_mutex);
wake_up(&module_wq);
return 0;
}

Some files were not shown because too many files have changed in this diff Show more