diff options
Diffstat (limited to 'drivers')
37 files changed, 708 insertions, 478 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index e942ffe8b57..7c49e103cf8 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -149,6 +149,7 @@ config ACPI_DOCK config ACPI_BAY tristate "Removable Drive Bay (EXPERIMENTAL)" depends on EXPERIMENTAL + depends on ACPI_DOCK help This driver adds support for ACPI controlled removable drive bays such as the IBM ultrabay or the Dell Module Bay. diff --git a/drivers/block/umem.c b/drivers/block/umem.c index dff3766f117..5872036e8ae 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -1179,8 +1179,10 @@ static int __init mm_init(void) return -ENOMEM; err = major_nr = register_blkdev(0, "umem"); - if (err < 0) + if (err < 0) { + pci_unregister_driver(&mm_pci_driver); return -EIO; + } for (i = 0; i < num_cards; i++) { mm_gendisk[i] = alloc_disk(1 << MM_SHIFT); @@ -1207,6 +1209,7 @@ static int __init mm_init(void) return 0; out: + pci_unregister_driver(&mm_pci_driver); unregister_blkdev(major_nr, "umem"); while (i--) put_disk(mm_gendisk[i]); diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index f24c26d2dba..e4532685668 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1901,6 +1901,20 @@ static int init_dev(struct tty_driver *driver, int idx, /* check whether we're reopening an existing tty */ if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { tty = devpts_get_tty(idx); + /* + * If we don't have a tty here on a slave open, it's because + * the master already started the close process and there's + * no relation between devpts file and tty anymore. + */ + if (!tty && driver->subtype == PTY_TYPE_SLAVE) { + retval = -EIO; + goto end_init; + } + /* + * It's safe from now on because init_dev() is called with + * tty_mutex held and release_dev() won't change tty->count + * or tty->flags without having to grab tty_mutex + */ if (tty && driver->subtype == PTY_TYPE_MASTER) tty = tty->link; } else { diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig index 8b6c9a431ff..c921d6c522f 100644 --- a/drivers/isdn/capi/Kconfig +++ b/drivers/isdn/capi/Kconfig @@ -2,13 +2,25 @@ # Config.in for the CAPI subsystem # config ISDN_DRV_AVMB1_VERBOSE_REASON - bool "Verbose reason code reporting (kernel size +=7K)" + bool "Verbose reason code reporting" depends on ISDN_CAPI + default y help - If you say Y here, the AVM B1 driver will give verbose reasons for + If you say Y here, the CAPI drivers will give verbose reasons for disconnecting. This will increase the size of the kernel by 7 KB. If unsure, say Y. +config CAPI_TRACE + bool "CAPI trace support" + depends on ISDN_CAPI + default y + help + If you say Y here, the kernelcapi driver can make verbose traces + of CAPI messages. This feature can be enabled/disabled via IOCTL for + every controler (default disabled). + This will increase the size of the kernelcapi module by 20 KB. + If unsure, say Y. + config ISDN_CAPI_MIDDLEWARE bool "CAPI2.0 Middleware support (EXPERIMENTAL)" depends on ISDN_CAPI && EXPERIMENTAL diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index 2a49cea0a22..23b6f7bc16b 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -990,6 +990,7 @@ static void handle_plci(_cmsg * cmsg) capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f); capidrv_plci *plcip; isdn_ctrl cmd; + _cdebbuf *cdb; if (!card) { printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n", @@ -1122,8 +1123,15 @@ static void handle_plci(_cmsg * cmsg) break; } } - printk(KERN_ERR "capidrv-%d: %s\n", - card->contrnr, capi_cmsg2str(cmsg)); + cdb = capi_cmsg2str(cmsg); + if (cdb) { + printk(KERN_WARNING "capidrv-%d: %s\n", + card->contrnr, cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_WARNING "capidrv-%d: CAPI_INFO_IND InfoNumber %x not handled\n", + card->contrnr, cmsg->InfoNumber); + break; case CAPI_CONNECT_ACTIVE_CONF: /* plci */ @@ -1371,10 +1379,18 @@ static _cmsg s_cmsg; static void capidrv_recv_message(struct capi20_appl *ap, struct sk_buff *skb) { capi_message2cmsg(&s_cmsg, skb->data); - if (debugmode > 3) - printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n", - ap->applid, capi_cmsg2str(&s_cmsg)); - + if (debugmode > 3) { + _cdebbuf *cdb = capi_cmsg2str(&s_cmsg); + + if (cdb) { + printk(KERN_DEBUG "%s: applid=%d %s\n", __FUNCTION__, + ap->applid, cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_DEBUG "%s: applid=%d %s not traced\n", + __FUNCTION__, ap->applid, + capi_cmd2str(s_cmsg.Command, s_cmsg.Subcommand)); + } if (s_cmsg.Command == CAPI_DATA_B3 && s_cmsg.Subcommand == CAPI_IND) { handle_data(&s_cmsg, skb); diff --git a/drivers/isdn/capi/capiutil.c b/drivers/isdn/capi/capiutil.c index c1b21552fc0..ad1e2702c2d 100644 --- a/drivers/isdn/capi/capiutil.c +++ b/drivers/isdn/capi/capiutil.c @@ -648,6 +648,9 @@ char *capi_cmd2str(u8 cmd, u8 subcmd) /*-------------------------------------------------------*/ + +#ifdef CONFIG_CAPI_TRACE + /*-------------------------------------------------------*/ static char *pnames[] = @@ -703,44 +706,77 @@ static char *pnames[] = }; -static char buf[8192]; -static char *p = NULL; #include <stdarg.h> /*-------------------------------------------------------*/ -static void bufprint(char *fmt,...) +static _cdebbuf *bufprint(_cdebbuf *cdb, char *fmt,...) { va_list f; + size_t n,r; + + if (!cdb) + return NULL; va_start(f, fmt); - vsprintf(p, fmt, f); + r = cdb->size - cdb->pos; + n = vsnprintf(cdb->p, r, fmt, f); va_end(f); - p += strlen(p); + if (n >= r) { + /* truncated, need bigger buffer */ + size_t ns = 2 * cdb->size; + u_char *nb; + + while ((ns - cdb->pos) <= n) + ns *= 2; + nb = kmalloc(ns, GFP_ATOMIC); + if (!nb) { + cdebbuf_free(cdb); + return NULL; + } + memcpy(nb, cdb->buf, cdb->pos); + kfree(cdb->buf); + nb[cdb->pos] = 0; + cdb->buf = nb; + cdb->p = cdb->buf + cdb->pos; + cdb->size = ns; + va_start(f, fmt); + r = cdb->size - cdb->pos; + n = vsnprintf(cdb->p, r, fmt, f); + va_end(f); + } + cdb->p += n; + cdb->pos += n; + return cdb; } -static void printstructlen(u8 * m, unsigned len) +static _cdebbuf *printstructlen(_cdebbuf *cdb, u8 * m, unsigned len) { unsigned hex = 0; + + if (!cdb) + return NULL; for (; len; len--, m++) if (isalnum(*m) || *m == ' ') { if (hex) - bufprint(">"); - bufprint("%c", *m); + cdb = bufprint(cdb, ">"); + cdb = bufprint(cdb, "%c", *m); hex = 0; } else { if (!hex) - bufprint("<%02x", *m); + cdb = bufprint(cdb, "<%02x", *m); else - bufprint(" %02x", *m); + cdb = bufprint(cdb, " %02x", *m); hex = 1; } if (hex) - bufprint(">"); + cdb = bufprint(cdb, ">"); + return cdb; } -static void printstruct(u8 * m) +static _cdebbuf *printstruct(_cdebbuf *cdb, u8 * m) { unsigned len; + if (m[0] != 0xff) { len = m[0]; m += 1; @@ -748,42 +784,45 @@ static void printstruct(u8 * m) len = ((u16 *) (m + 1))[0]; m += 3; } - printstructlen(m, len); + cdb = printstructlen(cdb, m, len); + return cdb; } /*-------------------------------------------------------*/ #define NAME (pnames[cmsg->par[cmsg->p]]) -static void protocol_message_2_pars(_cmsg * cmsg, int level) +static _cdebbuf *protocol_message_2_pars(_cdebbuf *cdb, _cmsg *cmsg, int level) { for (; TYP != _CEND; cmsg->p++) { int slen = 29 + 3 - level; int i; - bufprint(" "); + if (!cdb) + return NULL; + cdb = bufprint(cdb, " "); for (i = 0; i < level - 1; i++) - bufprint(" "); + cdb = bufprint(cdb, " "); switch (TYP) { case _CBYTE: - bufprint("%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l)); + cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u8 *) (cmsg->m + cmsg->l)); cmsg->l++; break; case _CWORD: - bufprint("%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l)); + cdb = bufprint(cdb, "%-*s = 0x%x\n", slen, NAME, *(u16 *) (cmsg->m + cmsg->l)); cmsg->l += 2; break; case _CDWORD: - bufprint("%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l)); + cdb = bufprint(cdb, "%-*s = 0x%lx\n", slen, NAME, *(u32 *) (cmsg->m + cmsg->l)); cmsg->l += 4; break; case _CSTRUCT: - bufprint("%-*s = ", slen, NAME); + cdb = bufprint(cdb, "%-*s = ", slen, NAME); if (cmsg->m[cmsg->l] == '\0') - bufprint("default"); + cdb = bufprint(cdb, "default"); else - printstruct(cmsg->m + cmsg->l); - bufprint("\n"); + cdb = printstruct(cdb, cmsg->m + cmsg->l); + cdb = bufprint(cdb, "\n"); if (cmsg->m[cmsg->l] != 0xff) cmsg->l += 1 + cmsg->m[cmsg->l]; else @@ -794,61 +833,184 @@ static void protocol_message_2_pars(_cmsg * cmsg, int level) case _CMSTRUCT: /*----- Metastruktur 0 -----*/ if (cmsg->m[cmsg->l] == '\0') { - bufprint("%-*s = default\n", slen, NAME); + cdb = bufprint(cdb, "%-*s = default\n", slen, NAME); cmsg->l++; jumpcstruct(cmsg); } else { char *name = NAME; unsigned _l = cmsg->l; - bufprint("%-*s\n", slen, name); + cdb = bufprint(cdb, "%-*s\n", slen, name); cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1; cmsg->p++; - protocol_message_2_pars(cmsg, level + 1); + cdb = protocol_message_2_pars(cdb, cmsg, level + 1); } break; } } + return cdb; } /*-------------------------------------------------------*/ -char *capi_message2str(u8 * msg) + +static _cdebbuf *g_debbuf; +static u_long g_debbuf_lock; +static _cmsg *g_cmsg; + +_cdebbuf *cdebbuf_alloc(void) { + _cdebbuf *cdb; + + if (likely(!test_and_set_bit(1, &g_debbuf_lock))) { + cdb = g_debbuf; + goto init; + } else + cdb = kmalloc(sizeof(_cdebbuf), GFP_ATOMIC); + if (!cdb) + return NULL; + cdb->buf = kmalloc(CDEBUG_SIZE, GFP_ATOMIC); + if (!cdb->buf) { + kfree(cdb); + return NULL; + } + cdb->size = CDEBUG_SIZE; +init: + cdb->buf[0] = 0; + cdb->p = cdb->buf; + cdb->pos = 0; + return cdb; +} - _cmsg cmsg; - p = buf; - p[0] = 0; +void cdebbuf_free(_cdebbuf *cdb) +{ + if (likely(cdb == g_debbuf)) { + test_and_clear_bit(1, &g_debbuf_lock); + return; + } + if (likely(cdb)) + kfree(cdb->buf); + kfree(cdb); +} - cmsg.m = msg; - cmsg.l = 8; - cmsg.p = 0; - byteTRcpy(cmsg.m + 4, &cmsg.Command); - byteTRcpy(cmsg.m + 5, &cmsg.Subcommand); - cmsg.par = cpars[command_2_index(cmsg.Command, cmsg.Subcommand)]; - bufprint("%-26s ID=%03d #0x%04x LEN=%04d\n", - mnames[command_2_index(cmsg.Command, cmsg.Subcommand)], +_cdebbuf *capi_message2str(u8 * msg) +{ + _cdebbuf *cdb; + _cmsg *cmsg; + + cdb = cdebbuf_alloc(); + if (unlikely(!cdb)) + return NULL; + if (likely(cdb == g_debbuf)) + cmsg = g_cmsg; + else + cmsg = kmalloc(sizeof(_cmsg), GFP_ATOMIC); + if (unlikely(!cmsg)) { + cdebbuf_free(cdb); + return NULL; + } + cmsg->m = msg; + cmsg->l = 8; + cmsg->p = 0; + byteTRcpy(cmsg->m + 4, &cmsg->Command); + byteTRcpy(cmsg->m + 5, &cmsg->Subcommand); + cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)]; + + cdb = bufprint(cdb, "%-26s ID=%03d #0x%04x LEN=%04d\n", + mnames[command_2_index(cmsg->Command, cmsg->Subcommand)], ((unsigned short *) msg)[1], ((unsigned short *) msg)[3], ((unsigned short *) msg)[0]); - protocol_message_2_pars(&cmsg, 1); - return buf; + cdb = protocol_message_2_pars(cdb, cmsg, 1); + if (unlikely(cmsg != g_cmsg)) + kfree(cmsg); + return cdb; } -char *capi_cmsg2str(_cmsg * cmsg) +_cdebbuf *capi_cmsg2str(_cmsg * cmsg) { - p = buf; - p[0] = 0; + _cdebbuf *cdb; + + cdb = cdebbuf_alloc(); + if (!cdb) + return NULL; cmsg->l = 8; cmsg->p = 0; - bufprint("%s ID=%03d #0x%04x LEN=%04d\n", + cdb = bufprint(cdb, "%s ID=%03d #0x%04x LEN=%04d\n", mnames[command_2_index(cmsg->Command, cmsg->Subcommand)], ((u16 *) cmsg->m)[1], ((u16 *) cmsg->m)[3], ((u16 *) cmsg->m)[0]); - protocol_message_2_pars(cmsg, 1); - return buf; + cdb = protocol_message_2_pars(cdb, cmsg, 1); + return cdb; } +int __init cdebug_init(void) +{ + g_cmsg= kmalloc(sizeof(_cmsg), GFP_KERNEL); + if (!g_cmsg) + return ENOMEM; + g_debbuf = kmalloc(sizeof(_cdebbuf), GFP_KERNEL); + if (!g_debbuf) { + kfree(g_cmsg); + return ENOMEM; + } + g_debbuf->buf = kmalloc(CDEBUG_GSIZE, GFP_KERNEL); + if (!g_debbuf->buf) { + kfree(g_cmsg); + kfree(g_debbuf); + return ENOMEM;; + } + g_debbuf->size = CDEBUG_GSIZE; + g_debbuf->buf[0] = 0; + g_debbuf->p = g_debbuf->buf; + g_debbuf->pos = 0; + return 0; +} + +void __exit cdebug_exit(void) +{ + if (g_debbuf) + kfree(g_debbuf->buf); + kfree(g_debbuf); + kfree(g_cmsg); +} + +#else /* !CONFIG_CAPI_TRACE */ + +static _cdebbuf g_debbuf = {"CONFIG_CAPI_TRACE not enabled", NULL, 0, 0}; + +_cdebbuf *capi_message2str(u8 * msg) +{ + return &g_debbuf; +} + +_cdebbuf *capi_cmsg2str(_cmsg * cmsg) +{ + return &g_debbuf; +} + +_cdebbuf *cdebbuf_alloc(void) +{ + return &g_debbuf; +} + +void cdebbuf_free(_cdebbuf *cdb) +{ +} + +int __init cdebug_init(void) +{ + return 0; +} + +void __exit cdebug_exit(void) +{ +} + +#endif + +EXPORT_SYMBOL(cdebbuf_alloc); +EXPORT_SYMBOL(cdebbuf_free); EXPORT_SYMBOL(capi_cmsg2message); EXPORT_SYMBOL(capi_message2cmsg); EXPORT_SYMBOL(capi_cmsg_header); diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index 783a2552631..3ed34f7a1c4 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -276,10 +276,17 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s int showctl = 0; u8 cmd, subcmd; unsigned long flags; + _cdebbuf *cdb; if (card->cardstate != CARD_RUNNING) { - printk(KERN_INFO "kcapi: controller %d not active, got: %s", - card->cnr, capi_message2str(skb->data)); + cdb = capi_message2str(skb->data); + if (cdb) { + printk(KERN_INFO "kcapi: controller [%03d] not active, got: %s", + card->cnr, cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_INFO "kcapi: controller [%03d] not active, cannot trace\n", + card->cnr); goto error; } @@ -295,15 +302,21 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s showctl |= (card->traceflag & 1); if (showctl & 2) { if (showctl & 1) { - printk(KERN_DEBUG "kcapi: got [0x%lx] id#%d %s len=%u\n", - (unsigned long) card->cnr, - CAPIMSG_APPID(skb->data), + printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u\n", + card->cnr, CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), CAPIMSG_LEN(skb->data)); } else { - printk(KERN_DEBUG "kcapi: got [0x%lx] %s\n", - (unsigned long) card->cnr, - capi_message2str(skb->data)); + cdb = capi_message2str(skb->data); + if (cdb) { + printk(KERN_DEBUG "kcapi: got [%03d] %s\n", + card->cnr, cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u, cannot trace\n", + card->cnr, CAPIMSG_APPID(skb->data), + capi_cmd2str(cmd, subcmd), + CAPIMSG_LEN(skb->data)); } } @@ -312,8 +325,15 @@ void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *s ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data)); if ((!ap) || (ap->release_in_progress)) { read_unlock_irqrestore(&application_lock, flags); - printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n", - CAPIMSG_APPID(skb->data), capi_message2str(skb->data)); + cdb = capi_message2str(skb->data); + if (cdb) { + printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n", + CAPIMSG_APPID(skb->data), cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s) cannot trace\n", + CAPIMSG_APPID(skb->data), + capi_cmd2str(cmd, subcmd)); goto error; } skb_queue_tail(&ap->recv_queue, skb); @@ -332,7 +352,7 @@ void capi_ctr_ready(struct capi_ctr * card) { card->cardstate = CARD_RUNNING; - printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n", + printk(KERN_NOTICE "kcapi: card [%03d] \"%s\" ready.\n", card->cnr, card->name); notify_push(KCI_CONTRUP, card->cnr, 0, 0); @@ -364,7 +384,7 @@ void capi_ctr_reseted(struct capi_ctr * card) capi_ctr_put(card); } - printk(KERN_NOTICE "kcapi: card %d down.\n", card->cnr); + printk(KERN_NOTICE "kcapi: card [%03d] down.\n", card->cnr); notify_push(KCI_CONTRDOWN, card->cnr, 0, 0); } @@ -374,7 +394,7 @@ EXPORT_SYMBOL(capi_ctr_reseted); void capi_ctr_suspend_output(struct capi_ctr *card) { if (!card->blocked) { - printk(KERN_DEBUG "kcapi: card %d suspend\n", card->cnr); + printk(KERN_DEBUG "kcapi: card [%03d] suspend\n", card->cnr); card->blocked = 1; } } @@ -384,7 +404,7 @@ EXPORT_SYMBOL(capi_ctr_suspend_output); void capi_ctr_resume_output(struct capi_ctr *card) { if (card->blocked) { - printk(KERN_DEBUG "kcapi: card %d resume\n", card->cnr); + printk(KERN_DEBUG "kcapi: card [%03d] resume\n", card->cnr); card->blocked = 0; } } @@ -432,7 +452,7 @@ attach_capi_ctr(struct capi_ctr *card) } ncards++; - printk(KERN_NOTICE "kcapi: Controller %d: %s attached\n", + printk(KERN_NOTICE "kcapi: Controller [%03d]: %s attached\n", card->cnr, card->name); return 0; } @@ -451,7 +471,7 @@ int detach_capi_ctr(struct capi_ctr *card) card->procent = NULL; } capi_cards[card->cnr - 1] = NULL; - printk(KERN_NOTICE "kcapi: Controller %d: %s unregistered\n", + printk(KERN_NOTICE "kcapi: Controller [%03d]: %s unregistered\n", card->cnr, card->name); return 0; @@ -623,17 +643,25 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) showctl |= (card->traceflag & 1); if (showctl & 2) { if (showctl & 1) { - printk(KERN_DEBUG "kcapi: put [%#x] id#%d %s len=%u\n", + printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u\n", CAPIMSG_CONTROLLER(skb->data), CAPIMSG_APPID(skb->data), capi_cmd2str(cmd, subcmd), CAPIMSG_LEN(skb->data)); } else { - printk(KERN_DEBUG "kcapi: put [%#x] %s\n", - CAPIMSG_CONTROLLER(skb->data), - capi_message2str(skb->data)); + _cdebbuf *cdb = capi_message2str(skb->data); + if (cdb) { + printk(KERN_DEBUG "kcapi: put [%03d] %s\n", + CAPIMSG_CONTROLLER(skb->data), + cdb->buf); + cdebbuf_free(cdb); + } else + printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u cannot trace\n", + CAPIMSG_CONTROLLER(skb->data), + CAPIMSG_APPID(skb->data), + capi_cmd2str(cmd, subcmd), + CAPIMSG_LEN(skb->data)); } - } return card->send_message(card, skb); } @@ -894,7 +922,7 @@ int capi20_manufacturer(unsigned int cmd, void __user *data) return -ESRCH; card->traceflag = fdef.flag; - printk(KERN_INFO "kcapi: contr %d set trace=%d\n", + printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n", card->cnr, card->traceflag); return 0; } @@ -967,7 +995,11 @@ static int __init kcapi_init(void) { char *p; char rev[32]; + int ret; + ret = cdebug_init(); + if (ret) + return ret; kcapi_proc_init(); if ((p = strchr(revision, ':')) != 0 && p[1]) { @@ -988,6 +1020,7 @@ static void __exit kcapi_exit(void) /* make sure all notifiers are finished */ flush_scheduled_work(); + cdebug_exit(); } module_init(kcapi_init); diff --git a/drivers/isdn/gigaset/Makefile b/drivers/isdn/gigaset/Makefile index 5158be0b7ab..e9d3189f56b 100644 --- a/drivers/isdn/gigaset/Makefile +++ b/drivers/isdn/gigaset/Makefile @@ -1,8 +1,9 @@ gigaset-y := common.o interface.o proc.o ev-layer.o i4l.o asyncdata.o usb_gigaset-y := usb-gigaset.o -bas_gigaset-y := bas-gigaset.o isocdata.o ser_gigaset-y := ser-gigaset.o +bas_gigaset-y := bas-gigaset.o isocdata.o -obj-$(CONFIG_GIGASET_M105) += usb_gigaset.o gigaset.o -obj-$(CONFIG_GIGASET_BASE) += bas_gigaset.o gigaset.o -obj-$(CONFIG_GIGASET_M101) += ser_gigaset.o gigaset.o +obj-$(CONFIG_ISDN_DRV_GIGASET) += gigaset.o +obj-$(CONFIG_GIGASET_M105) += usb_gigaset.o +obj-$(CONFIG_GIGASET_BASE) += bas_gigaset.o +obj-$(CONFIG_GIGASET_M101) += ser_gigaset.o diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index f2f108fcec4..00a3be5b862 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -13,11 +13,6 @@ * ===================================================================== */ -/* not set by Kbuild when building both ser_gigaset and usb_gigaset */ -#ifndef KBUILD_MODNAME -#define KBUILD_MODNAME "asy_gigaset" -#endif - #include "gigaset.h" #include <linux/crc-ccitt.h> #include <linux/bitrev.h> diff --git a/drivers/md/md.c b/drivers/md/md.c index 05febfd9f07..6c06e825cff 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1296,27 +1296,17 @@ static struct super_type super_types[] = { .sync_super = super_1_sync, }, }; - -static mdk_rdev_t * match_dev_unit(mddev_t *mddev, mdk_rdev_t *dev) -{ - struct list_head *tmp; - mdk_rdev_t *rdev; - - ITERATE_RDEV(mddev,rdev,tmp) - if (rdev->bdev->bd_contains == dev->bdev->bd_contains) - return rdev; - - return NULL; -} static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2) { - struct list_head *tmp; - mdk_rdev_t *rdev; + struct list_head *tmp, *tmp2; + mdk_rdev_t *rdev, *rdev2; ITERATE_RDEV(mddev1,rdev,tmp) - if (match_dev_unit(mddev2, rdev)) - return 1; + ITERATE_RDEV(mddev2, rdev2, tmp2) + if (rdev->bdev->bd_contains == + rdev2->bdev->bd_contains) + return 1; return 0; } @@ -1325,8 +1315,7 @@ static LIST_HEAD(pending_raid_disks); static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) { - mdk_rdev_t *same_pdev; - char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; + char b[BDEVNAME_SIZE]; struct kobject *ko; char *s; @@ -1342,14 +1331,6 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) else mddev->size = rdev->size; } - same_pdev = match_dev_unit(mddev, rdev); - if (same_pdev) - printk(KERN_WARNING - "%s: WARNING: %s appears to be on the same physical" - " disk as %s. True\n protection against single-disk" - " failure might be compromised.\n", - mdname(mddev), bdevname(rdev->bdev,b), - bdevname(same_pdev->bdev,b2)); /* Verify rdev->desc_nr is unique. * If it is -1, assign a free number, else @@ -3109,6 +3090,36 @@ static int do_md_run(mddev_t * mddev) return -EINVAL; } + if (pers->sync_request) { + /* Warn if this is a potentially silly + * configuration. + */ + char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; + mdk_rdev_t *rdev2; + struct list_head *tmp2; + int warned = 0; + ITERATE_RDEV(mddev, rdev, tmp) { + ITERATE_RDEV(mddev, rdev2, tmp2) { + if (rdev < rdev2 && + rdev->bdev->bd_contains == + rdev2->bdev->bd_contains) { + printk(KERN_WARNING + "%s: WARNING: %s appears to be" + " on the same physical disk as" + " %s.\n", + mdname(mddev), + bdevname(rdev->bdev,b), + bdevname(rdev2->bdev,b2)); + warned = 1; + } + } + } + if (warned) + printk(KERN_WARNING + "True protection against single-disk" + " failure might be compromised.\n"); + } + mddev->recovery = 0; mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ mddev->barriers_work = 1; @@ -3311,6 +3322,9 @@ static int do_md_stop(mddev_t * mddev, int mode) set_disk_ro(disk, 0); blk_queue_make_request(mddev->queue, md_fail_request); mddev->pers->stop(mddev); + mddev->queue->merge_bvec_fn = NULL; + mddev->queue->unplug_fn = NULL; + mddev->queue->issue_flush_fn = NULL; if (mddev->pers->sync_request) sysfs_remove_group(&mddev->kobj, &md_redundancy_group); @@ -5343,6 +5357,44 @@ void md_do_sync(mddev_t *mddev) EXPORT_SYMBOL_GPL(md_do_sync); +static int remove_and_add_spares(mddev_t *mddev) +{ + mdk_rdev_t *rdev; + struct list_head *rtmp; + int spares = 0; + + ITERATE_RDEV(mddev,rdev,rtmp) + if (rdev->raid_disk >= 0 && + (test_bit(Faulty, &rdev->flags) || + ! test_bit(In_sync, &rdev->flags)) && + atomic_read(&rdev->nr_pending)==0) { + if (mddev->pers->hot_remove_disk( + mddev, rdev->raid_disk)==0) { + char nm[20]; + sprintf(nm,"rd%d", rdev->raid_disk); + sysfs_remove_link(&mddev->kobj, nm); + rdev->raid_disk = -1; + } + } + + if (mddev->degraded) { + ITERATE_RDEV(mddev,rdev,rtmp) + if (rdev->raid_disk < 0 + && !test_bit(Faulty, &rdev->flags)) { + rdev->recovery_offset = 0; + if (mddev->pers->hot_add_disk(mddev,rdev)) { + char nm[20]; + sprintf(nm, "rd%d", rdev->raid_disk); + sysfs_create_link(&mddev->kobj, + &rdev->kobj, nm); + spares++; + md_new_event(mddev); + } else + break; + } + } + return spares; +} /* * This routine is regularly called by all per-raid-array threads to * deal with generic issues like resync and super-block update. @@ -5397,7 +5449,7 @@ void md_check_recovery(mddev_t *mddev) return; if (mddev_trylock(mddev)) { - int spares =0; + int spares = 0; spin_lock_irq(&mddev->write_lock); if (mddev->safemode && !atomic_read(&mddev->writes_pending) && @@ -5460,35 +5512,13 @@ void md_check_recovery(mddev_t *mddev) * Spare are also removed and re-added, to allow * the personality to fail the re-add. */ - ITERATE_RDEV(mddev,rdev,rtmp) - if (rdev->raid_disk >= 0 && - (test_bit(Faulty, &rdev->flags) || ! test_bit(In_sync, &rdev->flags)) && - atomic_read(&rdev->nr_pending)==0) { - if (mddev->pers->hot_remove_disk(mddev, rdev->raid_disk)==0) { - char nm[20]; - sprintf(nm,"rd%d", rdev->raid_disk); - sysfs_remove_link(&mddev->kobj, nm); - rdev->raid_disk = -1; - } - } - - if (mddev->degraded) { - ITERATE_RDEV(mddev,rdev,rtmp) - if (rdev->raid_disk < 0 - && !test_bit(Faulty, &rdev->flags)) { - rdev->recovery_offset = 0; - if (mddev->pers->hot_add_disk(mddev,rdev)) { - char nm[20]; - sprintf(nm, "rd%d", rdev->raid_disk); - sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); - spares++; - md_new_event(mddev); - } else - break; - } - } - if (spares) { + if (mddev->reshape_position != MaxSector) { + if (mddev->pers->check_reshape(mddev) != 0) + /* Cannot proceed */ + goto unlock; + set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); + } else if ((spares = remove_and_add_spares(mddev))) { clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); } else if (mddev->recovery_cp < MaxSector) { diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index a9401c017e3..82249a69014 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -429,7 +429,7 @@ static sector_t raid10_find_virt(conf_t *conf, sector_t sector, int dev) if (dev < 0) dev += conf->raid_disks; } else { - while (sector > conf->stride) { + while (sector >= conf->stride) { sector -= conf->stride; if (dev < conf->near_copies) dev += conf->raid_disks - conf->near_copies; @@ -1801,6 +1801,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i for (k=0; k<conf->copies; k++) if (r10_bio->devs[k].devnum == i) break; + BUG_ON(k == conf->copies); bio = r10_bio->devs[1].bio; bio->bi_next = biolist; biolist = bio; @@ -2021,19 +2022,30 @@ static int run(mddev_t *mddev) if (!conf->tmppage) goto out_free_conf; + conf->mddev = mddev; + conf->raid_disks = mddev->raid_disks; conf->near_copies = nc; conf->far_copies = fc; conf->copies = nc*fc; conf->far_offset = fo; conf->chunk_mask = (sector_t)(mddev->chunk_size>>9)-1; conf->chunk_shift = ffz(~mddev->chunk_size) - 9; + size = mddev->size >> (conf->chunk_shift-1); + sector_div(size, fc); + size = size * conf->raid_disks; + sector_div(size, nc); + /* 'size' is now the number of chunks in the array */ + /* calculate "used chunks per device" in 'stride' */ + stride = size * conf->copies; + sector_div(stride, conf->raid_disks); + mddev->size = stride << (conf->chunk_shift-1); + if (fo) - conf->stride = 1 << conf->chunk_shift; - else { - stride = mddev->size >> (conf->chunk_shift-1); + stride = 1; + else sector_div(stride, fc); - conf->stride = stride << conf->chunk_shift; - } + conf->stride = stride << conf->chunk_shift; + conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc, r10bio_pool_free, conf); if (!conf->r10bio_pool) { @@ -2063,8 +2075,6 @@ static int run(mddev_t *mddev) disk->head_position = 0; } - conf->raid_disks = mddev->raid_disks; - conf->mddev = mddev; spin_lock_init(&conf->device_lock); INIT_LIST_HEAD(&conf->retry_list); @@ -2106,16 +2116,8 @@ static int run(mddev_t *mddev) /* * Ok, everything is just fine now */ - if (conf->far_offset) { - size = mddev->size >> (conf->chunk_shift-1); - size *= conf->raid_disks; - size <<= conf->chunk_shift; - sector_div(size, conf->far_copies); - } else - size = conf->stride * conf->raid_disks; - sector_div(size, conf->near_copies); - mddev->array_size = size/2; - mddev->resync_max_sectors = size; + mddev->array_size = size << (conf->chunk_shift-1); + mddev->resync_max_sectors = size << conf->chunk_shift; mddev->queue->unplug_fn = raid10_unplug; mddev->queue->issue_flush_fn = raid10_issue_flush; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 11c3d7bfa79..d247429ee5e 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1050,7 +1050,7 @@ static void compute_parity5(struct stripe_head *sh, int method) static void compute_parity6(struct stripe_head *sh, int method) { raid6_conf_t *conf = sh->raid_conf; - int i, pd_idx = sh->pd_idx, qd_idx, d0_idx, disks = conf->raid_disks, count; + int i, pd_idx = sh->pd_idx, qd_idx, d0_idx, disks = sh->disks, count; struct bio *chosen; /**** FIX THIS: This could be very bad if disks is close to 256 ****/ void *ptrs[disks]; @@ -1131,8 +1131,7 @@ static void compute_parity6(struct stripe_head *sh, int method) /* Compute one missing block */ static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero) { - raid6_conf_t *conf = sh->raid_conf; - int i, count, disks = conf->raid_disks; + int i, count, disks = sh->disks; void *ptr[MAX_XOR_BLOCKS], *p; int pd_idx = sh->pd_idx; int qd_idx = raid6_next_disk(pd_idx, disks); @@ -1170,8 +1169,7 @@ static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero) /* Compute two missing blocks */ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2) { - raid6_conf_t *conf = sh->raid_conf; - int i, count, disks = conf->raid_disks; + int i, count, disks = sh->disks; int pd_idx = sh->pd_idx; int qd_idx = raid6_next_disk(pd_idx, disks); int d0_idx = raid6_next_disk(qd_idx, disks); @@ -1887,11 +1885,11 @@ static void handle_stripe5(struct stripe_head *sh) static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) { raid6_conf_t *conf = sh->raid_conf; - int disks = conf->raid_disks; + int disks = sh->disks; struct bio *return_bi= NULL; struct bio *bi; int i; - int syncing; + int syncing, expanding, expanded; int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0; int non_overwrite = 0; int failed_num[2] = {0, 0}; @@ -1909,6 +1907,8 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) clear_bit(STRIPE_DELAYED, &sh->state); syncing = test_bit(STRIPE_SYNCING, &sh->state); + expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state); + expanded = test_bit(STRIPE_EXPAND_READY, &sh->state); /* Now to look around and see what can be done */ rcu_read_lock(); @@ -2114,13 +2114,15 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) * parity, or to satisfy requests * or to load a block that is being partially written. */ - if (to_read || non_overwrite || (to_write && failed) || (syncing && (uptodate < disks))) { + if (to_read || non_overwrite || (to_write && failed) || + (syncing && (uptodate < disks)) || expanding) { for (i=disks; i--;) { dev = &sh->dev[i]; if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) && (dev->toread || (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) || syncing || + expanding || (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) || (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write)) ) @@ -2355,6 +2357,79 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) } } } + + if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) { + /* Need to write out all blocks after computing P&Q */ + sh->disks = conf->raid_disks; + sh->pd_idx = stripe_to_pdidx(sh->sector, conf, + conf->raid_disks); + compute_parity6(sh, RECONSTRUCT_WRITE); + for (i = conf->raid_disks ; i-- ; ) { + set_bit(R5_LOCKED, &sh->dev[i].flags); + locked++; + set_bit(R5_Wantwrite, &sh->dev[i].flags); + } + clear_bit(STRIPE_EXPANDING, &sh->state); + } else if (expanded) { + clear_bit(STRIPE_EXPAND_READY, &sh->state); + atomic_dec(&conf->reshape_stripes); + wake_up(&conf->wait_for_overlap); + md_done_sync(conf->mddev, STRIPE_SECTORS, 1); + } + + if (expanding && locked == 0) { + /* We have read all the blocks in this stripe and now we need to + * copy some of them into a target stripe for expand. + */ + clear_bit(STRIPE_EXPAND_SOURCE, &sh->state); + for (i = 0; i < sh->disks ; i++) + if (i != pd_idx && i != qd_idx) { + int dd_idx2, pd_idx2, j; + struct stripe_head *sh2; + + sector_t bn = compute_blocknr(sh, i); + sector_t s = raid5_compute_sector( + bn, conf->raid_disks, + conf->raid_disks - conf->max_degraded, + &dd_idx2, &pd_idx2, conf); + sh2 = get_active_stripe(conf, s, + conf->raid_disks, + pd_idx2, 1); + if (sh2 == NULL) + /* so for only the early blocks of + * this stripe have been requests. + * When later blocks get requests, we + * will try again + */ + continue; + if (!test_bit(STRIPE_EXPANDING, &sh2->state) || + test_bit(R5_Expanded, + &sh2->dev[dd_idx2].flags)) { + /* must have already done this block */ + release_stripe(sh2); + continue; + } + memcpy(page_address(sh2->dev[dd_idx2].page), + page_address(sh->dev[i].page), + STRIPE_SIZE); + set_bit(R5_Expanded, &sh2->dev[dd_idx2].flags); + set_bit(R5_UPTODATE, &sh2->dev[dd_idx2].flags); + for (j = 0 ; j < conf->raid_disks ; j++) + if (j != sh2->pd_idx && + j != raid6_next_disk(sh2->pd_idx, + sh2->disks) && + !test_bit(R5_Expanded, + &sh2->dev[j].flags)) + break; + if (j == conf->raid_disks) { + set_bit(STRIPE_EXPAND_READY, + &sh2->state); + set_bit(STRIPE_HANDLE, &sh2->state); + } + release_stripe(sh2); + } + } + spin_unlock(&sh->lock); while ((bi=return_bi)) { @@ -2395,7 +2470,7 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page) rcu_read_unlock(); if (rdev) { - if (syncing) + if (syncing || expanding || expanded) md_sync_acct(rdev->bdev, STRIPE_SECTORS); bi->bi_bdev = rdev->bdev; @@ -2915,8 +2990,9 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped struct stripe_head *sh; int pd_idx; sector_t first_sector, last_sector; - int raid_disks; - int data_disks; + int raid_disks = conf->previous_raid_disks; + int data_disks = raid_disks - conf->max_degraded; + int new_data_disks = conf->raid_disks - conf->max_degraded; int i; int dd_idx; sector_t writepos, safepos, gap; @@ -2925,7 +3001,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped conf->expand_progress != 0) { /* restarting in the middle, skip the initial sectors */ sector_nr = conf->expand_progress; - sector_div(sector_nr, conf->raid_disks-1); + sector_div(sector_nr, new_data_disks); *skipped = 1; return sector_nr; } @@ -2939,14 +3015,14 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped * to after where expand_lo old_maps to */ writepos = conf->expand_progress + - conf->chunk_size/512*(conf->raid_disks-1); - sector_div(writepos, conf->raid_disks-1); + conf->chunk_size/512*(new_data_disks); + sector_div(writepos, new_data_disks); safepos = conf->expand_lo; - sector_div(safepos, conf->previous_raid_disks-1); + sector_div(safepos, data_disks); gap = conf->expand_progress - conf->expand_lo; if (writepos >= safepos || - gap > (conf->raid_disks-1)*3000*2 /*3Meg*/) { + gap > (new_data_disks)*3000*2 /*3Meg*/) { /* Cannot proceed until we've updated the superblock... */ wait_event(conf->wait_for_overlap, atomic_read(&conf->reshape_stripes)==0); @@ -2976,6 +3052,9 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped sector_t s; if (j == sh->pd_idx) continue; + if (conf->level == 6 && + j == raid6_next_disk(sh->pd_idx, sh->disks)) + continue; s = compute_blocknr(sh, j); if (s < (mddev->array_size<<1)) { skipped = 1; @@ -2999,21 +3078,20 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped * The source stripes are determined by mapping the first and last * block on the destination stripes. */ - raid_disks = conf->previous_raid_disks; - data_disks = raid_disks - 1; first_sector = - raid5_compute_sector(sector_nr*(conf->raid_disks-1), + raid5_compute_sector(sector_nr*(new_data_disks), raid_disks, data_disks, &dd_idx, &pd_idx, conf); last_sector = raid5_compute_sector((sector_nr+conf->chunk_size/512) - *(conf->raid_disks-1) -1, + *(new_data_disks) -1, raid_disks, data_disks, &dd_idx, &pd_idx, conf); if (last_sector >= (mddev->size<<1)) last_sector = (mddev->size<<1)-1; while (first_sector <= last_sector) { - pd_idx = stripe_to_pdidx(first_sector, conf, conf->previous_raid_disks); + pd_idx = stripe_to_pdidx(first_sector, conf, + conf->previous_raid_disks); sh = get_active_stripe(conf, first_sector, conf->previous_raid_disks, pd_idx, 0); set_bit(STRIPE_EXPAND_SOURCE, &sh->state); @@ -3348,35 +3426,44 @@ static int run(mddev_t *mddev) */ sector_t here_new, here_old; int old_disks; + int max_degraded = (mddev->level == 5 ? 1 : 2); if (mddev->new_level != mddev->level || mddev->new_layout != mddev->layout || mddev->new_chunk != mddev->chunk_size) { - printk(KERN_ERR "raid5: %s: unsupported reshape required - aborting.\n", + printk(KERN_ERR "raid5: %s: unsupported reshape " + "required - aborting.\n", mdname(mddev)); return -EINVAL; } if (mddev->delta_disks <= 0) { - printk(KERN_ERR "raid5: %s: unsupported reshape (reduce disks) required - aborting.\n", + printk(KERN_ERR "raid5: %s: unsupported reshape " + "(reduce disks) required - aborting.\n", mdname(mddev)); return -EINVAL; } old_disks = mddev->raid_disks - mddev->delta_disks; /* reshape_position must be on a new-stripe boundary, and one - * further up in new geometry must map after here in old geometry. + * further up in new geometry must map after here in old + * geometry. */ here_new = mddev->reshape_position; - if (sector_div(here_new, (mddev->chunk_size>>9)*(mddev->raid_disks-1))) { - printk(KERN_ERR "raid5: reshape_position not on a stripe boundary\n"); + if (sector_div(here_new, (mddev->chunk_size>>9)* + (mddev->raid_disks - max_degraded))) { + printk(KERN_ERR "raid5: reshape_position not " + "on a stripe boundary\n"); return -EINVAL; } /* here_new is the stripe we will write to */ here_old = mddev->reshape_position; - sector_div(here_old, (mddev->chunk_size>>9)*(old_disks-1)); - /* here_old is the first stripe that we might need to read from */ + sector_div(here_old, (mddev->chunk_size>>9)* + (old_disks-max_degraded)); + /* here_old is the first stripe that we might need to read + * from */ if (here_new >= here_old) { /* Reading from the same stripe as writing to - bad */ - printk(KERN_ERR "raid5: reshape_position too early for auto-recovery - aborting.\n"); + printk(KERN_ERR "raid5: reshape_position too early for " + "auto-recovery - aborting.\n"); return -EINVAL; } printk(KERN_INFO "raid5: reshape will continue\n"); @@ -3814,6 +3901,8 @@ static int raid5_check_reshape(mddev_t *mddev) if (err) return err; + if (mddev->degraded > conf->max_degraded) + return -EINVAL; /* looks like we might be able to manage this */ return 0; } @@ -3827,8 +3916,7 @@ static int raid5_start_reshape(mddev_t *mddev) int added_devices = 0; unsigned long flags; - if (mddev->degraded || - test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) + if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) return -EBUSY; ITERATE_RDEV(mddev, rdev, rtmp) @@ -3836,7 +3924,7 @@ static int raid5_start_reshape(mddev_t *mddev) !test_bit(Faulty, &rdev->flags)) spares++; - if (spares < mddev->delta_disks-1) + if (spares - mddev->degraded < mddev->delta_disks - conf->max_degraded) /* Not enough devices even to make a degraded array * of that size */ @@ -3899,7 +3987,8 @@ static void end_reshape(raid5_conf_t *conf) struct block_device *bdev; if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) { - conf->mddev->array_size = conf->mddev->size * (conf->raid_disks-1); + conf->mddev->array_size = conf->mddev->size * + (conf->raid_disks - conf->max_degraded); set_capacity(conf->mddev->gendisk, conf->mddev->array_size << 1); conf->mddev->changed = 1; @@ -3972,6 +4061,10 @@ static struct mdk_personality raid6_personality = .spare_active = raid5_spare_active, .sync_request = sync_request, .resize = raid5_resize, +#ifdef CONFIG_MD_RAID5_RESHAPE + .check_reshape = raid5_check_reshape, + .start_reshape = raid5_start_reshape, +#endif .quiesce = raid5_quiesce, }; static struct mdk_personality raid5_personality = diff --git a/drivers/md/raid6mmx.c b/drivers/md/raid6mmx.c index 359157aaf9e..6181a5a3365 100644 --- a/drivers/md/raid6mmx.c +++ b/drivers/md/raid6mmx.c @@ -30,14 +30,8 @@ const struct raid6_mmx_constants { static int raid6_have_mmx(void) { -#ifdef __KERNEL__ /* Not really "boot_cpu" but "all_cpus" */ return boot_cpu_has(X86_FEATURE_MMX); -#else - /* User space test code */ - u32 features = cpuid_features(); - return ( (features & (1<<23)) == (1<<23) ); -#endif } /* @@ -48,13 +42,12 @@ static void raid6_mmx1_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_mmx_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_mmx(&sa); + kernel_fpu_begin(); asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d)); asm volatile("pxor %mm5,%mm5"); /* Zero temp */ @@ -78,7 +71,7 @@ static void raid6_mmx1_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("pxor %mm4,%mm4"); } - raid6_after_mmx(&sa); + kernel_fpu_end(); } const struct raid6_calls raid6_mmxx1 = { @@ -96,13 +89,12 @@ static void raid6_mmx2_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_mmx_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_mmx(&sa); + kernel_fpu_begin(); asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d)); asm volatile("pxor %mm5,%mm5"); /* Zero temp */ @@ -137,7 +129,7 @@ static void raid6_mmx2_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("movq %%mm6,%0" : "=m" (q[d+8])); } - raid6_after_mmx(&sa); + kernel_fpu_end(); } const struct raid6_calls raid6_mmxx2 = { diff --git a/drivers/md/raid6sse1.c b/drivers/md/raid6sse1.c index f7e7859f71a..f0a1ba8f40b 100644 --- a/drivers/md/raid6sse1.c +++ b/drivers/md/raid6sse1.c @@ -33,16 +33,10 @@ extern const struct raid6_mmx_constants { static int raid6_have_sse1_or_mmxext(void) { -#ifdef __KERNEL__ /* Not really boot_cpu but "all_cpus" */ return boot_cpu_has(X86_FEATURE_MMX) && (boot_cpu_has(X86_FEATURE_XMM) || boot_cpu_has(X86_FEATURE_MMXEXT)); -#else - /* User space test code - this incorrectly breaks on some Athlons */ - u32 features = cpuid_features(); - return ( (features & (5<<23)) == (5<<23) ); -#endif } /* @@ -53,14 +47,12 @@ static void raid6_sse11_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_mmx_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - /* This is really MMX code, not SSE */ - raid6_before_mmx(&sa); + kernel_fpu_begin(); asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d)); asm volatile("pxor %mm5,%mm5"); /* Zero temp */ @@ -94,8 +86,8 @@ static void raid6_sse11_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("movntq %%mm4,%0" : "=m" (q[d])); } - raid6_after_mmx(&sa); asm volatile("sfence" : : : "memory"); + kernel_fpu_end(); } const struct raid6_calls raid6_sse1x1 = { @@ -113,13 +105,12 @@ static void raid6_sse12_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_mmx_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_mmx(&sa); + kernel_fpu_begin(); asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d)); asm volatile("pxor %mm5,%mm5"); /* Zero temp */ @@ -157,8 +148,8 @@ static void raid6_sse12_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("movntq %%mm6,%0" : "=m" (q[d+8])); } - raid6_after_mmx(&sa); asm volatile("sfence" : :: "memory"); + kernel_fpu_end(); } const struct raid6_calls raid6_sse1x2 = { diff --git a/drivers/md/raid6sse2.c b/drivers/md/raid6sse2.c index b3aa7fe0877..0f019762a7c 100644 --- a/drivers/md/raid6sse2.c +++ b/drivers/md/raid6sse2.c @@ -30,17 +30,11 @@ static const struct raid6_sse_constants { static int raid6_have_sse2(void) { -#ifdef __KERNEL__ /* Not really boot_cpu but "all_cpus" */ return boot_cpu_has(X86_FEATURE_MMX) && boot_cpu_has(X86_FEATURE_FXSR) && boot_cpu_has(X86_FEATURE_XMM) && boot_cpu_has(X86_FEATURE_XMM2); -#else - /* User space test code */ - u32 features = cpuid_features(); - return ( (features & (15<<23)) == (15<<23) ); -#endif } /* @@ -51,13 +45,12 @@ static void raid6_sse21_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_sse_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_sse2(&sa); + kernel_fpu_begin(); asm volatile("movdqa %0,%%xmm0" : : "m" (raid6_sse_constants.x1d[0])); asm volatile("pxor %xmm5,%xmm5"); /* Zero temp */ @@ -93,8 +86,8 @@ static void raid6_sse21_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("pxor %xmm4,%xmm4"); } - raid6_after_sse2(&sa); asm volatile("sfence" : : : "memory"); + kernel_fpu_end(); } const struct raid6_calls raid6_sse2x1 = { @@ -112,13 +105,12 @@ static void raid6_sse22_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_sse_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_sse2(&sa); + kernel_fpu_begin(); asm volatile("movdqa %0,%%xmm0" : : "m" (raid6_sse_constants.x1d[0])); asm volatile("pxor %xmm5,%xmm5"); /* Zero temp */ @@ -156,8 +148,8 @@ static void raid6_sse22_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("movntdq %%xmm6,%0" : "=m" (q[d+16])); } - raid6_after_sse2(&sa); asm volatile("sfence" : : : "memory"); + kernel_fpu_end(); } const struct raid6_calls raid6_sse2x2 = { @@ -179,13 +171,12 @@ static void raid6_sse24_gen_syndrome(int disks, size_t bytes, void **ptrs) u8 **dptr = (u8 **)ptrs; u8 *p, *q; int d, z, z0; - raid6_sse16_save_t sa; z0 = disks - 3; /* Highest data disk */ p = dptr[z0+1]; /* XOR parity */ q = dptr[z0+2]; /* RS syndrome */ - raid6_before_sse16(&sa); + kernel_fpu_begin(); asm volatile("movdqa %0,%%xmm0" :: "m" (raid6_sse_constants.x1d[0])); asm volatile("pxor %xmm2,%xmm2"); /* P[0] */ @@ -256,8 +247,9 @@ static void raid6_sse24_gen_syndrome(int disks, size_t bytes, void **ptrs) asm volatile("movntdq %%xmm14,%0" : "=m" (q[d+48])); asm volatile("pxor %xmm14,%xmm14"); } + asm volatile("sfence" : : : "memory"); - raid6_after_sse16(&sa); + kernel_fpu_end(); } const struct raid6_calls raid6_sse2x4 = { diff --git a/drivers/md/raid6x86.h b/drivers/md/raid6x86.h index 4cf20534fe4..9111950414f 100644 --- a/drivers/md/raid6x86.h +++ b/drivers/md/raid6x86.h @@ -21,224 +21,40 @@ #if defined(__i386__) || defined(__x86_64__) -#ifdef __x86_64__ - -typedef struct { - unsigned int fsave[27]; - unsigned long cr0; -} raid6_mmx_save_t __attribute__((aligned(16))); - -/* N.B.: For SSE we only save %xmm0-%xmm7 even for x86-64, since - the code doesn't know about the additional x86-64 registers */ -typedef struct { - unsigned int sarea[8*4+2]; - unsigned long cr0; -} raid6_sse_save_t __attribute__((aligned(16))); - -/* This is for x86-64-specific code which uses all 16 XMM registers */ -typedef struct { - unsigned int sarea[16*4+2]; - unsigned long cr0; -} raid6_sse16_save_t __attribute__((aligned(16))); - -/* On x86-64 the stack *SHOULD* be 16-byte aligned, but currently this - is buggy in the kernel and it's only 8-byte aligned in places, so - we need to do this anyway. Sigh. */ -#define SAREA(x) ((unsigned int *)((((unsigned long)&(x)->sarea)+15) & ~15)) - -#else /* __i386__ */ - -typedef struct { - unsigned int fsave[27]; - unsigned long cr0; -} raid6_mmx_save_t; - -/* On i386, the stack is only 8-byte aligned, but SSE requires 16-byte - alignment. The +3 is so we have the slack space to manually align - a properly-sized area correctly. */ -typedef struct { - unsigned int sarea[8*4+3]; - unsigned long cr0; -} raid6_sse_save_t; - -/* Find the 16-byte aligned save area */ -#define SAREA(x) ((unsigned int *)((((unsigned long)&(x)->sarea)+15) & ~15)) - -#endif - #ifdef __KERNEL__ /* Real code */ -/* Note: %cr0 is 32 bits on i386 and 64 bits on x86-64 */ - -static inline unsigned long raid6_get_fpu(void) -{ - unsigned long cr0; - - preempt_disable(); - asm volatile("mov %%cr0,%0 ; clts" : "=r" (cr0)); - return cr0; -} - -static inline void raid6_put_fpu(unsigned long cr0) -{ - asm volatile("mov %0,%%cr0" : : "r" (cr0)); - preempt_enable(); -} +#include <asm/i387.h> #else /* Dummy code for user space testing */ -static inline unsigned long raid6_get_fpu(void) -{ - return 0xf00ba6; -} - -static inline void raid6_put_fpu(unsigned long cr0) -{ - (void)cr0; -} - -#endif - -static inline void raid6_before_mmx(raid6_mmx_save_t *s) -{ - s->cr0 = raid6_get_fpu(); - asm volatile("fsave %0 ; fwait" : "=m" (s->fsave[0])); -} - -static inline void raid6_after_mmx(raid6_mmx_save_t *s) -{ - asm volatile("frstor %0" : : "m" (s->fsave[0])); - raid6_put_fpu(s->cr0); -} - -static inline void raid6_before_sse(raid6_sse_save_t *s) -{ - unsigned int *rsa = SAREA(s); - - s->cr0 = raid6_get_fpu(); - - asm volatile("movaps %%xmm0,%0" : "=m" (rsa[0])); - asm volatile("movaps %%xmm1,%0" : "=m" (rsa[4])); - asm volatile("movaps %%xmm2,%0" : "=m" (rsa[8])); - asm volatile("movaps %%xmm3,%0" : "=m" (rsa[12])); - asm volatile("movaps %%xmm4,%0" : "=m" (rsa[16])); - asm volatile("movaps %%xmm5,%0" : "=m" (rsa[20])); - asm volatile("movaps %%xmm6,%0" : "=m" (rsa[24])); - asm volatile("movaps %%xmm7,%0" : "=m" (rsa[28])); -} - -static inline void raid6_after_sse(raid6_sse_save_t *s) -{ - unsigned int *rsa = SAREA(s); - - asm volatile("movaps %0,%%xmm0" : : "m" (rsa[0])); - asm volatile("movaps %0,%%xmm1" : : "m" (rsa[4])); - asm volatile("movaps %0,%%xmm2" : : "m" (rsa[8])); - asm volatile("movaps %0,%%xmm3" : : "m" (rsa[12])); - asm volatile("movaps %0,%%xmm4" : : "m" (rsa[16])); - asm volatile("movaps %0,%%xmm5" : : "m" (rsa[20])); - asm volatile("movaps %0,%%xmm6" : : "m" (rsa[24])); - asm volatile("movaps %0,%%xmm7" : : "m" (rsa[28])); - - raid6_put_fpu(s->cr0); -} - -static inline void raid6_before_sse2(raid6_sse_save_t *s) +static inline void kernel_fpu_begin(void) { - unsigned int *rsa = SAREA(s); - - s->cr0 = raid6_get_fpu(); - - asm volatile("movdqa %%xmm0,%0" : "=m" (rsa[0])); - asm volatile("movdqa %%xmm1,%0" : "=m" (rsa[4])); - asm volatile("movdqa %%xmm2,%0" : "=m" (rsa[8])); - asm volatile("movdqa %%xmm3,%0" : "=m" (rsa[12])); - asm volatile("movdqa %%xmm4,%0" : "=m" (rsa[16])); - asm volatile("movdqa %%xmm5,%0" : "=m" (rsa[20])); - asm volatile("movdqa %%xmm6,%0" : "=m" (rsa[24])); - asm volatile("movdqa %%xmm7,%0" : "=m" (rsa[28])); } -static inline void raid6_after_sse2(raid6_sse_save_t *s) +static inline void kernel_fpu_end(void) { - unsigned int *rsa = SAREA(s); - - asm volatile("movdqa %0,%%xmm0" : : "m" (rsa[0])); - asm volatile("movdqa %0,%%xmm1" : : "m" (rsa[4])); - asm volatile("movdqa %0,%%xmm2" : : "m" (rsa[8])); - asm volatile("movdqa %0,%%xmm3" : : "m" (rsa[12])); - asm volatile("movdqa %0,%%xmm4" : : "m" (rsa[16])); - asm volatile("movdqa %0,%%xmm5" : : "m" (rsa[20])); - asm volatile("movdqa %0,%%xmm6" : : "m" (rsa[24])); - asm volatile("movdqa %0,%%xmm7" : : "m" (rsa[28])); - - raid6_put_fpu(s->cr0); } -#ifdef __x86_64__ - -static inline void raid6_before_sse16(raid6_sse16_save_t *s) -{ - unsigned int *rsa = SAREA(s); - - s->cr0 = raid6_get_fpu(); +#define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */ +#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE and FXRSTOR instructions + * (fast save and restore) */ +#define X86_FEATURE_XMM (0*32+25) /* Streaming SIMD Extensions */ +#define X86_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */ +#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */ - asm volatile("movdqa %%xmm0,%0" : "=m" (rsa[0])); - asm volatile("movdqa %%xmm1,%0" : "=m" (rsa[4])); - asm volatile("movdqa %%xmm2,%0" : "=m" (rsa[8])); - asm volatile("movdqa %%xmm3,%0" : "=m" (rsa[12])); - asm volatile("movdqa %%xmm4,%0" : "=m" (rsa[16])); - asm volatile("movdqa %%xmm5,%0" : "=m" (rsa[20])); - asm volatile("movdqa %%xmm6,%0" : "=m" (rsa[24])); - asm volatile("movdqa %%xmm7,%0" : "=m" (rsa[28])); - asm volatile("movdqa %%xmm8,%0" : "=m" (rsa[32])); - asm volatile("movdqa %%xmm9,%0" : "=m" (rsa[36])); - asm volatile("movdqa %%xmm10,%0" : "=m" (rsa[40])); - asm volatile("movdqa %%xmm11,%0" : "=m" (rsa[44])); - asm volatile("movdqa %%xmm12,%0" : "=m" (rsa[48])); - asm volatile("movdqa %%xmm13,%0" : "=m" (rsa[52])); - asm volatile("movdqa %%xmm14,%0" : "=m" (rsa[56])); - asm volatile("movdqa %%xmm15,%0" : "=m" (rsa[60])); -} - -static inline void raid6_after_sse16(raid6_sse16_save_t *s) +/* Should work well enough on modern CPUs for testing */ +static inline int boot_cpu_has(int flag) { - unsigned int *rsa = SAREA(s); + u32 eax = (flag >> 5) ? 0x80000001 : 1; + u32 edx; - asm volatile("movdqa %0,%%xmm0" : : "m" (rsa[0])); - asm volatile("movdqa %0,%%xmm1" : : "m" (rsa[4])); - asm volatile("movdqa %0,%%xmm2" : : "m" (rsa[8])); - asm volatile("movdqa %0,%%xmm3" : : "m" (rsa[12])); - asm volatile("movdqa %0,%%xmm4" : : "m" (rsa[16])); - asm volatile("movdqa %0,%%xmm5" : : "m" (rsa[20])); - asm volatile("movdqa %0,%%xmm6" : : "m" (rsa[24])); - asm volatile("movdqa %0,%%xmm7" : : "m" (rsa[28])); - asm volatile("movdqa %0,%%xmm8" : : "m" (rsa[32])); - asm volatile("movdqa %0,%%xmm9" : : "m" (rsa[36])); - asm volatile("movdqa %0,%%xmm10" : : "m" (rsa[40])); - asm volatile("movdqa %0,%%xmm11" : : "m" (rsa[44])); - asm volatile("movdqa %0,%%xmm12" : : "m" (rsa[48])); - asm volatile("movdqa %0,%%xmm13" : : "m" (rsa[52])); - asm volatile("movdqa %0,%%xmm14" : : "m" (rsa[56])); - asm volatile("movdqa %0,%%xmm15" : : "m" (rsa[60])); + asm volatile("cpuid" + : "+a" (eax), "=d" (edx) + : : "ecx", "ebx"); - raid6_put_fpu(s->cr0); + return (edx >> (flag & 31)) & 1; } -#endif /* __x86_64__ */ - -/* User space test hack */ -#ifndef __KERNEL__ -static inline int cpuid_features(void) -{ - u32 eax = 1; - u32 ebx, ecx, edx; - - asm volatile("cpuid" : - "+a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)); - - return edx; -} #endif /* ndef __KERNEL__ */ #endif diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 15d12fce34d..127a94b9a1b 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -469,9 +469,9 @@ static int bluebird_patch_dvico_firmware_download(struct usb_device *udev, fw->data[BLUEBIRD_01_ID_OFFSET + 1] == USB_VID_DVICO >> 8) { fw->data[BLUEBIRD_01_ID_OFFSET + 2] = - udev->descriptor.idProduct + 1; + le16_to_cpu(udev->descriptor.idProduct) + 1; fw->data[BLUEBIRD_01_ID_OFFSET + 3] = - udev->descriptor.idProduct >> 8; + le16_to_cpu(udev->descriptor.idProduct) >> 8; return usb_cypress_load_firmware(udev, fw, CYPRESS_FX2); } diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c index 4a198d4755b..b5acb11c0bc 100644 --- a/drivers/media/dvb/dvb-usb/digitv.c +++ b/drivers/media/dvb/dvb-usb/digitv.c @@ -119,6 +119,8 @@ static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe, struct dvb_f struct dvb_usb_adapter *adap = fe->dvb->priv; u8 b[5]; dvb_usb_tuner_calc_regs(fe,fep,b, 5); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); return digitv_ctrl_msg(adap->dev, USB_WRITE_TUNER, 0, &b[1], 4, NULL, 0); } diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 682dc7ce48d..710c11a6829 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -1022,7 +1022,7 @@ static ssize_t cafe_v4l_read(struct file *filp, char __user *buffer, size_t len, loff_t *pos) { struct cafe_camera *cam = filp->private_data; - int ret; + int ret = 0; /* * Perhaps we're in speculative read mode and already @@ -1251,8 +1251,6 @@ static int cafe_vidioc_reqbufs(struct file *filp, void *priv, if (cam->n_sbufs == 0) /* no luck at all - ret already set */ kfree(cam->sb_bufs); - else - ret = 0; req->count = cam->n_sbufs; /* In case of partial success */ out: diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index cc535ca713d..774d2536555 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c @@ -633,7 +633,7 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_CX25840) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -903,13 +903,13 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, state->vbi_line_offset = 8; state->id = id; + i2c_attach_client(client); + if (state->is_cx25836) cx25836_initialize(client); else cx25840_initialize(client, 1); - i2c_attach_client(client); - return 0; } diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c index 1958d4016ea..0e86b9d033a 100644 --- a/drivers/media/video/cx25840/cx25840-firmware.c +++ b/drivers/media/video/cx25840/cx25840-firmware.c @@ -37,7 +37,7 @@ */ #define FWSEND 48 -#define FWDEV(x) &((x)->adapter->dev) +#define FWDEV(x) &((x)->dev) static char *firmware = FWFILE; diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index a97be1bdc31..bdfe2af7012 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1389,7 +1389,7 @@ static int vidioc_g_register (struct file *file, void *fh, { struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - if (reg->i2c_id != 0) + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; /* cx2388x has a 24-bit register space */ reg->val = cx_read(reg->reg&0xffffff); @@ -1401,7 +1401,7 @@ static int vidioc_s_register (struct file *file, void *fh, { struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; - if (reg->i2c_id != 0) + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; cx_write(reg->reg&0xffffff, reg->val); return 0; diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index a1ca0f5007e..1cd4bb3ae26 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -3256,8 +3256,8 @@ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) int pvr2_hdw_register_access(struct pvr2_hdw *hdw, - u32 chip_id, u64 reg_id, - int setFl,u32 *val_ptr) + u32 match_type, u32 match_chip, u64 reg_id, + int setFl,u64 *val_ptr) { #ifdef CONFIG_VIDEO_ADV_DEBUG struct list_head *item; @@ -3268,13 +3268,16 @@ int pvr2_hdw_register_access(struct pvr2_hdw *hdw, if (!capable(CAP_SYS_ADMIN)) return -EPERM; - req.i2c_id = chip_id; + req.match_type = match_type; + req.match_chip = match_chip; req.reg = reg_id; if (setFl) req.val = *val_ptr; mutex_lock(&hdw->i2c_list_lock); do { list_for_each(item,&hdw->i2c_clients) { cp = list_entry(item,struct pvr2_i2c_client,list); - if (cp->client->driver->id != chip_id) continue; + if (!v4l2_chip_match_i2c_client(cp->client, req.match_type, req.match_chip)) { + continue; + } stat = pvr2_i2c_client_cmd( cp,(setFl ? VIDIOC_DBG_S_REGISTER : VIDIOC_DBG_G_REGISTER),&req); diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h index 566a8ef7e12..0c9cca43ff8 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -217,13 +217,14 @@ void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *, enum pvr2_v4l_type index,int); /* Direct read/write access to chip's registers: - chip_id - unique id of chip (e.g. I2C_DRIVERD_xxxx) + match_type - how to interpret match_chip (e.g. driver ID, i2c address) + match_chip - chip match value (e.g. I2C_DRIVERD_xxxx) reg_id - register number to access setFl - true to set the register, false to read it val_ptr - storage location for source / result. */ int pvr2_hdw_register_access(struct pvr2_hdw *, - u32 chip_id,u64 reg_id, - int setFl,u32 *val_ptr); + u32 match_type, u32 match_chip,u64 reg_id, + int setFl,u64 *val_ptr); /* The following entry points are all lower level things you normally don't want to worry about. */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 4fe4136204c..5313d342666 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -740,11 +740,11 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_DBG_S_REGISTER: case VIDIOC_DBG_G_REGISTER: { - u32 val; + u64 val; struct v4l2_register *req = (struct v4l2_register *)arg; if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val; ret = pvr2_hdw_register_access( - hdw,req->i2c_id,req->reg, + hdw,req->match_type,req->match_chip,req->reg, cmd == VIDIOC_DBG_S_REGISTER,&val); if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val; break; diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index c4f066d6668..7735b675892 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1425,7 +1425,7 @@ static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *ar { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_SAA711X) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index bd9c4f3ad02..654863db159 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -619,7 +619,7 @@ static int saa7127_command(struct i2c_client *client, { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_SAA7127) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 886b5df7c9d..d5ec05f56ad 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c @@ -955,7 +955,7 @@ static int tvp5150_command(struct i2c_client *c, { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_TVP5150) + if (!v4l2_chip_match_i2c_client(c, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/upd64031a.c b/drivers/media/video/upd64031a.c index b3b5fd536dc..28d1133a3b7 100644 --- a/drivers/media/video/upd64031a.c +++ b/drivers/media/video/upd64031a.c @@ -167,7 +167,7 @@ static int upd64031a_command(struct i2c_client *client, unsigned int cmd, void * { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_UPD64031A) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/upd64083.c b/drivers/media/video/upd64083.c index 8852903e7a9..fe38224150d 100644 --- a/drivers/media/video/upd64083.c +++ b/drivers/media/video/upd64083.c @@ -144,7 +144,7 @@ static int upd64083_command(struct i2c_client *client, unsigned int cmd, void *a { struct v4l2_register *reg = arg; - if (reg->i2c_id != I2C_DRIVERID_UPD64083) + if (!v4l2_chip_match_i2c_client(client, reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index ae5f42562c0..6fc14557d62 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -521,7 +521,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, struct v4l2_register *reg = arg; int errCode; - if (reg->i2c_id != 0) + if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -540,7 +540,7 @@ static int usbvision_v4l2_do_ioctl(struct inode *inode, struct file *file, PDEBUG(DBG_IOCTL, "VIDIOC_DBG_%c_REGISTER reg=0x%02X, value=0x%02X", cmd == VIDIOC_DBG_G_REGISTER ? 'G' : 'S', - (unsigned int)reg->reg, reg->val); + (unsigned int)reg->reg, (unsigned int)reg->val); return 0; } #endif diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index ddfd80c5618..54747606eae 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c @@ -51,6 +51,7 @@ #include <linux/mm.h> #include <linux/string.h> #include <linux/errno.h> +#include <linux/i2c.h> #include <asm/uaccess.h> #include <asm/system.h> #include <asm/pgtable.h> @@ -365,13 +366,21 @@ static const char *v4l2_ioctls[] = { [_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT", [_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY", [_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY", -#if 1 [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP", -#endif [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS", [_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS", [_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS", - [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS" + [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS", +#if 1 + [_IOC_NR(VIDIOC_ENUM_FRAMESIZES)] = "VIDIOC_ENUM_FRAMESIZES", + [_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS", + [_IOC_NR(VIDIOC_G_ENC_INDEX)] = "VIDIOC_G_ENC_INDEX", + [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD", + [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD", + + [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", + [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", +#endif }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) @@ -395,9 +404,6 @@ static const char *v4l2_int_ioctls[] = { [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY", [_IOC_NR(TDA9887_SET_CONFIG)] = "TDA9887_SET_CONFIG", - [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER", - [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER", - [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)] = "VIDIOC_INT_S_TUNER_MODE", [_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET", [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ", @@ -947,6 +953,28 @@ u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) return **ctrl_classes; } +int v4l2_chip_match_i2c_client(struct i2c_client *c, u32 match_type, u32 match_chip) +{ + switch (match_type) { + case V4L2_CHIP_MATCH_I2C_DRIVER: + return (c != NULL && c->driver != NULL && c->driver->id == match_chip); + case V4L2_CHIP_MATCH_I2C_ADDR: + return (c != NULL && c->addr == match_chip); + default: + return 0; + } +} + +int v4l2_chip_match_host(u32 match_type, u32 match_chip) +{ + switch (match_type) { + case V4L2_CHIP_MATCH_HOST: + return match_chip == 0; + default: + return 0; + } +} + /* ----------------------------------------------------------------- */ EXPORT_SYMBOL(v4l2_norm_to_name); @@ -970,6 +998,9 @@ EXPORT_SYMBOL(v4l2_ctrl_query_menu); EXPORT_SYMBOL(v4l2_ctrl_query_fill); EXPORT_SYMBOL(v4l2_ctrl_query_fill_std); +EXPORT_SYMBOL(v4l2_chip_match_i2c_client); +EXPORT_SYMBOL(v4l2_chip_match_host); + /* * Local variables: * c-basic-offset: 8 diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index dc9b1ef678a..011938fb7e0 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c @@ -1342,6 +1342,42 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, ret=vfd->vidioc_s_jpegcomp(file, fh, p); break; } + case VIDIOC_G_ENC_INDEX: + { + struct v4l2_enc_idx *p=arg; + + if (!vfd->vidioc_g_enc_index) + break; + ret=vfd->vidioc_g_enc_index(file, fh, p); + if (!ret) + dbgarg (cmd, "entries=%d, entries_cap=%d\n", + p->entries,p->entries_cap); + break; + } + case VIDIOC_ENCODER_CMD: + { + struct v4l2_encoder_cmd *p=arg; + + if (!vfd->vidioc_encoder_cmd) + break; + ret=vfd->vidioc_encoder_cmd(file, fh, p); + if (!ret) + dbgarg (cmd, "cmd=%d, flags=%d\n", + p->cmd,p->flags); + break; + } + case VIDIOC_TRY_ENCODER_CMD: + { + struct v4l2_encoder_cmd *p=arg; + + if (!vfd->vidioc_try_encoder_cmd) + break; + ret=vfd->vidioc_try_encoder_cmd(file, fh, p); + if (!ret) + dbgarg (cmd, "cmd=%d, flags=%d\n", + p->cmd,p->flags); + break; + } case VIDIOC_G_PARM: { struct v4l2_streamparm *p=arg; diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 7a0d8ee2de9..04aaa634723 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -113,10 +113,16 @@ EXPORT_SYMBOL_GPL(rtc_device_register); */ void rtc_device_unregister(struct rtc_device *rtc) { - mutex_lock(&rtc->ops_lock); - rtc->ops = NULL; - mutex_unlock(&rtc->ops_lock); - class_device_unregister(&rtc->class_dev); + if (class_device_get(&rtc->class_dev) != NULL) { + mutex_lock(&rtc->ops_lock); + /* remove innards of this RTC, then disable it, before + * letting any rtc_class_open() users access it again + */ + class_device_unregister(&rtc->class_dev); + rtc->ops = NULL; + mutex_unlock(&rtc->ops_lock); + class_device_put(&rtc->class_dev); + } } EXPORT_SYMBOL_GPL(rtc_device_unregister); diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 6f11f6dfdd9..ef40df0f169 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -179,7 +179,7 @@ struct class_device *rtc_class_open(char *name) down(&rtc_class->sem); list_for_each_entry(class_dev_tmp, &rtc_class->children, node) { if (strncmp(class_dev_tmp->class_id, name, BUS_ID_SIZE) == 0) { - class_dev = class_dev_tmp; + class_dev = class_device_get(class_dev_tmp); break; } } @@ -197,6 +197,7 @@ EXPORT_SYMBOL_GPL(rtc_class_open); void rtc_class_close(struct class_device *class_dev) { module_put(to_rtc_device(class_dev)->owner); + class_device_put(class_dev); } EXPORT_SYMBOL_GPL(rtc_class_close); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index c1536d78555..b8f0a11e8f3 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1618,8 +1618,7 @@ config FB_IBM_GXT4500 config FB_PS3 bool "PS3 GPU framebuffer driver" - depends on FB && PPC_PS3 - select PS3_PS3AV + depends on FB && PS3_PS3AV select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 02b290ca01e..58c0ac733db 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -136,8 +136,8 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info) #define SM501_MEMF_CRT (4) #define SM501_MEMF_ACCEL (8) -int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, - unsigned int why, size_t size) +static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, + unsigned int why, size_t size) { unsigned int ptr = 0; @@ -926,7 +926,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info) * set or change the hardware cursor parameters */ -int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor) +static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor) { struct sm501fb_par *par = info->par; struct sm501fb_info *fbi = par->info; @@ -1225,7 +1225,7 @@ static struct sm501fb_info *sm501fb_info_alloc(struct fb_info *fbinfo_crt, * initialise hw cursor parameters */ -int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) +static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) { struct sm501fb_par *par = fbi->par; struct sm501fb_info *info = par->info; @@ -1768,7 +1768,7 @@ static struct platform_driver sm501fb_driver = { }, }; -int __devinit sm501fb_init(void) +static int __devinit sm501fb_init(void) { return platform_driver_register(&sm501fb_driver); } |