From 15c73aaa44e09222e9cccaa9f80e29f7f5351f2b Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 2 Oct 2008 19:47:12 +0900 Subject: serial: sh-sci: Kill off all of the SCI/SCIF special casing. This was added at a time when the compiler did a less than stellar job of optimizing out dead code. These days this tends to be less of a concern, so kill it all off. Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 17 +--------- drivers/serial/sh-sci.h | 82 +++++++++---------------------------------------- 2 files changed, 16 insertions(+), 83 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 3b9d2d83b59..6a5132f8403 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -250,8 +250,7 @@ static inline void h8300_sci_disable(struct uart_port *port) } #endif -#if defined(SCI_ONLY) || defined(SCI_AND_SCIF) && \ - defined(__H8300H__) || defined(__H8300S__) +#if defined(__H8300H__) || defined(__H8300S__) static void sci_init_pins_sci(struct uart_port* port, unsigned int cflag) { int ch = (port->mapbase - SMR0) >> 3; @@ -285,11 +284,6 @@ static void sci_init_pins_irda(struct uart_port *port, unsigned int cflag) #define sci_init_pins_irda NULL #endif -#ifdef SCI_ONLY -#define sci_init_pins_scif NULL -#endif - -#if defined(SCIF_ONLY) || defined(SCI_AND_SCIF) #if defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) static void sci_init_pins_scif(struct uart_port* port, unsigned int cflag) { @@ -449,7 +443,6 @@ static inline int scif_rxroom(struct uart_port *port) return sci_in(port, SCFDR) & SCIF_RFDC_MASK; } #endif -#endif /* SCIF_ONLY || SCI_AND_SCIF */ static inline int sci_txroom(struct uart_port *port) { @@ -485,11 +478,9 @@ static void sci_transmit_chars(struct uart_port *port) return; } -#ifndef SCI_ONLY if (port->type == PORT_SCIF) count = scif_txroom(port); else -#endif count = sci_txroom(port); do { @@ -519,12 +510,10 @@ static void sci_transmit_chars(struct uart_port *port) } else { ctrl = sci_in(port, SCSCR); -#if !defined(SCI_ONLY) if (port->type == PORT_SCIF) { sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); } -#endif ctrl |= SCI_CTRL_FLAGS_TIE; sci_out(port, SCSCR, ctrl); @@ -547,11 +536,9 @@ static inline void sci_receive_chars(struct uart_port *port) return; while (1) { -#if !defined(SCI_ONLY) if (port->type == PORT_SCIF) count = scif_rxroom(port); else -#endif count = sci_rxroom(port); /* Don't copy more bytes than there is room for in the buffer */ @@ -1054,10 +1041,8 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ -#if !defined(SCI_ONLY) if (port->type == PORT_SCIF) sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); -#endif smr_val = sci_in(port, SCSMR) & 3; if ((termios->c_cflag & CSIZE) == CS7) diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 511c10d4218..43c09a86221 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -16,7 +16,6 @@ # define SCPCR 0xA4000116 /* 16 bit SCI and SCIF */ # define SCPDR 0xA4000136 /* 8 bit SCI and SCIF */ # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ -# define SCI_AND_SCIF #elif defined(CONFIG_CPU_SUBTYPE_SH7705) # define SCIF0 0xA4400000 # define SCIF2 0xA4410000 @@ -30,17 +29,14 @@ * SCIF0 (0xA4400000) -> Internal clock, SCK pin as serial clock output */ # define SCSCR_INIT(port) (port->mapbase == SCIF2) ? 0xF3 : 0xF0 -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7720) || \ defined(CONFIG_CPU_SUBTYPE_SH7721) # define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */ -# define SCIF_ONLY #define SCIF_ORER 0x0200 /* overrun error bit */ #elif defined(CONFIG_SH_RTS7751R2D) # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \ defined(CONFIG_CPU_SUBTYPE_SH7750R) || \ defined(CONFIG_CPU_SUBTYPE_SH7750S) || \ @@ -53,28 +49,24 @@ # define SCSCR_INIT(port) (((port)->type == PORT_SCI) ? \ 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ : \ 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ ) -# define SCI_AND_SCIF #elif defined(CONFIG_CPU_SUBTYPE_SH7760) # define SCSPTR0 0xfe600024 /* 16 bit SCIF */ # define SCSPTR1 0xfe610024 /* 16 bit SCIF */ # define SCSPTR2 0xfe620024 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) # define SCSPTR0 0xA4400000 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ # define PACR 0xa4050100 # define PBCR 0xa4050102 # define SCSCR_INIT(port) 0x3B -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7343) # define SCSPTR0 0xffe00010 /* 16 bit SCIF */ # define SCSPTR1 0xffe10010 /* 16 bit SCIF */ # define SCSPTR2 0xffe20010 /* 16 bit SCIF */ # define SCSPTR3 0xffe30010 /* 16 bit SCIF */ # define SCSCR_INIT(port) 0x32 /* TIE=0,RIE=0,TE=1,RE=1,REIE=0,CKE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7722) # define PADR 0xA4050120 # define PSDR 0xA405013e @@ -82,7 +74,6 @@ # define PSCR 0xA405011E # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7366) # define SCPDR0 0xA405013E /* 16 bit SCIF0 PSDR */ # define SCSPTR0 SCPDR0 @@ -97,12 +88,10 @@ # define SCSPTR5 0xa4050128 # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) # define SCIF_BASE_ADDR 0x01030000 # define SCIF_ADDR_SH5 PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR @@ -111,14 +100,11 @@ # define SCSPTR2 ((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */ # define SCLSR2 ((port->mapbase)+SCIF_LSR2_OFFS) /* 16 bit SCIF */ # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0, TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_H83007) || defined(CONFIG_H83068) # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ -# define SCI_ONLY # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port) #elif defined(CONFIG_H8S2678) # define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ -# define SCI_ONLY # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port) #elif defined(CONFIG_CPU_SUBTYPE_SH7763) # define SCSPTR0 0xffe00024 /* 16 bit SCIF */ @@ -126,20 +112,17 @@ # define SCSPTR2 0xffe10020 /* 16 bit SCIF/IRDA */ # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7770) # define SCSPTR0 0xff923020 /* 16 bit SCIF */ # define SCSPTR1 0xff924020 /* 16 bit SCIF */ # define SCSPTR2 0xff925020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x3c /* TIE=0,RIE=0,TE=1,RE=1,REIE=1,cke=2 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7780) # define SCSPTR0 0xffe00024 /* 16 bit SCIF */ # define SCSPTR1 0xffe10024 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* Overrun error bit */ # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7785) # define SCSPTR0 0xffea0024 /* 16 bit SCIF */ # define SCSPTR1 0xffeb0024 /* 16 bit SCIF */ @@ -149,7 +132,6 @@ # define SCSPTR5 0xffef0024 /* 16 bit SCIF */ # define SCIF_OPER 0x0001 /* Overrun error bit */ # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7203) || \ defined(CONFIG_CPU_SUBTYPE_SH7206) || \ defined(CONFIG_CPU_SUBTYPE_SH7263) @@ -158,14 +140,12 @@ # define SCSPTR2 0xfffe9020 /* 16 bit SCIF */ # define SCSPTR3 0xfffe9820 /* 16 bit SCIF */ # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7619) # define SCSPTR0 0xf8400020 /* 16 bit SCIF */ # define SCSPTR1 0xf8410020 /* 16 bit SCIF */ # define SCSPTR2 0xf8420020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SHX3) # define SCSPTR0 0xffc30020 /* 16 bit SCIF */ # define SCSPTR1 0xffc40020 /* 16 bit SCIF */ @@ -173,7 +153,6 @@ # define SCSPTR3 0xffc60020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* Overrun error bit */ # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY #else # error CPU subtype not defined #endif @@ -244,55 +223,28 @@ # define SCIF_TXROOM_MAX 16 #endif -#if defined(SCI_ONLY) -# define SCxSR_TEND(port) SCI_TEND -# define SCxSR_ERRORS(port) SCI_ERRORS -# define SCxSR_RDxF(port) SCI_RDRF -# define SCxSR_TDxE(port) SCI_TDRE -# define SCxSR_ORER(port) SCI_ORER -# define SCxSR_FER(port) SCI_FER -# define SCxSR_PER(port) SCI_PER -# define SCxSR_BRK(port) 0x00 -# define SCxSR_RDxF_CLEAR(port) 0xbc -# define SCxSR_ERROR_CLEAR(port) 0xc4 -# define SCxSR_TDxE_CLEAR(port) 0x78 -# define SCxSR_BREAK_CLEAR(port) 0xc4 -#elif defined(SCIF_ONLY) -# define SCxSR_TEND(port) SCIF_TEND -# define SCxSR_ERRORS(port) SCIF_ERRORS -# define SCxSR_RDxF(port) SCIF_RDF -# define SCxSR_TDxE(port) SCIF_TDFE +#define SCxSR_TEND(port) (((port)->type == PORT_SCI) ? SCI_TEND : SCIF_TEND) +#define SCxSR_ERRORS(port) (((port)->type == PORT_SCI) ? SCI_ERRORS : SCIF_ERRORS) +#define SCxSR_RDxF(port) (((port)->type == PORT_SCI) ? SCI_RDRF : SCIF_RDF) +#define SCxSR_TDxE(port) (((port)->type == PORT_SCI) ? SCI_TDRE : SCIF_TDFE) +#define SCxSR_FER(port) (((port)->type == PORT_SCI) ? SCI_FER : SCIF_FER) +#define SCxSR_PER(port) (((port)->type == PORT_SCI) ? SCI_PER : SCIF_PER) +#define SCxSR_BRK(port) (((port)->type == PORT_SCI) ? 0x00 : SCIF_BRK) + #if defined(CONFIG_CPU_SUBTYPE_SH7705) -# define SCxSR_ORER(port) SCIF_ORER +# define SCxSR_ORER(port) (((port)->type == PORT_SCI) ? SCI_ORER : SCIF_ORER) #else -# define SCxSR_ORER(port) 0x0000 +# define SCxSR_ORER(port) (((port)->type == PORT_SCI) ? SCI_ORER : 0x0000) #endif -# define SCxSR_FER(port) SCIF_FER -# define SCxSR_PER(port) SCIF_PER -# define SCxSR_BRK(port) SCIF_BRK + #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ defined(CONFIG_CPU_SUBTYPE_SH7720) || \ defined(CONFIG_CPU_SUBTYPE_SH7721) -# define SCxSR_RDxF_CLEAR(port) (sci_in(port,SCxSR)&0xfffc) -# define SCxSR_ERROR_CLEAR(port) (sci_in(port,SCxSR)&0xfd73) -# define SCxSR_TDxE_CLEAR(port) (sci_in(port,SCxSR)&0xffdf) -# define SCxSR_BREAK_CLEAR(port) (sci_in(port,SCxSR)&0xffe3) -#else -/* SH7705 can also use this, clearing is same between 7705 and 7709 */ -# define SCxSR_RDxF_CLEAR(port) 0x00fc -# define SCxSR_ERROR_CLEAR(port) 0x0073 -# define SCxSR_TDxE_CLEAR(port) 0x00df -# define SCxSR_BREAK_CLEAR(port) 0x00e3 -#endif +# define SCxSR_RDxF_CLEAR(port) (sci_in(port, SCxSR) & 0xfffc) +# define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73) +# define SCxSR_TDxE_CLEAR(port) (sci_in(port, SCxSR) & 0xffdf) +# define SCxSR_BREAK_CLEAR(port) (sci_in(port, SCxSR) & 0xffe3) #else -# define SCxSR_TEND(port) (((port)->type == PORT_SCI) ? SCI_TEND : SCIF_TEND) -# define SCxSR_ERRORS(port) (((port)->type == PORT_SCI) ? SCI_ERRORS : SCIF_ERRORS) -# define SCxSR_RDxF(port) (((port)->type == PORT_SCI) ? SCI_RDRF : SCIF_RDF) -# define SCxSR_TDxE(port) (((port)->type == PORT_SCI) ? SCI_TDRE : SCIF_TDFE) -# define SCxSR_ORER(port) (((port)->type == PORT_SCI) ? SCI_ORER : 0x0000) -# define SCxSR_FER(port) (((port)->type == PORT_SCI) ? SCI_FER : SCIF_FER) -# define SCxSR_PER(port) (((port)->type == PORT_SCI) ? SCI_PER : SCIF_PER) -# define SCxSR_BRK(port) (((port)->type == PORT_SCI) ? 0x00 : SCIF_BRK) # define SCxSR_RDxF_CLEAR(port) (((port)->type == PORT_SCI) ? 0xbc : 0x00fc) # define SCxSR_ERROR_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x0073) # define SCxSR_TDxE_CLEAR(port) (((port)->type == PORT_SCI) ? 0x78 : 0x00df) @@ -578,14 +530,10 @@ static inline int sci_rxd_in(struct uart_port *port) defined(CONFIG_CPU_SUBTYPE_SH4_202) static inline int sci_rxd_in(struct uart_port *port) { -#ifndef SCIF_ONLY if (port->mapbase == 0xffe00000) return ctrl_inb(SCSPTR1)&0x01 ? 1 : 0; /* SCI */ -#endif -#ifndef SCI_ONLY if (port->mapbase == 0xffe80000) return ctrl_inw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ -#endif return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7760) -- cgit v1.2.3 From aafcf998c333a2a29e12093437eef32a60a8018d Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 5 Oct 2008 17:35:41 +0100 Subject: pcmcia: IRQ_TYPE_EXCLUSIVE is long obsoleted Switch more drivers to dynamic sharing after checking their IRQ handlers use dev_id and are robust Signed-off-by: Alan Cox Acked-by: Marcel Holtmann Signed-off-by: Dominik Brodowski --- drivers/bluetooth/bluecard_cs.c | 2 +- drivers/bluetooth/bt3c_cs.c | 6 ++++-- drivers/bluetooth/btuart_cs.c | 6 ++++-- drivers/bluetooth/dtl1_cs.c | 7 +++++-- drivers/char/pcmcia/synclink_cs.c | 2 +- drivers/parport/parport_cs.c | 2 +- 6 files changed, 16 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index e6ee21d99d9..b0e569ba730 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -867,7 +867,7 @@ static int bluecard_probe(struct pcmcia_device *link) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.NumPorts1 = 8; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = bluecard_interrupt; diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 2cbe70b6647..b3e4d07a4ac 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -343,6 +343,7 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst) bt3c_info_t *info = dev_inst; unsigned int iobase; int iir; + irqreturn_t r = IRQ_NONE; BUG_ON(!info->hdev); @@ -374,11 +375,12 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst) outb(iir, iobase + CONTROL); } + r = IRQ_HANDLED; } spin_unlock(&(info->lock)); - return IRQ_HANDLED; + return r; } @@ -657,7 +659,7 @@ static int bt3c_probe(struct pcmcia_device *link) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.NumPorts1 = 8; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = bt3c_interrupt; diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 8e556b7ff9f..efd689a062e 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -293,6 +293,7 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst) unsigned int iobase; int boguscount = 0; int iir, lsr; + irqreturn_t r = IRQ_NONE; BUG_ON(!info->hdev); @@ -302,6 +303,7 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst) iir = inb(iobase + UART_IIR) & UART_IIR_ID; while (iir) { + r = IRQ_HANDLED; /* Clear interrupt */ lsr = inb(iobase + UART_LSR); @@ -335,7 +337,7 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst) spin_unlock(&(info->lock)); - return IRQ_HANDLED; + return r; } @@ -586,7 +588,7 @@ static int btuart_probe(struct pcmcia_device *link) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.NumPorts1 = 8; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = btuart_interrupt; diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index e6e6b037695..901bdd95655 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -297,6 +297,7 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst) unsigned char msr; int boguscount = 0; int iir, lsr; + irqreturn_t r = IRQ_NONE; BUG_ON(!info->hdev); @@ -307,6 +308,7 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst) iir = inb(iobase + UART_IIR) & UART_IIR_ID; while (iir) { + r = IRQ_HANDLED; /* Clear interrupt */ lsr = inb(iobase + UART_LSR); @@ -343,11 +345,12 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst) info->ri_latch = msr & UART_MSR_RI; clear_bit(XMIT_WAITING, &(info->tx_state)); dtl1_write_wakeup(info); + r = IRQ_HANDLED; } spin_unlock(&(info->lock)); - return IRQ_HANDLED; + return r; } @@ -568,7 +571,7 @@ static int dtl1_probe(struct pcmcia_device *link) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.NumPorts1 = 8; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = dtl1_interrupt; diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 9a626e50b79..4d64a02612a 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -554,7 +554,7 @@ static int mgslpc_probe(struct pcmcia_device *link) /* Initialize the struct pcmcia_device structure */ /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.Handler = NULL; diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index b1899e9c1f6..0cd5fbc7f2c 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -112,7 +112,7 @@ static int parport_probe(struct pcmcia_device *link) link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; -- cgit v1.2.3 From 7bbfd39bb9a5623cb8e0bcc54aee9b43d9ee97b9 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 5 Oct 2008 17:35:59 +0100 Subject: pcmcia: Whine harder about use of EXCLUSIVE The exclusive IRQ line support is a legacy and any remaining drivers that cannot share interrupts need tidying up so whine harder about them. Signed-off-by: Alan Cox Signed-off-by: Dominik Brodowski --- drivers/pcmcia/pcmcia_resource.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index afea2b2558b..76d4a98f095 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -693,8 +693,9 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req) type = 0; if (s->functions > 1) /* All of this ought to be handled higher up */ type = IRQF_SHARED; - if (req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) + else if (req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) type = IRQF_SHARED; + else printk(KERN_WARNING "pcmcia: Driver needs updating to support IRQ sharing.\n"); #ifdef CONFIG_PCMCIA_PROBE -- cgit v1.2.3 From 5cb02ff3489d710c73b4a21bb804feedeacce116 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 5 Oct 2008 17:39:16 +0100 Subject: fdomain_cs: Sort out modules with duplicate description The PCMCIA one provides its own description so in PCMCIA mode we should use that. Signed-off-by: Alan Cox Signed-off-by: Dominik Brodowski --- drivers/scsi/fdomain.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index c33bcb284df..56f4e6bffc2 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -290,9 +290,11 @@ #include #include "fdomain.h" +#ifndef PCMCIA MODULE_AUTHOR("Rickard E. Faith"); MODULE_DESCRIPTION("Future domain SCSI driver"); MODULE_LICENSE("GPL"); +#endif #define VERSION "$Revision: 5.51 $" -- cgit v1.2.3 From 0f0254fa8ddce39ce4e98113e7050e1cd88ff884 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Tue, 21 Oct 2008 06:33:42 +0800 Subject: [MTD] [NAND] OMAP2: remove duplicated #include Removed duplicated #include in drivers/mtd/onenand/omap2.c. Signed-off-by: Huang Weiyi Signed-off-by: David Woodhouse --- drivers/mtd/onenand/omap2.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 8387e05daae..e39b21d3e16 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From ed6e5e507e4752c3fb1090d0601f46e7a78c860e Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 14 Oct 2008 17:50:40 -0700 Subject: xen: don't reload cr3 on suspend It isn't necessary, and it makes the code needlessly non-portable. Signed-off-by: Jeremy Fitzhardinge Cc: Isaku Yamahata Signed-off-by: Ingo Molnar --- drivers/xen/manage.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index d0e87cbe157..9b91617b958 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -39,8 +39,6 @@ static int xen_suspend(void *data) BUG_ON(!irqs_disabled()); - load_cr3(swapper_pg_dir); - err = device_power_down(PMSG_SUSPEND); if (err) { printk(KERN_ERR "xen_suspend: device_power_down failed: %d\n", -- cgit v1.2.3 From 75909fd619d15400e7c6d0fc3af09838ee8b166e Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Tue, 14 Oct 2008 17:50:41 -0700 Subject: xen: portability clean up and some minor clean up for xencomm.c clean up of xencomm.c. is_phys_contiguous() is arch dependent function that depends on how virtual memory are laid out. So split out the function into arch specific code. Signed-off-by: Isaku Yamahata Signed-off-by: Jeremy Fitzhardinge Cc: Isaku Yamahata Signed-off-by: Ingo Molnar Cc: "Luck, Tony" --- drivers/xen/xencomm.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/xen/xencomm.c b/drivers/xen/xencomm.c index 797cb4e31f0..a240b2c20b9 100644 --- a/drivers/xen/xencomm.c +++ b/drivers/xen/xencomm.c @@ -23,13 +23,7 @@ #include #include #include -#ifdef __ia64__ -#include /* for is_kern_addr() */ -#endif - -#ifdef HAVE_XEN_PLATFORM_COMPAT_H -#include -#endif +#include /* for xencomm_is_phys_contiguous() */ static int xencomm_init(struct xencomm_desc *desc, void *buffer, unsigned long bytes) @@ -157,20 +151,11 @@ static int xencomm_create(void *buffer, unsigned long bytes, return 0; } -/* check if memory address is within VMALLOC region */ -static int is_phys_contiguous(unsigned long addr) -{ - if (!is_kernel_addr(addr)) - return 0; - - return (addr < VMALLOC_START) || (addr >= VMALLOC_END); -} - static struct xencomm_handle *xencomm_create_inline(void *ptr) { unsigned long paddr; - BUG_ON(!is_phys_contiguous((unsigned long)ptr)); + BUG_ON(!xencomm_is_phys_contiguous((unsigned long)ptr)); paddr = (unsigned long)xencomm_pa(ptr); BUG_ON(paddr & XENCOMM_INLINE_FLAG); @@ -202,7 +187,7 @@ struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes) int rc; struct xencomm_desc *desc; - if (is_phys_contiguous((unsigned long)ptr)) + if (xencomm_is_phys_contiguous((unsigned long)ptr)) return xencomm_create_inline(ptr); rc = xencomm_create(ptr, bytes, &desc, GFP_KERNEL); @@ -219,7 +204,7 @@ struct xencomm_handle *__xencomm_map_no_alloc(void *ptr, unsigned long bytes, int rc; struct xencomm_desc *desc = NULL; - if (is_phys_contiguous((unsigned long)ptr)) + if (xencomm_is_phys_contiguous((unsigned long)ptr)) return xencomm_create_inline(ptr); rc = xencomm_create_mini(ptr, bytes, xc_desc, -- cgit v1.2.3 From ff3c536291ce96ef6f45704cd37eaed71127dd42 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Tue, 14 Oct 2008 17:50:44 -0700 Subject: xen: compilation fix of drivers/xen/events.c on IA64 use set_xen_guest_handle() instead of direct assigning. > linux-2.6/drivers/xen/events.c: In function 'xen_poll_irq': > linux-2.6/drivers/xen/events.c:757: error: incompatible types in assignment > make[4]: *** [drivers/xen/events.o] Error 1 Signed-off-by: Isaku Yamahata Signed-off-by: Jeremy Fitzhardinge Cc: Isaku Yamahata Signed-off-by: Ingo Molnar --- drivers/xen/events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 9ce1ab6c268..1e3b934a4cf 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -774,7 +774,7 @@ void xen_poll_irq(int irq) poll.nr_ports = 1; poll.timeout = 0; - poll.ports = &evtchn; + set_xen_guest_handle(poll.ports, &evtchn); if (HYPERVISOR_sched_op(SCHEDOP_poll, &poll) != 0) BUG(); -- cgit v1.2.3 From af4c293ffcdd76fc97469beb7d8861662232d92e Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 28 Sep 2008 16:21:43 -0700 Subject: [WATCHDOG] pci: use pci_ioremap_bar() in drivers/watchdog Use the newly introduced pci_ioremap_bar() function in drivers/watchdog. pci_ioremap_bar() just takes a pci device and a bar number, with the goal of making it really hard to get wrong, while also having a central place to stick sanity checks. Signed-off-by: Arjan van de Ven Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/i6300esb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index c13383f7fcb..74f951c18b9 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c @@ -394,8 +394,7 @@ static unsigned char __init esb_getdevice(void) goto err_disable; } - BASEADDR = ioremap(pci_resource_start(esb_pci, 0), - pci_resource_len(esb_pci, 0)); + BASEADDR = pci_ioremap_bar(esb_pci, 0); if (BASEADDR == NULL) { /* Something's wrong here, BASEADDR has to be set */ printk(KERN_ERR PFX "failed to get BASEADDR\n"); -- cgit v1.2.3 From 3b15e581981b3ad35809f56d8131d5c19b6da1bd Mon Sep 17 00:00:00 2001 From: Fenghua Yu Date: Thu, 23 Oct 2008 16:51:00 -0700 Subject: x86/PCI: build failure at x86/kernel/pci-dma.c with !CONFIG_PCI On Thu, Oct 23, 2008 at 04:09:52PM -0700, Alexander Beregalov wrote: > arch/x86/kernel/built-in.o: In function `iommu_setup': > pci-dma.c:(.init.text+0x36ad): undefined reference to `forbid_dac' > pci-dma.c:(.init.text+0x36cc): undefined reference to `forbid_dac' > pci-dma.c:(.init.text+0x3711): undefined reference to `forbid_dac This patch partially reverts a patch to add IOMMU support to ia64. The forbid_dac variable was incorrectly moved to quirks.c, which isn't built when PCI is disabled. Tested-by: "Alexander Beregalov" Acked-by: FUJITA Tomonori Signed-off-by: Fenghua Yu Signed-off-by: Jesse Barnes --- drivers/pci/quirks.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 96cf8ecd04c..bbf66ea8fd8 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -43,20 +43,6 @@ static void __devinit quirk_mellanox_tavor(struct pci_dev *dev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR,quirk_mellanox_tavor); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE,quirk_mellanox_tavor); -/* Many VIA bridges seem to corrupt data for DAC. Disable it here */ -int forbid_dac __read_mostly; -EXPORT_SYMBOL(forbid_dac); - -static __devinit void via_no_dac(struct pci_dev *dev) -{ - if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && forbid_dac == 0) { - dev_info(&dev->dev, - "VIA PCI bridge detected. Disabling DAC.\n"); - forbid_dac = 1; - } -} -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_ANY_ID, via_no_dac); - /* Deal with broken BIOS'es that neglect to enable passive release, which can cause problems in combination with the 82441FX/PPro MTRRs */ static void quirk_passive_release(struct pci_dev *dev) -- cgit v1.2.3 From 3d5afd324a4bf9f64f59599bf1e93cd7dd1dc97a Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 27 Oct 2008 12:16:15 +0100 Subject: HID: fix oops during suspend of unbound HID devices Usbhid structure is allocated on start invoked only from probe of some driver. When there is no driver, the structure is null and causes null-dereference oopses. Fix it by allocating the structure on probe and disconnect of the device itself. Also make sure we won't race between start and resume or stop and suspend respectively. References: http://bugzilla.kernel.org/show_bug.cgi?id=11827 Signed-off-by: Jiri Slaby Cc: Johannes Berg Cc: Andreas Schwab Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 58 ++++++++++++++++++++++++++++++------------- drivers/hid/usbhid/usbhid.h | 2 ++ 2 files changed, 43 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 42bdd83444c..3b1c489998c 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -776,21 +777,10 @@ static int usbhid_start(struct hid_device *hid) struct usb_interface *intf = to_usb_interface(hid->dev.parent); struct usb_host_interface *interface = intf->cur_altsetting; struct usb_device *dev = interface_to_usbdev(intf); - struct usbhid_device *usbhid; + struct usbhid_device *usbhid = hid->driver_data; unsigned int n, insize = 0; int ret; - WARN_ON(hid->driver_data); - - usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL); - if (usbhid == NULL) { - ret = -ENOMEM; - goto err; - } - - hid->driver_data = usbhid; - usbhid->hid = hid; - usbhid->bufsize = HID_MIN_BUFFER_SIZE; hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); @@ -804,6 +794,7 @@ static int usbhid_start(struct hid_device *hid) if (insize > HID_MAX_BUFFER_SIZE) insize = HID_MAX_BUFFER_SIZE; + mutex_lock(&usbhid->setup); if (hid_alloc_buffers(dev, hid)) { ret = -ENOMEM; goto fail; @@ -888,6 +879,9 @@ static int usbhid_start(struct hid_device *hid) usbhid_init_reports(hid); hid_dump_device(hid); + set_bit(HID_STARTED, &usbhid->iofl); + mutex_unlock(&usbhid->setup); + return 0; fail: @@ -895,8 +889,7 @@ fail: usb_free_urb(usbhid->urbout); usb_free_urb(usbhid->urbctrl); hid_free_buffers(dev, hid); - kfree(usbhid); -err: + mutex_unlock(&usbhid->setup); return ret; } @@ -907,6 +900,8 @@ static void usbhid_stop(struct hid_device *hid) if (WARN_ON(!usbhid)) return; + mutex_lock(&usbhid->setup); + clear_bit(HID_STARTED, &usbhid->iofl); spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ set_bit(HID_DISCONNECTED, &usbhid->iofl); spin_unlock_irq(&usbhid->inlock); @@ -931,8 +926,7 @@ static void usbhid_stop(struct hid_device *hid) usb_free_urb(usbhid->urbout); hid_free_buffers(hid_to_usb_dev(hid), hid); - kfree(usbhid); - hid->driver_data = NULL; + mutex_unlock(&usbhid->setup); } static struct hid_ll_driver usb_hid_driver = { @@ -947,6 +941,7 @@ static struct hid_ll_driver usb_hid_driver = { static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); + struct usbhid_device *usbhid; struct hid_device *hid; size_t len; int ret; @@ -1000,14 +995,26 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0) hid->uniq[0] = 0; + usbhid = kzalloc(sizeof(*usbhid), GFP_KERNEL); + if (usbhid == NULL) { + ret = -ENOMEM; + goto err; + } + + hid->driver_data = usbhid; + usbhid->hid = hid; + mutex_init(&usbhid->setup); /* needed on suspend/resume */ + ret = hid_add_device(hid); if (ret) { if (ret != -ENODEV) dev_err(&intf->dev, "can't add hid device: %d\n", ret); - goto err; + goto err_free; } return 0; +err_free: + kfree(usbhid); err: hid_destroy_device(hid); return ret; @@ -1016,11 +1023,14 @@ err: static void hid_disconnect(struct usb_interface *intf) { struct hid_device *hid = usb_get_intfdata(intf); + struct usbhid_device *usbhid; if (WARN_ON(!hid)) return; + usbhid = hid->driver_data; hid_destroy_device(hid); + kfree(usbhid); } static int hid_suspend(struct usb_interface *intf, pm_message_t message) @@ -1028,11 +1038,18 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) struct hid_device *hid = usb_get_intfdata (intf); struct usbhid_device *usbhid = hid->driver_data; + mutex_lock(&usbhid->setup); + if (!test_bit(HID_STARTED, &usbhid->iofl)) { + mutex_unlock(&usbhid->setup); + return 0; + } + spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ set_bit(HID_SUSPENDED, &usbhid->iofl); spin_unlock_irq(&usbhid->inlock); del_timer(&usbhid->io_retry); usb_kill_urb(usbhid->urbin); + mutex_unlock(&usbhid->setup); dev_dbg(&intf->dev, "suspend\n"); return 0; } @@ -1043,9 +1060,16 @@ static int hid_resume(struct usb_interface *intf) struct usbhid_device *usbhid = hid->driver_data; int status; + mutex_lock(&usbhid->setup); + if (!test_bit(HID_STARTED, &usbhid->iofl)) { + mutex_unlock(&usbhid->setup); + return 0; + } + clear_bit(HID_SUSPENDED, &usbhid->iofl); usbhid->retry_delay = 0; status = hid_start_in(hid); + mutex_unlock(&usbhid->setup); dev_dbg(&intf->dev, "resume status %d\n", status); return status; } diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index abedb13c623..55973ff5400 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -73,6 +74,7 @@ struct usbhid_device { dma_addr_t outbuf_dma; /* Output buffer dma */ spinlock_t outlock; /* Output fifo spinlock */ + struct mutex setup; unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ struct timer_list io_retry; /* Retry timer */ unsigned long stop_retry; /* Time to give up, in jiffies */ -- cgit v1.2.3 From b170060c6ccd719eebb53b10c98df2a4e6968f28 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 27 Oct 2008 12:16:16 +0100 Subject: HID: sync on deleted io_retry timer in usbhid driver When suspending, make sure that the timer is not running any more. Signed-off-by: Jiri Slaby Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 3b1c489998c..18e5ddd722c 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1047,7 +1047,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ set_bit(HID_SUSPENDED, &usbhid->iofl); spin_unlock_irq(&usbhid->inlock); - del_timer(&usbhid->io_retry); + del_timer_sync(&usbhid->io_retry); usb_kill_urb(usbhid->urbin); mutex_unlock(&usbhid->setup); dev_dbg(&intf->dev, "suspend\n"); -- cgit v1.2.3 From cae042a73bb22fc4132b04ff94bd684456203089 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Thu, 23 Oct 2008 16:25:54 +0200 Subject: oprofile: fix memory ordering Regular bitops don't work as locks on all architectures. Also: can use non-atomic unlock as no concurrent stores to the word. Signed-off-by: Nick Piggin Signed-off-by: Robert Richter --- drivers/oprofile/event_buffer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c index d962ba0dd87..191a3202cec 100644 --- a/drivers/oprofile/event_buffer.c +++ b/drivers/oprofile/event_buffer.c @@ -105,7 +105,7 @@ static int event_buffer_open(struct inode *inode, struct file *file) if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (test_and_set_bit(0, &buffer_opened)) + if (test_and_set_bit_lock(0, &buffer_opened)) return -EBUSY; /* Register as a user of dcookies @@ -129,7 +129,7 @@ static int event_buffer_open(struct inode *inode, struct file *file) fail: dcookie_unregister(file->private_data); out: - clear_bit(0, &buffer_opened); + __clear_bit_unlock(0, &buffer_opened); return err; } @@ -141,7 +141,7 @@ static int event_buffer_release(struct inode *inode, struct file *file) dcookie_unregister(file->private_data); buffer_pos = 0; atomic_set(&buffer_ready, 0); - clear_bit(0, &buffer_opened); + __clear_bit_unlock(0, &buffer_opened); return 0; } -- cgit v1.2.3 From 0f5623c9ebfc6576c5682ab3b335c57812f6c87e Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Fri, 24 Oct 2008 11:16:52 +0200 Subject: qeth: remove non-recover-thread checkings IP-threads have been removed from the qeth driver. Only the recover-thread is left over. This makes checkings for non-recover threads superfluous. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: Jeff Garzik --- drivers/s390/net/qeth_l2_main.c | 14 +------------- drivers/s390/net/qeth_l3_main.c | 13 +------------ 2 files changed, 2 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 955ba7a31b9..fdf4ffa2e71 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -373,8 +373,6 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); qeth_set_allowed_threads(card, 0, 1); - if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD)) - return -ERESTARTSYS; if (card->read.state == CH_STATE_UP && card->write.state == CH_STATE_UP && (card->state == CARD_STATE_UP)) { @@ -975,12 +973,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1); - if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD)) { - PRINT_WARN("set_online of card %s interrupted by user!\n", - CARD_BUS_ID(card)); - return -ERESTARTSYS; - } - recover_flag = card->state; rc = ccw_device_set_online(CARD_RDEV(card)); if (rc) { @@ -1091,11 +1083,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev, if (card->dev && netif_carrier_ok(card->dev)) netif_carrier_off(card->dev); recover_flag = card->state; - if (qeth_l2_stop_card(card, recovery_mode) == -ERESTARTSYS) { - PRINT_WARN("Stopping card %s interrupted by user!\n", - CARD_BUS_ID(card)); - return -ERESTARTSYS; - } + qeth_l2_stop_card(card, recovery_mode); rc = ccw_device_set_offline(CARD_DDEV(card)); rc2 = ccw_device_set_offline(CARD_WDEV(card)); rc3 = ccw_device_set_offline(CARD_RDEV(card)); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 99547dea44d..ed59fedd592 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2064,8 +2064,6 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); qeth_set_allowed_threads(card, 0, 1); - if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD)) - return -ERESTARTSYS; if (card->read.state == CH_STATE_UP && card->write.state == CH_STATE_UP && (card->state == CARD_STATE_UP)) { @@ -3049,11 +3047,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1); - if (qeth_wait_for_threads(card, ~QETH_RECOVER_THREAD)) { - PRINT_WARN("set_online of card %s interrupted by user!\n", - CARD_BUS_ID(card)); - return -ERESTARTSYS; - } recover_flag = card->state; rc = ccw_device_set_online(CARD_RDEV(card)); @@ -3170,11 +3163,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, if (card->dev && netif_carrier_ok(card->dev)) netif_carrier_off(card->dev); recover_flag = card->state; - if (qeth_l3_stop_card(card, recovery_mode) == -ERESTARTSYS) { - PRINT_WARN("Stopping card %s interrupted by user!\n", - CARD_BUS_ID(card)); - return -ERESTARTSYS; - } + qeth_l3_stop_card(card, recovery_mode); rc = ccw_device_set_offline(CARD_DDEV(card)); rc2 = ccw_device_set_offline(CARD_WDEV(card)); rc3 = ccw_device_set_offline(CARD_RDEV(card)); -- cgit v1.2.3 From e1f03ae8029cb8046ef3031e66d74430730c2727 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Fri, 24 Oct 2008 11:16:53 +0200 Subject: qeth: fix offset error in non prealloc header path For the non preallocated qeth header code path we should not change the header length. Signed-off-by: Frank Blaschka Signed-off-by: Jeff Garzik --- drivers/s390/net/qeth_core_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 7de410d5be4..52d26592c72 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -3025,7 +3025,7 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, int is_tso, int *next_element_to_fill, int offset) { - int length = skb->len - offset; + int length = skb->len; int length_here; int element; char *data; @@ -3037,6 +3037,7 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb, if (offset >= 0) { data = skb->data + offset; + length -= offset; first_lap = 0; } -- cgit v1.2.3 From cc181282fb2fa1af6d532f1333dd42af4814ff17 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Fri, 24 Oct 2008 11:16:54 +0200 Subject: qeth: remove unnecessary support ckeck in sysfs route6 Removing this check improves usability because you do not have to set the device online to initially set ipv6 routing option. Signed-off-by: Frank Blaschka Signed-off-by: Jeff Garzik --- drivers/s390/net/qeth_l3_sys.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index 210ddb63974..c144b9924d5 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c @@ -121,9 +121,6 @@ static ssize_t qeth_l3_dev_route6_show(struct device *dev, if (!card) return -EINVAL; - if (!qeth_is_supported(card, IPA_IPV6)) - return sprintf(buf, "%s\n", "n/a"); - return qeth_l3_dev_route_show(card, &card->options.route6, buf); } @@ -135,10 +132,6 @@ static ssize_t qeth_l3_dev_route6_store(struct device *dev, if (!card) return -EINVAL; - if (!qeth_is_supported(card, IPA_IPV6)) { - return -EOPNOTSUPP; - } - return qeth_l3_dev_route_store(card, &card->options.route6, QETH_PROT_IPV6, buf, count); } -- cgit v1.2.3 From 2d488c2f514a6c5248a0773c78345626abdc1818 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Fri, 24 Oct 2008 11:16:55 +0200 Subject: qeth: avoid skb_under_panic for malformatted inbound data To make the qeth driver more robust in case of malformatted inbound packets due to hardware problems, an additional check for OSN-card-type is added for OSN-type packets. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: Jeff Garzik --- drivers/s390/net/qeth_l2_main.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index fdf4ffa2e71..1b1e80336d2 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -449,12 +449,15 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card, netif_rx(skb); break; case QETH_HEADER_TYPE_OSN: - skb_push(skb, sizeof(struct qeth_hdr)); - skb_copy_to_linear_data(skb, hdr, + if (card->info.type == QETH_CARD_TYPE_OSN) { + skb_push(skb, sizeof(struct qeth_hdr)); + skb_copy_to_linear_data(skb, hdr, sizeof(struct qeth_hdr)); - len = skb->len; - card->osn_info.data_cb(skb); - break; + len = skb->len; + card->osn_info.data_cb(skb); + break; + } + /* else unknown */ default: dev_kfree_skb_any(skb); QETH_DBF_TEXT(TRACE, 3, "inbunkno"); -- cgit v1.2.3 From 74d5e8acd95ae934194303138a43b60005fcfad6 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 23 Oct 2008 18:01:13 +0900 Subject: dmfe: check pci_alloc_consistent errors We need to check the address that pci_alloc_consistent() returns since it might fail. Signed-off-by: FUJITA Tomonori Signed-off-by: Jeff Garzik --- drivers/net/tulip/dmfe.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 8e46a513a25..c91852f49a4 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -420,9 +420,13 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, /* Allocate Tx/Rx descriptor memory */ db->desc_pool_ptr = pci_alloc_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr); + if (!db->desc_pool_ptr) + goto err_out_res; db->buf_pool_ptr = pci_alloc_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, &db->buf_pool_dma_ptr); + if (!db->buf_pool_ptr) + goto err_out_free_desc; db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr; db->first_tx_desc_dma = db->desc_pool_dma_ptr; @@ -469,7 +473,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, err = register_netdev (dev); if (err) - goto err_out_res; + goto err_out_free_buf; printk(KERN_INFO "%s: Davicom DM%04lx at pci%s, " "%s, irq %d.\n", @@ -483,6 +487,12 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, return 0; +err_out_free_buf: + pci_free_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, + db->buf_pool_ptr, db->buf_pool_dma_ptr); +err_out_free_desc: + pci_free_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, + db->desc_pool_ptr, db->desc_pool_dma_ptr); err_out_res: pci_release_regions(pdev); err_out_disable: -- cgit v1.2.3 From 3fd09c45bfbcf77949ed6db36e67c1681424fedb Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Mon, 27 Oct 2008 10:38:46 +0100 Subject: ehea: Detect 16GB hugepages for firmware restriction All kernel memory which is used for kernel/hardware data transfer must be registered with firmware using "memory regions". 16GB hugepages may not be part of a memory region due to firmware restrictions. This patch modifies the walk_memory_resource callback fn to filter hugepages and add only standard memory to the busmap which is later on used for MR registration. Signed-off-by: Thomas Klein Signed-off-by: Jeff Garzik --- drivers/net/ehea/ehea.h | 2 +- drivers/net/ehea/ehea_qmr.c | 57 +++++++++++++++++++++++++++++++++++++++++---- drivers/net/ehea/ehea_qmr.h | 3 +++ 3 files changed, 56 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 82dd1a891ce..002d918fb4c 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0094" +#define DRV_VERSION "EHEA_0095" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index 9b61dc9865d..9d006878f04 100644 --- a/drivers/net/ehea/ehea_qmr.c +++ b/drivers/net/ehea/ehea_qmr.c @@ -632,10 +632,13 @@ static void ehea_rebuild_busmap(void) } } -static int ehea_update_busmap(unsigned long pfn, unsigned long pgnum, int add) +static int ehea_update_busmap(unsigned long pfn, unsigned long nr_pages, int add) { unsigned long i, start_section, end_section; + if (!nr_pages) + return 0; + if (!ehea_bmap) { ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL); if (!ehea_bmap) @@ -643,7 +646,7 @@ static int ehea_update_busmap(unsigned long pfn, unsigned long pgnum, int add) } start_section = (pfn * PAGE_SIZE) / EHEA_SECTSIZE; - end_section = start_section + ((pgnum * PAGE_SIZE) / EHEA_SECTSIZE); + end_section = start_section + ((nr_pages * PAGE_SIZE) / EHEA_SECTSIZE); /* Mark entries as valid or invalid only; address is assigned later */ for (i = start_section; i < end_section; i++) { u64 flag; @@ -692,10 +695,54 @@ int ehea_rem_sect_bmap(unsigned long pfn, unsigned long nr_pages) return ret; } -static int ehea_create_busmap_callback(unsigned long pfn, - unsigned long nr_pages, void *arg) +static int ehea_is_hugepage(unsigned long pfn) +{ + int page_order; + + if (pfn & EHEA_HUGEPAGE_PFN_MASK) + return 0; + + page_order = compound_order(pfn_to_page(pfn)); + if (page_order + PAGE_SHIFT != EHEA_HUGEPAGESHIFT) + return 0; + + return 1; +} + +static int ehea_create_busmap_callback(unsigned long initial_pfn, + unsigned long total_nr_pages, void *arg) { - return ehea_update_busmap(pfn, nr_pages, EHEA_BUSMAP_ADD_SECT); + int ret; + unsigned long pfn, start_pfn, end_pfn, nr_pages; + + if ((total_nr_pages * PAGE_SIZE) < EHEA_HUGEPAGE_SIZE) + return ehea_update_busmap(initial_pfn, total_nr_pages, + EHEA_BUSMAP_ADD_SECT); + + /* Given chunk is >= 16GB -> check for hugepages */ + start_pfn = initial_pfn; + end_pfn = initial_pfn + total_nr_pages; + pfn = start_pfn; + + while (pfn < end_pfn) { + if (ehea_is_hugepage(pfn)) { + /* Add mem found in front of the hugepage */ + nr_pages = pfn - start_pfn; + ret = ehea_update_busmap(start_pfn, nr_pages, + EHEA_BUSMAP_ADD_SECT); + if (ret) + return ret; + + /* Skip the hugepage */ + pfn += (EHEA_HUGEPAGE_SIZE / PAGE_SIZE); + start_pfn = pfn; + } else + pfn += (EHEA_SECTSIZE / PAGE_SIZE); + } + + /* Add mem found behind the hugepage(s) */ + nr_pages = pfn - start_pfn; + return ehea_update_busmap(start_pfn, nr_pages, EHEA_BUSMAP_ADD_SECT); } int ehea_create_busmap(void) diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h index 1e58dc06b7d..0817c1e74a1 100644 --- a/drivers/net/ehea/ehea_qmr.h +++ b/drivers/net/ehea/ehea_qmr.h @@ -40,6 +40,9 @@ #define EHEA_PAGESIZE (1UL << EHEA_PAGESHIFT) #define EHEA_SECTSIZE (1UL << 24) #define EHEA_PAGES_PER_SECTION (EHEA_SECTSIZE >> EHEA_PAGESHIFT) +#define EHEA_HUGEPAGESHIFT 34 +#define EHEA_HUGEPAGE_SIZE (1UL << EHEA_HUGEPAGESHIFT) +#define EHEA_HUGEPAGE_PFN_MASK ((EHEA_HUGEPAGE_SIZE - 1) >> PAGE_SHIFT) #if ((1UL << SECTION_SIZE_BITS) < EHEA_SECTSIZE) #error eHEA module cannot work if kernel sectionsize < ehea sectionsize -- cgit v1.2.3 From c778e11d686dd4bde9efe12d8135a9bcbfef17ef Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 24 Oct 2008 09:53:14 -0400 Subject: ibm_newemac: Fix typo in flow control config option The recent build fix for ibm_newemac has a typo in the config option #ifdef used for disabling flow control. This corrects it to the proper Kconfig option name. Reported-by: Christoph Hellwig Signed-off-by: Josh Boyer Signed-off-by: Jeff Garzik --- drivers/net/ibm_newemac/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 2ee2622258f..901212aa37c 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -2605,7 +2605,7 @@ static int __devinit emac_init_config(struct emac_instance *dev) of_device_is_compatible(np, "ibm,emac-440gr")) dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX; if (of_device_is_compatible(np, "ibm,emac-405ez")) { -#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CONTROL +#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL dev->features |= EMAC_FTR_NO_FLOW_CONTROL_40x; #else printk(KERN_ERR "%s: Flow control not disabled!\n", -- cgit v1.2.3 From 9de14eb59d0b28a2566344a961d716886fa85776 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sun, 26 Oct 2008 23:05:42 +0800 Subject: mlx4_en: remove duplicated #include Removed duplicated #include in drivers/net/mlx4/en_main.c. Signed-off-by: Huang Weiyi Signed-off-by: Jeff Garzik --- drivers/net/mlx4/en_main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c index 1b0eebf84f7..4b9794e97a7 100644 --- a/drivers/net/mlx4/en_main.c +++ b/drivers/net/mlx4/en_main.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From e65b95915d6ac8cd86152cfac762af8fc5fb3ff4 Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Sun, 26 Oct 2008 17:13:24 +0200 Subject: mlx4: Setting the correct offset for default mac address Signed-off-by: Yevgeny Petrilin Signed-off-by: Jeff Garzik --- drivers/net/mlx4/fw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c index be09fdb79cb..cee199ceba2 100644 --- a/drivers/net/mlx4/fw.c +++ b/drivers/net/mlx4/fw.c @@ -360,9 +360,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_PORT_ETH_MTU_OFFSET 0x02 #define QUERY_PORT_WIDTH_OFFSET 0x06 #define QUERY_PORT_MAX_GID_PKEY_OFFSET 0x07 -#define QUERY_PORT_MAC_OFFSET 0x08 #define QUERY_PORT_MAX_MACVLAN_OFFSET 0x0a #define QUERY_PORT_MAX_VL_OFFSET 0x0b +#define QUERY_PORT_MAC_OFFSET 0x10 for (i = 1; i <= dev_cap->num_ports; ++i) { err = mlx4_cmd_box(dev, 0, mailbox->dma, i, 0, MLX4_CMD_QUERY_PORT, -- cgit v1.2.3 From 404b12c10d2f4d77649a193af2ec69f77b852926 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Mon, 27 Oct 2008 15:06:51 -0400 Subject: drivers/net/wan/syncppp: Fix unused-var warnings Fix !CONFIG_INET warnings. Spotted, and original patch authored by: Manish Katiyar Signed-off-by: Jeff Garzik --- drivers/net/wan/syncppp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c index 327d58589e1..6e92f7b44b1 100644 --- a/drivers/net/wan/syncppp.c +++ b/drivers/net/wan/syncppp.c @@ -756,10 +756,11 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) case CISCO_ADDR_REQ: /* Stolen from net/ipv4/devinet.c -- SIOCGIFADDR ioctl */ { - struct in_device *in_dev; - struct in_ifaddr *ifa; __be32 addr = 0, mask = htonl(~0U); /* FIXME: is the mask correct? */ #ifdef CONFIG_INET + struct in_device *in_dev; + struct in_ifaddr *ifa; + rcu_read_lock(); if ((in_dev = __in_dev_get_rcu(dev)) != NULL) { -- cgit v1.2.3 From 07b5f6a6fd0ce47390f7fbec966cd5c70127e597 Mon Sep 17 00:00:00 2001 From: Sven Hartge Date: Thu, 23 Oct 2008 13:03:44 +0000 Subject: via-velocity: use driver string instead of dev->name before register_netdev() This patch corrects a message bug in the via-velocity driver which bothered me for some time. The messages printed during device init look like the following: [ 8.486422] eth%d: set value of parameter Wake On Lan options to 0 ^^! [ 8.487340] eth0: VIA Networking Velocity Family Gigabit Ethernet Adapter Note the unresolved format string. dev->name is unavailable before register_netdev, so use dev_driver_string(&pdev->dev), which is also consistent with other drivers. "char *devname" parameters had to be converted to "const char *devname" to be consistent with dev_driver_string return value. Signed-off-by: Sven Hartge Signed-off-by: Jeff Garzik --- drivers/net/via-velocity.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 2dced383bcf..3590ea5a902 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -521,7 +521,7 @@ static void __devexit velocity_remove1(struct pci_dev *pdev) * we don't duplicate code for each option. */ -static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max, int def, char *name, char *devname) +static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max, int def, char *name, const char *devname) { if (val == -1) *opt = def; @@ -550,7 +550,7 @@ static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max, * we don't duplicate code for each option. */ -static void __devinit velocity_set_bool_opt(u32 * opt, int val, int def, u32 flag, char *name, char *devname) +static void __devinit velocity_set_bool_opt(u32 * opt, int val, int def, u32 flag, char *name, const char *devname) { (*opt) &= (~flag); if (val == -1) @@ -576,7 +576,7 @@ static void __devinit velocity_set_bool_opt(u32 * opt, int val, int def, u32 fla * for the current device */ -static void __devinit velocity_get_options(struct velocity_opt *opts, int index, char *devname) +static void __devinit velocity_get_options(struct velocity_opt *opts, int index, const char *devname) { velocity_set_int_opt(&opts->rx_thresh, rx_thresh[index], RX_THRESH_MIN, RX_THRESH_MAX, RX_THRESH_DEF, "rx_thresh", devname); @@ -863,6 +863,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi static int first = 1; struct net_device *dev; int i; + const char *drv_string; const struct velocity_info_tbl *info = &chip_info_table[ent->driver_data]; struct velocity_info *vptr; struct mac_regs __iomem * regs; @@ -935,7 +936,9 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi dev->dev_addr[i] = readb(®s->PAR[i]); - velocity_get_options(&vptr->options, velocity_nics, dev->name); + drv_string = dev_driver_string(&pdev->dev); + + velocity_get_options(&vptr->options, velocity_nics, drv_string); /* * Mask out the options cannot be set to the chip -- cgit v1.2.3 From 753dcfeecc0e293dbe6f3d59643741af9e610f4f Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Fri, 24 Oct 2008 09:08:27 +0200 Subject: dm9601: runtime mac address change support Implement set_mac_address for runtime mac address change. Signed-off-by: Peter Korsgaard Signed-off-by: Jeff Garzik --- drivers/net/usb/dm9601.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 78df2be8a72..db3377dae9d 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -396,6 +396,20 @@ static void dm9601_set_multicast(struct net_device *net) dm_write_reg_async(dev, DM_RX_CTRL, rx_ctl); } +static int dm9601_set_mac_address(struct net_device *net, void *p) +{ + struct sockaddr *addr = p; + struct usbnet *dev = netdev_priv(net); + + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + + memcpy(net->dev_addr, addr->sa_data, net->addr_len); + dm_write_async(dev, DM_PHY_ADDR, net->addr_len, net->dev_addr); + + return 0; +} + static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) { int ret; @@ -406,6 +420,7 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->do_ioctl = dm9601_ioctl; dev->net->set_multicast_list = dm9601_set_multicast; + dev->net->set_mac_address = dm9601_set_mac_address; dev->net->ethtool_ops = &dm9601_ethtool_ops; dev->net->hard_header_len += DM_TX_OVERHEAD; dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; -- cgit v1.2.3 From 65e082c9a33a6e9f24e9a713a7d38d11206d3c3d Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 24 Oct 2008 17:18:10 -0400 Subject: build fix: CONFIG_DRM_I915=y && CONFIG_ACPI=n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/gpu/drm/i915/i915_opregion.c:340: error: implicit declaration of function ‘register_acpi_notifier’ drivers/gpu/drm/i915/i915_opregion.c:361: error: implicit declaration of function ‘unregister_acpi_notifier’ Signed-off-by: Len Brown Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/Makefile | 3 ++- drivers/gpu/drm/i915/i915_drv.h | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 5ba78e4fd2b..d8fb5d8ee7e 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -3,13 +3,14 @@ # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. ccflags-y := -Iinclude/drm -i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_opregion.o \ +i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ i915_suspend.o \ i915_gem.o \ i915_gem_debug.o \ i915_gem_proc.o \ i915_gem_tiling.o +i915-$(CONFIG_ACPI) += i915_opregion.o i915-$(CONFIG_COMPAT) += i915_ioc32.o obj-$(CONFIG_DRM_I915) += i915.o diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f20ffe17df7..901e80cf581 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -539,11 +539,18 @@ extern int i915_restore_state(struct drm_device *dev); extern int i915_save_state(struct drm_device *dev); extern int i915_restore_state(struct drm_device *dev); +#ifdef CONFIG_ACPI /* i915_opregion.c */ extern int intel_opregion_init(struct drm_device *dev); extern void intel_opregion_free(struct drm_device *dev); extern void opregion_asle_intr(struct drm_device *dev); extern void opregion_enable_asle(struct drm_device *dev); +#else +static inline int intel_opregion_init(struct drm_device *dev) { return 0; } +static inline void intel_opregion_free(struct drm_device *dev) { return; } +static inline void opregion_asle_intr(struct drm_device *dev) { return; } +static inline void opregion_enable_asle(struct drm_device *dev) { return; } +#endif /** * Lock test for when it's just for synchronization of ring access. -- cgit v1.2.3 From 35961627d3e7a4093eb307d782541700e9addec6 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 22 Oct 2008 14:19:56 +0200 Subject: p54: fix misbehavings when firmware can't be found MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes a double-free error in p54pci ( http://bugzilla.kernel.org/show_bug.cgi?id=11782 ) Trying to free already-free IRQ 10 Pid: 108, comm: pccardd Not tainted 2.6.27-05577-g0cfd810-dirty #1 Call Trace:  [] free_irq+0xad/0xb9  [] dma_generic_alloc_coherent+0x0/0xd7  [] p54p_stop+0x4a/0x1fa  [] dma_generic_alloc_coherent+0x0/0xd7  [] p54p_probe+0x23e/0x302 Tested-by: Sean Young Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54pci.c | 132 +++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 66 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 1c2a02a741a..88b3cad8b65 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -346,68 +346,6 @@ static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data, printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy)); } -static int p54p_open(struct ieee80211_hw *dev) -{ - struct p54p_priv *priv = dev->priv; - int err; - - init_completion(&priv->boot_comp); - err = request_irq(priv->pdev->irq, &p54p_interrupt, - IRQF_SHARED, "p54pci", dev); - if (err) { - printk(KERN_ERR "%s: failed to register IRQ handler\n", - wiphy_name(dev->wiphy)); - return err; - } - - memset(priv->ring_control, 0, sizeof(*priv->ring_control)); - err = p54p_upload_firmware(dev); - if (err) { - free_irq(priv->pdev->irq, dev); - return err; - } - priv->rx_idx_data = priv->tx_idx_data = 0; - priv->rx_idx_mgmt = priv->tx_idx_mgmt = 0; - - p54p_refill_rx_ring(dev, 0, priv->ring_control->rx_data, - ARRAY_SIZE(priv->ring_control->rx_data), priv->rx_buf_data); - - p54p_refill_rx_ring(dev, 2, priv->ring_control->rx_mgmt, - ARRAY_SIZE(priv->ring_control->rx_mgmt), priv->rx_buf_mgmt); - - P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma)); - P54P_READ(ring_control_base); - wmb(); - udelay(10); - - P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT)); - P54P_READ(int_enable); - wmb(); - udelay(10); - - P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); - P54P_READ(dev_int); - - if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) { - printk(KERN_ERR "%s: Cannot boot firmware!\n", - wiphy_name(dev->wiphy)); - free_irq(priv->pdev->irq, dev); - return -ETIMEDOUT; - } - - P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)); - P54P_READ(int_enable); - wmb(); - udelay(10); - - P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); - P54P_READ(dev_int); - wmb(); - udelay(10); - - return 0; -} - static void p54p_stop(struct ieee80211_hw *dev) { struct p54p_priv *priv = dev->priv; @@ -474,6 +412,68 @@ static void p54p_stop(struct ieee80211_hw *dev) memset(ring_control, 0, sizeof(*ring_control)); } +static int p54p_open(struct ieee80211_hw *dev) +{ + struct p54p_priv *priv = dev->priv; + int err; + + init_completion(&priv->boot_comp); + err = request_irq(priv->pdev->irq, &p54p_interrupt, + IRQF_SHARED, "p54pci", dev); + if (err) { + printk(KERN_ERR "%s: failed to register IRQ handler\n", + wiphy_name(dev->wiphy)); + return err; + } + + memset(priv->ring_control, 0, sizeof(*priv->ring_control)); + err = p54p_upload_firmware(dev); + if (err) { + free_irq(priv->pdev->irq, dev); + return err; + } + priv->rx_idx_data = priv->tx_idx_data = 0; + priv->rx_idx_mgmt = priv->tx_idx_mgmt = 0; + + p54p_refill_rx_ring(dev, 0, priv->ring_control->rx_data, + ARRAY_SIZE(priv->ring_control->rx_data), priv->rx_buf_data); + + p54p_refill_rx_ring(dev, 2, priv->ring_control->rx_mgmt, + ARRAY_SIZE(priv->ring_control->rx_mgmt), priv->rx_buf_mgmt); + + P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma)); + P54P_READ(ring_control_base); + wmb(); + udelay(10); + + P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT)); + P54P_READ(int_enable); + wmb(); + udelay(10); + + P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); + P54P_READ(dev_int); + + if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) { + printk(KERN_ERR "%s: Cannot boot firmware!\n", + wiphy_name(dev->wiphy)); + p54p_stop(dev); + return -ETIMEDOUT; + } + + P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)); + P54P_READ(int_enable); + wmb(); + udelay(10); + + P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); + P54P_READ(dev_int); + wmb(); + udelay(10); + + return 0; +} + static int __devinit p54p_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -556,11 +556,13 @@ static int __devinit p54p_probe(struct pci_dev *pdev, spin_lock_init(&priv->lock); tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev); - p54p_open(dev); + err = p54p_open(dev); + if (err) + goto err_free_common; err = p54_read_eeprom(dev); p54p_stop(dev); if (err) - goto err_free_desc; + goto err_free_common; err = ieee80211_register_hw(dev); if (err) { @@ -573,8 +575,6 @@ static int __devinit p54p_probe(struct pci_dev *pdev, err_free_common: p54_free_common(dev); - - err_free_desc: pci_free_consistent(pdev, sizeof(*priv->ring_control), priv->ring_control, priv->ring_control_dma); -- cgit v1.2.3 From bc1b32d6bdd2d6f3fbee9a7c01c9b099f11c579c Mon Sep 17 00:00:00 2001 From: Elias Oltmanns Date: Fri, 24 Oct 2008 21:59:18 +0200 Subject: ath5k: Reset key cache on interface up, thus fixing resume After a s2ram / resume cycle, resetting the key cache does not work unless it is deferred until after the hardware has been reinitialised by a call to ath5k_hw_reset(). This fixes a regression introduced by "ath5k: fix suspend-related oops on rmmod". Signed-off-by: Elias Oltmanns Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 0f1d6bdd51a..cfd4d052d66 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -661,8 +661,7 @@ ath5k_pci_resume(struct pci_dev *pdev) { struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - int i, err; + int err; pci_restore_state(pdev); @@ -688,16 +687,6 @@ ath5k_pci_resume(struct pci_dev *pdev) goto err_irq; ath5k_led_enable(sc); - /* - * Reset the key cache since some parts do not - * reset the contents on initial power up or resume. - * - * FIXME: This may need to be revisited when mac80211 becomes - * aware of suspend/resume. - */ - for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) - ath5k_hw_reset_key(ah, i); - return 0; err_irq: free_irq(pdev->irq, sc); @@ -718,7 +707,6 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) struct ath5k_softc *sc = hw->priv; struct ath5k_hw *ah = sc->ah; u8 mac[ETH_ALEN]; - unsigned int i; int ret; ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device); @@ -736,13 +724,6 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) if (ret > 0) __set_bit(ATH_STAT_MRRETRY, sc->status); - /* - * Reset the key cache since some parts do not - * reset the contents on initial power up. - */ - for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) - ath5k_hw_reset_key(ah, i); - /* * Collect the channel list. The 802.11 layer * is resposible for filtering this list based @@ -2202,7 +2183,8 @@ ath5k_beacon_config(struct ath5k_softc *sc) static int ath5k_init(struct ath5k_softc *sc, bool is_resume) { - int ret; + struct ath5k_hw *ah = sc->ah; + int ret, i; mutex_lock(&sc->lock); @@ -2235,10 +2217,17 @@ ath5k_init(struct ath5k_softc *sc, bool is_resume) if (ret) goto done; + /* + * Reset the key cache since some parts do not reset the + * contents on initial power up or resume from suspend. + */ + for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) + ath5k_hw_reset_key(ah, i); + __set_bit(ATH_STAT_STARTED, sc->status); /* Set ack to be sent at low bit-rates */ - ath5k_hw_set_ack_bitrate_high(sc->ah, false); + ath5k_hw_set_ack_bitrate_high(ah, false); mod_timer(&sc->calib_tim, round_jiffies(jiffies + msecs_to_jiffies(ath5k_calinterval * 1000))); -- cgit v1.2.3 From f2c2e25554991f9c17bcd24028db5e1c50ecb0ad Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 25 Oct 2008 16:14:14 +0200 Subject: p54: fix build warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Saturday 25 October 2008 10:24:10 Johannes Berg wrote: > just FYI in case you haven't seen them. the p54 one looks like a genuine > problem. > > drivers/net/wireless/p54/p54common.c: In function ‘p54_parse_eeprom’: > drivers/net/wireless/p54/p54common.c:325: warning: ‘synth’ may be used uninitialized in this function There you go. Yes, it is a genuine problem, if the device's eeprom is screwed really up. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 2d022f83774..827ca0384a4 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -319,7 +319,7 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) void *tmp; int err; u8 *end = (u8 *)eeprom + len; - u16 synth; + u16 synth = 0; DECLARE_MAC_BUF(mac); wrap = (struct eeprom_pda_wrap *) eeprom; @@ -422,7 +422,8 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) entry = (void *)entry + (entry_len + 1)*2; } - if (!priv->iq_autocal || !priv->output_limit || !priv->curve_data) { + if (!synth || !priv->iq_autocal || !priv->output_limit || + !priv->curve_data) { printk(KERN_ERR "p54: not all required entries found in eeprom!\n"); err = -EINVAL; goto err; -- cgit v1.2.3 From 4e270e9b8a9d246290f3901f1fb6c5efdb734ddf Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Oct 2008 07:48:34 +1000 Subject: drm/radeon: fixup further bus mastering confusion. rs400/480 are like previous chips not like rs6xx chips. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_cp.c | 15 ++++++++------- drivers/gpu/drm/radeon/radeon_drv.h | 12 ++++++------ 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 59a2132a8f5..073894824e6 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -653,15 +653,16 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev, RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7); /* Turn on bus mastering */ - if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || + if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) { - /* rs400, rs690/rs740 */ - tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RS400_BUS_MASTER_DIS; + /* rs600/rs690/rs740 */ + tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS; RADEON_WRITE(RADEON_BUS_CNTL, tmp); - } else if (!(((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) || - ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R423))) { - /* r1xx, r2xx, r300, r(v)350, r420/r481, rs480 */ + } else if (((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV350) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) || + ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) { + /* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; RADEON_WRITE(RADEON_BUS_CNTL, tmp); } /* PCIE cards appears to not need this */ diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 4dbb813910c..02f5575ba39 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -447,12 +447,12 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev, * handling, not bus mastering itself. */ #define RADEON_BUS_CNTL 0x0030 -/* r1xx, r2xx, r300, r(v)350, r420/r481, rs480 */ +/* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ # define RADEON_BUS_MASTER_DIS (1 << 6) -/* rs400, rs690/rs740 */ -# define RS400_BUS_MASTER_DIS (1 << 14) -# define RS400_MSI_REARM (1 << 20) -/* see RS480_MSI_REARM in AIC_CNTL for rs480 */ +/* rs600/rs690/rs740 */ +# define RS600_BUS_MASTER_DIS (1 << 14) +# define RS600_MSI_REARM (1 << 20) +/* see RS400_MSI_REARM in AIC_CNTL for rs480 */ #define RADEON_BUS_CNTL1 0x0034 # define RADEON_PMI_BM_DIS (1 << 2) @@ -937,7 +937,7 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev, #define RADEON_AIC_CNTL 0x01d0 # define RADEON_PCIGART_TRANSLATE_EN (1 << 0) -# define RS480_MSI_REARM (1 << 3) +# define RS400_MSI_REARM (1 << 3) #define RADEON_AIC_STAT 0x01d4 #define RADEON_AIC_PT_BASE 0x01d8 #define RADEON_AIC_LO_ADDR 0x01dc -- cgit v1.2.3 From a8b56f296d7d977fea2512e353a131f8da490aa5 Mon Sep 17 00:00:00 2001 From: Ralph Campbell Date: Mon, 27 Oct 2008 15:31:25 -0700 Subject: IB/ipath: Fix RDMA write with immediate copy of last packet When the last packet of a RDMA write with immediate is received, the next receive work queue entry ID should be used to generate a completion entry. The code was incorrectly resetting part of the state used to copy the last packet. Signed-off-by: Ralph Campbell Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_ruc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c index fc0f6d9e603..2296832f94d 100644 --- a/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/drivers/infiniband/hw/ipath/ipath_ruc.c @@ -156,7 +156,7 @@ bail: /** * ipath_get_rwqe - copy the next RWQE into the QP's RWQE * @qp: the QP - * @wr_id_only: update wr_id only, not SGEs + * @wr_id_only: update qp->r_wr_id only, not qp->r_sge * * Return 0 if no RWQE is available, otherwise return 1. * @@ -173,8 +173,6 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) u32 tail; int ret; - qp->r_sge.sg_list = qp->r_sg_list; - if (qp->ibqp.srq) { srq = to_isrq(qp->ibqp.srq); handler = srq->ibsrq.event_handler; @@ -206,8 +204,10 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) wqe = get_rwqe_ptr(rq, tail); if (++tail >= rq->size) tail = 0; - } while (!wr_id_only && !ipath_init_sge(qp, wqe, &qp->r_len, - &qp->r_sge)); + if (wr_id_only) + break; + qp->r_sge.sg_list = qp->r_sg_list; + } while (!ipath_init_sge(qp, wqe, &qp->r_len, &qp->r_sge)); qp->r_wr_id = wqe->wr_id; wq->tail = tail; -- cgit v1.2.3 From 9e9430213f85ebdaf40026ec790295420efd0f91 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 24 Oct 2008 21:17:50 +0100 Subject: [ARM] 5322/1: Fix fastpath issue in mmci.c Fix fastpath issues Since mmci_request() can be called from a non-interrupt context, and does, during kernel init, causing a host of debug messages during boot if you enable spinlock debugging, we need to use the spinlock calls that save IRQ flags and restore them. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 696cf3647ce..2fadf323c69 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -391,6 +391,7 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) { struct mmci_host *host = mmc_priv(mmc); + unsigned long flags; WARN_ON(host->mrq != NULL); @@ -402,7 +403,7 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) return; } - spin_lock_irq(&host->lock); + spin_lock_irqsave(&host->lock, flags); host->mrq = mrq; @@ -411,7 +412,7 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) mmci_start_command(host, mrq->cmd, 0); - spin_unlock_irq(&host->lock); + spin_unlock_irqrestore(&host->lock, flags); } static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -- cgit v1.2.3 From ab77163008c596aad9624ceab190d840c0143fa8 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 27 Oct 2008 15:09:10 +0000 Subject: ata: Switch all my stuff to a common address Signed-off-by: Jeff Garzik --- drivers/ata/ata_generic.c | 2 +- drivers/ata/ata_piix.c | 2 +- drivers/ata/pata_acpi.c | 2 +- drivers/ata/pata_ali.c | 1 - drivers/ata/pata_amd.c | 1 - drivers/ata/pata_artop.c | 2 +- drivers/ata/pata_atiixp.c | 1 - drivers/ata/pata_cmd640.c | 1 - drivers/ata/pata_cmd64x.c | 2 +- drivers/ata/pata_cs5530.c | 1 - drivers/ata/pata_cs5535.c | 2 +- drivers/ata/pata_cypress.c | 2 +- drivers/ata/pata_efar.c | 2 +- drivers/ata/pata_isapnp.c | 2 +- drivers/ata/pata_it821x.c | 4 ++-- drivers/ata/pata_jmicron.c | 2 +- drivers/ata/pata_legacy.c | 2 +- drivers/ata/pata_marvell.c | 2 +- drivers/ata/pata_mpiix.c | 2 +- drivers/ata/pata_netcell.c | 2 +- drivers/ata/pata_ninja32.c | 1 - drivers/ata/pata_ns87410.c | 1 - drivers/ata/pata_ns87415.c | 2 +- drivers/ata/pata_oldpiix.c | 2 +- drivers/ata/pata_opti.c | 1 - drivers/ata/pata_optidma.c | 1 - drivers/ata/pata_pcmcia.c | 2 +- drivers/ata/pata_pdc202xx_old.c | 2 +- drivers/ata/pata_platform.c | 2 +- drivers/ata/pata_qdi.c | 2 +- drivers/ata/pata_radisys.c | 2 +- drivers/ata/pata_sc1200.c | 2 +- drivers/ata/pata_scc.c | 2 +- drivers/ata/pata_serverworks.c | 1 - drivers/ata/pata_sil680.c | 1 - drivers/ata/pata_sis.c | 2 +- drivers/ata/pata_sl82c105.c | 1 - drivers/ata/pata_triflex.c | 2 +- drivers/ata/pata_via.c | 1 - drivers/ata/pata_winbond.c | 2 +- 40 files changed, 28 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index 75a406f5e69..5c33767e66d 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -1,6 +1,6 @@ /* * ata_generic.c - Generic PATA/SATA controller driver. - * Copyright 2005 Red Hat Inc , all rights reserved. + * Copyright 2005 Red Hat Inc, all rights reserved. * * Elements from ide/pci/generic.c * Copyright (C) 2001-2002 Andre Hedrick diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index e9e32ed6b1a..52dc2d8b8f2 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -14,7 +14,7 @@ * * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-2000 Andre Hedrick - * Copyright (C) 2003 Red Hat Inc + * Copyright (C) 2003 Red Hat Inc * * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c index eb919c16a03..e2e332d8ff9 100644 --- a/drivers/ata/pata_acpi.c +++ b/drivers/ata/pata_acpi.c @@ -1,7 +1,7 @@ /* * ACPI PATA driver * - * (c) 2007 Red Hat + * (c) 2007 Red Hat */ #include diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index 5ca70fa1f58..73c466e452c 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -1,7 +1,6 @@ /* * pata_ali.c - ALI 15x3 PATA for new ATA layer * (C) 2005 Red Hat Inc - * Alan Cox * * based in part upon * linux/drivers/ide/pci/alim15x3.c Version 0.17 2003/01/02 diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index 57dd00f463d..0ec9c7d9fe9 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c @@ -1,7 +1,6 @@ /* * pata_amd.c - AMD PATA for new ATA layer * (C) 2005-2006 Red Hat Inc - * Alan Cox * * Based on pata-sil680. Errata information is taken from data sheets * and the amd74xx.c driver by Vojtech Pavlik. Nvidia SATA devices are diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c index 0f513bc1119..6b3092c75ff 100644 --- a/drivers/ata/pata_artop.c +++ b/drivers/ata/pata_artop.c @@ -1,7 +1,7 @@ /* * pata_artop.c - ARTOP ATA controller driver * - * (C) 2006 Red Hat + * (C) 2006 Red Hat * (C) 2007 Bartlomiej Zolnierkiewicz * * Based in part on drivers/ide/pci/aec62xx.c diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index e8a0d99d735..0e2cde8f997 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c @@ -1,7 +1,6 @@ /* * pata_atiixp.c - ATI PATA for new ATA layer * (C) 2005 Red Hat Inc - * Alan Cox * * Based on * diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c index 2de30b99027..34a394264c3 100644 --- a/drivers/ata/pata_cmd640.c +++ b/drivers/ata/pata_cmd640.c @@ -1,7 +1,6 @@ /* * pata_cmd640.c - CMD640 PCI PATA for new ATA layer * (C) 2007 Red Hat Inc - * Alan Cox * * Based upon * linux/drivers/ide/pci/cmd640.c Version 1.02 Sep 01, 1996 diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index ddd09b7d98c..3167d8fed2f 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c @@ -1,7 +1,7 @@ /* * pata_cmd64x.c - CMD64x PATA for new ATA layer * (C) 2005 Red Hat Inc - * Alan Cox + * Alan Cox * * Based upon * linux/drivers/ide/pci/cmd64x.c Version 1.30 Sept 10, 2002 diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c index 0c4b271a9d5..bba453381f4 100644 --- a/drivers/ata/pata_cs5530.c +++ b/drivers/ata/pata_cs5530.c @@ -1,7 +1,6 @@ /* * pata-cs5530.c - CS5530 PATA for new ATA layer * (C) 2005 Red Hat Inc - * Alan Cox * * based upon cs5530.c by Mark Lord. * diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c index f1b6556f048..1b2d4a0f5f7 100644 --- a/drivers/ata/pata_cs5535.c +++ b/drivers/ata/pata_cs5535.c @@ -1,7 +1,7 @@ /* * pata-cs5535.c - CS5535 PATA for new ATA layer * (C) 2005-2006 Red Hat Inc - * Alan Cox + * Alan Cox * * based upon cs5535.c from AMD as cleaned up and * made readable and Linux style by Wolfgang Zuleger + * Alan Cox * * Based heavily on * linux/drivers/ide/pci/cy82c693.c Version 0.40 Sep. 10, 2002 diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index 9fba82976ba..ac6392ea35b 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c @@ -1,7 +1,7 @@ /* * pata_efar.c - EFAR PIIX clone controller driver * - * (C) 2005 Red Hat + * (C) 2005 Red Hat * * Some parts based on ata_piix.c by Jeff Garzik and others. * diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index 6a111baab52..15cdb9148aa 100644 --- a/drivers/ata/pata_isapnp.c +++ b/drivers/ata/pata_isapnp.c @@ -1,7 +1,7 @@ /* * pata-isapnp.c - ISA PnP PATA controller driver. - * Copyright 2005/2006 Red Hat Inc , all rights reserved. + * Copyright 2005/2006 Red Hat Inc, all rights reserved. * * Based in part on ide-pnp.c by Andrey Panin */ diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 0221c9a4676..4e13aadb877 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -1,7 +1,7 @@ /* * pata_it821x.c - IT821x PATA for new ATA layer * (C) 2005 Red Hat Inc - * Alan Cox + * Alan Cox * (C) 2007 Bartlomiej Zolnierkiewicz * * based upon @@ -10,7 +10,7 @@ * * linux/drivers/ide/pci/it821x.c Version 0.09 December 2004 * - * Copyright (C) 2004 Red Hat + * Copyright (C) 2004 Red Hat * * May be copied or modified under the terms of the GNU General Public License * Based in part on the ITE vendor provided SCSI driver. diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index 73b7596816b..38cf1ab2d28 100644 --- a/drivers/ata/pata_jmicron.c +++ b/drivers/ata/pata_jmicron.c @@ -4,7 +4,7 @@ * driven by AHCI in the usual configuration although * this driver can handle other setups if we need it. * - * (c) 2006 Red Hat + * (c) 2006 Red Hat */ #include diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index bc037ffce20..930c2208640 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -1,6 +1,6 @@ /* * pata-legacy.c - Legacy port PATA/SATA controller driver. - * Copyright 2005/2006 Red Hat , all rights reserved. + * Copyright 2005/2006 Red Hat, all rights reserved. * * 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 diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index 0d87eec8496..76e399bf8c1 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -5,7 +5,7 @@ * isn't making full use of the device functionality but it is * easy to get working. * - * (c) 2006 Red Hat + * (c) 2006 Red Hat */ #include diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c index 7d7e3fdab71..7c8faa48b5f 100644 --- a/drivers/ata/pata_mpiix.c +++ b/drivers/ata/pata_mpiix.c @@ -1,7 +1,7 @@ /* * pata_mpiix.c - Intel MPIIX PATA for new ATA layer * (C) 2005-2006 Red Hat Inc - * Alan Cox + * Alan Cox * * The MPIIX is different enough to the PIIX4 and friends that we give it * a separate driver. The old ide/pci code handles this by just not tuning diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c index d9719c8b9db..9dc05e1656a 100644 --- a/drivers/ata/pata_netcell.c +++ b/drivers/ata/pata_netcell.c @@ -1,7 +1,7 @@ /* * pata_netcell.c - Netcell PATA driver * - * (c) 2006 Red Hat + * (c) 2006 Red Hat */ #include diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c index 565e67cd13f..5e76f96ec7e 100644 --- a/drivers/ata/pata_ninja32.c +++ b/drivers/ata/pata_ninja32.c @@ -1,7 +1,6 @@ /* * pata_ninja32.c - Ninja32 PATA for new ATA layer * (C) 2007 Red Hat Inc - * Alan Cox * * Note: The controller like many controllers has shared timings for * PIO and DMA. We thus flip to the DMA timings in dma_start and flip back diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c index be756b7ef07..40d411c460d 100644 --- a/drivers/ata/pata_ns87410.c +++ b/drivers/ata/pata_ns87410.c @@ -1,7 +1,6 @@ /* * pata_ns87410.c - National Semiconductor 87410 PATA for new ATA layer * (C) 2006 Red Hat Inc - * Alan Cox * * 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 diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c index e0aa7eaaee0..89bf5f865d6 100644 --- a/drivers/ata/pata_ns87415.c +++ b/drivers/ata/pata_ns87415.c @@ -1,7 +1,7 @@ /* * pata_ns87415.c - NS87415 (non PARISC) PATA * - * (C) 2005 Red Hat + * (C) 2005 Red Hat * * This is a fairly generic MWDMA controller. It has some limitations * as it requires timing reloads on PIO/DMA transitions but it is otherwise diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c index df64f244300..c0dbc46a348 100644 --- a/drivers/ata/pata_oldpiix.c +++ b/drivers/ata/pata_oldpiix.c @@ -1,7 +1,7 @@ /* * pata_oldpiix.c - Intel PATA/SATA controllers * - * (C) 2005 Red Hat + * (C) 2005 Red Hat * * Some parts based on ata_piix.c by Jeff Garzik and others. * diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c index fb2cf661b0e..e4fa4d565e9 100644 --- a/drivers/ata/pata_opti.c +++ b/drivers/ata/pata_opti.c @@ -1,7 +1,6 @@ /* * pata_opti.c - ATI PATA for new ATA layer * (C) 2005 Red Hat Inc - * Alan Cox * * Based on * linux/drivers/ide/pci/opti621.c Version 0.7 Sept 10, 2002 diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c index 4cd74445631..93bb6e91973 100644 --- a/drivers/ata/pata_optidma.c +++ b/drivers/ata/pata_optidma.c @@ -1,7 +1,6 @@ /* * pata_optidma.c - Opti DMA PATA for new ATA layer * (C) 2006 Red Hat Inc - * Alan Cox * * The Opti DMA controllers are related to the older PIO PCI controllers * and indeed the VLB ones. The main differences are that the timing diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 02b596b9cf6..271cb64d429 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -1,6 +1,6 @@ /* * pata_pcmcia.c - PCMCIA PATA controller driver. - * Copyright 2005-2006 Red Hat Inc , all rights reserved. + * Copyright 2005-2006 Red Hat Inc, all rights reserved. * PCMCIA ident update Copyright 2006 Marcin Juszkiewicz * * diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index d2673060bc8..799a6a09871 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -1,7 +1,7 @@ /* * pata_pdc202xx_old.c - Promise PDC202xx PATA for new ATA layer * (C) 2005 Red Hat Inc - * Alan Cox + * Alan Cox * (C) 2007 Bartlomiej Zolnierkiewicz * * Based in part on linux/drivers/ide/pci/pdc202xx_old.c diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index 8f65ad61b8a..77e4e3b17f5 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c @@ -5,7 +5,7 @@ * * Based on pata_pcmcia: * - * Copyright 2005-2006 Red Hat Inc , all rights reserved. + * Copyright 2005-2006 Red Hat Inc, all rights reserved. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c index 63b7a1c165a..3080f371222 100644 --- a/drivers/ata/pata_qdi.c +++ b/drivers/ata/pata_qdi.c @@ -1,6 +1,6 @@ /* * pata_qdi.c - QDI VLB ATA controllers - * (C) 2006 Red Hat + * (C) 2006 Red Hat * * This driver mostly exists as a proof of concept for non PCI devices under * libata. While the QDI6580 was 'neat' in 1993 it is no longer terribly diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c index 1c0d9fa7ee5..0b0aa452de1 100644 --- a/drivers/ata/pata_radisys.c +++ b/drivers/ata/pata_radisys.c @@ -1,7 +1,7 @@ /* * pata_radisys.c - Intel PATA/SATA controllers * - * (C) 2006 Red Hat + * (C) 2006 Red Hat * * Some parts based on ata_piix.c by Jeff Garzik and others. * diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c index 0278fd2b8fb..9a4bdca5461 100644 --- a/drivers/ata/pata_sc1200.c +++ b/drivers/ata/pata_sc1200.c @@ -1,5 +1,5 @@ /* - * New ATA layer SC1200 driver Alan Cox + * New ATA layer SC1200 driver Alan Cox * * TODO: Mode selection filtering * TODO: Can't enable second channel until ATA core has serialize diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index 16673d16857..cf3707e516a 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -8,7 +8,7 @@ * Copyright 2003-2005 Jeff Garzik * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-2000 Andre Hedrick - * Copyright (C) 2003 Red Hat Inc + * Copyright (C) 2003 Red Hat Inc * * and drivers/ata/ahci.c: * Copyright 2004-2005 Red Hat, Inc. diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index ffd26d0dc50..72e41c9f969 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -1,7 +1,6 @@ /* * pata_serverworks.c - Serverworks PATA for new ATA layer * (C) 2005 Red Hat Inc - * Alan Cox * * based upon * diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index a598bb36aaf..83580a59db5 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -1,7 +1,6 @@ /* * pata_sil680.c - SIL680 PATA for new ATA layer * (C) 2005 Red Hat Inc - * Alan Cox * * based upon * diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index 26345d7b531..d3423661175 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c @@ -1,7 +1,7 @@ /* * pata_sis.c - SiS ATA driver * - * (C) 2005 Red Hat + * (C) 2005 Red Hat * (C) 2007 Bartlomiej Zolnierkiewicz * * Based upon linux/drivers/ide/pci/sis5513.c diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c index 69877bd8181..1b0e7b6d8ef 100644 --- a/drivers/ata/pata_sl82c105.c +++ b/drivers/ata/pata_sl82c105.c @@ -1,7 +1,6 @@ /* * pata_sl82c105.c - SL82C105 PATA for new ATA layer * (C) 2005 Red Hat Inc - * Alan Cox * * Based in part on linux/drivers/ide/pci/sl82c105.c * SL82C105/Winbond 553 IDE driver diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c index b181261f274..ef9597517cd 100644 --- a/drivers/ata/pata_triflex.c +++ b/drivers/ata/pata_triflex.c @@ -1,7 +1,7 @@ /* * pata_triflex.c - Compaq PATA for new ATA layer * (C) 2005 Red Hat Inc - * Alan Cox + * Alan Cox * * based upon * diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index 8fdb2ce7321..681169c9c64 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -1,7 +1,6 @@ /* * pata_via.c - VIA PATA for new ATA layer * (C) 2005-2006 Red Hat Inc - * Alan Cox * * Documentation * Most chipset documentation available under NDA only diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c index a7606b044a6..319e164a3d7 100644 --- a/drivers/ata/pata_winbond.c +++ b/drivers/ata/pata_winbond.c @@ -1,6 +1,6 @@ /* * pata_winbond.c - Winbond VLB ATA controllers - * (C) 2006 Red Hat + * (C) 2006 Red Hat * * Support for the Winbond 83759A when operating in advanced mode. * Multichip mode is not currently supported. -- cgit v1.2.3 From c77a036beceabbfd85b366193685cb49f38292bd Mon Sep 17 00:00:00 2001 From: Mark Nelson Date: Thu, 23 Oct 2008 14:08:16 +1100 Subject: ahci: Add support for Promise PDC42819 Add an appropriate entry for the Promise PDC42819 controller. It has an AHCI mode and so far works correctly with board_ahci. This chip is found on Promise's FastTrak TX2650 (2 port) and TX4650 (4 port) software-based RAID cards (for which there is a binary driver, t3sas) and can be found on some motherboards, for example the MSI K9A2 Platinum, which calls the chip a Promise T3 controller. Although this controller also supports SAS devices, its default bootup mode is AHCI and the binary driver has to do some magic to get the chip into the appropriate mode to drive SAS disks. Seeing as no documentation is provided by Promise, adding this entry to the ahci driver allows the controller to be useful to people as a SATA controller (with no ill effects on the system if a SAS disk is connected - probing of the port just times out with "link online but device misclassified"), without having to resort to using the binary driver. Users who require SAS or the proprietary software raid can get this functionality using the binary driver. Signed-off-by: Mark Nelson Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index aeadd00411a..289719b2cb3 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -588,6 +588,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ + /* Promise */ + { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ + /* Generic, PCI class code for AHCI */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, -- cgit v1.2.3 From 4a9c7b3359889399aacb94019bbdfc9f38d4cff7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 27 Oct 2008 19:59:23 +0900 Subject: libata: fix device iteration bugs There were several places where only enabled devices should be iterated over but device enabledness wasn't checked. * IDENTIFY data 40 wire check in cable_is_40wire() * xfer_mode/ncq_enabled saving in ata_scsi_error() * DUBIOUS_XFER handling in ata_set_mode() While at it, reformat comments in cable_is_40wire(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 34 +++++++++++++++++++--------------- drivers/ata/libata-eh.c | 9 +++++++++ 2 files changed, 28 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 8cb0b360bfd..97df4807a08 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4156,29 +4156,33 @@ static int cable_is_40wire(struct ata_port *ap) struct ata_link *link; struct ata_device *dev; - /* If the controller thinks we are 40 wire, we are */ + /* If the controller thinks we are 40 wire, we are. */ if (ap->cbl == ATA_CBL_PATA40) return 1; - /* If the controller thinks we are 80 wire, we are */ + + /* If the controller thinks we are 80 wire, we are. */ if (ap->cbl == ATA_CBL_PATA80 || ap->cbl == ATA_CBL_SATA) return 0; - /* If the system is known to be 40 wire short cable (eg laptop), - then we allow 80 wire modes even if the drive isn't sure */ + + /* If the system is known to be 40 wire short cable (eg + * laptop), then we allow 80 wire modes even if the drive + * isn't sure. + */ if (ap->cbl == ATA_CBL_PATA40_SHORT) return 0; - /* If the controller doesn't know we scan - - - Note: We look for all 40 wire detects at this point. - Any 80 wire detect is taken to be 80 wire cable - because - - In many setups only the one drive (slave if present) - will give a valid detect - - If you have a non detect capable drive you don't - want it to colour the choice - */ + + /* If the controller doesn't know, we scan. + * + * Note: We look for all 40 wire detects at this point. Any + * 80 wire detect is taken to be 80 wire cable because + * - in many setups only the one drive (slave if present) will + * give a valid detect + * - if you have a non detect capable drive you don't want it + * to colour the choice + */ ata_port_for_each_link(link, ap) { ata_link_for_each_dev(dev, link) { - if (!ata_is_40wire(dev)) + if (ata_dev_enabled(dev) && !ata_is_40wire(dev)) return 0; } } diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 5d687d7cffa..a6a3b1554c4 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -603,6 +603,9 @@ void ata_scsi_error(struct Scsi_Host *host) ata_link_for_each_dev(dev, link) { int devno = dev->devno; + if (!ata_dev_enabled(dev)) + continue; + ehc->saved_xfer_mode[devno] = dev->xfer_mode; if (ata_ncq_enabled(dev)) ehc->saved_ncq_enabled |= 1 << devno; @@ -2787,6 +2790,9 @@ int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) /* if data transfer is verified, clear DUBIOUS_XFER on ering top */ ata_link_for_each_dev(dev, link) { + if (!ata_dev_enabled(dev)) + continue; + if (!(dev->flags & ATA_DFLAG_DUBIOUS_XFER)) { struct ata_ering_entry *ent; @@ -2808,6 +2814,9 @@ int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) u8 saved_xfer_mode = ehc->saved_xfer_mode[dev->devno]; u8 saved_ncq = !!(ehc->saved_ncq_enabled & (1 << dev->devno)); + if (!ata_dev_enabled(dev)) + continue; + if (dev->xfer_mode != saved_xfer_mode || ata_ncq_enabled(dev) != saved_ncq) dev->flags |= ATA_DFLAG_DUBIOUS_XFER; -- cgit v1.2.3 From 3cd8ddbd86e4ea6f2f6582da217651f048d76130 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 26 Oct 2008 20:19:32 -0700 Subject: libata: add missing kernel-doc Fix libata missing kernel-doc: Warning(lin2628-rc2//drivers/ata/libata-core.c:4562): No description found for parameter 'tag' Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 97df4807a08..2ff633c119e 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4557,6 +4557,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) /** * ata_qc_new_init - Request an available ATA command, and initialize it * @dev: Device from whom we request an available command structure + * @tag: command tag * * LOCKING: * None. -- cgit v1.2.3 From e8b3b5e9f54512bfdb7c154da07ec0408cbd6c56 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 25 Oct 2008 14:26:54 +0900 Subject: sata_sil24: configure max read request size to 4k Due to request posting limitations, bandwidth of sil3132 is limited to around 120MB/s with the minimum pci-e payload size (128bytes) which is used by most consumer systems. However, write throughput can be slightly (~3%) increased by increasing the max read requeset size. Configure it to 4k which is the maximum supported. This optimization is also done by SIMG's windows driver. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/sata_sil24.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 4621807a1a6..ccee930f1e1 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -1329,6 +1329,11 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } } + /* Set max read request size to 4096. This slightly increases + * write throughput for pci-e variants. + */ + pcie_set_readrq(pdev, 4096); + sil24_init_controller(host); pci_set_master(pdev); -- cgit v1.2.3 From 90484ebfc96c5dc5c498ed72cf2d370575db9b76 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 26 Oct 2008 15:43:03 +0900 Subject: libata: clear saved xfer_mode and ncq_enabled on device detach libata EH saves xfer_mode and ncq_enabled at start to later set DUBIOUS_XFER flag if it has changed. These values need to be cleared on device detach such that hot device swap doesn't accidentally miss DUBIOUS_XFER. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index a6a3b1554c4..8077bdf5d30 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1164,6 +1164,7 @@ void ata_eh_detach_dev(struct ata_device *dev) { struct ata_link *link = dev->link; struct ata_port *ap = link->ap; + struct ata_eh_context *ehc = &link->eh_context; unsigned long flags; ata_dev_disable(dev); @@ -1177,9 +1178,11 @@ void ata_eh_detach_dev(struct ata_device *dev) ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; } - /* clear per-dev EH actions */ + /* clear per-dev EH info */ ata_eh_clear_action(link, dev, &link->eh_info, ATA_EH_PERDEV_MASK); ata_eh_clear_action(link, dev, &link->eh_context.i, ATA_EH_PERDEV_MASK); + ehc->saved_xfer_mode[dev->devno] = 0; + ehc->saved_ncq_enabled &= ~(1 << dev->devno); spin_unlock_irqrestore(ap->lock, flags); } -- cgit v1.2.3 From 054e5f616b5becdc096b793407dc33fe379749ac Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sun, 26 Oct 2008 18:10:19 -0400 Subject: libata: Fix LBA48 on pata_it821x RAID volumes. [http://lkml.org/lkml/2008/10/18/82] Signed-off-by: Ondrej Zary Acked-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/pata_it821x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 4e13aadb877..860ede52628 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -557,9 +557,8 @@ static unsigned int it821x_read_id(struct ata_device *adev, if (strstr(model_num, "Integrated Technology Express")) { /* Set feature bits the firmware neglects */ id[49] |= 0x0300; /* LBA, DMA */ - id[82] |= 0x0400; /* LBA48 */ id[83] &= 0x7FFF; - id[83] |= 0x4000; /* Word 83 is valid */ + id[83] |= 0x4400; /* Word 83 is valid and LBA48 */ id[86] |= 0x0400; /* LBA48 on */ id[ATA_ID_MAJOR_VER] |= 0x1F; } -- cgit v1.2.3 From 2830c9fb8e66cee70b8bffdfb0de01c144c7e643 Mon Sep 17 00:00:00 2001 From: Venki Pallipadi Date: Fri, 24 Oct 2008 11:00:35 -0700 Subject: i7300_idle: Kconfig, show menu only on x86_64 ...since today it contains only a single driver which is visible to just x86_64 Signed-off-by: Venkatesh Pallipadi Signed-off-by: Len Brown --- drivers/idle/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/idle/Kconfig b/drivers/idle/Kconfig index 108264de0ac..f15e90a453d 100644 --- a/drivers/idle/Kconfig +++ b/drivers/idle/Kconfig @@ -1,5 +1,6 @@ menu "Memory power savings" +depends on X86_64 config I7300_IDLE_IOAT_CHANNEL bool @@ -7,7 +8,7 @@ config I7300_IDLE_IOAT_CHANNEL config I7300_IDLE tristate "Intel chipset idle memory power saving driver" select I7300_IDLE_IOAT_CHANNEL - depends on X86_64 && EXPERIMENTAL + depends on EXPERIMENTAL help Enable memory power savings when idle with certain Intel server chipsets. The chipset must have I/O AT support, such as the -- cgit v1.2.3 From e7c0d217cdaa837d30bc265eddac4d176969fd68 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 17 Oct 2008 19:08:31 +0100 Subject: pata_ninja32: suspend/resume support I had assumed that the standard recovery would be sufficient for this hardware but it isn't. Fix up the other registers on resume as needed. See bug #11735 Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/pata_ninja32.c | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c index 5e76f96ec7e..4e466eae8b4 100644 --- a/drivers/ata/pata_ninja32.c +++ b/drivers/ata/pata_ninja32.c @@ -44,7 +44,7 @@ #include #define DRV_NAME "pata_ninja32" -#define DRV_VERSION "0.0.1" +#define DRV_VERSION "0.1.1" /** @@ -88,6 +88,17 @@ static struct ata_port_operations ninja32_port_ops = { .set_piomode = ninja32_set_piomode, }; +static void ninja32_program(void __iomem *base) +{ + iowrite8(0x05, base + 0x01); /* Enable interrupt lines */ + iowrite8(0xBE, base + 0x02); /* Burst, ?? setup */ + iowrite8(0x01, base + 0x03); /* Unknown */ + iowrite8(0x20, base + 0x04); /* WAIT0 */ + iowrite8(0x8f, base + 0x05); /* Unknown */ + iowrite8(0xa4, base + 0x1c); /* Unknown */ + iowrite8(0x83, base + 0x1d); /* BMDMA control: WAIT0 */ +} + static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id) { struct ata_host *host; @@ -133,18 +144,28 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id) ap->ioaddr.bmdma_addr = base; ata_sff_std_ports(&ap->ioaddr); - iowrite8(0x05, base + 0x01); /* Enable interrupt lines */ - iowrite8(0xBE, base + 0x02); /* Burst, ?? setup */ - iowrite8(0x01, base + 0x03); /* Unknown */ - iowrite8(0x20, base + 0x04); /* WAIT0 */ - iowrite8(0x8f, base + 0x05); /* Unknown */ - iowrite8(0xa4, base + 0x1c); /* Unknown */ - iowrite8(0x83, base + 0x1d); /* BMDMA control: WAIT0 */ + ninja32_program(base); /* FIXME: Should we disable them at remove ? */ return ata_host_activate(host, dev->irq, ata_sff_interrupt, IRQF_SHARED, &ninja32_sht); } +#ifdef CONFIG_PM + +static int ninja32_reinit_one(struct pci_dev *pdev) +{ + struct ata_host *host = dev_get_drvdata(&pdev->dev); + int rc; + + rc = ata_pci_device_do_resume(pdev); + if (rc) + return rc; + ninja32_program(host->iomap[0]); + ata_host_resume(host); + return 0; +} +#endif + static const struct pci_device_id ninja32[] = { { 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, @@ -155,7 +176,11 @@ static struct pci_driver ninja32_pci_driver = { .name = DRV_NAME, .id_table = ninja32, .probe = ninja32_init_one, - .remove = ata_pci_remove_one + .remove = ata_pci_remove_one, +#ifdef CONFIG_PM + .suspend = ata_pci_device_suspend, + .resume = ninja32_reinit_one, +#endif }; static int __init ninja32_init(void) -- cgit v1.2.3 From eb40963c835c69681af516388a2a92b57e2f0fe7 Mon Sep 17 00:00:00 2001 From: David Milburn Date: Thu, 16 Oct 2008 09:26:19 -0500 Subject: libata: ahci enclosure management led sync Synchronize ahci_sw_activity and ahci_sw_activity_blink with ata_port lock. Signed-off-by: David Milburn Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 289719b2cb3..3c71d313343 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1223,6 +1223,7 @@ static void ahci_sw_activity_blink(unsigned long arg) struct ahci_em_priv *emp = &pp->em_priv[link->pmp]; unsigned long led_message = emp->led_state; u32 activity_led_state; + unsigned long flags; led_message &= 0xffff0000; led_message |= ap->port_no | (link->pmp << 8); @@ -1231,6 +1232,7 @@ static void ahci_sw_activity_blink(unsigned long arg) * toggle state of LED and reset timer. If not, * turn LED to desired idle state. */ + spin_lock_irqsave(ap->lock, flags); if (emp->saved_activity != emp->activity) { emp->saved_activity = emp->activity; /* get the current LED state */ @@ -1253,6 +1255,7 @@ static void ahci_sw_activity_blink(unsigned long arg) if (emp->blink_policy == BLINK_OFF) led_message |= (1 << 16); } + spin_unlock_irqrestore(ap->lock, flags); ahci_transmit_led_message(ap, led_message, 4); } -- cgit v1.2.3 From 87943acf60898a3efb6b5ee85d4cc789898bf5e8 Mon Sep 17 00:00:00 2001 From: David Milburn Date: Mon, 13 Oct 2008 14:38:36 -0500 Subject: libata: ahci enclosure management bit mask Enclosure management bit mask definitions. Signed-off-by: David Milburn Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 3c71d313343..a67b8e7c712 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -49,6 +49,17 @@ #define DRV_NAME "ahci" #define DRV_VERSION "3.0" +/* Enclosure Management Control */ +#define EM_CTRL_MSG_TYPE 0x000f0000 + +/* Enclosure Management LED Message Type */ +#define EM_MSG_LED_HBA_PORT 0x0000000f +#define EM_MSG_LED_PMP_SLOT 0x0000ff00 +#define EM_MSG_LED_VALUE 0xffff0000 +#define EM_MSG_LED_VALUE_ACTIVITY 0x00070000 +#define EM_MSG_LED_VALUE_OFF 0xfff80000 +#define EM_MSG_LED_VALUE_ON 0x00010000 + static int ahci_skip_host_reset; module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444); MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)"); @@ -1225,7 +1236,7 @@ static void ahci_sw_activity_blink(unsigned long arg) u32 activity_led_state; unsigned long flags; - led_message &= 0xffff0000; + led_message &= EM_MSG_LED_VALUE; led_message |= ap->port_no | (link->pmp << 8); /* check to see if we've had activity. If so, @@ -1236,7 +1247,7 @@ static void ahci_sw_activity_blink(unsigned long arg) if (emp->saved_activity != emp->activity) { emp->saved_activity = emp->activity; /* get the current LED state */ - activity_led_state = led_message & 0x00010000; + activity_led_state = led_message & EM_MSG_LED_VALUE_ON; if (activity_led_state) activity_led_state = 0; @@ -1244,14 +1255,14 @@ static void ahci_sw_activity_blink(unsigned long arg) activity_led_state = 1; /* clear old state */ - led_message &= 0xfff8ffff; + led_message &= ~EM_MSG_LED_VALUE_ACTIVITY; /* toggle state */ led_message |= (activity_led_state << 16); mod_timer(&emp->timer, jiffies + msecs_to_jiffies(100)); } else { /* switch to idle */ - led_message &= 0xfff8ffff; + led_message &= ~EM_MSG_LED_VALUE_ACTIVITY; if (emp->blink_policy == BLINK_OFF) led_message |= (1 << 16); } @@ -1300,7 +1311,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state, struct ahci_em_priv *emp; /* get the slot number from the message */ - pmp = (state & 0x0000ff00) >> 8; + pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; if (pmp < MAX_SLOTS) emp = &pp->em_priv[pmp]; else @@ -1325,7 +1336,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state, message[0] |= (4 << 8); /* ignore 0:4 of byte zero, fill in port info yourself */ - message[1] = ((state & 0xfffffff0) | ap->port_no); + message[1] = ((state & ~EM_MSG_LED_HBA_PORT) | ap->port_no); /* write message to EM_LOC */ writel(message[0], mmio + hpriv->em_loc); @@ -1368,7 +1379,7 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf, state = simple_strtoul(buf, NULL, 0); /* get the slot number from the message */ - pmp = (state & 0x0000ff00) >> 8; + pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; if (pmp < MAX_SLOTS) emp = &pp->em_priv[pmp]; else @@ -1379,7 +1390,7 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf, * activity led through em_message */ if (emp->blink_policy) - state &= 0xfff8ffff; + state &= ~EM_MSG_LED_VALUE_ACTIVITY; return ahci_transmit_led_message(ap, state, size); } @@ -1398,16 +1409,16 @@ static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val) link->flags &= ~(ATA_LFLAG_SW_ACTIVITY); /* set the LED to OFF */ - port_led_state &= 0xfff80000; + port_led_state &= EM_MSG_LED_VALUE_OFF; port_led_state |= (ap->port_no | (link->pmp << 8)); ahci_transmit_led_message(ap, port_led_state, 4); } else { link->flags |= ATA_LFLAG_SW_ACTIVITY; if (val == BLINK_OFF) { /* set LED to ON for idle */ - port_led_state &= 0xfff80000; + port_led_state &= EM_MSG_LED_VALUE_OFF; port_led_state |= (ap->port_no | (link->pmp << 8)); - port_led_state |= 0x00010000; /* check this */ + port_led_state |= EM_MSG_LED_VALUE_ON; /* check this */ ahci_transmit_led_message(ap, port_led_state, 4); } } @@ -2618,7 +2629,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) u32 em_loc = readl(mmio + HOST_EM_LOC); u32 em_ctl = readl(mmio + HOST_EM_CTL); - messages = (em_ctl & 0x000f0000) >> 16; + messages = (em_ctl & EM_CTRL_MSG_TYPE) >> 16; /* we only support LED message type right now */ if ((messages & 0x01) && (ahci_em_messages == 1)) { -- cgit v1.2.3 From b1b57fbe9bb10d94682a975456de7a727d1dbc84 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 27 Oct 2008 16:04:53 +0800 Subject: ACPI: fix de-reference bug in power resource driver change state to *state in the function of acpi_power_get_state() Signed-off-by: yakui.zhao@intel.com Signed-off-by: Len Brown --- drivers/acpi/power.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index a1718e56103..30d4a5282a2 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -153,7 +153,8 @@ static int acpi_power_get_state(acpi_handle handle, int *state) ACPI_POWER_RESOURCE_STATE_OFF; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] is %s\n", - acpi_ut_get_node_name(handle), state ? "on" : "off")); + acpi_ut_get_node_name(handle), + *state ? "on" : "off")); return 0; } -- cgit v1.2.3 From 676962dac6e267ce7c13f73962208f9124a084bb Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Mon, 27 Oct 2008 16:05:39 +0800 Subject: ACPI: fan: Delete the strict check in power transition On some laptops the Fan device is turned on/off by controlling the corresponding power resource. For example: If the power resource defined in _PR0 object is turned off, it indicates that the FAN device is in off state(the ACPI state is in D3 state). Maybe the device is already in D3 state and expected to be transited to D3 state. As there is no _PR3 object, the power transition can't be finished and it will be switched to the Unknown state. Maybe it is more reasonable that the strick check in power transistion is deleted. http://bugzilla.kernel.org/show_bug.cgi?id=9485 Signed-off-by: yakui.zhao@intel.com Signed-off-by: Len Brown --- drivers/acpi/power.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 30d4a5282a2..89111cd28ed 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -517,11 +517,6 @@ int acpi_power_transition(struct acpi_device *device, int state) cl = &device->power.states[device->power.state].resources; tl = &device->power.states[state].resources; - if (!cl->count && !tl->count) { - result = -ENODEV; - goto end; - } - /* TBD: Resources must be ordered. */ /* -- cgit v1.2.3 From ed206fac87d65917280b6c3edd3f01125d4095c9 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 27 Oct 2008 14:01:02 -0700 Subject: ACPI: bugfix reporting of event handler status Introduce a new flag showing whether the event has an event handler/method. For all the GPEs and Fixed Events, 1. ACPI_EVENT_FLAG_HANDLE is cleared, it's an "invalid" ACPI event. 2. Both ACPI_EVENT_FLAG_HANDLE and ACPI_EVENT_FLAG_DISABLE are set, it's "disabled". 3. Both ACPI_EVENT_FLAG_HANDLE and ACPI_EVENT_FLAG_ENABLE are set, it's "enabled". 4. Both ACPI_EVENT_FLAG_HANDLE and ACPI_EVENT_FLAG_WAKE_ENABLE are set, it's "wake_enabled". Among other things, this prevents incorrect reporting of ACPI events as being "invalid" when it's really just (temporarily) "disabled". Signed-off-by: Zhang Rui Signed-off-by: David Brownell Signed-off-by: Len Brown --- drivers/acpi/events/evxfevnt.c | 6 ++++++ drivers/acpi/system.c | 19 +++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index 73bfd6bf962..211e93a90e9 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c @@ -521,6 +521,9 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) if (value) *event_status |= ACPI_EVENT_FLAG_SET; + if (acpi_gbl_fixed_event_handlers[event].handler) + *event_status |= ACPI_EVENT_FLAG_HANDLE; + return_ACPI_STATUS(status); } @@ -571,6 +574,9 @@ acpi_get_gpe_status(acpi_handle gpe_device, status = acpi_hw_get_gpe_status(gpe_event_info, event_status); + if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) + *event_status |= ACPI_EVENT_FLAG_HANDLE; + unlock_and_exit: if (flags & ACPI_NOT_ISR) { (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 1d74171b794..6d348dce081 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -167,7 +167,6 @@ static int acpi_system_sysfs_init(void) #define COUNT_ERROR 2 /* other */ #define NUM_COUNTERS_EXTRA 3 -#define ACPI_EVENT_VALID 0x01 struct event_counter { u32 count; u32 flags; @@ -312,12 +311,6 @@ static int get_status(u32 index, acpi_event_status *status, acpi_handle *handle) } else if (index < (num_gpes + ACPI_NUM_FIXED_EVENTS)) result = acpi_get_event_status(index - num_gpes, status); - /* - * sleep/power button GPE/Fixed Event is enabled after acpi_system_init, - * check the status at runtime and mark it as valid once it's enabled - */ - if (!result && (*status & ACPI_EVENT_FLAG_ENABLED)) - all_counters[index].flags |= ACPI_EVENT_VALID; end: return result; } @@ -346,12 +339,14 @@ static ssize_t counter_show(struct kobject *kobj, if (result) goto end; - if (!(all_counters[index].flags & ACPI_EVENT_VALID)) - size += sprintf(buf + size, " invalid"); + if (!(status & ACPI_EVENT_FLAG_HANDLE)) + size += sprintf(buf + size, " invalid"); else if (status & ACPI_EVENT_FLAG_ENABLED) - size += sprintf(buf + size, " enable"); + size += sprintf(buf + size, " enabled"); + else if (status & ACPI_EVENT_FLAG_WAKE_ENABLED) + size += sprintf(buf + size, " wake_enabled"); else - size += sprintf(buf + size, " disable"); + size += sprintf(buf + size, " disabled"); end: size += sprintf(buf + size, "\n"); @@ -385,7 +380,7 @@ static ssize_t counter_set(struct kobject *kobj, if (result) goto end; - if (!(all_counters[index].flags & ACPI_EVENT_VALID)) { + if (!(status & ACPI_EVENT_FLAG_HANDLE)) { printk(KERN_WARNING PREFIX "Can not change Invalid GPE/Fixed Event status\n"); return -EINVAL; -- cgit v1.2.3 From 934d9c23b4c7e31840a895ba4b7e88d6413c81f3 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 28 Oct 2008 17:01:23 +1100 Subject: md: destroy partitions and notify udev when md array is stopped. md arrays are not currently destroyed when they are stopped - they remain in /sys/block. Last time I tried this I tripped over locking too much. A consequence of this is that udev doesn't remove anything from /dev. This is rather ugly. As an interim measure until proper device removal can be achieved, make sure all partitions are removed using the BLKRRPART ioctl, and send a KOBJ_CHANGE when an md array is stopped. Signed-off-by: NeilBrown --- drivers/md/md.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index b4162f6f1b7..9abf6ed1653 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3884,6 +3884,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) if (mode == 0) { mdk_rdev_t *rdev; struct list_head *tmp; + struct block_device *bdev; printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); @@ -3940,6 +3941,12 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) mddev->degraded = 0; mddev->barriers_work = 0; mddev->safemode = 0; + bdev = bdget_disk(mddev->gendisk, 0); + if (bdev) { + blkdev_ioctl(bdev, 0, BLKRRPART, 0); + bdput(bdev); + } + kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); } else if (mddev->pers) printk(KERN_INFO "md: %s switched to read-only mode.\n", -- cgit v1.2.3 From 545727f32049f6e7269f73a49904e3229192988e Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Mon, 27 Oct 2008 11:32:27 +0900 Subject: gdrom: Fix compile error Return value and argument of block_device_operations.release of gdrom was changed. This patch fix this problem. Signed-off-by: Nobuhiro Iwamatsu Acked-by: Al Viro Signed-off-by: Paul Mundt --- drivers/cdrom/gdrom.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index 9aaa86b232b..2eecb779437 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -495,9 +495,10 @@ static int gdrom_bdops_open(struct block_device *bdev, fmode_t mode) return cdrom_open(gd.cd_info, bdev, mode); } -static int gdrom_bdops_release(struct block_device *bdev, fmode_t mode) +static int gdrom_bdops_release(struct gendisk *disk, fmode_t mode) { - return cdrom_release(gd.cd_info, mode); + cdrom_release(gd.cd_info, mode); + return 0; } static int gdrom_bdops_mediachanged(struct gendisk *disk) -- cgit v1.2.3 From 5ca8c4852fcbbc8a8497c4ee8b2a0a7466f3524c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 28 Oct 2008 15:33:48 +0900 Subject: SH 7366 needs SCIF_ONLY SH 7366 has compile bug. because there is no SCIF_ONLY for SH 7366. this patch add it. Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 7cd28b22680..44e952bca1e 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -88,6 +88,7 @@ # define SCSPTR0 SCPDR0 # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7723) # define SCSPTR0 0xa4050160 # define SCSPTR1 0xa405013e -- cgit v1.2.3 From 7c045aa2c8eb731996b0c5c6552356b8946e6894 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Tue, 28 Oct 2008 11:10:13 +0100 Subject: [S390] qdio: prevent double qdio shutdown in case of I/O errors In case of I/O errors on a qdio subchannel qdio_shutdown may be called twice by the qdio driver and by zfcp. Remove the superfluous shutdown from qdio and let the upper layer driver handle the error condition. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio_main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index a50682d2a0f..7c865915199 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -1083,7 +1083,6 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, case -EIO: sprintf(dbf_text, "ierr%4x", irq_ptr->schid.sch_no); QDIO_DBF_TEXT2(1, setup, dbf_text); - qdio_int_error(cdev); return; case -ETIMEDOUT: sprintf(dbf_text, "qtoh%4x", irq_ptr->schid.sch_no); -- cgit v1.2.3 From 2c78091405d6f54748b1fac78c45f2a799e3073a Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Tue, 28 Oct 2008 11:10:14 +0100 Subject: [S390] qdio: remove incorrect memset Remove the memset since zeroing the string is not needed and use snprintf instead of sprintf. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio_debug.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index b5390821434..f05590355be 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c @@ -20,6 +20,7 @@ static struct dentry *debugfs_root; #define MAX_DEBUGFS_QUEUES 32 static struct dentry *debugfs_queues[MAX_DEBUGFS_QUEUES] = { NULL }; static DEFINE_MUTEX(debugfs_mutex); +#define QDIO_DEBUGFS_NAME_LEN 40 void qdio_allocate_do_dbf(struct qdio_initialize *init_data) { @@ -152,17 +153,6 @@ static int qstat_seq_open(struct inode *inode, struct file *filp) filp->f_path.dentry->d_inode->i_private); } -static void get_queue_name(struct qdio_q *q, struct ccw_device *cdev, char *name) -{ - memset(name, 0, sizeof(name)); - sprintf(name, "%s", dev_name(&cdev->dev)); - if (q->is_input_q) - sprintf(name + strlen(name), "_input"); - else - sprintf(name + strlen(name), "_output"); - sprintf(name + strlen(name), "_%d", q->nr); -} - static void remove_debugfs_entry(struct qdio_q *q) { int i; @@ -189,14 +179,17 @@ static struct file_operations debugfs_fops = { static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev) { int i = 0; - char name[40]; + char name[QDIO_DEBUGFS_NAME_LEN]; while (debugfs_queues[i] != NULL) { i++; if (i >= MAX_DEBUGFS_QUEUES) return; } - get_queue_name(q, cdev, name); + snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%s_%d", + dev_name(&cdev->dev), + q->is_input_q ? "input" : "output", + q->nr); debugfs_queues[i] = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR, debugfs_root, q, &debugfs_fops); } -- cgit v1.2.3 From 7a4a1ccd44c85c7d92b20a361e3854431c6935e0 Mon Sep 17 00:00:00 2001 From: Frank Munzert Date: Tue, 28 Oct 2008 11:10:17 +0100 Subject: [S390] tape block: complete request with correct locking __blk_end_request must be called with request queue lock held. We need to use blk_end_request rather than __blk_end_request. Signed-off-by: Frank Munzert Signed-off-by: Martin Schwidefsky --- drivers/s390/char/tape_block.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index 023803dbb0c..ae18baf59f0 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -76,7 +76,7 @@ tapeblock_trigger_requeue(struct tape_device *device) static void tapeblock_end_request(struct request *req, int error) { - if (__blk_end_request(req, error, blk_rq_bytes(req))) + if (blk_end_request(req, error, blk_rq_bytes(req))) BUG(); } @@ -166,7 +166,7 @@ tapeblock_requeue(struct work_struct *work) { nr_queued++; spin_unlock(get_ccwdev_lock(device->cdev)); - spin_lock(&device->blk_data.request_queue_lock); + spin_lock_irq(&device->blk_data.request_queue_lock); while ( !blk_queue_plugged(queue) && elv_next_request(queue) && @@ -176,7 +176,9 @@ tapeblock_requeue(struct work_struct *work) { if (rq_data_dir(req) == WRITE) { DBF_EVENT(1, "TBLOCK: Rejecting write request\n"); blkdev_dequeue_request(req); + spin_unlock_irq(&device->blk_data.request_queue_lock); tapeblock_end_request(req, -EIO); + spin_lock_irq(&device->blk_data.request_queue_lock); continue; } blkdev_dequeue_request(req); -- cgit v1.2.3 From b3c21e4919c8598c58faaa0a650dc398baddd993 Mon Sep 17 00:00:00 2001 From: Frank Munzert Date: Tue, 28 Oct 2008 11:10:19 +0100 Subject: [S390] tape: disable interrupts in tape_open and tape_release Get tape device lock with interrupts disabled. Otherwise lockdep will issue a warning similar to: ================================= [ INFO: inconsistent lock state ] 2.6.27 #1 --------------------------------- inconsistent {in-hardirq-W} -> {hardirq-on-W} usage. vol_id/2903 [HC0[0]:SC0[0]:HE1:SE1] takes: (sch->lock){++..}, at: [<000003e00004c7a2>] tape_open+0x42/0x1a4 [tape] {in-hardirq-W} state was registered at: [<000000000007ce5c>] __lock_acquire+0x894/0xa74 [<000000000007d0ce>] lock_acquire+0x92/0xb8 [<0000000000345154>] _spin_lock+0x5c/0x9c [<0000000000202264>] do_IRQ+0x124/0x1f0 [<0000000000026610>] io_return+0x0/0x8 irq event stamp: 847 hardirqs last enabled at (847): [<000000000007aca6>] trace_hardirqs_on+0x2a/0x38 hardirqs last disabled at (846): [<0000000000076ca2>] trace_hardirqs_off+0x2a/0x38 softirqs last enabled at (0): [<000000000004909e>] copy_process+0x43e/0x11f4 softirqs last disabled at (0): [<0000000000000000>] 0x0 other info that might help us debug this: 1 lock held by vol_id/2903: #0: (&bdev->bd_mutex){--..}, at: [<000000000010e0f4>] do_open+0x78/0x358 stack backtrace: CPU: 1 Not tainted 2.6.27 #1}, Process vol_id (pid: 2903, task: 000000003d4c0000, ksp: 000000003d4e3b10) 0400000000000000 000000003d4e3830 0000000000000002 0000000000000000 000000003d4e38d0 000000003d4e3848 000000003d4e3848 00000000000168a8 0000000000000000 000000003d4e3b10 0000000000000000 0000000000000000 000000003d4e3830 000000000000000c 000000003d4e3830 000000003d4e38a0 000000000034aa98 00000000000168a8 000000003d4e3830 000000003d4e3880 Call Trace: ([<000000000001681c>] show_trace+0x138/0x158) [<0000000000016902>] show_stack+0xc6/0xf8 [<00000000000170d4>] dump_stack+0xb0/0xc0 [<0000000000078810>] print_usage_bug+0x1e8/0x228 [<000000000007a71c>] mark_lock+0xb14/0xd24 [<000000000007cd5a>] __lock_acquire+0x792/0xa74 [<000000000007d0ce>] lock_acquire+0x92/0xb8 [<0000000000345154>] _spin_lock+0x5c/0x9c [<000003e00004c7a2>] tape_open+0x42/0x1a4 [tape] [<000003e00005185c>] tapeblock_open+0x98/0xd0 [tape] Signed-off-by: Frank Munzert Signed-off-by: Martin Schwidefsky --- drivers/s390/char/tape_core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index d7073dbf825..f9bb51fa7f5 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -1200,7 +1200,7 @@ tape_open(struct tape_device *device) { int rc; - spin_lock(get_ccwdev_lock(device->cdev)); + spin_lock_irq(get_ccwdev_lock(device->cdev)); if (device->tape_state == TS_NOT_OPER) { DBF_EVENT(6, "TAPE:nodev\n"); rc = -ENODEV; @@ -1218,7 +1218,7 @@ tape_open(struct tape_device *device) tape_state_set(device, TS_IN_USE); rc = 0; } - spin_unlock(get_ccwdev_lock(device->cdev)); + spin_unlock_irq(get_ccwdev_lock(device->cdev)); return rc; } @@ -1228,11 +1228,11 @@ tape_open(struct tape_device *device) int tape_release(struct tape_device *device) { - spin_lock(get_ccwdev_lock(device->cdev)); + spin_lock_irq(get_ccwdev_lock(device->cdev)); if (device->tape_state == TS_IN_USE) tape_state_set(device, TS_UNUSED); module_put(device->discipline->owner); - spin_unlock(get_ccwdev_lock(device->cdev)); + spin_unlock_irq(get_ccwdev_lock(device->cdev)); return 0; } -- cgit v1.2.3 From 5ff0594e2f6fb3242a1a2a4794286244e95afab1 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 28 Oct 2008 19:45:47 +0900 Subject: sh: Revert "SH 7366 needs SCIF_ONLY" This reverts commit 5ca8c4852fcbbc8a8497c4ee8b2a0a7466f3524c. With the killing off of SCIF_ONLY and its spawn in sh-sci, we no longer require this change, so just revert it. Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 36ce9de4b2c..257b2235d12 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -79,7 +79,6 @@ # define SCSPTR0 SCPDR0 # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH7723) # define SCSPTR0 0xa4050160 # define SCSPTR1 0xa405013e -- cgit v1.2.3 From 3eeebf17f31c583f83e081b17b3076477cb96886 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 28 Oct 2008 20:07:44 +0900 Subject: sh: Kill off long-dead HD64465 cchip support. This code has been dead for many years. The last update it received was in 2003 in order to update it for the driver model changes, though it had already been in disarray and unused before that point. The only boards that ever used this chip have not had users in many years either, so it is finally safe to just kill it off and move on with life. Signed-off-by: Paul Mundt --- drivers/pcmcia/Kconfig | 4 - drivers/pcmcia/Makefile | 1 - drivers/pcmcia/hd64465_ss.c | 939 -------------------------------------------- 3 files changed, 944 deletions(-) delete mode 100644 drivers/pcmcia/hd64465_ss.c (limited to 'drivers') diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index f57eeae3830..222904411a1 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -188,10 +188,6 @@ config PCMCIA_M8XX This driver is also available as a module called m8xx_pcmcia. -config HD64465_PCMCIA - tristate "HD64465 host bridge support" - depends on HD64465 && PCMCIA - config PCMCIA_AU1X00 tristate "Au1x00 pcmcia support" depends on SOC_AU1X00 && PCMCIA diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 23e492bf75c..238629ad7f7 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -22,7 +22,6 @@ obj-$(CONFIG_I82365) += i82365.o obj-$(CONFIG_I82092) += i82092.o obj-$(CONFIG_TCIC) += tcic.o obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o -obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o obj-$(CONFIG_M32R_PCC) += m32r_pcc.o diff --git a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c deleted file mode 100644 index 9ef69cdb318..00000000000 --- a/drivers/pcmcia/hd64465_ss.c +++ /dev/null @@ -1,939 +0,0 @@ -/* - * Device driver for the PCMCIA controller module of the - * Hitachi HD64465 handheld companion chip. - * - * Note that the HD64465 provides a very thin PCMCIA host bridge - * layer, requiring a lot of the work of supporting cards to be - * performed by the processor. For example: mapping of card - * interrupts to processor IRQs is done by IRQ demuxing software; - * IO and memory mappings are fixed; setting voltages according - * to card Voltage Select pins etc is done in software. - * - * Note also that this driver uses only the simple, fixed, - * 16MB, 16-bit wide mappings to PCMCIA spaces defined by the - * HD64465. Larger mappings, smaller mappings, or mappings of - * different width to the same socket, are all possible only by - * involving the SH7750's MMU, which is considered unnecessary here. - * The downside is that it may be possible for some drivers to - * break because they need or expect 8-bit mappings. - * - * This driver currently supports only the following configuration: - * SH7750 CPU, HD64465, TPS2206 voltage control chip. - * - * by Greg Banks - * (c) 2000 PocketPenguins Inc - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#define MODNAME "hd64465_ss" - -/* #define HD64465_DEBUG 1 */ - -#if HD64465_DEBUG -#define DPRINTK(args...) printk(MODNAME ": " args) -#else -#define DPRINTK(args...) -#endif - -extern int hd64465_io_debug; -extern void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags); -extern void p3_iounmap(void *addr); - -/*============================================================*/ - -#define HS_IO_MAP_SIZE (64*1024) - -typedef struct hs_socket_t -{ - unsigned int number; - u_int irq; - u_long mem_base; - void *io_base; - u_long mem_length; - u_int ctrl_base; - socket_state_t state; - pccard_io_map io_maps[MAX_IO_WIN]; - pccard_mem_map mem_maps[MAX_WIN]; - struct pcmcia_socket socket; -} hs_socket_t; - - - -#define HS_MAX_SOCKETS 2 -static hs_socket_t hs_sockets[HS_MAX_SOCKETS]; - -#define hs_in(sp, r) inb((sp)->ctrl_base + (r)) -#define hs_out(sp, v, r) outb(v, (sp)->ctrl_base + (r)) - - -/* translate a boolean value to a bit in a register */ -#define bool_to_regbit(sp, r, bi, bo) \ - do { \ - unsigned short v = hs_in(sp, r); \ - if (bo) \ - v |= (bi); \ - else \ - v &= ~(bi); \ - hs_out(sp, v, r); \ - } while(0) - -/* register offsets from HD64465_REG_PCC[01]ISR */ -#define ISR 0x0 -#define GCR 0x2 -#define CSCR 0x4 -#define CSCIER 0x6 -#define SCR 0x8 - - -/* Mask and values for CSCIER register */ -#define IER_MASK 0x80 -#define IER_ON 0x3f /* interrupts on */ -#define IER_OFF 0x00 /* interrupts off */ - -/*============================================================*/ - -#if HD64465_DEBUG > 10 - -static void cis_hex_dump(const unsigned char *x, int len) -{ - int i; - - for (i=0 ; inumber); - - cscier = hs_in(sp, CSCIER); - cscier &= ~HD64465_PCCCSCIER_PIREQE_MASK; - cscier |= HD64465_PCCCSCIER_PIREQE_LEVEL; - hs_out(sp, cscier, CSCIER); -} - -static void hs_socket_disable_ireq(hs_socket_t *sp) -{ - unsigned short cscier; - - DPRINTK("hs_socket_disable_ireq(sock=%d)\n", sp->number); - - cscier = hs_in(sp, CSCIER); - cscier &= ~HD64465_PCCCSCIER_PIREQE_MASK; - hs_out(sp, cscier, CSCIER); -} - -static unsigned int hs_startup_irq(unsigned int irq) -{ - hs_socket_enable_ireq(hs_mapped_irq[irq].sock); - hs_mapped_irq[irq].old_handler->startup(irq); - return 0; -} - -static void hs_shutdown_irq(unsigned int irq) -{ - hs_socket_disable_ireq(hs_mapped_irq[irq].sock); - hs_mapped_irq[irq].old_handler->shutdown(irq); -} - -static void hs_enable_irq(unsigned int irq) -{ - hs_socket_enable_ireq(hs_mapped_irq[irq].sock); - hs_mapped_irq[irq].old_handler->enable(irq); -} - -static void hs_disable_irq(unsigned int irq) -{ - hs_socket_disable_ireq(hs_mapped_irq[irq].sock); - hs_mapped_irq[irq].old_handler->disable(irq); -} - -extern struct hw_interrupt_type no_irq_type; - -static void hs_mask_and_ack_irq(unsigned int irq) -{ - hs_socket_disable_ireq(hs_mapped_irq[irq].sock); - /* ack_none() spuriously complains about an unexpected IRQ */ - if (hs_mapped_irq[irq].old_handler != &no_irq_type) - hs_mapped_irq[irq].old_handler->ack(irq); -} - -static void hs_end_irq(unsigned int irq) -{ - hs_socket_enable_ireq(hs_mapped_irq[irq].sock); - hs_mapped_irq[irq].old_handler->end(irq); -} - - -static struct hw_interrupt_type hd64465_ss_irq_type = { - .typename = "PCMCIA-IRQ", - .startup = hs_startup_irq, - .shutdown = hs_shutdown_irq, - .enable = hs_enable_irq, - .disable = hs_disable_irq, - .ack = hs_mask_and_ack_irq, - .end = hs_end_irq -}; - -/* - * This function should only ever be called with interrupts disabled. - */ -static void hs_map_irq(hs_socket_t *sp, unsigned int irq) -{ - struct irq_desc *desc; - - DPRINTK("hs_map_irq(sock=%d irq=%d)\n", sp->number, irq); - - if (irq >= HS_NUM_MAPPED_IRQS) - return; - - desc = irq_to_desc(irq); - hs_mapped_irq[irq].sock = sp; - /* insert ourselves as the irq controller */ - hs_mapped_irq[irq].old_handler = desc->chip; - desc->chip = &hd64465_ss_irq_type; -} - - -/* - * This function should only ever be called with interrupts disabled. - */ -static void hs_unmap_irq(hs_socket_t *sp, unsigned int irq) -{ - struct irq_desc *desc; - - DPRINTK("hs_unmap_irq(sock=%d irq=%d)\n", sp->number, irq); - - if (irq >= HS_NUM_MAPPED_IRQS) - return; - - desc = irq_to_desc(irq); - /* restore the original irq controller */ - desc->chip = hs_mapped_irq[irq].old_handler; -} - -/*============================================================*/ - - -/* - * Set Vpp and Vcc (in tenths of a Volt). Does not - * support the hi-Z state. - * - * Note, this assumes the board uses a TPS2206 chip to control - * the Vcc and Vpp voltages to the hs_sockets. If your board - * uses the MIC2563 (also supported by the HD64465) then you - * will have to modify this function. - */ - /* 0V 3.3V 5.5V */ -static const u_char hs_tps2206_avcc[3] = { 0x00, 0x04, 0x08 }; -static const u_char hs_tps2206_bvcc[3] = { 0x00, 0x80, 0x40 }; - -static int hs_set_voltages(hs_socket_t *sp, int Vcc, int Vpp) -{ - u_int psr; - u_int vcci = 0; - u_int sock = sp->number; - - DPRINTK("hs_set_voltage(%d, %d, %d)\n", sock, Vcc, Vpp); - - switch (Vcc) - { - case 0: vcci = 0; break; - case 33: vcci = 1; break; - case 50: vcci = 2; break; - default: return 0; - } - - /* Note: Vpp = 120 not supported -- Greg Banks */ - if (Vpp != 0 && Vpp != Vcc) - return 0; - - /* The PSR register holds 8 of the 9 bits which control - * the TPS2206 via its serial interface. - */ - psr = inw(HD64465_REG_PCCPSR); - switch (sock) - { - case 0: - psr &= 0x0f; - psr |= hs_tps2206_avcc[vcci]; - psr |= (Vpp == 0 ? 0x00 : 0x02); - break; - case 1: - psr &= 0xf0; - psr |= hs_tps2206_bvcc[vcci]; - psr |= (Vpp == 0 ? 0x00 : 0x20); - break; - }; - outw(psr, HD64465_REG_PCCPSR); - - return 1; -} - - -/*============================================================*/ - -/* - * Drive the RESET line to the card. - */ -static void hs_reset_socket(hs_socket_t *sp, int on) -{ - unsigned short v; - - v = hs_in(sp, GCR); - if (on) - v |= HD64465_PCCGCR_PCCR; - else - v &= ~HD64465_PCCGCR_PCCR; - hs_out(sp, v, GCR); -} - -/*============================================================*/ - -static int hs_init(struct pcmcia_socket *s) -{ - hs_socket_t *sp = container_of(s, struct hs_socket_t, socket); - - DPRINTK("hs_init(%d)\n", sp->number); - - return 0; -} - -/*============================================================*/ - - -static int hs_get_status(struct pcmcia_socket *s, u_int *value) -{ - hs_socket_t *sp = container_of(s, struct hs_socket_t, socket); - unsigned int isr; - u_int status = 0; - - - isr = hs_in(sp, ISR); - - /* Card is seated and powered when *both* CD pins are low */ - if ((isr & HD64465_PCCISR_PCD_MASK) == 0) - { - status |= SS_DETECT; /* card present */ - - switch (isr & HD64465_PCCISR_PBVD_MASK) - { - case HD64465_PCCISR_PBVD_BATGOOD: - break; - case HD64465_PCCISR_PBVD_BATWARN: - status |= SS_BATWARN; - break; - default: - status |= SS_BATDEAD; - break; - } - - if (isr & HD64465_PCCISR_PREADY) - status |= SS_READY; - - if (isr & HD64465_PCCISR_PMWP) - status |= SS_WRPROT; - - /* Voltage Select pins interpreted as per Table 4-5 of the std. - * Assuming we have the TPS2206, the socket is a "Low Voltage - * key, 3.3V and 5V available, no X.XV available". - */ - switch (isr & (HD64465_PCCISR_PVS2|HD64465_PCCISR_PVS1)) - { - case HD64465_PCCISR_PVS1: - printk(KERN_NOTICE MODNAME ": cannot handle X.XV card, ignored\n"); - status = 0; - break; - case 0: - case HD64465_PCCISR_PVS2: - /* 3.3V */ - status |= SS_3VCARD; - break; - case HD64465_PCCISR_PVS2|HD64465_PCCISR_PVS1: - /* 5V */ - break; - } - - /* TODO: SS_POWERON */ - /* TODO: SS_STSCHG */ - } - - DPRINTK("hs_get_status(%d) = %x\n", sock, status); - - *value = status; - return 0; -} - -/*============================================================*/ - -static int hs_set_socket(struct pcmcia_socket *s, socket_state_t *state) -{ - hs_socket_t *sp = container_of(s, struct hs_socket_t, socket); - u_long flags; - u_int changed; - unsigned short cscier; - - DPRINTK("hs_set_socket(sock=%d, flags=%x, csc_mask=%x, Vcc=%d, Vpp=%d, io_irq=%d)\n", - sock, state->flags, state->csc_mask, state->Vcc, state->Vpp, state->io_irq); - - local_irq_save(flags); /* Don't want interrupts happening here */ - - if (state->Vpp != sp->state.Vpp || - state->Vcc != sp->state.Vcc) { - if (!hs_set_voltages(sp, state->Vcc, state->Vpp)) { - local_irq_restore(flags); - return -EINVAL; - } - } - -/* hd64465_io_debug = 1; */ - /* - * Handle changes in the Card Status Change mask, - * by propagating to the CSCR register - */ - changed = sp->state.csc_mask ^ state->csc_mask; - cscier = hs_in(sp, CSCIER); - - if (changed & SS_DETECT) { - if (state->csc_mask & SS_DETECT) - cscier |= HD64465_PCCCSCIER_PCDE; - else - cscier &= ~HD64465_PCCCSCIER_PCDE; - } - - if (changed & SS_READY) { - if (state->csc_mask & SS_READY) - cscier |= HD64465_PCCCSCIER_PRE; - else - cscier &= ~HD64465_PCCCSCIER_PRE; - } - - if (changed & SS_BATDEAD) { - if (state->csc_mask & SS_BATDEAD) - cscier |= HD64465_PCCCSCIER_PBDE; - else - cscier &= ~HD64465_PCCCSCIER_PBDE; - } - - if (changed & SS_BATWARN) { - if (state->csc_mask & SS_BATWARN) - cscier |= HD64465_PCCCSCIER_PBWE; - else - cscier &= ~HD64465_PCCCSCIER_PBWE; - } - - if (changed & SS_STSCHG) { - if (state->csc_mask & SS_STSCHG) - cscier |= HD64465_PCCCSCIER_PSCE; - else - cscier &= ~HD64465_PCCCSCIER_PSCE; - } - - hs_out(sp, cscier, CSCIER); - - if (sp->state.io_irq && !state->io_irq) - hs_unmap_irq(sp, sp->state.io_irq); - else if (!sp->state.io_irq && state->io_irq) - hs_map_irq(sp, state->io_irq); - - - /* - * Handle changes in the flags field, - * by propagating to config registers. - */ - changed = sp->state.flags ^ state->flags; - - if (changed & SS_IOCARD) { - DPRINTK("card type: %s\n", - (state->flags & SS_IOCARD ? "i/o" : "memory" )); - bool_to_regbit(sp, GCR, HD64465_PCCGCR_PCCT, - state->flags & SS_IOCARD); - } - - if (changed & SS_RESET) { - DPRINTK("%s reset card\n", - (state->flags & SS_RESET ? "start" : "stop")); - bool_to_regbit(sp, GCR, HD64465_PCCGCR_PCCR, - state->flags & SS_RESET); - } - - if (changed & SS_OUTPUT_ENA) { - DPRINTK("%sabling card output\n", - (state->flags & SS_OUTPUT_ENA ? "en" : "dis")); - bool_to_regbit(sp, GCR, HD64465_PCCGCR_PDRV, - state->flags & SS_OUTPUT_ENA); - } - - /* TODO: SS_SPKR_ENA */ - -/* hd64465_io_debug = 0; */ - sp->state = *state; - - local_irq_restore(flags); - -#if HD64465_DEBUG > 10 - if (state->flags & SS_OUTPUT_ENA) - cis_hex_dump((const unsigned char*)sp->mem_base, 0x100); -#endif - return 0; -} - -/*============================================================*/ - -static int hs_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) -{ - hs_socket_t *sp = container_of(s, struct hs_socket_t, socket); - int map = io->map; - int sock = sp->number; - struct pccard_io_map *sio; - pgprot_t prot; - - DPRINTK("hs_set_io_map(sock=%d, map=%d, flags=0x%x, speed=%dns, start=%#lx, stop=%#lx)\n", - sock, map, io->flags, io->speed, io->start, io->stop); - if (map >= MAX_IO_WIN) - return -EINVAL; - sio = &sp->io_maps[map]; - - /* check for null changes */ - if (io->flags == sio->flags && - io->start == sio->start && - io->stop == sio->stop) - return 0; - - if (io->flags & MAP_AUTOSZ) - prot = PAGE_KERNEL_PCC(sock, _PAGE_PCC_IODYN); - else if (io->flags & MAP_16BIT) - prot = PAGE_KERNEL_PCC(sock, _PAGE_PCC_IO16); - else - prot = PAGE_KERNEL_PCC(sock, _PAGE_PCC_IO8); - - /* TODO: handle MAP_USE_WAIT */ - if (io->flags & MAP_USE_WAIT) - printk(KERN_INFO MODNAME ": MAP_USE_WAIT unimplemented\n"); - /* TODO: handle MAP_PREFETCH */ - if (io->flags & MAP_PREFETCH) - printk(KERN_INFO MODNAME ": MAP_PREFETCH unimplemented\n"); - /* TODO: handle MAP_WRPROT */ - if (io->flags & MAP_WRPROT) - printk(KERN_INFO MODNAME ": MAP_WRPROT unimplemented\n"); - /* TODO: handle MAP_0WS */ - if (io->flags & MAP_0WS) - printk(KERN_INFO MODNAME ": MAP_0WS unimplemented\n"); - - if (io->flags & MAP_ACTIVE) { - unsigned long pstart, psize, paddrbase; - - paddrbase = virt_to_phys((void*)(sp->mem_base + 2 * HD64465_PCC_WINDOW)); - pstart = io->start & PAGE_MASK; - psize = ((io->stop + PAGE_SIZE) & PAGE_MASK) - pstart; - - /* - * Change PTEs in only that portion of the mapping requested - * by the caller. This means that most of the time, most of - * the PTEs in the io_vma will be unmapped and only the bottom - * page will be mapped. But the code allows for weird cards - * that might want IO ports > 4K. - */ - sp->io_base = p3_ioremap(paddrbase + pstart, psize, pgprot_val(prot)); - - /* - * Change the mapping used by inb() outb() etc - */ - hd64465_port_map(io->start, - io->stop - io->start + 1, - (unsigned long)sp->io_base + io->start, 0); - } else { - hd64465_port_unmap(sio->start, sio->stop - sio->start + 1); - p3_iounmap(sp->io_base); - } - - *sio = *io; - return 0; -} - -/*============================================================*/ - -static int hs_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem) -{ - hs_socket_t *sp = container_of(s, struct hs_socket_t, socket); - struct pccard_mem_map *smem; - int map = mem->map; - unsigned long paddr; - -#if 0 - DPRINTK("hs_set_mem_map(sock=%d, map=%d, flags=0x%x, card_start=0x%08x)\n", - sock, map, mem->flags, mem->card_start); -#endif - - if (map >= MAX_WIN) - return -EINVAL; - smem = &sp->mem_maps[map]; - - paddr = sp->mem_base; /* base of Attribute mapping */ - if (!(mem->flags & MAP_ATTRIB)) - paddr += HD64465_PCC_WINDOW; /* base of Common mapping */ - paddr += mem->card_start; - - /* Because we specified SS_CAP_STATIC_MAP, we are obliged - * at this time to report the system address corresponding - * to the card address requested. This is how Socket Services - * queries our fixed mapping. I wish this fact had been - * documented - Greg Banks. - */ - mem->static_start = paddr; - - *smem = *mem; - - return 0; -} - -/* TODO: do we need to use the MMU to access Common memory ??? */ - -/*============================================================*/ - -/* - * This function is registered with the HD64465 glue code to do a - * secondary demux step on the PCMCIA interrupts. It handles - * mapping the IREQ request from the card to a standard Linux - * IRQ, as requested by SocketServices. - */ -static int hs_irq_demux(int irq, void *dev) -{ - hs_socket_t *sp = dev; - u_int cscr; - - DPRINTK("hs_irq_demux(irq=%d)\n", irq); - - if (sp->state.io_irq && - (cscr = hs_in(sp, CSCR)) & HD64465_PCCCSCR_PIREQ) { - cscr &= ~HD64465_PCCCSCR_PIREQ; - hs_out(sp, cscr, CSCR); - return sp->state.io_irq; - } - - return irq; -} - -/*============================================================*/ - -/* - * Interrupt handling routine. - */ - -static irqreturn_t hs_interrupt(int irq, void *dev) -{ - hs_socket_t *sp = dev; - u_int events = 0; - u_int cscr; - - cscr = hs_in(sp, CSCR); - - DPRINTK("hs_interrupt, cscr=%04x\n", cscr); - - /* check for bus-related changes to be reported to Socket Services */ - if (cscr & HD64465_PCCCSCR_PCDC) { - /* double-check for a 16-bit card, as we don't support CardBus */ - if ((hs_in(sp, ISR) & HD64465_PCCISR_PCD_MASK) != 0) { - printk(KERN_NOTICE MODNAME - ": socket %d, card not a supported card type or not inserted correctly\n", - sp->number); - /* Don't do the rest unless a card is present */ - cscr &= ~(HD64465_PCCCSCR_PCDC| - HD64465_PCCCSCR_PRC| - HD64465_PCCCSCR_PBW| - HD64465_PCCCSCR_PBD| - HD64465_PCCCSCR_PSC); - } else { - cscr &= ~HD64465_PCCCSCR_PCDC; - events |= SS_DETECT; /* card insertion or removal */ - } - } - if (cscr & HD64465_PCCCSCR_PRC) { - cscr &= ~HD64465_PCCCSCR_PRC; - events |= SS_READY; /* ready signal changed */ - } - if (cscr & HD64465_PCCCSCR_PBW) { - cscr &= ~HD64465_PCCCSCR_PSC; - events |= SS_BATWARN; /* battery warning */ - } - if (cscr & HD64465_PCCCSCR_PBD) { - cscr &= ~HD64465_PCCCSCR_PSC; - events |= SS_BATDEAD; /* battery dead */ - } - if (cscr & HD64465_PCCCSCR_PSC) { - cscr &= ~HD64465_PCCCSCR_PSC; - events |= SS_STSCHG; /* STSCHG (status changed) signal */ - } - - if (cscr & HD64465_PCCCSCR_PIREQ) { - cscr &= ~HD64465_PCCCSCR_PIREQ; - - /* This should have been dealt with during irq demux */ - printk(KERN_NOTICE MODNAME ": unexpected IREQ from card\n"); - } - - hs_out(sp, cscr, CSCR); - - if (events) - pcmcia_parse_events(&sp->socket, events); - - return IRQ_HANDLED; -} - -/*============================================================*/ - -static struct pccard_operations hs_operations = { - .init = hs_init, - .get_status = hs_get_status, - .set_socket = hs_set_socket, - .set_io_map = hs_set_io_map, - .set_mem_map = hs_set_mem_map, -}; - -static int hs_init_socket(hs_socket_t *sp, int irq, unsigned long mem_base, - unsigned int ctrl_base) -{ - unsigned short v; - int i, err; - - memset(sp, 0, sizeof(*sp)); - sp->irq = irq; - sp->mem_base = mem_base; - sp->mem_length = 4*HD64465_PCC_WINDOW; /* 16MB */ - sp->ctrl_base = ctrl_base; - - for (i=0 ; iio_maps[i].map = i; - for (i=0 ; imem_maps[i].map = i; - - hd64465_register_irq_demux(sp->irq, hs_irq_demux, sp); - - if ((err = request_irq(sp->irq, hs_interrupt, IRQF_DISABLED, MODNAME, sp)) < 0) - return err; - if (request_mem_region(sp->mem_base, sp->mem_length, MODNAME) == 0) { - sp->mem_base = 0; - return -ENOMEM; - } - - - /* According to section 3.2 of the PCMCIA standard, low-voltage - * capable cards must implement cold insertion, i.e. Vpp and - * Vcc set to 0 before card is inserted. - */ - /*hs_set_voltages(sp, 0, 0);*/ - - /* hi-Z the outputs to the card and set 16MB map mode */ - v = hs_in(sp, GCR); - v &= ~HD64465_PCCGCR_PCCT; /* memory-only card */ - hs_out(sp, v, GCR); - - v = hs_in(sp, GCR); - v |= HD64465_PCCGCR_PDRV; /* enable outputs to card */ - hs_out(sp, v, GCR); - - v = hs_in(sp, GCR); - v |= HD64465_PCCGCR_PMMOD; /* 16MB mapping mode */ - hs_out(sp, v, GCR); - - v = hs_in(sp, GCR); - /* lowest 16MB of Common */ - v &= ~(HD64465_PCCGCR_PPA25|HD64465_PCCGCR_PPA24); - hs_out(sp, v, GCR); - - hs_reset_socket(sp, 1); - - printk(KERN_INFO "HD64465 PCMCIA bridge socket %d at 0x%08lx irq %d\n", - i, sp->mem_base, sp->irq); - - return 0; -} - -static void hs_exit_socket(hs_socket_t *sp) -{ - unsigned short cscier, gcr; - unsigned long flags; - - local_irq_save(flags); - - /* turn off interrupts in hardware */ - cscier = hs_in(sp, CSCIER); - cscier = (cscier & IER_MASK) | IER_OFF; - hs_out(sp, cscier, CSCIER); - - /* hi-Z the outputs to the card */ - gcr = hs_in(sp, GCR); - gcr &= HD64465_PCCGCR_PDRV; - hs_out(sp, gcr, GCR); - - /* power the card down */ - hs_set_voltages(sp, 0, 0); - - if (sp->mem_base != 0) - release_mem_region(sp->mem_base, sp->mem_length); - if (sp->irq != 0) { - free_irq(sp->irq, hs_interrupt); - hd64465_unregister_irq_demux(sp->irq); - } - - local_irq_restore(flags); -} - -static struct device_driver hd64465_driver = { - .name = "hd64465-pcmcia", - .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, -}; - -static struct platform_device hd64465_device = { - .name = "hd64465-pcmcia", - .id = 0, -}; - -static int __init init_hs(void) -{ - int i; - unsigned short v; - -/* hd64465_io_debug = 1; */ - if (driver_register(&hd64465_driver)) - return -EINVAL; - - /* Wake both sockets out of STANDBY mode */ - /* TODO: wait 15ms */ - v = inw(HD64465_REG_SMSCR); - v &= ~(HD64465_SMSCR_PC0ST|HD64465_SMSCR_PC1ST); - outw(v, HD64465_REG_SMSCR); - - /* keep power controller out of shutdown mode */ - v = inb(HD64465_REG_PCC0SCR); - v |= HD64465_PCCSCR_SHDN; - outb(v, HD64465_REG_PCC0SCR); - - /* use serial (TPS2206) power controller */ - v = inb(HD64465_REG_PCC0CSCR); - v |= HD64465_PCCCSCR_PSWSEL; - outb(v, HD64465_REG_PCC0CSCR); - - /* - * Setup hs_sockets[] structures and request system resources. - * TODO: on memory allocation failure, power down the socket - * before quitting. - */ - for (i=0; i Date: Mon, 27 Oct 2008 15:17:56 +0000 Subject: [PATCH] Switch all my contributions stuff to a single common address Signed-off-by: Alan Cox Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/acquirewdt.c | 6 +++--- drivers/watchdog/advantechwdt.c | 6 +++--- drivers/watchdog/bfin_wdt.c | 2 +- drivers/watchdog/eurotechwdt.c | 4 ++-- drivers/watchdog/ib700wdt.c | 6 +++--- drivers/watchdog/indydog.c | 2 +- drivers/watchdog/mpcore_wdt.c | 4 ++-- drivers/watchdog/omap_wdt.c | 2 +- drivers/watchdog/pcwd_pci.c | 2 +- drivers/watchdog/pcwd_usb.c | 2 +- drivers/watchdog/rc32434_wdt.c | 3 ++- drivers/watchdog/s3c2410_wdt.c | 2 +- drivers/watchdog/sa1100_wdt.c | 2 +- drivers/watchdog/sb_wdog.c | 4 ++-- drivers/watchdog/sbc8360.c | 6 +++--- drivers/watchdog/sbc_epx_c3.c | 2 +- drivers/watchdog/smsc37b787_wdt.c | 2 +- drivers/watchdog/softdog.c | 3 +-- drivers/watchdog/w83627hf_wdt.c | 6 +++--- drivers/watchdog/w83697hf_wdt.c | 4 ++-- drivers/watchdog/wafer5823wdt.c | 4 ++-- drivers/watchdog/wdt.c | 4 ++-- drivers/watchdog/wdt285.c | 3 ++- drivers/watchdog/wdt_pci.c | 4 ++-- 24 files changed, 43 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c index 6e46a551395..3e57aa4d643 100644 --- a/drivers/watchdog/acquirewdt.c +++ b/drivers/watchdog/acquirewdt.c @@ -3,8 +3,8 @@ * * Based on wdt.c. Original copyright messages: * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. - * http://www.redhat.com + * (c) Copyright 1996 Alan Cox , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -15,7 +15,7 @@ * warranty for any of this software. This material is provided * "AS-IS" and at no charge. * - * (c) Copyright 1995 Alan Cox + * (c) Copyright 1995 Alan Cox * * 14-Dec-2001 Matt Domsch * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c index a5110f93a75..a1d7856ea6e 100644 --- a/drivers/watchdog/advantechwdt.c +++ b/drivers/watchdog/advantechwdt.c @@ -6,8 +6,8 @@ * Based on acquirewdt.c which is based on wdt.c. * Original copyright messages: * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. - * http://www.redhat.com + * (c) Copyright 1996 Alan Cox , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,7 +18,7 @@ * warranty for any of this software. This material is provided * "AS-IS" and at no charge. * - * (c) Copyright 1995 Alan Cox + * (c) Copyright 1995 Alan Cox * * 14-Dec-2001 Matt Domsch * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c index 31b42253054..067a57cb3f8 100644 --- a/drivers/watchdog/bfin_wdt.c +++ b/drivers/watchdog/bfin_wdt.c @@ -5,7 +5,7 @@ * Originally based on softdog.c * Copyright 2006-2007 Analog Devices Inc. * Copyright 2006-2007 Michele d'Amico - * Copyright 1996 Alan Cox + * Copyright 1996 Alan Cox * * Enter bugs at http://blackfin.uclinux.org/ * diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c index bbd14e34319..a171fc6ae1c 100644 --- a/drivers/watchdog/eurotechwdt.c +++ b/drivers/watchdog/eurotechwdt.c @@ -8,8 +8,8 @@ * Based on wdt.c. * Original copyright messages: * - * (c) Copyright 1996-1997 Alan Cox , All Rights Reserved. - * http://www.redhat.com + * (c) Copyright 1996-1997 Alan Cox , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c index 8782ec1f5aa..317ef2b16cf 100644 --- a/drivers/watchdog/ib700wdt.c +++ b/drivers/watchdog/ib700wdt.c @@ -11,8 +11,8 @@ * Based on acquirewdt.c which is based on wdt.c. * Original copyright messages: * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. - * http://www.redhat.com + * (c) Copyright 1996 Alan Cox , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,7 +23,7 @@ * warranty for any of this software. This material is provided * "AS-IS" and at no charge. * - * (c) Copyright 1995 Alan Cox + * (c) Copyright 1995 Alan Cox * * 14-Dec-2001 Matt Domsch * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT diff --git a/drivers/watchdog/indydog.c b/drivers/watchdog/indydog.c index 73c9e7992fe..0f761db9a27 100644 --- a/drivers/watchdog/indydog.c +++ b/drivers/watchdog/indydog.c @@ -9,7 +9,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * based on softdog.c by Alan Cox + * based on softdog.c by Alan Cox */ #include diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c index 2a9bfa81f9d..1130ad697ce 100644 --- a/drivers/watchdog/mpcore_wdt.c +++ b/drivers/watchdog/mpcore_wdt.c @@ -4,8 +4,8 @@ * (c) Copyright 2004 ARM Limited * * Based on the SoftDog driver: - * (c) Copyright 1996 Alan Cox , All Rights Reserved. - * http://www.redhat.com + * (c) Copyright 1996 Alan Cox , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 7bcbb7f4745..2f2ce7429f5 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -16,7 +16,7 @@ * 20030527: George G. Davis * Initially based on linux-2.4.19-rmk7-pxa1/drivers/char/sa1100_wdt.c * (c) Copyright 2000 Oleg Drokin - * Based on SoftDog driver by Alan Cox + * Based on SoftDog driver by Alan Cox * * Copyright (c) 2004 Texas Instruments. * 1. Modified to support OMAP1610 32-KHz watchdog timer diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c index 90eb1d4271d..5d76422c402 100644 --- a/drivers/watchdog/pcwd_pci.c +++ b/drivers/watchdog/pcwd_pci.c @@ -6,7 +6,7 @@ * Based on source code of the following authors: * Ken Hollis , * Lindsay Harris , - * Alan Cox , + * Alan Cox , * Matt Domsch , * Rob Radez * diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c index c1685c942de..afb089695da 100644 --- a/drivers/watchdog/pcwd_usb.c +++ b/drivers/watchdog/pcwd_usb.c @@ -5,7 +5,7 @@ * * Based on source code of the following authors: * Ken Hollis , - * Alan Cox , + * Alan Cox , * Matt Domsch , * Rob Radez , * Greg Kroah-Hartman diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index c9c73b69c5e..57027f4653c 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -7,7 +7,8 @@ * based on * SoftDog 0.05: A Software Watchdog Device * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. + * (c) Copyright 1996 Alan Cox , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 86d42801de4..f7f6ce82a5e 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -6,7 +6,7 @@ * S3C2410 Watchdog Timer Support * * Based on, softdog.c by Alan Cox, - * (c) Copyright 1996 Alan Cox + * (c) Copyright 1996 Alan Cox * * 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 diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c index 31a48437dc3..ed01e4c2bef 100644 --- a/drivers/watchdog/sa1100_wdt.c +++ b/drivers/watchdog/sa1100_wdt.c @@ -2,7 +2,7 @@ * Watchdog driver for the SA11x0/PXA2xx * * (c) Copyright 2000 Oleg Drokin - * Based on SoftDog driver by Alan Cox + * Based on SoftDog driver by Alan Cox * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c index 27e526a07c9..38f5831c929 100644 --- a/drivers/watchdog/sb_wdog.c +++ b/drivers/watchdog/sb_wdog.c @@ -35,8 +35,8 @@ * Based on various other watchdog drivers, which are probably all * loosely based on something Alan Cox wrote years ago. * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. - * http://www.redhat.com + * (c) Copyright 1996 Alan Cox , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/watchdog/sbc8360.c b/drivers/watchdog/sbc8360.c index fd83dd052d8..ae74f6bcfa2 100644 --- a/drivers/watchdog/sbc8360.c +++ b/drivers/watchdog/sbc8360.c @@ -16,8 +16,8 @@ * Based on acquirewdt.c which is based on wdt.c. * Original copyright messages: * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. - * http://www.redhat.com + * (c) Copyright 1996 Alan Cox , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -28,7 +28,7 @@ * warranty for any of this software. This material is provided * "AS-IS" and at no charge. * - * (c) Copyright 1995 Alan Cox + * (c) Copyright 1995 Alan Cox * * 14-Dec-2001 Matt Domsch * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT diff --git a/drivers/watchdog/sbc_epx_c3.c b/drivers/watchdog/sbc_epx_c3.c index e5e470ca775..06553debc7b 100644 --- a/drivers/watchdog/sbc_epx_c3.c +++ b/drivers/watchdog/sbc_epx_c3.c @@ -10,7 +10,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * based on softdog.c by Alan Cox + * based on softdog.c by Alan Cox */ #include diff --git a/drivers/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c index 988ff1d5b4b..2e56cad77d1 100644 --- a/drivers/watchdog/smsc37b787_wdt.c +++ b/drivers/watchdog/smsc37b787_wdt.c @@ -1,7 +1,7 @@ /* * SMsC 37B787 Watchdog Timer driver for Linux 2.6.x.x * - * Based on acquirewdt.c by Alan Cox + * Based on acquirewdt.c by Alan Cox * and some other existing drivers * * This program is free software; you can redistribute it and/or diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c index c650464c5c6..7204f966211 100644 --- a/drivers/watchdog/softdog.c +++ b/drivers/watchdog/softdog.c @@ -1,8 +1,7 @@ /* * SoftDog 0.07: A Software Watchdog Device * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. - * http://www.redhat.com + * (c) Copyright 1996 Alan Cox , All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c index 69396adaa5c..916890abffd 100644 --- a/drivers/watchdog/w83627hf_wdt.c +++ b/drivers/watchdog/w83627hf_wdt.c @@ -11,8 +11,8 @@ * * (c) Copyright 2000-2001 Marek Michalkiewicz * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. - * http://www.redhat.com + * (c) Copyright 1996 Alan Cox , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,7 +23,7 @@ * warranty for any of this software. This material is provided * "AS-IS" and at no charge. * - * (c) Copyright 1995 Alan Cox + * (c) Copyright 1995 Alan Cox */ #include diff --git a/drivers/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c index 445d30a01ed..3c7aa412b1f 100644 --- a/drivers/watchdog/w83697hf_wdt.c +++ b/drivers/watchdog/w83697hf_wdt.c @@ -12,8 +12,8 @@ * * (c) Copyright 2000-2001 Marek Michalkiewicz * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. - * http://www.redhat.com + * (c) Copyright 1996 Alan Cox , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/watchdog/wafer5823wdt.c b/drivers/watchdog/wafer5823wdt.c index 68377ae171f..42e940c2389 100644 --- a/drivers/watchdog/wafer5823wdt.c +++ b/drivers/watchdog/wafer5823wdt.c @@ -10,8 +10,8 @@ * Based on advantechwdt.c which is based on wdt.c. * Original copyright messages: * - * (c) Copyright 1996-1997 Alan Cox , All Rights Reserved. - * http://www.redhat.com + * (c) Copyright 1996-1997 Alan Cox , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c index deeebb2b13e..eddb9187e7b 100644 --- a/drivers/watchdog/wdt.c +++ b/drivers/watchdog/wdt.c @@ -1,8 +1,8 @@ /* * Industrial Computer Source WDT500/501 driver * - * (c) Copyright 1996-1997 Alan Cox , All Rights Reserved. - * http://www.redhat.com + * (c) Copyright 1996-1997 Alan Cox , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/watchdog/wdt285.c b/drivers/watchdog/wdt285.c index 191ea630210..f55135662d7 100644 --- a/drivers/watchdog/wdt285.c +++ b/drivers/watchdog/wdt285.c @@ -6,7 +6,8 @@ * * SoftDog 0.05: A Software Watchdog Device * - * (c) Copyright 1996 Alan Cox , All Rights Reserved. + * (c) Copyright 1996 Alan Cox , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index ed02bdb38c0..c45839a4a34 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c @@ -1,8 +1,8 @@ /* * Industrial Computer Source PCI-WDT500/501 driver * - * (c) Copyright 1996-1997 Alan Cox , All Rights Reserved. - * http://www.redhat.com + * (c) Copyright 1996-1997 Alan Cox , + * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License -- cgit v1.2.3 From f49d81a8992c4ec43480195a93f30ab4b736f960 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 15 Oct 2008 11:53:34 +0100 Subject: regulator: Build on non-ARM platforms When the regulator API was merged it was added to the separate Kconfig which ARM uses for drivers but not the generic one in drivers/. Since there is nothing ARM-specific about the API add it there too. Signed-off-by: Mark Brown Signed-off-by: Liam Girdwood --- drivers/Kconfig | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/Kconfig b/drivers/Kconfig index d38f43f593d..2f557f570ad 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -68,6 +68,8 @@ source "drivers/ssb/Kconfig" source "drivers/mfd/Kconfig" +source "drivers/regulator/Kconfig" + source "drivers/media/Kconfig" source "drivers/video/Kconfig" -- cgit v1.2.3 From 48e5ecae691cfb50aa39036ba9fc193f5c24dbb3 Mon Sep 17 00:00:00 2001 From: Chris Friesen Date: Tue, 28 Oct 2008 15:50:54 -0700 Subject: amd8111e: Fix rx return code The amd8111e rx poll routine currently mishandles the case when we process exactly the number of packets specified in the budget. This patch is basically as suggested by David Miller. Signed-off-by: Chris Friesen Signed-off-by: David S. Miller --- drivers/net/amd8111e.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index c54967f7942..ba1be0b3a8c 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -833,12 +833,14 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget) } while(intr0 & RINT0); - /* Receive descriptor is empty now */ - spin_lock_irqsave(&lp->lock, flags); - __netif_rx_complete(dev, napi); - writel(VAL0|RINTEN0, mmio + INTEN0); - writel(VAL2 | RDMD0, mmio + CMD0); - spin_unlock_irqrestore(&lp->lock, flags); + if (rx_pkt_limit > 0) { + /* Receive descriptor is empty now */ + spin_lock_irqsave(&lp->lock, flags); + __netif_rx_complete(dev, napi); + writel(VAL0|RINTEN0, mmio + INTEN0); + writel(VAL2 | RDMD0, mmio + CMD0); + spin_unlock_irqrestore(&lp->lock, flags); + } rx_not_empty: return num_rx_pkt; -- cgit v1.2.3 From 5cbff9603a77d01315859690a8f125f817bed73b Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 28 Oct 2008 20:26:40 +0300 Subject: [ARM] corgi_lcd: fix simultaneous compilation with corgi_bl corgi_lcd has symbol conflict with corgi_bl driver. Fix it by renaming common symbol in new corgi_lcd driver. Signed-off-by: Dmitry Baryshkov Signed-off-by: Eric Miao --- drivers/video/backlight/corgi_lcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c index 2afd47eefe7..f8a4bb20f41 100644 --- a/drivers/video/backlight/corgi_lcd.c +++ b/drivers/video/backlight/corgi_lcd.c @@ -439,7 +439,7 @@ static int corgi_bl_update_status(struct backlight_device *bd) return corgi_bl_set_intensity(lcd, intensity); } -void corgibl_limit_intensity(int limit) +void corgi_lcd_limit_intensity(int limit) { if (limit) corgibl_flags |= CORGIBL_BATTLOW; @@ -448,7 +448,7 @@ void corgibl_limit_intensity(int limit) backlight_update_status(the_corgi_lcd->bl_dev); } -EXPORT_SYMBOL(corgibl_limit_intensity); +EXPORT_SYMBOL(corgi_lcd_limit_intensity); static struct backlight_ops corgi_bl_ops = { .get_brightness = corgi_bl_get_intensity, -- cgit v1.2.3 From 556dcee7b829e5c350c3ffdbdb87a8b15aa3c5d3 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 21 Oct 2008 17:45:58 +0200 Subject: [CRIS] Move header files from include to arch/cris/include. Change all users of header files to correct path. Remove some unneeded headers for arch-v32. Signed-off-by: Jesper Nilsson --- drivers/net/cris/eth_v10.c | 4 ++-- drivers/serial/crisv10.c | 4 ++-- drivers/serial/crisv10.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index 65d0a910329..7e8a63106bd 100644 --- a/drivers/net/cris/eth_v10.c +++ b/drivers/net/cris/eth_v10.c @@ -32,14 +32,14 @@ #include #include -#include /* DMA and register descriptions */ +#include /* DMA and register descriptions */ #include /* CRIS_LED_* I/O functions */ #include #include #include #include #include -#include +#include //#define ETHDEBUG #define D(x) diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 211c21797ce..8b2c619a09f 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -34,14 +34,14 @@ static char *serial_version = "$Revision: 1.25 $"; #include #include -#include +#include /* non-arch dependent serial structures are in linux/serial.h */ #include /* while we keep our own stuff (struct e100_serial) in a local .h file */ #include "crisv10.h" #include -#include +#include #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER #ifndef CONFIG_ETRAX_FAST_TIMER diff --git a/drivers/serial/crisv10.h b/drivers/serial/crisv10.h index e3c5c8c3c09..f36a729280b 100644 --- a/drivers/serial/crisv10.h +++ b/drivers/serial/crisv10.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include /* Software state per channel */ -- cgit v1.2.3 From 10d0bd56966571d0324dfd9bbb8aa913a60bef5f Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 29 Oct 2008 01:03:01 +0200 Subject: iwlwifi: fix suspend to RAM in iwlwifi This patch fixes suspend to RAM after by moving notify_mac out of iwlwifi mutex http://bugzilla.kernel.org/show_bug.cgi?id=11845 Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Tested-by: Carlos R. Mafra Tested-by: Christian Borntraeger Cc: Rafael J. Wysocki Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 24a1aeb6448..321dbc8c034 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2090,7 +2090,6 @@ static void iwl_alive_start(struct iwl_priv *priv) iwl4965_error_recovery(priv); iwl_power_update_mode(priv, 1); - ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) iwl4965_set_mode(priv, priv->iw_mode); @@ -2342,6 +2341,7 @@ static void iwl_bg_alive_start(struct work_struct *data) mutex_lock(&priv->mutex); iwl_alive_start(priv); mutex_unlock(&priv->mutex); + ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); } static void iwl4965_bg_rf_kill(struct work_struct *work) -- cgit v1.2.3 From 87bf24f3d2e076468deaa5181d44184887072904 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 29 Oct 2008 10:35:02 +0100 Subject: libertas: remove two libertas sparse warning Johannes Berg detected this two sparse warnings: drivers/net/wireless/libertas/cmd.c:609:16: warning: cast to restricted __le16 drivers/net/wireless/libertas/cmd.c:611:16: warning: cast to restricted __le16 ... but cmd.minlevel is "s8", so we can access it directly and hope for the sign-extension-code in the compiler to convert that to the "s16" type. Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 297696de2da..8265c7d25ed 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -605,9 +605,9 @@ int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, if (ret == 0) { *curlevel = le16_to_cpu(cmd.curlevel); if (minlevel) - *minlevel = le16_to_cpu(cmd.minlevel); + *minlevel = cmd.minlevel; if (maxlevel) - *maxlevel = le16_to_cpu(cmd.maxlevel); + *maxlevel = cmd.maxlevel; } lbs_deb_leave(LBS_DEB_CMD); -- cgit v1.2.3 From 48735d8d8bd701b1e0cd3d49c21e5e385ddcb077 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 29 Oct 2008 11:43:32 +0100 Subject: libertas: fix buffer overrun If somebody sends an invalid beacon/probe response, that can trash the whole BSS descriptor. The descriptor is, luckily, large enough so that it cannot scribble past the end of it; it's well above 400 bytes long. Signed-off-by: Johannes Berg Cc: stable@kernel.org [2.6.24-2.6.27, bug present in some form since driver was added (2.6.22)] Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/scan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 8f66903641b..22c4c611052 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -598,8 +598,8 @@ static int lbs_process_bss(struct bss_descriptor *bss, switch (elem->id) { case MFIE_TYPE_SSID: - bss->ssid_len = elem->len; - memcpy(bss->ssid, elem->data, elem->len); + bss->ssid_len = min_t(int, 32, elem->len); + memcpy(bss->ssid, elem->data, bss->ssid_len); lbs_deb_scan("got SSID IE: '%s', len %u\n", escape_essid(bss->ssid, bss->ssid_len), bss->ssid_len); -- cgit v1.2.3 From 85519a65fd1100ceede7318a89f77a219c69c6ac Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 29 Oct 2008 08:30:53 -0400 Subject: ath5k: correct misspelling in debug help Change "mamagement" to "management" Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 8f92d670f61..19980cbd5d5 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -339,7 +339,7 @@ static struct { { ATH5K_DEBUG_BEACON, "beacon", "beacon handling" }, { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" }, { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" }, - { ATH5K_DEBUG_LED, "led", "LED mamagement" }, + { ATH5K_DEBUG_LED, "led", "LED management" }, { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, -- cgit v1.2.3 From 5dc5340cfc00097e79d9d787567d311e898aaa84 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Wed, 29 Oct 2008 17:19:08 +0100 Subject: rt2x00: Fix build error when mac80211=M rt2x00=Y Make menuconfig RT2X00 a tristate instead of boolean, otherwise we do not correctly inherit the mac80211 value on which RT2X00 depends, and makes it possible to compile rt2x00 into the kernel while mac80211 is a module. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index f839ce044af..95511ac2247 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -1,5 +1,5 @@ menuconfig RT2X00 - bool "Ralink driver support" + tristate "Ralink driver support" depends on MAC80211 && WLAN_80211 && EXPERIMENTAL ---help--- This will enable the experimental support for the Ralink drivers, -- cgit v1.2.3 From 7d19267b8d1e12c0baebf9be96e04cddffe63f67 Mon Sep 17 00:00:00 2001 From: Elias Oltmanns Date: Wed, 29 Oct 2008 14:25:42 +0100 Subject: ath5k: Fix reset sequence for AR5212 in general and RF5111 in particular Take care to handle register 0xa228 exactly as in the HAL released by Atheros. This change is required to make ath5k work again on my system since commit 2203d6be (ath5k: Misc hw_reset updates), thus fixing a regression in 2.6.27 and therefore hopefully eligible for inclusion into a stable release. v2: Only overwrite initial register values on later revisions of AR5212 chips. v3: Use standard macros to manipulate the register. Signed-off-by: Elias Oltmanns Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/initvals.c | 2 ++ drivers/net/wireless/ath5k/reset.c | 22 +++++++--------------- 2 files changed, 9 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c index ea2e1a20b49..ceaa6c475c0 100644 --- a/drivers/net/wireless/ath5k/initvals.c +++ b/drivers/net/wireless/ath5k/initvals.c @@ -806,6 +806,8 @@ static const struct ath5k_ini_mode ar5212_rf5111_ini_mode_end[] = { { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, { AR5K_PHY(642), { 0xd03e6788, 0xd03e6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, + { 0xa228, + { 0x000001b5, 0x000001b5, 0x000001b5, 0x000001b5, 0x000001b5 } }, { 0xa23c, { 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af } }, }; diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c index 8f1886834e6..1b6d45b6772 100644 --- a/drivers/net/wireless/ath5k/reset.c +++ b/drivers/net/wireless/ath5k/reset.c @@ -537,9 +537,10 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, mdelay(1); /* - * Write some more initial register settings + * Write some more initial register settings for revised chips */ - if (ah->ah_version == AR5K_AR5212) { + if (ah->ah_version == AR5K_AR5212 && + ah->ah_phy_revision > 0x41) { ath5k_hw_reg_write(ah, 0x0002a002, 0x982c); if (channel->hw_value == CHANNEL_G) @@ -558,19 +559,10 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, else ath5k_hw_reg_write(ah, 0x00000000, 0x994c); - /* Some bits are disabled here, we know nothing about - * register 0xa228 yet, most of the times this ends up - * with a value 0x9b5 -haven't seen any dump with - * a different value- */ - /* Got this from decompiling binary HAL */ - data = ath5k_hw_reg_read(ah, 0xa228); - data &= 0xfffffdff; - ath5k_hw_reg_write(ah, data, 0xa228); - - data = ath5k_hw_reg_read(ah, 0xa228); - data &= 0xfffe03ff; - ath5k_hw_reg_write(ah, data, 0xa228); - data = 0; + /* Got this from legacy-hal */ + AR5K_REG_DISABLE_BITS(ah, 0xa228, 0x200); + + AR5K_REG_MASKED_BITS(ah, 0xa228, 0x800, 0xfffe03ff); /* Just write 0x9b5 ? */ /* ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); */ -- cgit v1.2.3 From 063279062a8c530cc90fb77797db16c49c905b26 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Wed, 29 Oct 2008 08:30:56 -0400 Subject: ath5k: honor FIF_BCN_PRBRESP_PROMISC in STA mode We were setting RX_FILTER_BEACON even after entering STA mode, which leads to a lot of unnecessary wakeups. This should fix the bug "Ath5k driver has too many interrupts per second at idle" at http://bugzilla.kernel.org/show_bug.cgi?id=11749. Signed-off-by: Bob Copeland Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index cfd4d052d66..9e47d727e22 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -2942,10 +2942,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, sc->opmode != NL80211_IFTYPE_MESH_POINT && test_bit(ATH_STAT_PROMISC, sc->status)) rfilt |= AR5K_RX_FILTER_PROM; - if (sc->opmode == NL80211_IFTYPE_STATION || - sc->opmode == NL80211_IFTYPE_ADHOC) { + if (sc->opmode == NL80211_IFTYPE_ADHOC) rfilt |= AR5K_RX_FILTER_BEACON; - } /* Set filters */ ath5k_hw_set_rx_filter(ah,rfilt); -- cgit v1.2.3 From cde217a556ec552d28ac9e136c5a94684a69ae94 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 21 Oct 2008 15:28:46 -0400 Subject: USB: fix crash when URBs are unlinked after the device is gone This patch (as1151) protects usbcore against drivers that try to unlink an URB after the URB's device or bus have been removed. The core does not currently check for this, and certain drivers can cause a crash if they are running while an HCD is unloaded. Certainly it would be best to fix the guilty drivers. But a little defensive programming doesn't hurt, especially since it appears that quite a few drivers need to be fixed. The patch prevents the problem by grabbing a reference to the device while an unlink is in progress and using a new spinlock to synchronize unlinks with device removal. (There's no need to acquire a reference to the bus as well, since the device structure itself keeps a reference to the bus.) In addition, the kerneldoc is updated to indicate that URBs should not be unlinked after the disconnect method returns. Signed-off-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 35 ++++++++++++++++++++++++++++++++--- drivers/usb/core/hcd.h | 1 + drivers/usb/core/hub.c | 1 + drivers/usb/core/urb.c | 22 ++++++++++++++++++++++ 4 files changed, 56 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index fc9018e72a0..e1b42626d04 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -106,6 +106,9 @@ static DEFINE_SPINLOCK(hcd_root_hub_lock); /* used when updating an endpoint's URB list */ static DEFINE_SPINLOCK(hcd_urb_list_lock); +/* used to protect against unlinking URBs after the device is gone */ +static DEFINE_SPINLOCK(hcd_urb_unlink_lock); + /* wait queue for synchronous unlinks */ DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue); @@ -1376,10 +1379,25 @@ static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status) int usb_hcd_unlink_urb (struct urb *urb, int status) { struct usb_hcd *hcd; - int retval; + int retval = -EIDRM; + unsigned long flags; - hcd = bus_to_hcd(urb->dev->bus); - retval = unlink1(hcd, urb, status); + /* Prevent the device and bus from going away while + * the unlink is carried out. If they are already gone + * then urb->use_count must be 0, since disconnected + * devices can't have any active URBs. + */ + spin_lock_irqsave(&hcd_urb_unlink_lock, flags); + if (atomic_read(&urb->use_count) > 0) { + retval = 0; + usb_get_dev(urb->dev); + } + spin_unlock_irqrestore(&hcd_urb_unlink_lock, flags); + if (retval == 0) { + hcd = bus_to_hcd(urb->dev->bus); + retval = unlink1(hcd, urb, status); + usb_put_dev(urb->dev); + } if (retval == 0) retval = -EINPROGRESS; @@ -1528,6 +1546,17 @@ void usb_hcd_disable_endpoint(struct usb_device *udev, hcd->driver->endpoint_disable(hcd, ep); } +/* Protect against drivers that try to unlink URBs after the device + * is gone, by waiting until all unlinks for @udev are finished. + * Since we don't currently track URBs by device, simply wait until + * nothing is running in the locked region of usb_hcd_unlink_urb(). + */ +void usb_hcd_synchronize_unlinks(struct usb_device *udev) +{ + spin_lock_irq(&hcd_urb_unlink_lock); + spin_unlock_irq(&hcd_urb_unlink_lock); +} + /*-------------------------------------------------------------------------*/ /* called in any context */ diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 2dcde61c465..9465e70f4dd 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -232,6 +232,7 @@ extern void usb_hcd_flush_endpoint(struct usb_device *udev, struct usb_host_endpoint *ep); extern void usb_hcd_disable_endpoint(struct usb_device *udev, struct usb_host_endpoint *ep); +extern void usb_hcd_synchronize_unlinks(struct usb_device *udev); extern int usb_hcd_get_frame_number(struct usb_device *udev); extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 9b3f16bd12c..37ff8aed256 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1429,6 +1429,7 @@ void usb_disconnect(struct usb_device **pdev) */ dev_dbg (&udev->dev, "unregistering device\n"); usb_disable_device(udev, 0); + usb_hcd_synchronize_unlinks(udev); usb_unlock_device(udev); diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index f2638009a46..4342bd9c3bb 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -474,6 +474,12 @@ EXPORT_SYMBOL_GPL(usb_submit_urb); * indicating that the request has been canceled (rather than any other * code). * + * Drivers should not call this routine or related routines, such as + * usb_kill_urb() or usb_unlink_anchored_urbs(), after their disconnect + * method has returned. The disconnect function should synchronize with + * a driver's I/O routines to insure that all URB-related activity has + * completed before it returns. + * * This request is always asynchronous. Success is indicated by * returning -EINPROGRESS, at which time the URB will probably not yet * have been given back to the device driver. When it is eventually @@ -550,6 +556,9 @@ EXPORT_SYMBOL_GPL(usb_unlink_urb); * This routine may not be used in an interrupt context (such as a bottom * half or a completion handler), or when holding a spinlock, or in other * situations where the caller can't schedule(). + * + * This routine should not be called by a driver after its disconnect + * method has returned. */ void usb_kill_urb(struct urb *urb) { @@ -588,6 +597,9 @@ EXPORT_SYMBOL_GPL(usb_kill_urb); * This routine may not be used in an interrupt context (such as a bottom * half or a completion handler), or when holding a spinlock, or in other * situations where the caller can't schedule(). + * + * This routine should not be called by a driver after its disconnect + * method has returned. */ void usb_poison_urb(struct urb *urb) { @@ -622,6 +634,9 @@ EXPORT_SYMBOL_GPL(usb_unpoison_urb); * * this allows all outstanding URBs to be killed starting * from the back of the queue + * + * This routine should not be called by a driver after its disconnect + * method has returned. */ void usb_kill_anchored_urbs(struct usb_anchor *anchor) { @@ -651,6 +666,9 @@ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs); * this allows all outstanding URBs to be poisoned starting * from the back of the queue. Newly added URBs will also be * poisoned + * + * This routine should not be called by a driver after its disconnect + * method has returned. */ void usb_poison_anchored_urbs(struct usb_anchor *anchor) { @@ -672,6 +690,7 @@ void usb_poison_anchored_urbs(struct usb_anchor *anchor) spin_unlock_irq(&anchor->lock); } EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs); + /** * usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse * @anchor: anchor the requests are bound to @@ -680,6 +699,9 @@ EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs); * from the back of the queue. This function is asynchronous. * The unlinking is just tiggered. It may happen after this * function has returned. + * + * This routine should not be called by a driver after its disconnect + * method has returned. */ void usb_unlink_anchored_urbs(struct usb_anchor *anchor) { -- cgit v1.2.3 From b361a6e348a5de9e18eb17542663d34a57740e87 Mon Sep 17 00:00:00 2001 From: Chris Malley Date: Sat, 25 Oct 2008 22:07:32 +0100 Subject: USB: usbtmc: Use explicit unsigned type for input buffer instead of char* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Silences compiler warning about comparison with 0x80, and type now matches the corresponding _bulk_out function. drivers/usb/class/usbtmc.c: In function ‘usbtmc_ioctl_abort_bulk_in’: drivers/usb/class/usbtmc.c:163: warning: comparison is always false due to limited range of data type Signed-off-by: Chris Malley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 543811f6e6e..8e74657f106 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -133,7 +133,7 @@ static int usbtmc_release(struct inode *inode, struct file *file) static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data) { - char *buffer; + u8 *buffer; struct device *dev; int rv; int n; -- cgit v1.2.3 From 74511bb340059be5a3fceb032213c7f325344694 Mon Sep 17 00:00:00 2001 From: Jens Taprogge Date: Sun, 26 Oct 2008 18:16:09 +0100 Subject: USB: Unusual dev for the "Kyocera / Contax SL300R T*" digital camera. The camera reports an incorrect size and fails to handle PREVENT-ALLOW MEDIUM REMOVAL commands. The patch marks the camera as an unusual dev and adds the flags to enable the workarounds for both shortcomings. Signed-off-by: Jens Taprogge Cc: Alan Stern Cc: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index a2b9ebbef38..fb9e20e624c 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -333,6 +333,13 @@ UNUSUAL_DEV( 0x0482, 0x0103, 0x0100, 0x0100, "Finecam S5", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), +/* Patch submitted by Jens Taprogge */ +UNUSUAL_DEV( 0x0482, 0x0107, 0x0100, 0x0100, + "Kyocera", + "CONTAX SL300R T*", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE), + /* Reported by Paul Stewart * This entry is needed because the device reports Sub=ff */ UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, -- cgit v1.2.3 From 61fbeba11c553c489ba5284c0ed67067dc7b7c0f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 27 Oct 2008 12:07:44 -0400 Subject: USB: prevent autosuspend during hub initialization This patch (as1153) fixes a potential problem in hub initialization. Starting in 2.6.28, initialization was split into several tasks to help speed up booting. This opens the possibility that the hub may be autosuspended before all the initialization tasks can complete. Normally that wouldn't matter, but with incomplete initialization there is a risk that the hub would never autoresume -- especially if devices were plugged into the hub beforehand. The solution is a simple one-line change to suppress autosuspend until the initialization is finished. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 37ff8aed256..b19cbfcd51d 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -659,6 +659,9 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func2); schedule_delayed_work(&hub->init_work, msecs_to_jiffies(delay)); + + /* Suppress autosuspend until init is done */ + to_usb_interface(hub->intfdev)->pm_usage_cnt = 1; return; /* Continues at init2: below */ } else { hub_power_on(hub, true); -- cgit v1.2.3 From 65151365ad59af00e229d0fe33b4f1f9350c685f Mon Sep 17 00:00:00 2001 From: Qinghuang Feng Date: Mon, 13 Oct 2008 18:05:04 +0800 Subject: driver core: drivers/base/sys.c: update comments There are no functions named sys_device_shutdown or sys_device_suspend in the kernel. They should be fixed to sysdev_shutdown and sysdev_suspend respectively. Signed-off-by: Qinghuang Feng Signed-off-by: Greg Kroah-Hartman --- drivers/base/sys.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 75dd6e22faf..3ca9c5e8d76 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -355,7 +355,7 @@ static void __sysdev_resume(struct sys_device *dev) * sysdev_suspend - Suspend all system devices. * @state: Power state to enter. * - * We perform an almost identical operation as sys_device_shutdown() + * We perform an almost identical operation as sysdev_shutdown() * above, though calling ->suspend() instead. Interrupts are disabled * when this called. Devices are responsible for both saving state and * quiescing or powering down the device. @@ -437,7 +437,7 @@ aux_driver: /** * sysdev_resume - Bring system devices back to life. * - * Similar to sys_device_suspend(), but we iterate the list forwards + * Similar to sysdev_suspend(), but we iterate the list forwards * to guarantee that parent devices are resumed before their children. * * Note: Interrupts are disabled when called. -- cgit v1.2.3 From 4e318d7c6c9dd5cdae48bcf61558bbc0c09b12ac Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 13 Oct 2008 12:03:03 +0200 Subject: sysfs: Fix return values for sysdev_store_{ulong,int} SYSFS: Fix return values for sysdev_store_{ulong,int} Always return the full size instead of the consumed length of the string in sysdev_store_{ulong,int} This avoids EINVAL errors in some echo versions. Signed-off-by: Andi Kleen Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/base/sys.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 3ca9c5e8d76..c98c31ec2f7 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -488,7 +488,8 @@ ssize_t sysdev_store_ulong(struct sys_device *sysdev, if (end == buf) return -EINVAL; *(unsigned long *)(ea->var) = new; - return end - buf; + /* Always return full write size even if we didn't consume all */ + return size; } EXPORT_SYMBOL_GPL(sysdev_store_ulong); @@ -511,7 +512,8 @@ ssize_t sysdev_store_int(struct sys_device *sysdev, if (end == buf || new > INT_MAX || new < INT_MIN) return -EINVAL; *(int *)(ea->var) = new; - return end - buf; + /* Always return full write size even if we didn't consume all */ + return size; } EXPORT_SYMBOL_GPL(sysdev_store_int); -- cgit v1.2.3 From 12a9ee3cce256ae0f178d604f2c8764fb2942cfe Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Wed, 29 Oct 2008 15:35:24 -0700 Subject: rtc-m48t59: shift zero year to 1968 on sparc (rev 2) Shift the first year to 1968 for Sun SPARC machines. Move this logic from platform specific files to rtc driver as this fixes problems with calculating a century bit. Signed-off-by: Krzysztof Helt Tested-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/rtc/rtc-m48t59.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 04b63dab693..43afb7ab528 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -87,6 +87,10 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) dev_dbg(dev, "Century bit is enabled\n"); tm->tm_year += 100; /* one century */ } +#ifdef CONFIG_SPARC + /* Sun SPARC machines count years since 1968 */ + tm->tm_year += 68; +#endif tm->tm_wday = bcd2bin(val & 0x07); tm->tm_hour = bcd2bin(M48T59_READ(M48T59_HOUR) & 0x3F); @@ -110,11 +114,20 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) struct m48t59_private *m48t59 = platform_get_drvdata(pdev); unsigned long flags; u8 val = 0; + int year = tm->tm_year; + +#ifdef CONFIG_SPARC + /* Sun SPARC machines count years since 1968 */ + year -= 68; +#endif dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d/%02d/%02d\n", - tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, + year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); + if (year < 0) + return -EINVAL; + spin_lock_irqsave(&m48t59->lock, flags); /* Issue the WRITE command */ M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); @@ -125,9 +138,9 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) M48T59_WRITE((bin2bcd(tm->tm_mday) & 0x3F), M48T59_MDAY); /* tm_mon is 0-11 */ M48T59_WRITE((bin2bcd(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); - M48T59_WRITE(bin2bcd(tm->tm_year % 100), M48T59_YEAR); + M48T59_WRITE(bin2bcd(year % 100), M48T59_YEAR); - if (pdata->type == M48T59RTC_TYPE_M48T59 && (tm->tm_year / 100)) + if (pdata->type == M48T59RTC_TYPE_M48T59 && (year / 100)) val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); val |= (bin2bcd(tm->tm_wday) & 0x07); M48T59_WRITE(val, M48T59_WDAY); @@ -159,6 +172,10 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL); tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR)); +#ifdef CONFIG_SPARC + /* Sun SPARC machines count years since 1968 */ + tm->tm_year += 68; +#endif /* tm_mon is 0-11 */ tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1; @@ -192,11 +209,20 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) struct rtc_time *tm = &alrm->time; u8 mday, hour, min, sec; unsigned long flags; + int year = tm->tm_year; + +#ifdef CONFIG_SPARC + /* Sun SPARC machines count years since 1968 */ + year -= 68; +#endif /* If no irq, we don't support ALARM */ if (m48t59->irq == NO_IRQ) return -EIO; + if (year < 0) + return -EINVAL; + /* * 0xff means "always match" */ @@ -228,7 +254,7 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) spin_unlock_irqrestore(&m48t59->lock, flags); dev_dbg(dev, "RTC set alarm time %04d-%02d-%02d %02d/%02d/%02d\n", - tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, + year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); return 0; } -- cgit v1.2.3 From fa157bdfe87c5ea98a80b96cb08f1ab509e21a52 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 30 Oct 2008 01:06:13 +0100 Subject: HID: add quirk entry for no-name keyboard (0x13ba/0x0017) This patch (as1157) adds a no-name PS/2-to-USB keyboard+mouse adapter to the hid-dell driver. (The device shows up with a Product string saying "Generic USB K/B", nothing more.) This will force an initial "Set-LEDs" report to be sent to the device, without which it won't send any keystroke information. Several bug reports mentioning this device have been filed in various forums; the patch should resolve them. This is just a temporary stop-gap for 2.6.28. A later patch for 2.6.29 will introduce a more generic mechanism for "Set-LEDs", making this change (and the entire hid-dell driver) unnecessary. Signed-off-by: Alan Stern Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-dell.c | 1 + drivers/hid/hid-ids.h | 3 +++ 3 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 743e6f8cb20..1903e751565 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1263,6 +1263,7 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) }, { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) }, { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, diff --git a/drivers/hid/hid-dell.c b/drivers/hid/hid-dell.c index 1a0d0dfc62f..f5474300b83 100644 --- a/drivers/hid/hid-dell.c +++ b/drivers/hid/hid-dell.c @@ -48,6 +48,7 @@ err_free: static const struct hid_device_id dell_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) }, { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) }, { } }; MODULE_DEVICE_TABLE(hid, dell_devices); diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index a0d6a6cb184..5cc40429173 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -163,6 +163,9 @@ #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc +#define USB_VENDOR_ID_GENERIC_13BA 0x13ba +#define USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE 0x0017 + #define USB_VENDOR_ID_GLAB 0x06c2 #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 #define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 -- cgit v1.2.3 From fb881f785f0003fc904c6db82909d937d968bcc9 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Tue, 14 Oct 2008 18:13:45 +0200 Subject: [ARM] build fixes for netX serial driver Make the netX serial driver tristate (as the help text implied). Make the serial driver build correctly if the netX serial console is disabled. Do not allow the netX serial console if the netX serial driver is build as a module. Signed-off-by: Paul Bolle Signed-off-by: Sascha Hauer --- drivers/serial/Kconfig | 4 ++-- drivers/serial/netx-serial.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index c94d3c4b752..579d63a81aa 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -1276,7 +1276,7 @@ config SERIAL_SGI_IOC3 say Y or M. Otherwise, say N. config SERIAL_NETX - bool "NetX serial port support" + tristate "NetX serial port support" depends on ARM && ARCH_NETX select SERIAL_CORE help @@ -1288,7 +1288,7 @@ config SERIAL_NETX config SERIAL_NETX_CONSOLE bool "Console on NetX serial port" - depends on SERIAL_NETX + depends on SERIAL_NETX=y select SERIAL_CORE_CONSOLE help If you have enabled the serial port on the Hilscher NetX SoC diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c index 3f489329e8d..3e5dda8518b 100644 --- a/drivers/serial/netx-serial.c +++ b/drivers/serial/netx-serial.c @@ -42,8 +42,6 @@ #define SERIAL_NX_MAJOR 204 #define MINOR_START 170 -#ifdef CONFIG_SERIAL_NETX_CONSOLE - enum uart_regs { UART_DR = 0x00, UART_SR = 0x04, @@ -528,6 +526,8 @@ static struct netx_port netx_ports[] = { } }; +#ifdef CONFIG_SERIAL_NETX_CONSOLE + static void netx_console_putchar(struct uart_port *port, int ch) { while (readl(port->membase + UART_FR) & FR_BUSY); -- cgit v1.2.3 From 9a5415fbe87ad7b99ecf9b7ef6bf091c7479f2a4 Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Thu, 30 Oct 2008 09:11:40 -0400 Subject: Input: elo - fix format string in elo driver Fix typo in format string. Signed-off-by: Vojtech Pavlik Signed-off-by: Jiri Kosina Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/elo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index d20689cdbd5..8f38c5e55ce 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c @@ -262,7 +262,7 @@ static int elo_setup_10(struct elo *elo) input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); printk(KERN_INFO "elo: %sTouch touchscreen, fw: %02x.%02x, " - "features: %x02x, controller: 0x%02x\n", + "features: 0x%02x, controller: 0x%02x\n", elo_types[(packet[1] -'0') & 0x03], packet[5], packet[4], packet[3], packet[7]); -- cgit v1.2.3 From b34578a48459ed1bd5396631aaa4a65d6bcc7726 Mon Sep 17 00:00:00 2001 From: Ilpo Jarvinen Date: Thu, 30 Oct 2008 13:33:07 +0000 Subject: dm raid1: fix do_failures Missing braces. Commit 1f965b1943 (dm raid1: separate region_hash interface part1) broke it. Signed-off-by: Ilpo Jarvinen Signed-off-by: Alasdair G Kergon Cc: Heinz Mauelshagen --- drivers/md/dm-raid1.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 92dcc06832a..9d7b53ed75b 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -656,9 +656,10 @@ static void do_failures(struct mirror_set *ms, struct bio_list *failures) return; if (!ms->log_failure) { - while ((bio = bio_list_pop(failures))) + while ((bio = bio_list_pop(failures))) { ms->in_sync = 0; dm_rh_mark_nosync(ms->rh, bio, bio->bi_size, 0); + } return; } -- cgit v1.2.3 From 60c856c8e2f57a3f69c505735ef66e3719ea0bd6 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 30 Oct 2008 13:33:12 +0000 Subject: dm snapshot: fix register_snapshot deadlock register_snapshot() performs a GFP_KERNEL allocation while holding _origins_lock for write, but that could write out dirty pages onto a device that attempts to acquire _origins_lock for read, resulting in deadlock. So move the allocation up before taking the lock. This path is not performance-critical, so it doesn't matter that we allocate memory and free it if we find that we won't need it. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm-snap.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index b2d9d1ac28a..746603b42f8 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -229,19 +229,21 @@ static void __insert_origin(struct origin *o) */ static int register_snapshot(struct dm_snapshot *snap) { - struct origin *o; + struct origin *o, *new_o; struct block_device *bdev = snap->origin->bdev; + new_o = kmalloc(sizeof(*new_o), GFP_KERNEL); + if (!new_o) + return -ENOMEM; + down_write(&_origins_lock); o = __lookup_origin(bdev); - if (!o) { + if (o) + kfree(new_o); + else { /* New origin */ - o = kmalloc(sizeof(*o), GFP_KERNEL); - if (!o) { - up_write(&_origins_lock); - return -ENOMEM; - } + o = new_o; /* Initialise the struct */ INIT_LIST_HEAD(&o->snapshots); -- cgit v1.2.3 From 879129d208f725267366296b631aef31409cf304 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 30 Oct 2008 13:33:16 +0000 Subject: dm snapshot: wait for chunks in destructor If there are several snapshots sharing an origin and one is removed while the origin is being written to, the snapshot's mempool may get deleted while elements are still referenced. Prior to dm-snapshot-use-per-device-mempools.patch the pending exceptions may still have been referenced after the snapshot was destroyed, but this was not a problem because the shared mempool was still there. This patch fixes the problem by tracking the number of mempool elements in use. The scenario: - You have an origin and two snapshots 1 and 2. - Someone writes to the origin. - It creates two exceptions in the snapshots, snapshot 1 will be primary exception, snapshot 2's pending_exception->primary_pe will point to the exception in snapshot 1. - The exceptions are being relocated, relocation of exception 1 finishes (but it's pending_exception is still allocated, because it is referenced by an exception from snapshot 2) - The user lvremoves snapshot 1 --- it calls just suspend (does nothing) and destructor. md->pending is zero (there is no I/O submitted to the snapshot by md layer), so it won't help us. - The destructor waits for kcopyd jobs to finish on snapshot 1 --- but there are none. - The destructor on snapshot 1 cleans up everything. - The relocation of exception on snapshot 2 finishes, it drops reference on primary_pe. This frees its primary_pe pointer. Primary_pe points to pending exception created for snapshot 1. So it frees memory into non-existing mempool. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm-snap.c | 16 +++++++++++++++- drivers/md/dm-snap.h | 2 ++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 746603b42f8..6c96db26b87 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -370,6 +370,7 @@ static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snaps struct dm_snap_pending_exception *pe = mempool_alloc(s->pending_pool, GFP_NOIO); + atomic_inc(&s->pending_exceptions_count); pe->snap = s; return pe; @@ -377,7 +378,11 @@ static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snaps static void free_pending_exception(struct dm_snap_pending_exception *pe) { - mempool_free(pe, pe->snap->pending_pool); + struct dm_snapshot *s = pe->snap; + + mempool_free(pe, s->pending_pool); + smp_mb__before_atomic_dec(); + atomic_dec(&s->pending_exceptions_count); } static void insert_completed_exception(struct dm_snapshot *s, @@ -602,6 +607,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) s->valid = 1; s->active = 0; + atomic_set(&s->pending_exceptions_count, 0); init_rwsem(&s->lock); spin_lock_init(&s->pe_lock); s->ti = ti; @@ -728,6 +734,14 @@ static void snapshot_dtr(struct dm_target *ti) /* After this returns there can be no new kcopyd jobs. */ unregister_snapshot(s); + while (atomic_read(&s->pending_exceptions_count)) + yield(); + /* + * Ensure instructions in mempool_destroy aren't reordered + * before atomic_read. + */ + smp_mb(); + #ifdef CONFIG_DM_DEBUG for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++) BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i])); diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h index f07315fe236..99c0106ede2 100644 --- a/drivers/md/dm-snap.h +++ b/drivers/md/dm-snap.h @@ -160,6 +160,8 @@ struct dm_snapshot { mempool_t *pending_pool; + atomic_t pending_exceptions_count; + struct exception_table pending; struct exception_table complete; -- cgit v1.2.3 From a0601c8944dc08c2d349c24bd9c0b09c406229fc Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 30 Oct 2008 11:05:00 +0000 Subject: leds: da903x: (da9030 only) led brightness reversed. The brightness control register calculation (for the pwm) is effectively the reverse of what would be expected. 1 is maximum brightness, 255 minimum. This patch inverts this. Signed-off-by: Jonathan Cameron Acked-by: Mike Rapoport Signed-off-by: Eric Miao --- drivers/leds/leds-da903x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c index 2768c69257f..1f3cc512eff 100644 --- a/drivers/leds/leds-da903x.c +++ b/drivers/leds/leds-da903x.c @@ -58,7 +58,7 @@ static void da903x_led_work(struct work_struct *work) offset = DA9030_LED_OFFSET(led->id); val = led->flags & ~0x87; val |= (led->new_brightness) ? 0x80 : 0; /* EN bit */ - val |= (led->new_brightness >> 5) & 0x7; /* PWM<2:0> */ + val |= (0x7 - (led->new_brightness >> 5)) & 0x7; /* PWM<2:0> */ da903x_write(led->master, DA9030_LED1_CONTROL + offset, val); break; case DA9030_ID_VIBRA: -- cgit v1.2.3 From 4bdebe5b4a7216bd6bfca9e9b368abad8e9f9bd9 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 26 Oct 2008 16:12:13 +0000 Subject: CHAR: Delete old and now unused DS1286 driver. It was only used by two SGI platforms which recently were converted to RTC_LIB and with RTC_LIB enabled the legacy drivers are no more selectable. Signed-off-by: Ralf Baechle Signed-off-by: Yoichi Yuasa --- drivers/char/Kconfig | 11 - drivers/char/Makefile | 1 - drivers/char/ds1286.c | 585 -------------------------------------------------- 3 files changed, 597 deletions(-) delete mode 100644 drivers/char/ds1286.c (limited to 'drivers') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 122254155ae..9d2c4364550 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -812,17 +812,6 @@ config JS_RTC To compile this driver as a module, choose M here: the module will be called js-rtc. -config SGI_DS1286 - tristate "SGI DS1286 RTC support" - depends on SGI_HAS_DS1286 - help - If you say Y here and create a character special file /dev/rtc with - major number 10 and minor number 135 using mknod ("man mknod"), you - will get access to the real time clock built into your computer. - Every SGI has such a clock built in. It reports status information - via the file /proc/rtc and its behaviour is set by various ioctls on - /dev/rtc. - config SGI_IP27_RTC bool "SGI M48T35 RTC support" depends on SGI_IP27 diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 1a4247dccac..917f0f4faf7 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -74,7 +74,6 @@ obj-$(CONFIG_RTC) += rtc.o obj-$(CONFIG_HPET) += hpet.o obj-$(CONFIG_GEN_RTC) += genrtc.o obj-$(CONFIG_EFI_RTC) += efirtc.o -obj-$(CONFIG_SGI_DS1286) += ds1286.o obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o obj-$(CONFIG_DS1302) += ds1302.o obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap/ diff --git a/drivers/char/ds1286.c b/drivers/char/ds1286.c deleted file mode 100644 index 0a826d7be10..00000000000 --- a/drivers/char/ds1286.c +++ /dev/null @@ -1,585 +0,0 @@ -/* - * DS1286 Real Time Clock interface for Linux - * - * Copyright (C) 1998, 1999, 2000 Ralf Baechle - * - * Based on code written by Paul Gortmaker. - * - * This driver allows use of the real time clock (built into nearly all - * computers) from user space. It exports the /dev/rtc interface supporting - * various ioctl() and also the /proc/rtc pseudo-file for status - * information. - * - * The ioctls can be used to set the interrupt behaviour and generation rate - * from the RTC via IRQ 8. Then the /dev/rtc interface can be used to make - * use of these timer interrupts, be they interval or alarm based. - * - * The /dev/rtc interface will block on reads until an interrupt has been - * received. If a RTC interrupt has already happened, it will output an - * unsigned long and then block. The output value contains the interrupt - * status in the low byte and the number of interrupts since the last read - * in the remaining high bytes. The /dev/rtc interface can also be used with - * the select(2) call. - * - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define DS1286_VERSION "1.0" - -/* - * We sponge a minor off of the misc major. No need slurping - * up another valuable major dev number for this. If you add - * an ioctl, make sure you don't conflict with SPARC's RTC - * ioctls. - */ - -static DECLARE_WAIT_QUEUE_HEAD(ds1286_wait); - -static ssize_t ds1286_read(struct file *file, char *buf, - size_t count, loff_t *ppos); - -static int ds1286_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); - -static unsigned int ds1286_poll(struct file *file, poll_table *wait); - -static void ds1286_get_alm_time (struct rtc_time *alm_tm); -static void ds1286_get_time(struct rtc_time *rtc_tm); -static int ds1286_set_time(struct rtc_time *rtc_tm); - -static inline unsigned char ds1286_is_updating(void); - -static DEFINE_SPINLOCK(ds1286_lock); - -static int ds1286_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data); - -/* - * Bits in rtc_status. (7 bits of room for future expansion) - */ - -#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ -#define RTC_TIMER_ON 0x02 /* missed irq timer active */ - -static unsigned char ds1286_status; /* bitmapped status byte. */ - -static unsigned char days_in_mo[] = { - 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; - -/* - * Now all the various file operations that we export. - */ - -static ssize_t ds1286_read(struct file *file, char *buf, - size_t count, loff_t *ppos) -{ - return -EIO; -} - -static int ds1286_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct rtc_time wtime; - - switch (cmd) { - case RTC_AIE_OFF: /* Mask alarm int. enab. bit */ - { - unsigned long flags; - unsigned char val; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - spin_lock_irqsave(&ds1286_lock, flags); - val = rtc_read(RTC_CMD); - val |= RTC_TDM; - rtc_write(val, RTC_CMD); - spin_unlock_irqrestore(&ds1286_lock, flags); - - return 0; - } - case RTC_AIE_ON: /* Allow alarm interrupts. */ - { - unsigned long flags; - unsigned char val; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - spin_lock_irqsave(&ds1286_lock, flags); - val = rtc_read(RTC_CMD); - val &= ~RTC_TDM; - rtc_write(val, RTC_CMD); - spin_unlock_irqrestore(&ds1286_lock, flags); - - return 0; - } - case RTC_WIE_OFF: /* Mask watchdog int. enab. bit */ - { - unsigned long flags; - unsigned char val; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - spin_lock_irqsave(&ds1286_lock, flags); - val = rtc_read(RTC_CMD); - val |= RTC_WAM; - rtc_write(val, RTC_CMD); - spin_unlock_irqrestore(&ds1286_lock, flags); - - return 0; - } - case RTC_WIE_ON: /* Allow watchdog interrupts. */ - { - unsigned long flags; - unsigned char val; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - spin_lock_irqsave(&ds1286_lock, flags); - val = rtc_read(RTC_CMD); - val &= ~RTC_WAM; - rtc_write(val, RTC_CMD); - spin_unlock_irqrestore(&ds1286_lock, flags); - - return 0; - } - case RTC_ALM_READ: /* Read the present alarm time */ - { - /* - * This returns a struct rtc_time. Reading >= 0xc0 - * means "don't care" or "match all". Only the tm_hour, - * tm_min, and tm_sec values are filled in. - */ - - memset(&wtime, 0, sizeof(wtime)); - ds1286_get_alm_time(&wtime); - break; - } - case RTC_ALM_SET: /* Store a time into the alarm */ - { - /* - * This expects a struct rtc_time. Writing 0xff means - * "don't care" or "match all". Only the tm_hour, - * tm_min and tm_sec are used. - */ - unsigned char hrs, min, sec; - struct rtc_time alm_tm; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - if (copy_from_user(&alm_tm, (struct rtc_time*)arg, - sizeof(struct rtc_time))) - return -EFAULT; - - hrs = alm_tm.tm_hour; - min = alm_tm.tm_min; - sec = alm_tm.tm_sec; - - if (hrs >= 24) - hrs = 0xff; - - if (min >= 60) - min = 0xff; - - if (sec != 0) - return -EINVAL; - - min = bin2bcd(min); - min = bin2bcd(hrs); - - spin_lock(&ds1286_lock); - rtc_write(hrs, RTC_HOURS_ALARM); - rtc_write(min, RTC_MINUTES_ALARM); - spin_unlock(&ds1286_lock); - - return 0; - } - case RTC_RD_TIME: /* Read the time/date from RTC */ - { - memset(&wtime, 0, sizeof(wtime)); - ds1286_get_time(&wtime); - break; - } - case RTC_SET_TIME: /* Set the RTC */ - { - struct rtc_time rtc_tm; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, - sizeof(struct rtc_time))) - return -EFAULT; - - return ds1286_set_time(&rtc_tm); - } - default: - return -EINVAL; - } - return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; -} - -/* - * We enforce only one user at a time here with the open/close. - * Also clear the previous interrupt data on an open, and clean - * up things on a close. - */ - -static int ds1286_open(struct inode *inode, struct file *file) -{ - lock_kernel(); - spin_lock_irq(&ds1286_lock); - - if (ds1286_status & RTC_IS_OPEN) - goto out_busy; - - ds1286_status |= RTC_IS_OPEN; - - spin_unlock_irq(&ds1286_lock); - unlock_kernel(); - return 0; - -out_busy: - spin_lock_irq(&ds1286_lock); - unlock_kernel(); - return -EBUSY; -} - -static int ds1286_release(struct inode *inode, struct file *file) -{ - ds1286_status &= ~RTC_IS_OPEN; - - return 0; -} - -static unsigned int ds1286_poll(struct file *file, poll_table *wait) -{ - poll_wait(file, &ds1286_wait, wait); - - return 0; -} - -/* - * The various file operations we support. - */ - -static const struct file_operations ds1286_fops = { - .llseek = no_llseek, - .read = ds1286_read, - .poll = ds1286_poll, - .ioctl = ds1286_ioctl, - .open = ds1286_open, - .release = ds1286_release, -}; - -static struct miscdevice ds1286_dev= -{ - .minor = RTC_MINOR, - .name = "rtc", - .fops = &ds1286_fops, -}; - -static int __init ds1286_init(void) -{ - int err; - - printk(KERN_INFO "DS1286 Real Time Clock Driver v%s\n", DS1286_VERSION); - - err = misc_register(&ds1286_dev); - if (err) - goto out; - - if (!create_proc_read_entry("driver/rtc", 0, 0, ds1286_read_proc, NULL)) { - err = -ENOMEM; - - goto out_deregister; - } - - return 0; - -out_deregister: - misc_deregister(&ds1286_dev); - -out: - return err; -} - -static void __exit ds1286_exit(void) -{ - remove_proc_entry("driver/rtc", NULL); - misc_deregister(&ds1286_dev); -} - -static char *days[] = { - "***", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; - -/* - * Info exported via "/proc/rtc". - */ -static int ds1286_proc_output(char *buf) -{ - char *p, *s; - struct rtc_time tm; - unsigned char hundredth, month, cmd, amode; - - p = buf; - - ds1286_get_time(&tm); - hundredth = rtc_read(RTC_HUNDREDTH_SECOND); - hundredth = bcd2bin(hundredth); - - p += sprintf(p, - "rtc_time\t: %02d:%02d:%02d.%02d\n" - "rtc_date\t: %04d-%02d-%02d\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, hundredth, - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); - - /* - * We implicitly assume 24hr mode here. Alarm values >= 0xc0 will - * match any value for that particular field. Values that are - * greater than a valid time, but less than 0xc0 shouldn't appear. - */ - ds1286_get_alm_time(&tm); - p += sprintf(p, "alarm\t\t: %s ", days[tm.tm_wday]); - if (tm.tm_hour <= 24) - p += sprintf(p, "%02d:", tm.tm_hour); - else - p += sprintf(p, "**:"); - - if (tm.tm_min <= 59) - p += sprintf(p, "%02d\n", tm.tm_min); - else - p += sprintf(p, "**\n"); - - month = rtc_read(RTC_MONTH); - p += sprintf(p, - "oscillator\t: %s\n" - "square_wave\t: %s\n", - (month & RTC_EOSC) ? "disabled" : "enabled", - (month & RTC_ESQW) ? "disabled" : "enabled"); - - amode = ((rtc_read(RTC_MINUTES_ALARM) & 0x80) >> 5) | - ((rtc_read(RTC_HOURS_ALARM) & 0x80) >> 6) | - ((rtc_read(RTC_DAY_ALARM) & 0x80) >> 7); - if (amode == 7) s = "each minute"; - else if (amode == 3) s = "minutes match"; - else if (amode == 1) s = "hours and minutes match"; - else if (amode == 0) s = "days, hours and minutes match"; - else s = "invalid"; - p += sprintf(p, "alarm_mode\t: %s\n", s); - - cmd = rtc_read(RTC_CMD); - p += sprintf(p, - "alarm_enable\t: %s\n" - "wdog_alarm\t: %s\n" - "alarm_mask\t: %s\n" - "wdog_alarm_mask\t: %s\n" - "interrupt_mode\t: %s\n" - "INTB_mode\t: %s_active\n" - "interrupt_pins\t: %s\n", - (cmd & RTC_TDF) ? "yes" : "no", - (cmd & RTC_WAF) ? "yes" : "no", - (cmd & RTC_TDM) ? "disabled" : "enabled", - (cmd & RTC_WAM) ? "disabled" : "enabled", - (cmd & RTC_PU_LVL) ? "pulse" : "level", - (cmd & RTC_IBH_LO) ? "low" : "high", - (cmd & RTC_IPSW) ? "unswapped" : "swapped"); - - return p - buf; -} - -static int ds1286_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = ds1286_proc_output (page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) - len = count; - if (len<0) - len = 0; - - return len; -} - -/* - * Returns true if a clock update is in progress - */ -static inline unsigned char ds1286_is_updating(void) -{ - return rtc_read(RTC_CMD) & RTC_TE; -} - - -static void ds1286_get_time(struct rtc_time *rtc_tm) -{ - unsigned char save_control; - unsigned long flags; - - /* - * read RTC once any update in progress is done. The update - * can take just over 2ms. We wait 10 to 20ms. There is no need to - * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. - * If you need to know *exactly* when a second has started, enable - * periodic update complete interrupts, (via ioctl) and then - * immediately read /dev/rtc which will block until you get the IRQ. - * Once the read clears, read the RTC time (again via ioctl). Easy. - */ - - if (ds1286_is_updating() != 0) - msleep(20); - - /* - * Only the values that we read from the RTC are set. We leave - * tm_wday, tm_yday and tm_isdst untouched. Even though the - * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated - * by the RTC when initially set to a non-zero value. - */ - spin_lock_irqsave(&ds1286_lock, flags); - save_control = rtc_read(RTC_CMD); - rtc_write((save_control|RTC_TE), RTC_CMD); - - rtc_tm->tm_sec = rtc_read(RTC_SECONDS); - rtc_tm->tm_min = rtc_read(RTC_MINUTES); - rtc_tm->tm_hour = rtc_read(RTC_HOURS) & 0x3f; - rtc_tm->tm_mday = rtc_read(RTC_DATE); - rtc_tm->tm_mon = rtc_read(RTC_MONTH) & 0x1f; - rtc_tm->tm_year = rtc_read(RTC_YEAR); - - rtc_write(save_control, RTC_CMD); - spin_unlock_irqrestore(&ds1286_lock, flags); - - rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); - rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min); - rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour); - rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday); - rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon); - rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); - - /* - * Account for differences between how the RTC uses the values - * and how they are defined in a struct rtc_time; - */ - if (rtc_tm->tm_year < 45) - rtc_tm->tm_year += 30; - if ((rtc_tm->tm_year += 40) < 70) - rtc_tm->tm_year += 100; - - rtc_tm->tm_mon--; -} - -static int ds1286_set_time(struct rtc_time *rtc_tm) -{ - unsigned char mon, day, hrs, min, sec, leap_yr; - unsigned char save_control; - unsigned int yrs; - unsigned long flags; - - - yrs = rtc_tm->tm_year + 1900; - mon = rtc_tm->tm_mon + 1; /* tm_mon starts at zero */ - day = rtc_tm->tm_mday; - hrs = rtc_tm->tm_hour; - min = rtc_tm->tm_min; - sec = rtc_tm->tm_sec; - - if (yrs < 1970) - return -EINVAL; - - leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); - - if ((mon > 12) || (day == 0)) - return -EINVAL; - - if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) - return -EINVAL; - - if ((hrs >= 24) || (min >= 60) || (sec >= 60)) - return -EINVAL; - - if ((yrs -= 1940) > 255) /* They are unsigned */ - return -EINVAL; - - if (yrs >= 100) - yrs -= 100; - - sec = bin2bcd(sec); - min = bin2bcd(min); - hrs = bin2bcd(hrs); - day = bin2bcd(day); - mon = bin2bcd(mon); - yrs = bin2bcd(yrs); - - spin_lock_irqsave(&ds1286_lock, flags); - save_control = rtc_read(RTC_CMD); - rtc_write((save_control|RTC_TE), RTC_CMD); - - rtc_write(yrs, RTC_YEAR); - rtc_write(mon, RTC_MONTH); - rtc_write(day, RTC_DATE); - rtc_write(hrs, RTC_HOURS); - rtc_write(min, RTC_MINUTES); - rtc_write(sec, RTC_SECONDS); - rtc_write(0, RTC_HUNDREDTH_SECOND); - - rtc_write(save_control, RTC_CMD); - spin_unlock_irqrestore(&ds1286_lock, flags); - - return 0; -} - -static void ds1286_get_alm_time(struct rtc_time *alm_tm) -{ - unsigned char cmd; - unsigned long flags; - - /* - * Only the values that we read from the RTC are set. That - * means only tm_wday, tm_hour, tm_min. - */ - spin_lock_irqsave(&ds1286_lock, flags); - alm_tm->tm_min = rtc_read(RTC_MINUTES_ALARM) & 0x7f; - alm_tm->tm_hour = rtc_read(RTC_HOURS_ALARM) & 0x1f; - alm_tm->tm_wday = rtc_read(RTC_DAY_ALARM) & 0x07; - cmd = rtc_read(RTC_CMD); - spin_unlock_irqrestore(&ds1286_lock, flags); - - alm_tm->tm_min = bcd2bin(alm_tm->tm_min); - alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour); - alm_tm->tm_sec = 0; -} - -module_init(ds1286_init); -module_exit(ds1286_exit); - -MODULE_AUTHOR("Ralf Baechle"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(RTC_MINOR); -- cgit v1.2.3 From 09d9327b3420002c9952a81db37effec9dc1135e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 27 Oct 2008 13:10:29 +0000 Subject: CHAR: Delete old and now unused M48T35 RTC driver for SGI IP27. It was only used by this one SGI platform which recently was converted to RTC_LIB and with RTC_LIB enabled the legacy drivers are no more selectable. Signed-off-by: Ralf Baechle --- drivers/char/Kconfig | 11 -- drivers/char/Makefile | 1 - drivers/char/ip27-rtc.c | 329 ------------------------------------------------ 3 files changed, 341 deletions(-) delete mode 100644 drivers/char/ip27-rtc.c (limited to 'drivers') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 9d2c4364550..43b35d0369d 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -812,17 +812,6 @@ config JS_RTC To compile this driver as a module, choose M here: the module will be called js-rtc. -config SGI_IP27_RTC - bool "SGI M48T35 RTC support" - depends on SGI_IP27 - help - If you say Y here and create a character special file /dev/rtc with - major number 10 and minor number 135 using mknod ("man mknod"), you - will get access to the real time clock built into your computer. - Every SGI has such a clock built in. It reports status information - via the file /proc/rtc and its behaviour is set by various ioctls on - /dev/rtc. - config GEN_RTC tristate "Generic /dev/rtc emulation" depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32 diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 917f0f4faf7..438f71317c5 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -74,7 +74,6 @@ obj-$(CONFIG_RTC) += rtc.o obj-$(CONFIG_HPET) += hpet.o obj-$(CONFIG_GEN_RTC) += genrtc.o obj-$(CONFIG_EFI_RTC) += efirtc.o -obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o obj-$(CONFIG_DS1302) += ds1302.o obj-$(CONFIG_XILINX_HWICAP) += xilinx_hwicap/ ifeq ($(CONFIG_GENERIC_NVRAM),y) diff --git a/drivers/char/ip27-rtc.c b/drivers/char/ip27-rtc.c deleted file mode 100644 index 2abd881b4cb..00000000000 --- a/drivers/char/ip27-rtc.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Driver for the SGS-Thomson M48T35 Timekeeper RAM chip - * - * Real Time Clock interface for Linux - * - * TODO: Implement periodic interrupts. - * - * Copyright (C) 2000 Silicon Graphics, Inc. - * Written by Ulf Carlsson (ulfc@engr.sgi.com) - * - * Based on code written by Paul Gortmaker. - * - * This driver allows use of the real time clock (built into - * nearly all computers) from user space. It exports the /dev/rtc - * interface supporting various ioctl() and also the /proc/rtc - * pseudo-file for status information. - * - * 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. - * - */ - -#define RTC_VERSION "1.09b" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static long rtc_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg); - -static int rtc_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data); - -static void get_rtc_time(struct rtc_time *rtc_tm); - -/* - * Bits in rtc_status. (6 bits of room for future expansion) - */ - -#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ -#define RTC_TIMER_ON 0x02 /* missed irq timer active */ - -static unsigned char rtc_status; /* bitmapped status byte. */ -static unsigned long rtc_freq; /* Current periodic IRQ rate */ -static struct m48t35_rtc *rtc; - -/* - * If this driver ever becomes modularised, it will be really nice - * to make the epoch retain its value across module reload... - */ - -static unsigned long epoch = 1970; /* year corresponding to 0x00 */ - -static const unsigned char days_in_mo[] = -{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - -static long rtc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - - struct rtc_time wtime; - - switch (cmd) { - case RTC_RD_TIME: /* Read the time/date from RTC */ - { - get_rtc_time(&wtime); - break; - } - case RTC_SET_TIME: /* Set the RTC */ - { - struct rtc_time rtc_tm; - unsigned char mon, day, hrs, min, sec, leap_yr; - unsigned int yrs; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, - sizeof(struct rtc_time))) - return -EFAULT; - - yrs = rtc_tm.tm_year + 1900; - mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ - day = rtc_tm.tm_mday; - hrs = rtc_tm.tm_hour; - min = rtc_tm.tm_min; - sec = rtc_tm.tm_sec; - - if (yrs < 1970) - return -EINVAL; - - leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); - - if ((mon > 12) || (day == 0)) - return -EINVAL; - - if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) - return -EINVAL; - - if ((hrs >= 24) || (min >= 60) || (sec >= 60)) - return -EINVAL; - - if ((yrs -= epoch) > 255) /* They are unsigned */ - return -EINVAL; - - if (yrs > 169) - return -EINVAL; - - if (yrs >= 100) - yrs -= 100; - - sec = bin2bcd(sec); - min = bin2bcd(min); - hrs = bin2bcd(hrs); - day = bin2bcd(day); - mon = bin2bcd(mon); - yrs = bin2bcd(yrs); - - spin_lock_irq(&rtc_lock); - rtc->control |= M48T35_RTC_SET; - rtc->year = yrs; - rtc->month = mon; - rtc->date = day; - rtc->hour = hrs; - rtc->min = min; - rtc->sec = sec; - rtc->control &= ~M48T35_RTC_SET; - spin_unlock_irq(&rtc_lock); - - return 0; - } - default: - return -EINVAL; - } - return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; -} - -/* - * We enforce only one user at a time here with the open/close. - * Also clear the previous interrupt data on an open, and clean - * up things on a close. - */ - -static int rtc_open(struct inode *inode, struct file *file) -{ - lock_kernel(); - spin_lock_irq(&rtc_lock); - - if (rtc_status & RTC_IS_OPEN) { - spin_unlock_irq(&rtc_lock); - unlock_kernel(); - return -EBUSY; - } - - rtc_status |= RTC_IS_OPEN; - spin_unlock_irq(&rtc_lock); - unlock_kernel(); - - return 0; -} - -static int rtc_release(struct inode *inode, struct file *file) -{ - /* - * Turn off all interrupts once the device is no longer - * in use, and clear the data. - */ - - spin_lock_irq(&rtc_lock); - rtc_status &= ~RTC_IS_OPEN; - spin_unlock_irq(&rtc_lock); - - return 0; -} - -/* - * The various file operations we support. - */ - -static const struct file_operations rtc_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = rtc_ioctl, - .open = rtc_open, - .release = rtc_release, -}; - -static struct miscdevice rtc_dev= -{ - RTC_MINOR, - "rtc", - &rtc_fops -}; - -static int __init rtc_init(void) -{ - rtc = (struct m48t35_rtc *) - (KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base + IOC3_BYTEBUS_DEV0); - - printk(KERN_INFO "Real Time Clock Driver v%s\n", RTC_VERSION); - if (misc_register(&rtc_dev)) { - printk(KERN_ERR "rtc: cannot register misc device.\n"); - return -ENODEV; - } - if (!create_proc_read_entry("driver/rtc", 0, NULL, rtc_read_proc, NULL)) { - printk(KERN_ERR "rtc: cannot create /proc/rtc.\n"); - misc_deregister(&rtc_dev); - return -ENOENT; - } - - rtc_freq = 1024; - - return 0; -} - -static void __exit rtc_exit (void) -{ - /* interrupts and timer disabled at this point by rtc_release */ - - remove_proc_entry ("rtc", NULL); - misc_deregister(&rtc_dev); -} - -module_init(rtc_init); -module_exit(rtc_exit); - -/* - * Info exported via "/proc/rtc". - */ - -static int rtc_get_status(char *buf) -{ - char *p; - struct rtc_time tm; - - /* - * Just emulate the standard /proc/rtc - */ - - p = buf; - - get_rtc_time(&tm); - - /* - * There is no way to tell if the luser has the RTC set for local - * time or for Universal Standard Time (GMT). Probably local though. - */ - p += sprintf(p, - "rtc_time\t: %02d:%02d:%02d\n" - "rtc_date\t: %04d-%02d-%02d\n" - "rtc_epoch\t: %04lu\n" - "24hr\t\t: yes\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch); - - return p - buf; -} - -static int rtc_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = rtc_get_status(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; -} - -static void get_rtc_time(struct rtc_time *rtc_tm) -{ - /* - * Do we need to wait for the last update to finish? - */ - - /* - * Only the values that we read from the RTC are set. We leave - * tm_wday, tm_yday and tm_isdst untouched. Even though the - * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated - * by the RTC when initially set to a non-zero value. - */ - spin_lock_irq(&rtc_lock); - rtc->control |= M48T35_RTC_READ; - rtc_tm->tm_sec = rtc->sec; - rtc_tm->tm_min = rtc->min; - rtc_tm->tm_hour = rtc->hour; - rtc_tm->tm_mday = rtc->date; - rtc_tm->tm_mon = rtc->month; - rtc_tm->tm_year = rtc->year; - rtc->control &= ~M48T35_RTC_READ; - spin_unlock_irq(&rtc_lock); - - rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec); - rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min); - rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour); - rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday); - rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon); - rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year); - - /* - * Account for differences between how the RTC uses the values - * and how they are defined in a struct rtc_time; - */ - if ((rtc_tm->tm_year += (epoch - 1900)) <= 69) - rtc_tm->tm_year += 100; - - rtc_tm->tm_mon--; -} -- cgit v1.2.3 From 4a029abee0f1d69cb0445657d6fa5a38597bd17d Mon Sep 17 00:00:00 2001 From: Lennart Sorensen Date: Thu, 30 Oct 2008 15:55:47 +0100 Subject: scx200_i2c: Add missing class parameter The scx200_i2c driver is missing the .class parameter, which means no i2c drivers are willing to probe for devices on the bus and attach to them. Signed-off-by: Len Sorensen Signed-off-by: Jean Delvare --- drivers/i2c/busses/scx200_i2c.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c index c3022a02344..e4c98539c51 100644 --- a/drivers/i2c/busses/scx200_i2c.c +++ b/drivers/i2c/busses/scx200_i2c.c @@ -81,6 +81,7 @@ static struct i2c_algo_bit_data scx200_i2c_data = { static struct i2c_adapter scx200_i2c_ops = { .owner = THIS_MODULE, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .id = I2C_HW_B_SCX200, .algo_data = &scx200_i2c_data, .name = "NatSemi SCx200 I2C", -- cgit v1.2.3 From da6801e38b7fba28fbdc0ceae6681d5a261a42a6 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 30 Oct 2008 15:55:47 +0100 Subject: i2c-s3c2410: Correct use of ! and & In commit e6bafba5b4765a5a252f1b8d31cbf6d2459da337, a bug was fixed that involved converting !x & y to !(x & y). The code below shows the same pattern, and thus should perhaps be fixed in the same way. In particular, the result of !readl(i2c->regs + S3C2410_IICCON) & S3C2410_IICCON_IRQEN is always 0. The semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @@ expression E; constant C; @@ ( !E & !C | - !E & C + !(E & C) ) // Signed-off-by: Julia Lawall Cc: Ben Dooks Signed-off-by: Andrew Morton Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-s3c2410.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index c772e02c280..1fac4e23313 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -507,7 +507,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int unsigned long timeout; int ret; - if (!readl(i2c->regs + S3C2410_IICCON) & S3C2410_IICCON_IRQEN) + if (!(readl(i2c->regs + S3C2410_IICCON) & S3C2410_IICCON_IRQEN)) return -EIO; ret = s3c24xx_i2c_set_master(i2c); -- cgit v1.2.3 From 1841c0f2bf6835aa3d18216e3a932371efa902f0 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Tue, 28 Oct 2008 11:03:48 +0000 Subject: regulator: da903x regulator bug fix Changes the device registration part of the probe function to supply the regulator device rather than its parent (the mfd device) as this caused problems when the regulator core attempted to find constraints associated with the regulators. Signed-off-by: Jonathan Cameron Acked-by: Eric Miao Signed-off-by: Liam Girdwood --- drivers/regulator/da903x.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index 3688e339db8..773b29cec8b 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -79,6 +79,11 @@ struct da903x_regulator_info { int enable_bit; }; +static inline struct device *to_da903x_dev(struct regulator_dev *rdev) +{ + return rdev_get_dev(rdev)->parent->parent; +} + static inline int check_range(struct da903x_regulator_info *info, int min_uV, int max_uV) { @@ -93,7 +98,7 @@ static int da903x_set_ldo_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - struct device *da9034_dev = rdev_get_dev(rdev)->parent; + struct device *da9034_dev = to_da903x_dev(rdev); uint8_t val, mask; if (check_range(info, min_uV, max_uV)) { @@ -111,7 +116,7 @@ static int da903x_set_ldo_voltage(struct regulator_dev *rdev, static int da903x_get_voltage(struct regulator_dev *rdev) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - struct device *da9034_dev = rdev_get_dev(rdev)->parent; + struct device *da9034_dev = to_da903x_dev(rdev); uint8_t val, mask; int ret; @@ -128,7 +133,7 @@ static int da903x_get_voltage(struct regulator_dev *rdev) static int da903x_enable(struct regulator_dev *rdev) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - struct device *da9034_dev = rdev_get_dev(rdev)->parent; + struct device *da9034_dev = to_da903x_dev(rdev); return da903x_set_bits(da9034_dev, info->enable_reg, 1 << info->enable_bit); @@ -137,7 +142,7 @@ static int da903x_enable(struct regulator_dev *rdev) static int da903x_disable(struct regulator_dev *rdev) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - struct device *da9034_dev = rdev_get_dev(rdev)->parent; + struct device *da9034_dev = to_da903x_dev(rdev); return da903x_clr_bits(da9034_dev, info->enable_reg, 1 << info->enable_bit); @@ -146,7 +151,7 @@ static int da903x_disable(struct regulator_dev *rdev) static int da903x_is_enabled(struct regulator_dev *rdev) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - struct device *da9034_dev = rdev_get_dev(rdev)->parent; + struct device *da9034_dev = to_da903x_dev(rdev); uint8_t reg_val; int ret; @@ -162,7 +167,7 @@ static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - struct device *da903x_dev = rdev_get_dev(rdev)->parent; + struct device *da903x_dev = to_da903x_dev(rdev); uint8_t val, mask; int ret; @@ -189,7 +194,7 @@ static int da9030_set_ldo14_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - struct device *da903x_dev = rdev_get_dev(rdev)->parent; + struct device *da903x_dev = to_da903x_dev(rdev); uint8_t val, mask; int thresh; @@ -215,7 +220,7 @@ static int da9030_set_ldo14_voltage(struct regulator_dev *rdev, static int da9030_get_ldo14_voltage(struct regulator_dev *rdev) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - struct device *da903x_dev = rdev_get_dev(rdev)->parent; + struct device *da903x_dev = to_da903x_dev(rdev); uint8_t val, mask; int ret; @@ -238,7 +243,7 @@ static int da9034_set_dvc_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - struct device *da9034_dev = rdev_get_dev(rdev)->parent; + struct device *da9034_dev = to_da903x_dev(rdev); uint8_t val, mask; int ret; @@ -264,7 +269,7 @@ static int da9034_set_ldo12_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - struct device *da9034_dev = rdev_get_dev(rdev)->parent; + struct device *da9034_dev = to_da903x_dev(rdev); uint8_t val, mask; if (check_range(info, min_uV, max_uV)) { @@ -283,7 +288,7 @@ static int da9034_set_ldo12_voltage(struct regulator_dev *rdev, static int da9034_get_ldo12_voltage(struct regulator_dev *rdev) { struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - struct device *da9034_dev = rdev_get_dev(rdev)->parent; + struct device *da9034_dev = to_da903x_dev(rdev); uint8_t val, mask; int ret; @@ -466,7 +471,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev) if (ri->desc.id == DA9030_ID_LDO1 || ri->desc.id == DA9030_ID_LDO15) ri->desc.ops = &da9030_regulator_ldo1_15_ops; - rdev = regulator_register(&ri->desc, pdev->dev.parent, ri); + rdev = regulator_register(&ri->desc, &pdev->dev, ri); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", ri->desc.name); -- cgit v1.2.3 From 75b7edfdc12c213402b17a62e5cfe7a802a4ab57 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Wed, 29 Oct 2008 14:00:49 -0700 Subject: viafb: removed duplicated #include's Removed duplicated #include's in drivers/video/via/global.h. debug.h viafbdev.h viamode.h Signed-off-by: Huang Weiyi Cc: Joseph Chan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/via/global.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h index 8e5263c5b81..7543d5f7e30 100644 --- a/drivers/video/via/global.h +++ b/drivers/video/via/global.h @@ -38,7 +38,6 @@ #include "iface.h" #include "viafbdev.h" #include "chip.h" -#include "debug.h" #include "accel.h" #include "share.h" #include "dvi.h" @@ -48,12 +47,10 @@ #include "lcd.h" #include "ioctl.h" -#include "viamode.h" #include "via_utility.h" #include "vt1636.h" #include "tblDPASetting.h" #include "tbl1636.h" -#include "viafbdev.h" /* External struct*/ -- cgit v1.2.3 From df8bc08c192f00f155185bfd6f052d46a728814a Mon Sep 17 00:00:00 2001 From: Hitoshi Mitake Date: Wed, 29 Oct 2008 14:00:50 -0700 Subject: edac x38: new MC driver module I wrote a new module for Intel X38 chipset. This chipset is very similar to Intel 3200 chipset, but there are some different points, so I copyed i3200_edac.c and modified. This is Intel's web page describing this chipset. http://www.intel.com/Products/Desktop/Chipsets/X38/X38-overview.htm I've tested this new module with broken memory, and it seems to be working well. Signed-off-by: Hitoshi Mitake Signed-off-by: Doug Thompson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/Kconfig | 7 + drivers/edac/Makefile | 1 + drivers/edac/x38_edac.c | 524 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 532 insertions(+) create mode 100644 drivers/edac/x38_edac.c (limited to 'drivers') diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 5a11e3cbcae..e0dbd388757 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -102,6 +102,13 @@ config EDAC_I3000 Support for error detection and correction on the Intel 3000 and 3010 server chipsets. +config EDAC_X38 + tristate "Intel X38" + depends on EDAC_MM_EDAC && PCI && X86 + help + Support for error detection and correction on the Intel + X38 server chipsets. + config EDAC_I82860 tristate "Intel 82860" depends on EDAC_MM_EDAC && PCI && X86_32 diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index e5e9104b552..62c2d9bad8d 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_EDAC_I82443BXGX) += i82443bxgx_edac.o obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o obj-$(CONFIG_EDAC_I82975X) += i82975x_edac.o obj-$(CONFIG_EDAC_I3000) += i3000_edac.o +obj-$(CONFIG_EDAC_X38) += x38_edac.o obj-$(CONFIG_EDAC_I82860) += i82860_edac.o obj-$(CONFIG_EDAC_R82600) += r82600_edac.o obj-$(CONFIG_EDAC_PASEMI) += pasemi_edac.o diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c new file mode 100644 index 00000000000..2406c2ce284 --- /dev/null +++ b/drivers/edac/x38_edac.c @@ -0,0 +1,524 @@ +/* + * Intel X38 Memory Controller kernel module + * Copyright (C) 2008 Cluster Computing, Inc. + * + * This file may be distributed under the terms of the + * GNU General Public License. + * + * This file is based on i3200_edac.c + * + */ + +#include +#include +#include +#include +#include +#include +#include "edac_core.h" + +#define X38_REVISION "1.1" + +#define EDAC_MOD_STR "x38_edac" + +#define PCI_DEVICE_ID_INTEL_X38_HB 0x29e0 + +#define X38_RANKS 8 +#define X38_RANKS_PER_CHANNEL 4 +#define X38_CHANNELS 2 + +/* Intel X38 register addresses - device 0 function 0 - DRAM Controller */ + +#define X38_MCHBAR_LOW 0x48 /* MCH Memory Mapped Register BAR */ +#define X38_MCHBAR_HIGH 0x4b +#define X38_MCHBAR_MASK 0xfffffc000ULL /* bits 35:14 */ +#define X38_MMR_WINDOW_SIZE 16384 + +#define X38_TOM 0xa0 /* Top of Memory (16b) + * + * 15:10 reserved + * 9:0 total populated physical memory + */ +#define X38_TOM_MASK 0x3ff /* bits 9:0 */ +#define X38_TOM_SHIFT 26 /* 64MiB grain */ + +#define X38_ERRSTS 0xc8 /* Error Status Register (16b) + * + * 15 reserved + * 14 Isochronous TBWRR Run Behind FIFO Full + * (ITCV) + * 13 Isochronous TBWRR Run Behind FIFO Put + * (ITSTV) + * 12 reserved + * 11 MCH Thermal Sensor Event + * for SMI/SCI/SERR (GTSE) + * 10 reserved + * 9 LOCK to non-DRAM Memory Flag (LCKF) + * 8 reserved + * 7 DRAM Throttle Flag (DTF) + * 6:2 reserved + * 1 Multi-bit DRAM ECC Error Flag (DMERR) + * 0 Single-bit DRAM ECC Error Flag (DSERR) + */ +#define X38_ERRSTS_UE 0x0002 +#define X38_ERRSTS_CE 0x0001 +#define X38_ERRSTS_BITS (X38_ERRSTS_UE | X38_ERRSTS_CE) + + +/* Intel MMIO register space - device 0 function 0 - MMR space */ + +#define X38_C0DRB 0x200 /* Channel 0 DRAM Rank Boundary (16b x 4) + * + * 15:10 reserved + * 9:0 Channel 0 DRAM Rank Boundary Address + */ +#define X38_C1DRB 0x600 /* Channel 1 DRAM Rank Boundary (16b x 4) */ +#define X38_DRB_MASK 0x3ff /* bits 9:0 */ +#define X38_DRB_SHIFT 26 /* 64MiB grain */ + +#define X38_C0ECCERRLOG 0x280 /* Channel 0 ECC Error Log (64b) + * + * 63:48 Error Column Address (ERRCOL) + * 47:32 Error Row Address (ERRROW) + * 31:29 Error Bank Address (ERRBANK) + * 28:27 Error Rank Address (ERRRANK) + * 26:24 reserved + * 23:16 Error Syndrome (ERRSYND) + * 15: 2 reserved + * 1 Multiple Bit Error Status (MERRSTS) + * 0 Correctable Error Status (CERRSTS) + */ +#define X38_C1ECCERRLOG 0x680 /* Channel 1 ECC Error Log (64b) */ +#define X38_ECCERRLOG_CE 0x1 +#define X38_ECCERRLOG_UE 0x2 +#define X38_ECCERRLOG_RANK_BITS 0x18000000 +#define X38_ECCERRLOG_SYNDROME_BITS 0xff0000 + +#define X38_CAPID0 0xe0 /* see P.94 of spec for details */ + +static int x38_channel_num; + +static int how_many_channel(struct pci_dev *pdev) +{ + unsigned char capid0_8b; /* 8th byte of CAPID0 */ + + pci_read_config_byte(pdev, X38_CAPID0 + 8, &capid0_8b); + if (capid0_8b & 0x20) { /* check DCD: Dual Channel Disable */ + debugf0("In single channel mode.\n"); + x38_channel_num = 1; + } else { + debugf0("In dual channel mode.\n"); + x38_channel_num = 2; + } + + return x38_channel_num; +} + +static unsigned long eccerrlog_syndrome(u64 log) +{ + return (log & X38_ECCERRLOG_SYNDROME_BITS) >> 16; +} + +static int eccerrlog_row(int channel, u64 log) +{ + return ((log & X38_ECCERRLOG_RANK_BITS) >> 27) | + (channel * X38_RANKS_PER_CHANNEL); +} + +enum x38_chips { + X38 = 0, +}; + +struct x38_dev_info { + const char *ctl_name; +}; + +struct x38_error_info { + u16 errsts; + u16 errsts2; + u64 eccerrlog[X38_CHANNELS]; +}; + +static const struct x38_dev_info x38_devs[] = { + [X38] = { + .ctl_name = "x38"}, +}; + +static struct pci_dev *mci_pdev; +static int x38_registered = 1; + + +static void x38_clear_error_info(struct mem_ctl_info *mci) +{ + struct pci_dev *pdev; + + pdev = to_pci_dev(mci->dev); + + /* + * Clear any error bits. + * (Yes, we really clear bits by writing 1 to them.) + */ + pci_write_bits16(pdev, X38_ERRSTS, X38_ERRSTS_BITS, + X38_ERRSTS_BITS); +} + +static u64 x38_readq(const void __iomem *addr) +{ + return readl(addr) | (((u64)readl(addr + 4)) << 32); +} + +static void x38_get_and_clear_error_info(struct mem_ctl_info *mci, + struct x38_error_info *info) +{ + struct pci_dev *pdev; + void __iomem *window = mci->pvt_info; + + pdev = to_pci_dev(mci->dev); + + /* + * This is a mess because there is no atomic way to read all the + * registers at once and the registers can transition from CE being + * overwritten by UE. + */ + pci_read_config_word(pdev, X38_ERRSTS, &info->errsts); + if (!(info->errsts & X38_ERRSTS_BITS)) + return; + + info->eccerrlog[0] = x38_readq(window + X38_C0ECCERRLOG); + if (x38_channel_num == 2) + info->eccerrlog[1] = x38_readq(window + X38_C1ECCERRLOG); + + pci_read_config_word(pdev, X38_ERRSTS, &info->errsts2); + + /* + * If the error is the same for both reads then the first set + * of reads is valid. If there is a change then there is a CE + * with no info and the second set of reads is valid and + * should be UE info. + */ + if ((info->errsts ^ info->errsts2) & X38_ERRSTS_BITS) { + info->eccerrlog[0] = x38_readq(window + X38_C0ECCERRLOG); + if (x38_channel_num == 2) + info->eccerrlog[1] = + x38_readq(window + X38_C1ECCERRLOG); + } + + x38_clear_error_info(mci); +} + +static void x38_process_error_info(struct mem_ctl_info *mci, + struct x38_error_info *info) +{ + int channel; + u64 log; + + if (!(info->errsts & X38_ERRSTS_BITS)) + return; + + if ((info->errsts ^ info->errsts2) & X38_ERRSTS_BITS) { + edac_mc_handle_ce_no_info(mci, "UE overwrote CE"); + info->errsts = info->errsts2; + } + + for (channel = 0; channel < x38_channel_num; channel++) { + log = info->eccerrlog[channel]; + if (log & X38_ECCERRLOG_UE) { + edac_mc_handle_ue(mci, 0, 0, + eccerrlog_row(channel, log), "x38 UE"); + } else if (log & X38_ECCERRLOG_CE) { + edac_mc_handle_ce(mci, 0, 0, + eccerrlog_syndrome(log), + eccerrlog_row(channel, log), 0, "x38 CE"); + } + } +} + +static void x38_check(struct mem_ctl_info *mci) +{ + struct x38_error_info info; + + debugf1("MC%d: %s()\n", mci->mc_idx, __func__); + x38_get_and_clear_error_info(mci, &info); + x38_process_error_info(mci, &info); +} + + +void __iomem *x38_map_mchbar(struct pci_dev *pdev) +{ + union { + u64 mchbar; + struct { + u32 mchbar_low; + u32 mchbar_high; + }; + } u; + void __iomem *window; + + pci_read_config_dword(pdev, X38_MCHBAR_LOW, &u.mchbar_low); + pci_write_config_dword(pdev, X38_MCHBAR_LOW, u.mchbar_low | 0x1); + pci_read_config_dword(pdev, X38_MCHBAR_HIGH, &u.mchbar_high); + u.mchbar &= X38_MCHBAR_MASK; + + if (u.mchbar != (resource_size_t)u.mchbar) { + printk(KERN_ERR + "x38: mmio space beyond accessible range (0x%llx)\n", + (unsigned long long)u.mchbar); + return NULL; + } + + window = ioremap_nocache(u.mchbar, X38_MMR_WINDOW_SIZE); + if (!window) + printk(KERN_ERR "x38: cannot map mmio space at 0x%llx\n", + (unsigned long long)u.mchbar); + + return window; +} + + +static void x38_get_drbs(void __iomem *window, + u16 drbs[X38_CHANNELS][X38_RANKS_PER_CHANNEL]) +{ + int i; + + for (i = 0; i < X38_RANKS_PER_CHANNEL; i++) { + drbs[0][i] = readw(window + X38_C0DRB + 2*i) & X38_DRB_MASK; + drbs[1][i] = readw(window + X38_C1DRB + 2*i) & X38_DRB_MASK; + } +} + +static bool x38_is_stacked(struct pci_dev *pdev, + u16 drbs[X38_CHANNELS][X38_RANKS_PER_CHANNEL]) +{ + u16 tom; + + pci_read_config_word(pdev, X38_TOM, &tom); + tom &= X38_TOM_MASK; + + return drbs[X38_CHANNELS - 1][X38_RANKS_PER_CHANNEL - 1] == tom; +} + +static unsigned long drb_to_nr_pages( + u16 drbs[X38_CHANNELS][X38_RANKS_PER_CHANNEL], + bool stacked, int channel, int rank) +{ + int n; + + n = drbs[channel][rank]; + if (rank > 0) + n -= drbs[channel][rank - 1]; + if (stacked && (channel == 1) && drbs[channel][rank] == + drbs[channel][X38_RANKS_PER_CHANNEL - 1]) { + n -= drbs[0][X38_RANKS_PER_CHANNEL - 1]; + } + + n <<= (X38_DRB_SHIFT - PAGE_SHIFT); + return n; +} + +static int x38_probe1(struct pci_dev *pdev, int dev_idx) +{ + int rc; + int i; + struct mem_ctl_info *mci = NULL; + unsigned long last_page; + u16 drbs[X38_CHANNELS][X38_RANKS_PER_CHANNEL]; + bool stacked; + void __iomem *window; + + debugf0("MC: %s()\n", __func__); + + window = x38_map_mchbar(pdev); + if (!window) + return -ENODEV; + + x38_get_drbs(window, drbs); + + how_many_channel(pdev); + + /* FIXME: unconventional pvt_info usage */ + mci = edac_mc_alloc(0, X38_RANKS, x38_channel_num, 0); + if (!mci) + return -ENOMEM; + + debugf3("MC: %s(): init mci\n", __func__); + + mci->dev = &pdev->dev; + mci->mtype_cap = MEM_FLAG_DDR2; + + mci->edac_ctl_cap = EDAC_FLAG_SECDED; + mci->edac_cap = EDAC_FLAG_SECDED; + + mci->mod_name = EDAC_MOD_STR; + mci->mod_ver = X38_REVISION; + mci->ctl_name = x38_devs[dev_idx].ctl_name; + mci->dev_name = pci_name(pdev); + mci->edac_check = x38_check; + mci->ctl_page_to_phys = NULL; + mci->pvt_info = window; + + stacked = x38_is_stacked(pdev, drbs); + + /* + * The dram rank boundary (DRB) reg values are boundary addresses + * for each DRAM rank with a granularity of 64MB. DRB regs are + * cumulative; the last one will contain the total memory + * contained in all ranks. + */ + last_page = -1UL; + for (i = 0; i < mci->nr_csrows; i++) { + unsigned long nr_pages; + struct csrow_info *csrow = &mci->csrows[i]; + + nr_pages = drb_to_nr_pages(drbs, stacked, + i / X38_RANKS_PER_CHANNEL, + i % X38_RANKS_PER_CHANNEL); + + if (nr_pages == 0) { + csrow->mtype = MEM_EMPTY; + continue; + } + + csrow->first_page = last_page + 1; + last_page += nr_pages; + csrow->last_page = last_page; + csrow->nr_pages = nr_pages; + + csrow->grain = nr_pages << PAGE_SHIFT; + csrow->mtype = MEM_DDR2; + csrow->dtype = DEV_UNKNOWN; + csrow->edac_mode = EDAC_UNKNOWN; + } + + x38_clear_error_info(mci); + + rc = -ENODEV; + if (edac_mc_add_mc(mci)) { + debugf3("MC: %s(): failed edac_mc_add_mc()\n", __func__); + goto fail; + } + + /* get this far and it's successful */ + debugf3("MC: %s(): success\n", __func__); + return 0; + +fail: + iounmap(window); + if (mci) + edac_mc_free(mci); + + return rc; +} + +static int __devinit x38_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int rc; + + debugf0("MC: %s()\n", __func__); + + if (pci_enable_device(pdev) < 0) + return -EIO; + + rc = x38_probe1(pdev, ent->driver_data); + if (!mci_pdev) + mci_pdev = pci_dev_get(pdev); + + return rc; +} + +static void __devexit x38_remove_one(struct pci_dev *pdev) +{ + struct mem_ctl_info *mci; + + debugf0("%s()\n", __func__); + + mci = edac_mc_del_mc(&pdev->dev); + if (!mci) + return; + + iounmap(mci->pvt_info); + + edac_mc_free(mci); +} + +static const struct pci_device_id x38_pci_tbl[] __devinitdata = { + { + PCI_VEND_DEV(INTEL, X38_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + X38}, + { + 0, + } /* 0 terminated list. */ +}; + +MODULE_DEVICE_TABLE(pci, x38_pci_tbl); + +static struct pci_driver x38_driver = { + .name = EDAC_MOD_STR, + .probe = x38_init_one, + .remove = __devexit_p(x38_remove_one), + .id_table = x38_pci_tbl, +}; + +static int __init x38_init(void) +{ + int pci_rc; + + debugf3("MC: %s()\n", __func__); + + /* Ensure that the OPSTATE is set correctly for POLL or NMI */ + opstate_init(); + + pci_rc = pci_register_driver(&x38_driver); + if (pci_rc < 0) + goto fail0; + + if (!mci_pdev) { + x38_registered = 0; + mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_X38_HB, NULL); + if (!mci_pdev) { + debugf0("x38 pci_get_device fail\n"); + pci_rc = -ENODEV; + goto fail1; + } + + pci_rc = x38_init_one(mci_pdev, x38_pci_tbl); + if (pci_rc < 0) { + debugf0("x38 init fail\n"); + pci_rc = -ENODEV; + goto fail1; + } + } + + return 0; + +fail1: + pci_unregister_driver(&x38_driver); + +fail0: + if (mci_pdev) + pci_dev_put(mci_pdev); + + return pci_rc; +} + +static void __exit x38_exit(void) +{ + debugf3("MC: %s()\n", __func__); + + pci_unregister_driver(&x38_driver); + if (!x38_registered) { + x38_remove_one(mci_pdev); + pci_dev_put(mci_pdev); + } +} + +module_init(x38_init); +module_exit(x38_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Cluster Computing, Inc. Hitoshi Mitake"); +MODULE_DESCRIPTION("MC support for Intel X38 memory hub controllers"); + +module_param(edac_op_state, int, 0444); +MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); -- cgit v1.2.3 From 4e02ed4b4a2fae34aae766a5bb93ae235f60adb8 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 29 Oct 2008 14:00:55 -0700 Subject: fs: remove prepare_write/commit_write Nothing uses prepare_write or commit_write. Remove them from the tree completely. [akpm@linux-foundation.org: schedule simple_prepare_write() for unexporting] Signed-off-by: Nick Piggin Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/loop.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 3f09cd8bcc3..5c4ee70d5cf 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -40,8 +40,7 @@ * Heinz Mauelshagen , Feb 2002 * * Support for falling back on the write file operation when the address space - * operations prepare_write and/or commit_write are not available on the - * backing filesystem. + * operations write_begin is not available on the backing filesystem. * Anton Altaparmakov, 16 Feb 2005 * * Still To Fix: @@ -765,7 +764,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, */ if (!file->f_op->splice_read) goto out_putf; - if (aops->prepare_write || aops->write_begin) + if (aops->write_begin) lo_flags |= LO_FLAGS_USE_AOPS; if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write) lo_flags |= LO_FLAGS_READ_ONLY; -- cgit v1.2.3 From eb944db0cfeb0ee934e2a74d5b3516f80cf2c208 Mon Sep 17 00:00:00 2001 From: Yauhen Kharuzhy Date: Wed, 29 Oct 2008 14:00:59 -0700 Subject: rtc-s3c: fix section mismatch warnings Warnings was appeared when compile rtc-s3c.c because platform_driver structure s3c2410_rtcdrv has wrong name. Signed-off-by: Yauhen Kharuzhy Acked-by: Alessandro Zummo Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-s3c.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 910bc704939..340d03be820 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -507,7 +507,7 @@ static int s3c_rtc_resume(struct platform_device *pdev) #define s3c_rtc_resume NULL #endif -static struct platform_driver s3c2410_rtcdrv = { +static struct platform_driver s3c2410_rtc_driver = { .probe = s3c_rtc_probe, .remove = __devexit_p(s3c_rtc_remove), .suspend = s3c_rtc_suspend, @@ -523,12 +523,12 @@ static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics static int __init s3c_rtc_init(void) { printk(banner); - return platform_driver_register(&s3c2410_rtcdrv); + return platform_driver_register(&s3c2410_rtc_driver); } static void __exit s3c_rtc_exit(void) { - platform_driver_unregister(&s3c2410_rtcdrv); + platform_driver_unregister(&s3c2410_rtc_driver); } module_init(s3c_rtc_init); -- cgit v1.2.3 From 992b692dcf43612be805465ca4b76f434c715023 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 29 Oct 2008 14:01:00 -0700 Subject: edac: fix enabling of polling cell module The edac driver on cell turned out to be not enabled because of a missing op_state. This patch introduces it. Verified to work on top of Ben's next branch. Signed-off-by: Arnd Bergmann Signed-off-by: Jens Osterkamp Acked-by: Benjamin Herrenschmidt Signed-off-by: Doug Thompson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/cell_edac.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index 887072f5dc8..cd2e3b8087e 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c @@ -9,6 +9,7 @@ */ #undef DEBUG +#include #include #include #include @@ -164,6 +165,8 @@ static int __devinit cell_edac_probe(struct platform_device *pdev) if (regs == NULL) return -ENODEV; + edac_op_state = EDAC_OPSTATE_POLL; + /* Get channel population */ reg = in_be64(®s->mic_mnt_cfg); dev_dbg(&pdev->dev, "MIC_MNT_CFG = 0x%016lx\n", reg); -- cgit v1.2.3 From def1be2d727a1764205479b3e3e3ba16ffbad028 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Wed, 29 Oct 2008 14:01:01 -0700 Subject: fbcon: don't inline updatescrollmode Updatescrollmode is marked inline, but it's big and is called only from non-critical codepaths (fbcon_resize, fbcon_switch, fbcon_modechanged). Dropping it saves almost 800 bytes of text size. text data bss dec hex filename 23859 287 8448 32594 7f52 drivers/video/console/fbcon.o.before 23065 287 8448 31800 7c38 drivers/video/console/fbcon.o.after Signed-off-by: Marcin Slusarz Cc: Antonino Daplas Cc: Krzysztof Helt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 64b3d30027b..b92947d62ad 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -2118,7 +2118,7 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s height, width); } -static __inline__ void updatescrollmode(struct display *p, +static void updatescrollmode(struct display *p, struct fb_info *info, struct vc_data *vc) { -- cgit v1.2.3 From 6158d3a2323835546c7cf83a170316fa77b726e0 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 29 Oct 2008 14:01:03 -0700 Subject: sony-laptop: ignore missing _DIS method on pic device At least the Vaio VGN-Z540N doesn't have this method, so let's not fail to suspend just because it doesn't exist. Signed-off-by: Adam Jackson Acked-by: Mattia Dongili Cc: Len Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/sony-laptop.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 5a97d3a9d74..f483c4221f7 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c @@ -2315,8 +2315,10 @@ end: */ static int sony_pic_disable(struct acpi_device *device) { - if (ACPI_FAILURE(acpi_evaluate_object(device->handle, - "_DIS", NULL, NULL))) + acpi_status ret = acpi_evaluate_object(device->handle, "_DIS", NULL, + NULL); + + if (ACPI_FAILURE(ret) && ret != AE_NOT_FOUND) return -ENXIO; dprintk("Device disabled\n"); -- cgit v1.2.3 From 99e87fd19a2dfba8ec0f2110f6f1b63062a52a6f Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 29 Oct 2008 14:01:05 -0700 Subject: hdpuftrs: fix build drivers/misc/hdpuftrs/hdpu_nexus.c:118: error: expected identifier or '(' before 'return' drivers/misc/hdpuftrs/hdpu_nexus.c:119: error: expected identifier or '(' before '}' token Signed-off-by: Mariusz Kozlowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/hdpuftrs/hdpu_nexus.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c index 08e26beefe6..ce39fa54949 100644 --- a/drivers/misc/hdpuftrs/hdpu_nexus.c +++ b/drivers/misc/hdpuftrs/hdpu_nexus.c @@ -113,7 +113,6 @@ static int hdpu_nexus_probe(struct platform_device *pdev) if (!hdpu_chassis_id) printk(KERN_WARNING "sky_nexus: " "Unable to create proc dir entry: sky_chassis_id\n"); - } return 0; } -- cgit v1.2.3 From b77b0ef207624c9d9f8064ccbfd6da169780df44 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 29 Oct 2008 14:01:09 -0700 Subject: i2o: fix kernel-doc warnings Fixup i2o kernel-doc warnings: Warning(linux-next-20081022//drivers/message/i2o/i2o_block.c:579): No description found for parameter 'bdev' Warning(linux-next-20081022//drivers/message/i2o/i2o_block.c:579): No description found for parameter 'mode' Warning(linux-next-20081022//drivers/message/i2o/i2o_block.c:608): No description found for parameter 'disk' Warning(linux-next-20081022//drivers/message/i2o/i2o_block.c:608): No description found for parameter 'mode' Warning(linux-next-20081022//drivers/message/i2o/i2o_block.c:657): No description found for parameter 'bdev' Warning(linux-next-20081022//drivers/message/i2o/i2o_block.c:657): No description found for parameter 'mode' Signed-off-by: Randy Dunlap Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/message/i2o/i2o_block.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 11a617ab424..84bdc2ee69e 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -567,8 +567,8 @@ static void i2o_block_biosparam(unsigned long capacity, unsigned short *cyls, /** * i2o_block_open - Open the block device - * @inode: inode for block device being opened - * @file: file to open + * @bdev: block device being opened + * @mode: file open mode * * Power up the device, mount and lock the media. This function is called, * if the block device is opened for access. @@ -596,8 +596,8 @@ static int i2o_block_open(struct block_device *bdev, fmode_t mode) /** * i2o_block_release - Release the I2O block device - * @inode: inode for block device being released - * @file: file to close + * @disk: gendisk device being released + * @mode: file open mode * * Unlock and unmount the media, and power down the device. Gets called if * the block device is closed. @@ -643,8 +643,8 @@ static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo) /** * i2o_block_ioctl - Issue device specific ioctl calls. - * @inode: inode for block device ioctl - * @file: file for ioctl + * @bdev: block device being opened + * @mode: file open mode * @cmd: ioctl command * @arg: arg * -- cgit v1.2.3 From b7f7b07479de2d91443b81938db1e1940c56b13c Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Wed, 29 Oct 2008 14:01:12 -0700 Subject: sgi-xp: only build for ia64-sn2 when CONFIG_IA64_GENERIC specified For the time being build for ia64-sn2 alone when CONFIG_IA64_GENERIC is specified. This eliminates a dependency of the XP/XPC drivers on having the GRU driver insmod'd in order to insmod them, when running on an ia64-sn2 system. On such a system the GRU driver serves no useful purpose. Signed-off-by: Dean Nelson Cc: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/sgi-xp/Makefile | 4 ++-- drivers/misc/sgi-xp/xp.h | 4 ++++ drivers/misc/sgi-xp/xpc_main.c | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/sgi-xp/Makefile b/drivers/misc/sgi-xp/Makefile index 35ce2857807..4fc40d8e1bc 100644 --- a/drivers/misc/sgi-xp/Makefile +++ b/drivers/misc/sgi-xp/Makefile @@ -5,14 +5,14 @@ obj-$(CONFIG_SGI_XP) += xp.o xp-y := xp_main.o xp-$(CONFIG_IA64_SGI_SN2) += xp_sn2.o xp_nofault.o -xp-$(CONFIG_IA64_GENERIC) += xp_sn2.o xp_nofault.o xp_uv.o +xp-$(CONFIG_IA64_GENERIC) += xp_sn2.o xp_nofault.o xp-$(CONFIG_IA64_SGI_UV) += xp_uv.o xp-$(CONFIG_X86_64) += xp_uv.o obj-$(CONFIG_SGI_XP) += xpc.o xpc-y := xpc_main.o xpc_channel.o xpc_partition.o xpc-$(CONFIG_IA64_SGI_SN2) += xpc_sn2.o -xpc-$(CONFIG_IA64_GENERIC) += xpc_sn2.o xpc_uv.o +xpc-$(CONFIG_IA64_GENERIC) += xpc_sn2.o xpc-$(CONFIG_IA64_SGI_UV) += xpc_uv.o xpc-$(CONFIG_X86_64) += xpc_uv.o diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h index 859a5281c61..ed1722e5004 100644 --- a/drivers/misc/sgi-xp/xp.h +++ b/drivers/misc/sgi-xp/xp.h @@ -19,7 +19,11 @@ #include #include /* defines is_shub1() and is_shub2() */ #define is_shub() ia64_platform_is("sn2") +#ifdef CONFIG_IA64_SGI_UV #define is_uv() ia64_platform_is("uv") +#else +#define is_uv() 0 +#endif #endif #ifdef CONFIG_X86_64 #include diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index 46325fc8481..e8d5cfbd32c 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c @@ -1104,7 +1104,7 @@ xpc_do_exit(enum xp_retval reason) if (is_shub()) xpc_exit_sn2(); - else + else if (is_uv()) xpc_exit_uv(); } @@ -1363,7 +1363,7 @@ out_2: out_1: if (is_shub()) xpc_exit_sn2(); - else + else if (is_uv()) xpc_exit_uv(); return ret; } -- cgit v1.2.3 From bcc378e777514832c11b09d194a7f946e7ad803a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 29 Oct 2008 14:01:13 -0700 Subject: rtc: ds3234 doesn't link when built-in When ds3234 is built-in, the final links fails with the following vague error message: `.exit.text' referenced in section `.data' of drivers/built-in.o: defined in discarded section `.exit.text' of drivers/built-in.o ds3234_remove() cannot be marked __exit, as it's accessed via __devexit_p(). In addition, mark ds3234_probe() __devinit while we're at it. Signed-off-by: Geert Uytterhoeven Acked-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-ds3234.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c index 37d131d03f3..45e5b106af7 100644 --- a/drivers/rtc/rtc-ds3234.c +++ b/drivers/rtc/rtc-ds3234.c @@ -189,7 +189,7 @@ static const struct rtc_class_ops ds3234_rtc_ops = { .set_time = ds3234_set_time, }; -static int ds3234_probe(struct spi_device *spi) +static int __devinit ds3234_probe(struct spi_device *spi) { struct rtc_device *rtc; unsigned char tmp; @@ -249,7 +249,7 @@ static int ds3234_probe(struct spi_device *spi) return 0; } -static int __exit ds3234_remove(struct spi_device *spi) +static int __devexit ds3234_remove(struct spi_device *spi) { struct ds3234 *chip = platform_get_drvdata(spi); struct rtc_device *rtc = chip->rtc; -- cgit v1.2.3 From 51b7616e36fbad93d7ba9e41f11fb57143d11252 Mon Sep 17 00:00:00 2001 From: Yauhen Kharuzhy Date: Wed, 29 Oct 2008 14:01:16 -0700 Subject: rtc S3C: add device_init_wakeup() invokation tAdd adds device_init_wakeup() ivokation to probe function of s3c2410_rtc_driver. Without of this wakealarm sysfs attribute does not initialise. Signed-off-by: Yauhen Kharuzhy Acked-by: Ben Dooks Acked-by: Alessandro Zummo Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-s3c.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 340d03be820..f59277bbeda 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -455,6 +455,8 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) s3c_rtc_setfreq(&pdev->dev, 1); + device_init_wakeup(&pdev->dev, 1); + /* register RTC and exit */ rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops, -- cgit v1.2.3 From 120a37470c2831fea49fdebaceb5a7039f700ce6 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Wed, 29 Oct 2008 14:01:17 -0700 Subject: framebuffer compat_ioctl deadlock Fix deadlock in fb_compat_ioctl. fb_compat_ioctl acquires a mutex and calls fb_ioctl that tries to acquire that mutex too. A regression added during BKL removal. Signed-off-by: Mikulas Patocka Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/fbmem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index cd5f20da738..6048b55f287 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1262,8 +1262,8 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case FBIOPUT_CON2FBMAP: arg = (unsigned long) compat_ptr(arg); case FBIOBLANK: - ret = fb_ioctl(file, cmd, arg); - break; + mutex_unlock(&info->lock); + return fb_ioctl(file, cmd, arg); case FBIOGET_FSCREENINFO: ret = fb_get_fscreeninfo(inode, file, cmd, arg); -- cgit v1.2.3 From 6c89161b10f5771ee0b51ada0fce0e8835e72ade Mon Sep 17 00:00:00 2001 From: Scott James Remnant Date: Wed, 29 Oct 2008 14:01:18 -0700 Subject: ipmi: add MODULE_ALIAS to load ipmi_devintf with ipmi_si The ipmi_devintf module contains the userspace interface for IPMI devices, yet will not be loaded automatically with a system interface handler driver. Add a MODULE_ALIAS for the "platform:ipmi_si" MODALIAS exported by the ipmi_si driver, so that userspace knows of the recommendation. Signed-off-by: Scott James Remnant Cc: Tim Gardner Cc: Corey Minyard Cc: [2.6.27.x, maybe earlier?] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_devintf.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 835a33c8d5f..1d7b429f7ff 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -957,3 +957,4 @@ module_exit(cleanup_ipmi); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Corey Minyard "); MODULE_DESCRIPTION("Linux device interface for the IPMI message handler."); +MODULE_ALIAS("platform:ipmi_si"); -- cgit v1.2.3 From fce4877a6792ad72b88f6fd7556d19da5f20364d Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 30 Oct 2008 15:54:12 +0000 Subject: tty: Fix USB kref leak When we close we must clear the extra reference we got when we read port->tty. Setting the port tty NULL will clear the kref held by the driver but not the one we obtained ourselves while doing the lookup. Signed-off-by: Alan Cox Tested-by: Helge Hafting Signed-off-by: Linus Torvalds --- drivers/usb/serial/usb-serial.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 8be3f39891c..794b5ffe439 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -281,6 +281,7 @@ static void serial_close(struct tty_struct *tty, struct file *filp) if (tty->driver_data) tty->driver_data = NULL; tty_port_tty_set(&port->port, NULL); + tty_kref_put(tty); } } -- cgit v1.2.3 From fba4acda35f3119328bcba28aacefae14245d2bb Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Thu, 30 Oct 2008 17:41:14 -0700 Subject: bonding: fix miimon failure counter During the rework of the mii monitor for: commit f0c76d61779b153dbfb955db3f144c62d02173c2 Author: Jay Vosburgh Date: Wed Jul 2 18:21:58 2008 -0700 bonding: refactor mii monitor I left out the increment of the link failure counter. This patch corrects that omission. Signed-off-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 832739f38db..85de1d04d1e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2376,6 +2376,9 @@ static void bond_miimon_commit(struct bonding *bond) continue; case BOND_LINK_DOWN: + if (slave->link_failure_count < UINT_MAX) + slave->link_failure_count++; + slave->link = BOND_LINK_DOWN; if (bond->params.mode == BOND_MODE_ACTIVEBACKUP || -- cgit v1.2.3 From a434e43f3d844192bc23bd7b408bac979c40efe7 Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Thu, 30 Oct 2008 17:41:15 -0700 Subject: bonding: Clean up resource leaks This patch reworks the resource free logic performed at the time a bonding device is released. This (a) closes two resource leaks, one for workqueues and one for multicast lists, and (b) improves commonality of code between the "destroy one" and "destroy all" paths by performing final free activity via destructor instead of explicitly (and differently) in each path. "Sean E. Millichamp" reported the workqueue leak, and included a different patch. Signed-off-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_main.c | 49 ++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 85de1d04d1e..a3efba59eee 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1979,6 +1979,20 @@ void bond_destroy(struct bonding *bond) unregister_netdevice(bond->dev); } +static void bond_destructor(struct net_device *bond_dev) +{ + struct bonding *bond = bond_dev->priv; + + if (bond->wq) + destroy_workqueue(bond->wq); + + netif_addr_lock_bh(bond_dev); + bond_mc_list_destroy(bond); + netif_addr_unlock_bh(bond_dev); + + free_netdev(bond_dev); +} + /* * First release a slave and than destroy the bond if no more slaves iare left. * Must be under rtnl_lock when this function is called. @@ -4553,7 +4567,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) bond_set_mode_ops(bond, bond->params.mode); - bond_dev->destructor = free_netdev; + bond_dev->destructor = bond_destructor; /* Initialize the device options */ bond_dev->tx_queue_len = 0; @@ -4592,20 +4606,6 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params) return 0; } -/* De-initialize device specific data. - * Caller must hold rtnl_lock. - */ -static void bond_deinit(struct net_device *bond_dev) -{ - struct bonding *bond = bond_dev->priv; - - list_del(&bond->bond_list); - -#ifdef CONFIG_PROC_FS - bond_remove_proc_entry(bond); -#endif -} - static void bond_work_cancel_all(struct bonding *bond) { write_lock_bh(&bond->lock); @@ -4627,6 +4627,22 @@ static void bond_work_cancel_all(struct bonding *bond) cancel_delayed_work(&bond->ad_work); } +/* De-initialize device specific data. + * Caller must hold rtnl_lock. + */ +static void bond_deinit(struct net_device *bond_dev) +{ + struct bonding *bond = bond_dev->priv; + + list_del(&bond->bond_list); + + bond_work_cancel_all(bond); + +#ifdef CONFIG_PROC_FS + bond_remove_proc_entry(bond); +#endif +} + /* Unregister and free all bond devices. * Caller must hold rtnl_lock. */ @@ -4638,9 +4654,6 @@ static void bond_free_all(void) struct net_device *bond_dev = bond->dev; bond_work_cancel_all(bond); - netif_addr_lock_bh(bond_dev); - bond_mc_list_destroy(bond); - netif_addr_unlock_bh(bond_dev); /* Release the bonded slaves */ bond_release_all(bond_dev); bond_destroy(bond); -- cgit v1.2.3 From ce39a800ea87c655de49af021c8b20ee323cb40d Mon Sep 17 00:00:00 2001 From: Andy Gospodarek Date: Thu, 30 Oct 2008 17:41:16 -0700 Subject: bonding: fix panic when taking bond interface down before removing module A panic was discovered with bonding when using mode 5 or 6 and trying to remove the slaves from the bond after the interface was taken down. When calling 'ifconfig bond0 down' the following happens: bond_close() bond_alb_deinitialize() tlb_deinitialize() kfree(bond_info->tx_hashtbl) bond_info->tx_hashtbl = NULL Unfortunately if there are still slaves in the bond, when removing the module the following happens: bonding_exit() bond_free_all() bond_release_all() bond_alb_deinit_slave() tlb_clear_slave() tx_hash_table = BOND_ALB_INFO(bond).tx_hashtbl u32 next_index = tx_hash_table[index].next As you might guess we panic when trying to access a few entries into the table that no longer exists. I experimented with several options (like moving the calls to tlb_deinitialize somewhere else), but it really makes the most sense to be part of the bond_close routine. It also didn't seem logical move tlb_clear_slave around too much, so the simplest option seems to add a check in tlb_clear_slave to make sure we haven't already wiped the tx_hashtbl away before searching for all the non-existent hash-table entries that used to point to the slave as the output interface. Signed-off-by: Andy Gospodarek Signed-off-by: Jay Vosburgh Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_alb.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index ade5f3f6693..87437c78847 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -169,11 +169,14 @@ static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_ /* clear slave from tx_hashtbl */ tx_hash_table = BOND_ALB_INFO(bond).tx_hashtbl; - index = SLAVE_TLB_INFO(slave).head; - while (index != TLB_NULL_INDEX) { - u32 next_index = tx_hash_table[index].next; - tlb_init_table_entry(&tx_hash_table[index], save_load); - index = next_index; + /* skip this if we've already freed the tx hash table */ + if (tx_hash_table) { + index = SLAVE_TLB_INFO(slave).head; + while (index != TLB_NULL_INDEX) { + u32 next_index = tx_hash_table[index].next; + tlb_init_table_entry(&tx_hash_table[index], save_load); + index = next_index; + } } tlb_init_slave(slave); -- cgit v1.2.3 From 6824a105d4b699e3c08cc3df371de4b0480017b9 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Thu, 30 Oct 2008 08:59:33 +0100 Subject: myri10ge: fix stop/go mmio ordering Use mmiowb() to ensure "stop" and "go" commands are sent in order on ia64. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index b1556b2e404..a5f428bcc0e 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -75,7 +75,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.4.3-1.371" +#define MYRI10GE_VERSION_STR "1.4.3-1.375" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -1393,6 +1393,7 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index) if (tx->req == tx->done) { tx->queue_active = 0; put_be32(htonl(1), tx->send_stop); + mmiowb(); } __netif_tx_unlock(dev_queue); } @@ -2864,6 +2865,7 @@ again: if ((mgp->dev->real_num_tx_queues > 1) && tx->queue_active == 0) { tx->queue_active = 1; put_be32(htonl(1), tx->send_go); + mmiowb(); } tx->pkt_start++; if ((avail - count) < MXGEFW_MAX_SEND_DESC) { -- cgit v1.2.3 From 51ac3beffd4afaea4350526cf01fe74aaff25eff Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 29 Oct 2008 09:56:06 -0400 Subject: SMC91x: delete unused local variable "lp" Signed-off-by: Mike Frysinger Signed-off-by: Jeff Garzik --- drivers/net/smc91x.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index c70870e0fd6..6f9895d4e5b 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -2060,7 +2060,6 @@ static int smc_request_attrib(struct platform_device *pdev, struct net_device *ndev) { struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib"); - struct smc_local *lp = netdev_priv(ndev); if (!res) return 0; @@ -2075,7 +2074,6 @@ static void smc_release_attrib(struct platform_device *pdev, struct net_device *ndev) { struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib"); - struct smc_local *lp = netdev_priv(ndev); if (res) release_mem_region(res->start, ATTRIB_SIZE); -- cgit v1.2.3 From dc5596d920b504d263c7ca38bd76326179b13dee Mon Sep 17 00:00:00 2001 From: Jay Cliburn Date: Wed, 29 Oct 2008 11:01:36 -0500 Subject: atl1: fix vlan tag regression Commit 401c0aabec4b97320f962a0161a846d230a6f7aa introduced a regression in the atl1 driver by storing the VLAN tag in the wrong TX descriptor field. This patch causes the VLAN tag to be stored in its proper location. Tested-by: Ramon Casellas Signed-off-by: Jay Cliburn Cc: stable@kernel.org Signed-off-by: Jeff Garzik --- drivers/net/atlx/atl1.c | 7 ++++--- drivers/net/atlx/atl1.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 3cf59a7f5a1..246d92b4263 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -2310,7 +2310,8 @@ static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count, if (tpd != ptpd) memcpy(tpd, ptpd, sizeof(struct tx_packet_desc)); tpd->buffer_addr = cpu_to_le64(buffer_info->dma); - tpd->word2 = (cpu_to_le16(buffer_info->length) & + tpd->word2 &= ~(TPD_BUFLEN_MASK << TPD_BUFLEN_SHIFT); + tpd->word2 |= (cpu_to_le16(buffer_info->length) & TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT; /* @@ -2409,8 +2410,8 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) | ((vlan_tag >> 9) & 0x8); ptpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT; - ptpd->word3 |= (vlan_tag & TPD_VL_TAGGED_MASK) << - TPD_VL_TAGGED_SHIFT; + ptpd->word2 |= (vlan_tag & TPD_VLANTAG_MASK) << + TPD_VLANTAG_SHIFT; } tso = atl1_tso(adapter, skb, ptpd); diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h index a5015b14a42..ffa73fc8d95 100644 --- a/drivers/net/atlx/atl1.h +++ b/drivers/net/atlx/atl1.h @@ -504,7 +504,7 @@ struct rx_free_desc { #define TPD_PKTNT_MASK 0x0001 #define TPD_PKTINT_SHIFT 15 #define TPD_VLANTAG_MASK 0xFFFF -#define TPD_VLAN_SHIFT 16 +#define TPD_VLANTAG_SHIFT 16 /* tpd word 3 bits 0:13 */ #define TPD_EOP_MASK 0x0001 -- cgit v1.2.3 From e83603fd4ace0bc8e2585cf9d450bb1dc80db448 Mon Sep 17 00:00:00 2001 From: Chunbo Luo Date: Tue, 28 Oct 2008 09:51:46 +0800 Subject: amd8111e: fix dma_free_coherent context Acoording commit aa24886e379d2b641c5117e178b15ce1d5d366ba, dma_free_coherent() need irqs enabled. This patch fix following warning messages: WARNING: at linux/arch/x86/kernel/pci-dma.c:376 dma_free_coherent+0xaa/0xb0() Call Trace: [] warn_on_slowpath+0x5f/0x90 [] ? __kfree_skb+0x3a/0xa0 [] ? discard_slab+0x23/0x40 [] dma_free_coherent+0xaa/0xb0 [] amd8111e_close+0x10f/0x1b0 [] dev_close+0x5e/0xb0 [] dev_change_flags+0xa1/0x1e0 [] ic_close_devs+0x36/0x4e [] ip_auto_config+0x581/0x10f3 [] ? kobject_add+0x69/0x90 [] ? kobject_get+0x1a/0x30 [] ? kobject_uevent+0xb/0x10 [] ? kset_register+0x52/0x60 [] ? kset_create_and_add+0x6b/0xa0 [] ? tcp_ca_find+0x24/0x50 [] ? ip_auto_config+0x0/0x10f3 [] _stext+0x3c/0x150 [] ? register_irq_proc+0xd3/0xf0 [] ? mb_cache_create+0x80/0x1f0 [] kernel_init+0x141/0x1b8 [] ? kernel_init+0x0/0x1b8 [] child_rip+0xa/0x11 [] ? kernel_init+0x0/0x1b8 [] ? kernel_init+0x0/0x1b8 [] ? child_rip+0x0/0x11 Signed-off-by: Chunbo Luo Signed-off-by: Jeff Garzik --- drivers/net/amd8111e.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index ba1be0b3a8c..07a6697e363 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -644,10 +644,6 @@ This function frees the transmiter and receiver descriptor rings. */ static void amd8111e_free_ring(struct amd8111e_priv* lp) { - - /* Free transmit and receive skbs */ - amd8111e_free_skbs(lp->amd8111e_net_dev); - /* Free transmit and receive descriptor rings */ if(lp->rx_ring){ pci_free_consistent(lp->pci_dev, @@ -1233,7 +1229,9 @@ static int amd8111e_close(struct net_device * dev) amd8111e_disable_interrupt(lp); amd8111e_stop_chip(lp); - amd8111e_free_ring(lp); + + /* Free transmit and receive skbs */ + amd8111e_free_skbs(lp->amd8111e_net_dev); netif_carrier_off(lp->amd8111e_net_dev); @@ -1243,6 +1241,7 @@ static int amd8111e_close(struct net_device * dev) spin_unlock_irq(&lp->lock); free_irq(dev->irq, dev); + amd8111e_free_ring(lp); /* Update the statistics before closing */ amd8111e_get_stats(dev); -- cgit v1.2.3 From 71527ef484426f2a4fb868da379b46f4408e80d6 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 27 Oct 2008 14:11:34 -0700 Subject: at91_ether: request/free GPIO for PHY interrupt When the at91_ether driver is using a GPIO for its PHY interrupt, be sure to request (and later, if needed, free) that GPIO. Signed-off-by: David Brownell Signed-off-by: Jeff Garzik --- drivers/net/arm/at91_ether.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index 0fa53464efb..6f431a887e7 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -1080,7 +1080,8 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add init_timer(&lp->check_timer); lp->check_timer.data = (unsigned long)dev; lp->check_timer.function = at91ether_check_link; - } + } else if (lp->board_data.phy_irq_pin >= 32) + gpio_request(lp->board_data.phy_irq_pin, "ethernet_phy"); /* Display ethernet banner */ printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%s)\n", @@ -1167,6 +1168,9 @@ static int __devexit at91ether_remove(struct platform_device *pdev) struct net_device *dev = platform_get_drvdata(pdev); struct at91_private *lp = netdev_priv(dev); + if (lp->board_data.phy_irq_pin >= 32) + gpio_free(lp->board_data.phy_irq_pin); + unregister_netdev(dev); free_irq(dev->irq, dev); dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys); -- cgit v1.2.3 From c132419e560a2ecd3c8cf77f9c37e103e74b3754 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 30 Oct 2008 18:17:06 -0700 Subject: gianfar: Fix race in TBI/SerDes configuration The init_phy() function attaches to the PHY, then configures the SerDes<->TBI link (in SGMII mode). The TBI is on the MDIO bus with the PHY (sort of) and is accessed via the gianfar's MDIO registers, using the functions gfar_local_mdio_read/write(), which don't do any locking. The previously attached PHY will start a work-queue on a timer, and probably an irq handler as well, which will talk to the PHY and thus use the MDIO bus. This uses phy_read/write(), which have locking, but not against the gfar_local_mdio versions. The result is that PHY code will try to use the MDIO bus at the same time as the SerDes setup code, corrupting the transfers. Setting up the SerDes before attaching to the PHY will insure that there is no race between the SerDes code and *our* PHY, but doesn't fix everything. Typically the PHYs for all gianfar devices are on the same MDIO bus, which is associated with the first gianfar device. This means that the first gianfar's SerDes code could corrupt the MDIO transfers for a different gianfar's PHY. The lock used by phy_read/write() is contained in the mii_bus structure, which is pointed to by the PHY. This is difficult to access from the gianfar drivers, as there is no link between a gianfar device and the mii_bus which shares the same MDIO registers. As far as the device layer and drivers are concerned they are two unrelated devices (which happen to share registers). Generally all gianfar devices' PHYs will be on the bus associated with the first gianfar. But this might not be the case, so simply locking the gianfar's PHY's mii bus might not lock the mii bus that the SerDes setup code is going to use. We solve this by having the code that creates the gianfar platform device look in the device tree for an mdio device that shares the gianfar's registers. If one is found the ID of its platform device is saved in the gianfar's platform data. A new function in the gianfar mii code, gfar_get_miibus(), can use the bus ID to search through the platform devices for a gianfar_mdio device with the right ID. The platform device's driver data is the mii_bus structure, which the SerDes setup code can use to lock the current bus. Signed-off-by: Trent Piepho CC: Andy Fleming Signed-off-by: Jeff Garzik --- drivers/net/gianfar.c | 7 +++++++ drivers/net/gianfar_mii.c | 21 +++++++++++++++++++++ drivers/net/gianfar_mii.h | 3 +++ 3 files changed, 31 insertions(+) (limited to 'drivers') diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 64b201134fd..249541a1814 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -586,6 +586,10 @@ static void gfar_configure_serdes(struct net_device *dev) struct gfar_mii __iomem *regs = (void __iomem *)&priv->regs->gfar_mii_regs; int tbipa = gfar_read(&priv->regs->tbipa); + struct mii_bus *bus = gfar_get_miibus(priv); + + if (bus) + mutex_lock(&bus->mdio_lock); /* Single clk mode, mii mode off(for serdes communication) */ gfar_local_mdio_write(regs, tbipa, MII_TBICON, TBICON_CLK_SELECT); @@ -596,6 +600,9 @@ static void gfar_configure_serdes(struct net_device *dev) gfar_local_mdio_write(regs, tbipa, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000); + + if (bus) + mutex_unlock(&bus->mdio_lock); } static void init_registers(struct net_device *dev) diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index bf73eea9801..0e2595d2493 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -269,6 +269,27 @@ static struct device_driver gianfar_mdio_driver = { .remove = gfar_mdio_remove, }; +static int match_mdio_bus(struct device *dev, void *data) +{ + const struct gfar_private *priv = data; + const struct platform_device *pdev = to_platform_device(dev); + + return !strcmp(pdev->name, gianfar_mdio_driver.name) && + pdev->id == priv->einfo->mdio_bus; +} + +/* Given a gfar_priv structure, find the mii_bus controlled by this device (not + * necessarily the same as the bus the gfar's PHY is on), if one exists. + * Normally only the first gianfar controls a mii_bus. */ +struct mii_bus *gfar_get_miibus(const struct gfar_private *priv) +{ + /*const*/ struct device *d; + + d = bus_find_device(gianfar_mdio_driver.bus, NULL, (void *)priv, + match_mdio_bus); + return d ? dev_get_drvdata(d) : NULL; +} + int __init gfar_mdio_init(void) { return driver_register(&gianfar_mdio_driver); diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h index 2af28b16a0e..02dc970ca1f 100644 --- a/drivers/net/gianfar_mii.h +++ b/drivers/net/gianfar_mii.h @@ -18,6 +18,8 @@ #ifndef __GIANFAR_MII_H #define __GIANFAR_MII_H +struct gfar_private; /* forward ref */ + #define MIIMIND_BUSY 0x00000001 #define MIIMIND_NOTVALID 0x00000004 @@ -44,6 +46,7 @@ int gfar_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value); int gfar_local_mdio_write(struct gfar_mii __iomem *regs, int mii_id, int regnum, u16 value); int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum); +struct mii_bus *gfar_get_miibus(const struct gfar_private *priv); int __init gfar_mdio_init(void); void gfar_mdio_exit(void); #endif /* GIANFAR_PHY_H */ -- cgit v1.2.3 From bdb59f949d663b7e943fb5f40b2557af4314abf9 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 30 Oct 2008 18:17:07 -0700 Subject: gianfar: Don't reset TBI<->SerDes link if it's already up The link may be up already via the chip's reset strapping, or though action of U-Boot, or from the last time the interface was brought up. Resetting the link causes it to go down for several seconds. This can significantly increase the time from power-on to DHCP completion and a device being accessible to the network. Signed-off-by: Trent Piepho Acked-by: Andy Fleming Signed-off-by: Jeff Garzik --- drivers/net/gianfar.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 249541a1814..83a5cb6aa23 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -591,6 +591,14 @@ static void gfar_configure_serdes(struct net_device *dev) if (bus) mutex_lock(&bus->mdio_lock); + /* If the link is already up, we must already be ok, and don't need to + * configure and reset the TBI<->SerDes link. Maybe U-Boot configured + * everything for us? Resetting it takes the link down and requires + * several seconds for it to come back. + */ + if (gfar_local_mdio_read(regs, tbipa, MII_BMSR) & BMSR_LSTATUS) + goto done; + /* Single clk mode, mii mode off(for serdes communication) */ gfar_local_mdio_write(regs, tbipa, MII_TBICON, TBICON_CLK_SELECT); @@ -601,6 +609,7 @@ static void gfar_configure_serdes(struct net_device *dev) gfar_local_mdio_write(regs, tbipa, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000); + done: if (bus) mutex_unlock(&bus->mdio_lock); } -- cgit v1.2.3 From 6098e2ee14849e0819ffa887ebf470dcfad4a2be Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Sun, 26 Oct 2008 21:51:25 +0000 Subject: OF-device: Don't overwrite numa_node in device registration Currently, the numa_node of OF-devices will be overwritten during device_register, which simply sets the node to -1. On cell machines, this means that devices can't find their IOMMU, which is referenced through the device's numa node. Set the numa node for OF devices with no parent, and use the lower-level device_initialize and device_add functions, so that the node is preserved. We can remove the call to set_dev_node in of_device_alloc, as it will be overwritten during register. Signed-off-by: Jeremy Kerr Signed-off-by: Paul Mackerras --- drivers/of/device.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/of/device.c b/drivers/of/device.c index 51e5214071d..224ae6bc67b 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -105,7 +105,16 @@ EXPORT_SYMBOL(of_release_dev); int of_device_register(struct of_device *ofdev) { BUG_ON(ofdev->node == NULL); - return device_register(&ofdev->dev); + + device_initialize(&ofdev->dev); + + /* device_add will assume that this device is on the same node as + * the parent. If there is no parent defined, set the node + * explicitly */ + if (!ofdev->dev.parent) + set_dev_node(&ofdev->dev, of_node_to_nid(ofdev->node)); + + return device_add(&ofdev->dev); } EXPORT_SYMBOL(of_device_register); -- cgit v1.2.3 From 5b97fbd093ac2e0da0c7eec894fee065a04af55d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 29 Oct 2008 22:35:08 -0700 Subject: ATA: remove excess kernel-doc notation Remove excess kernel-doc function parameter notation from drivers/ata/: Warning(drivers/ata/libata-core.c:1622): Excess function parameter or struct member 'fn' description in 'ata_pio_queue_task' Warning(drivers/ata/libata-core.c:4655): Excess function parameter or struct member 'err_mask' description in 'ata_qc_complete' Warning(drivers/ata/ata_piix.c:751): Excess function parameter or struct member 'udma' description in 'do_pata_set_dmamode' Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 1 - drivers/ata/libata-core.c | 2 -- 2 files changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 52dc2d8b8f2..8e37be19bbf 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -738,7 +738,6 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) * do_pata_set_dmamode - Initialize host controller PATA PIO timings * @ap: Port whose timings we are configuring * @adev: Drive in question - * @udma: udma mode, 0 - 6 * @isich: set if the chip is an ICH device * * Set UDMA mode for device, in host controller PCI config space. diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 2ff633c119e..e398df12fd1 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1602,7 +1602,6 @@ unsigned long ata_id_xfermask(const u16 *id) /** * ata_pio_queue_task - Queue port_task * @ap: The ata_port to queue port_task for - * @fn: workqueue function to be scheduled * @data: data for @fn to use * @delay: delay time in msecs for workqueue function * @@ -4648,7 +4647,6 @@ static void ata_verify_xfer(struct ata_queued_cmd *qc) /** * ata_qc_complete - Complete an active ATA command * @qc: Command to complete - * @err_mask: ATA Status register contents * * Indicate to the mid and upper layers that an ATA * command has completed, with either an ok or not-ok status. -- cgit v1.2.3 From ba14a9c291aa867896a90b3571fcc1c3759942ff Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 28 Oct 2008 16:52:20 -0700 Subject: libata: Avoid overflow in ata_tf_to_lba48() when tf->hba_lbal > 127 In ata_tf_to_lba48(), when evaluating (tf->hob_lbal & 0xff) << 24 the expression is promoted to signed int (since int can hold all values of u8). However, if hob_lbal is 128 or more, then it is treated as a negative signed value and sign-extended when promoted to u64 to | into sectors, which leads to the MSB 32 bits of section getting set incorrectly. For example, Phillip O'Donnell reported that a 1.5GB drive caused: ata3.00: HPA detected: current 2930277168, native 18446744072344861488 where 2930277168 == 0xAEA87B30 and 18446744072344861488 == 0xffffffffaea87b30 which shows the problem when hob_lbal is 0xae. Fix this by adding a cast to u64, just as is used by for hob_lbah and hob_lbam in the function. Reported-by: Phillip O'Donnell Signed-off-by: Roland Dreier Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index e398df12fd1..8824c8da3f2 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1268,7 +1268,7 @@ u64 ata_tf_to_lba48(const struct ata_taskfile *tf) sectors |= ((u64)(tf->hob_lbah & 0xff)) << 40; sectors |= ((u64)(tf->hob_lbam & 0xff)) << 32; - sectors |= (tf->hob_lbal & 0xff) << 24; + sectors |= ((u64)(tf->hob_lbal & 0xff)) << 24; sectors |= (tf->lbah & 0xff) << 16; sectors |= (tf->lbam & 0xff) << 8; sectors |= (tf->lbal & 0xff); -- cgit v1.2.3 From b9d5b89b487517cbd4cb4702da829e07ef9e4432 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 22 Oct 2008 00:46:36 +0900 Subject: sata_via: fix support for 5287 5287 used to be treated as vt6420 but it didn't work. It's new family of controllers called vt8251 which hosts four SATA ports as M/S of the two ATA ports. This configuration is rather peculiar in that although the M/S devices are on the same port, each have its own SCR (or equivalent link status/control) registers which screws up the port-link-device hierarchy assumed by libata. Another controller which falls into this category is ata_piix w/ SIDPR access. libata now has facility to deal with this class of controllers named slave_link. A low level driver for such controllers can just call ata_slave_link_init() on the respective ports and libata will handle all the difficult parts like following up with single SRST after hardresetting both ports. This patch creates new controller class vt8251, implements slave_link aware init sequence and config space based SCR access for it and moves 5287 to the new class. This patch is based on Joseph Chan's larger patch which was created before slave_link was implemented in libata. http://thread.gmane.org/gmane.linux.kernel.commits.mm/40640 Signed-off-by: Tejun Heo Cc: Joseph Chan Signed-off-by: Jeff Garzik --- drivers/ata/sata_via.c | 155 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 143 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 5b72e734300..62367fe4d5d 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -44,11 +44,16 @@ #include #define DRV_NAME "sata_via" -#define DRV_VERSION "2.3" +#define DRV_VERSION "2.4" +/* + * vt8251 is different from other sata controllers of VIA. It has two + * channels, each channel has both Master and Slave slot. + */ enum board_ids_enum { vt6420, vt6421, + vt8251, }; enum { @@ -70,6 +75,8 @@ enum { static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static int svia_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); +static int vt8251_scr_read(struct ata_link *link, unsigned int scr, u32 *val); +static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val); static void svia_tf_load(struct ata_port *ap, const struct ata_taskfile *tf); static void svia_noop_freeze(struct ata_port *ap); static int vt6420_prereset(struct ata_link *link, unsigned long deadline); @@ -79,12 +86,12 @@ static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev); static const struct pci_device_id svia_pci_tbl[] = { { PCI_VDEVICE(VIA, 0x5337), vt6420 }, - { PCI_VDEVICE(VIA, 0x0591), vt6420 }, - { PCI_VDEVICE(VIA, 0x3149), vt6420 }, - { PCI_VDEVICE(VIA, 0x3249), vt6421 }, - { PCI_VDEVICE(VIA, 0x5287), vt6420 }, + { PCI_VDEVICE(VIA, 0x0591), vt6420 }, /* 2 sata chnls (Master) */ + { PCI_VDEVICE(VIA, 0x3149), vt6420 }, /* 2 sata chnls (Master) */ + { PCI_VDEVICE(VIA, 0x3249), vt6421 }, /* 2 sata chnls, 1 pata chnl */ { PCI_VDEVICE(VIA, 0x5372), vt6420 }, { PCI_VDEVICE(VIA, 0x7372), vt6420 }, + { PCI_VDEVICE(VIA, 0x5287), vt8251 }, /* 2 sata chnls (Master/Slave) */ { } /* terminate list */ }; @@ -128,6 +135,13 @@ static struct ata_port_operations vt6421_sata_ops = { .scr_write = svia_scr_write, }; +static struct ata_port_operations vt8251_ops = { + .inherits = &svia_base_ops, + .hardreset = sata_std_hardreset, + .scr_read = vt8251_scr_read, + .scr_write = vt8251_scr_write, +}; + static const struct ata_port_info vt6420_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = 0x1f, @@ -152,6 +166,15 @@ static struct ata_port_info vt6421_pport_info = { .port_ops = &vt6421_pata_ops, }; +static struct ata_port_info vt8251_port_info = { + .flags = ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS | + ATA_FLAG_NO_LEGACY, + .pio_mask = 0x1f, + .mwdma_mask = 0x07, + .udma_mask = ATA_UDMA6, + .port_ops = &vt8251_ops, +}; + MODULE_AUTHOR("Jeff Garzik"); MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers"); MODULE_LICENSE("GPL"); @@ -174,6 +197,83 @@ static int svia_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) return 0; } +static int vt8251_scr_read(struct ata_link *link, unsigned int scr, u32 *val) +{ + static const u8 ipm_tbl[] = { 1, 2, 6, 0 }; + struct pci_dev *pdev = to_pci_dev(link->ap->host->dev); + int slot = 2 * link->ap->port_no + link->pmp; + u32 v = 0; + u8 raw; + + switch (scr) { + case SCR_STATUS: + pci_read_config_byte(pdev, 0xA0 + slot, &raw); + + /* read the DET field, bit0 and 1 of the config byte */ + v |= raw & 0x03; + + /* read the SPD field, bit4 of the configure byte */ + if (raw & (1 << 4)) + v |= 0x02 << 4; + else + v |= 0x01 << 4; + + /* read the IPM field, bit2 and 3 of the config byte */ + v |= ipm_tbl[(raw >> 2) & 0x3]; + break; + + case SCR_ERROR: + /* devices other than 5287 uses 0xA8 as base */ + WARN_ON(pdev->device != 0x5287); + pci_read_config_dword(pdev, 0xB0 + slot * 4, &v); + break; + + case SCR_CONTROL: + pci_read_config_byte(pdev, 0xA4 + slot, &raw); + + /* read the DET field, bit0 and bit1 */ + v |= ((raw & 0x02) << 1) | (raw & 0x01); + + /* read the IPM field, bit2 and bit3 */ + v |= ((raw >> 2) & 0x03) << 8; + break; + + default: + return -EINVAL; + } + + *val = v; + return 0; +} + +static int vt8251_scr_write(struct ata_link *link, unsigned int scr, u32 val) +{ + struct pci_dev *pdev = to_pci_dev(link->ap->host->dev); + int slot = 2 * link->ap->port_no + link->pmp; + u32 v = 0; + + switch (scr) { + case SCR_ERROR: + /* devices other than 5287 uses 0xA8 as base */ + WARN_ON(pdev->device != 0x5287); + pci_write_config_dword(pdev, 0xB0 + slot * 4, val); + return 0; + + case SCR_CONTROL: + /* set the DET field */ + v |= ((val & 0x4) >> 1) | (val & 0x1); + + /* set the IPM field */ + v |= ((val >> 8) & 0x3) << 2; + + pci_write_config_byte(pdev, 0xA4 + slot, v); + return 0; + + default: + return -EINVAL; + } +} + /** * svia_tf_load - send taskfile registers to host controller * @ap: Port to which output is sent @@ -396,6 +496,30 @@ static int vt6421_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) return 0; } +static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) +{ + const struct ata_port_info *ppi[] = { &vt8251_port_info, NULL }; + struct ata_host *host; + int i, rc; + + rc = ata_pci_sff_prepare_host(pdev, ppi, &host); + if (rc) + return rc; + *r_host = host; + + rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, "failed to iomap PCI BAR 5\n"); + return rc; + } + + /* 8251 hosts four sata ports as M/S of the two channels */ + for (i = 0; i < host->n_ports; i++) + ata_slave_link_init(host->ports[i]); + + return 0; +} + static void svia_configure(struct pci_dev *pdev) { u8 tmp8; @@ -451,10 +575,10 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) return rc; - if (board_id == vt6420) - bar_sizes = &svia_bar_sizes[0]; - else + if (board_id == vt6421) bar_sizes = &vt6421_bar_sizes[0]; + else + bar_sizes = &svia_bar_sizes[0]; for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++) if ((pci_resource_start(pdev, i) == 0) || @@ -467,12 +591,19 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } - if (board_id == vt6420) + switch (board_id) { + case vt6420: rc = vt6420_prepare_host(pdev, &host); - else + break; + case vt6421: rc = vt6421_prepare_host(pdev, &host); - if (rc) - return rc; + break; + case vt8251: + rc = vt8251_prepare_host(pdev, &host); + break; + default: + return -EINVAL; + } svia_configure(pdev); -- cgit v1.2.3 From 9ce8e3073d9cfd6f859c22a25441db41b85cbf6e Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 27 Aug 2008 15:23:18 +0200 Subject: libata: add whitelist for devices with known good pata-sata bridges libata currently imposes a UDMA5 max transfer rate and 200 sector max transfer size for SATA devices that sit behind a pata-sata bridge. Lots of devices have known good bridges that don't need this limit applied. The MTRON SSD disks are such devices. Transfer rates are increased by 20-30% with the restriction removed. So add a "blacklist" entry for the MTRON devices, with a flag indicating that the bridge is known good. Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 8824c8da3f2..82af7011f2d 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2158,6 +2158,10 @@ retry: static inline u8 ata_dev_knobble(struct ata_device *dev) { struct ata_port *ap = dev->link->ap; + + if (ata_dev_blacklisted(dev) & ATA_HORKAGE_BRIDGE_OK) + return 0; + return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); } @@ -4062,6 +4066,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "TSSTcorp CDDVDW SH-S202N", "SB00", ATA_HORKAGE_IVB, }, { "TSSTcorp CDDVDW SH-S202N", "SB01", ATA_HORKAGE_IVB, }, + /* Devices that do not need bridging limits applied */ + { "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, }, + /* End Marker */ { } }; -- cgit v1.2.3 From 263e69cbc9e5a9e7bcf6a24f641ef0717d1ae4df Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 30 Oct 2008 23:11:44 -0700 Subject: pppoe: Fix socket leak. Move SKB trim before we lookup the socket so we don't have to put it on failure. Based upon an initial patch by Jarek Poplawski and suggestions from Herbert Xu. Signed-off-by: David S. Miller --- drivers/net/pppoe.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index fc6f4b8c64b..b646e92134d 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -399,11 +399,11 @@ static int pppoe_rcv(struct sk_buff *skb, if (skb->len < len) goto drop; - po = get_item(ph->sid, eth_hdr(skb)->h_source, dev->ifindex); - if (!po) + if (pskb_trim_rcsum(skb, len)) goto drop; - if (pskb_trim_rcsum(skb, len)) + po = get_item(ph->sid, eth_hdr(skb)->h_source, dev->ifindex); + if (!po) goto drop; return sk_receive_skb(sk_pppox(po), skb, 0); -- cgit v1.2.3 From ad1d967c88e349c7e822ad75dd3247a2a50d2ea3 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 30 Oct 2008 23:54:35 -0700 Subject: net: delete excess kernel-doc notation Remove excess kernel-doc function parameters from networking header & driver files: Warning(include/net/sock.h:946): Excess function parameter or struct member 'sk' description in 'sk_filter_release' Warning(include/linux/netdevice.h:1545): Excess function parameter or struct member 'cpu' description in 'netif_tx_lock' Warning(drivers/net/wan/z85230.c:712): Excess function parameter or struct member 'regs' description in 'z8530_interrupt' Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller --- drivers/net/wan/z85230.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c index ccd9cd35ecb..5bf7e01ef0e 100644 --- a/drivers/net/wan/z85230.c +++ b/drivers/net/wan/z85230.c @@ -695,7 +695,6 @@ EXPORT_SYMBOL(z8530_nop); * z8530_interrupt - Handle an interrupt from a Z8530 * @irq: Interrupt number * @dev_id: The Z8530 device that is interrupting. - * @regs: unused * * A Z85[2]30 device has stuck its hand in the air for attention. * We scan both the channels on the chip for events and then call -- cgit v1.2.3 From 3a8af722495469e9c550386b910c5b93c91cf107 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 31 Oct 2008 00:00:33 -0700 Subject: net: Really remove all of LOOPBACK_TSO code. As noticed by Saikiran Madugula, commit 7447ef63cf2dfdc444f4c72ae13f604350b2e25f ("loopback: Remove rest of LOOPBACK_TSO code.") got rid of emulate_large_send_offload() but didn't get rid of the call site as well. Signed-off-by: David S. Miller --- drivers/net/loopback.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 3b43bfd85a0..b1ac63ab8c1 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -76,15 +76,6 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) skb->protocol = eth_type_trans(skb,dev); -#ifdef LOOPBACK_TSO - if (skb_is_gso(skb)) { - BUG_ON(skb->protocol != htons(ETH_P_IP)); - BUG_ON(ip_hdr(skb)->protocol != IPPROTO_TCP); - - emulate_large_send_offload(skb); - return 0; - } -#endif dev->last_rx = jiffies; /* it's OK to use per_cpu_ptr() because BHs are off */ -- cgit v1.2.3 From aeffd54ad7e3af513c6a0dadda71e6316e5ba230 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Wed, 29 Oct 2008 13:34:50 +0900 Subject: sh: Change register name SCSPTR to SCSPTR2 This change a name of SCSPTR used in sci_rxd_in of SH5-101. SCSPTR is not declared and will become the error. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 257b2235d12..96cae15db9c 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -599,7 +599,7 @@ static inline int sci_rxd_in(struct uart_port *port) #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) static inline int sci_rxd_in(struct uart_port *port) { - return sci_in(port, SCSPTR)&0x0001 ? 1 : 0; /* SCIF */ + return sci_in(port, SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ } #elif defined(__H8300H__) || defined(__H8300S__) static inline int sci_rxd_in(struct uart_port *port) -- cgit v1.2.3 From 961e9ff9025ef2dfdebe843549b7e1ec4d48c17c Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Wed, 29 Oct 2008 13:33:45 +0900 Subject: sh: Add sci_rxd_in of SH4-202 SH4-202 doesn't have SCSXX1. But it is treated so that there is SCSPTR1 in current code. This patch add sci_rxd_in of SH4-202. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 96cae15db9c..f4bd93e02ee 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -526,8 +526,7 @@ static inline int sci_rxd_in(struct uart_port *port) defined(CONFIG_CPU_SUBTYPE_SH7751R) || \ defined(CONFIG_CPU_SUBTYPE_SH7750R) || \ defined(CONFIG_CPU_SUBTYPE_SH7750S) || \ - defined(CONFIG_CPU_SUBTYPE_SH7091) || \ - defined(CONFIG_CPU_SUBTYPE_SH4_202) + defined(CONFIG_CPU_SUBTYPE_SH7091) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) @@ -536,6 +535,13 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ return 1; } +#elif defined(CONFIG_CPU_SUBTYPE_SH4_202) +static inline int sci_rxd_in(struct uart_port *port) +{ + if (port->mapbase == 0xffe80000) + return ctrl_inw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ + return 1; +} #elif defined(CONFIG_CPU_SUBTYPE_SH7760) static inline int sci_rxd_in(struct uart_port *port) { -- cgit v1.2.3 From 7abc404a5a1e3785749acb8dbfcc558223f78444 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Wed, 29 Oct 2008 07:16:02 +0000 Subject: Define SCSPTR1 for SH 7751R After the recent commit to kill off SCI/SCIF special casing SH 7751R fails to compile with CONFIG_SH_RTS7751R2D set. This is because SCSPTR1 is undefined. Take the value for SCSPTR1 from the SH7751R Group Hardware Manual. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index f4bd93e02ee..c17e541a07c 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -34,6 +34,7 @@ # define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */ #define SCIF_ORER 0x0200 /* overrun error bit */ #elif defined(CONFIG_SH_RTS7751R2D) +# define SCSPTR1 0xFFE0001C /* 8 bit SCIF */ # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -- cgit v1.2.3 From a8884e3415c29c58a5875d54c109c4a7fcaa6fb4 Mon Sep 17 00:00:00 2001 From: Michael Trimarchi Date: Fri, 31 Oct 2008 16:10:23 +0900 Subject: sh: Fix up the shared IRQ demuxer's control bit testing logic. Correct the interrupt handler in sh4 serial device, return the correct value and check for what is anabled in the SCSCR register. The sh7722 is broken just sending a break using minicom. Signed-off-by: Michael Trimarchi Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 23 ++++++++++++----------- drivers/serial/sh-sci.h | 1 + 2 files changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 47816e68c90..5c0f32c7fbf 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -797,26 +797,27 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr) static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) { - unsigned short ssr_status, scr_status; - struct uart_port *port = ptr; + unsigned short ssr_status, scr_status; + struct uart_port *port = ptr; + irqreturn_t ret = IRQ_NONE; ssr_status = sci_in(port,SCxSR); scr_status = sci_in(port,SCSCR); /* Tx Interrupt */ - if ((ssr_status & 0x0020) && (scr_status & 0x0080)) - sci_tx_interrupt(irq, ptr); + if ((ssr_status & 0x0020) && (scr_status & SCI_CTRL_FLAGS_TIE)) + ret = sci_tx_interrupt(irq, ptr); /* Rx Interrupt */ - if ((ssr_status & 0x0002) && (scr_status & 0x0040)) - sci_rx_interrupt(irq, ptr); + if ((ssr_status & 0x0002) && (scr_status & SCI_CTRL_FLAGS_RIE)) + ret = sci_rx_interrupt(irq, ptr); /* Error Interrupt */ - if ((ssr_status & 0x0080) && (scr_status & 0x0400)) - sci_er_interrupt(irq, ptr); + if ((ssr_status & 0x0080) && (scr_status & SCI_CTRL_FLAGS_REIE)) + ret = sci_er_interrupt(irq, ptr); /* Break Interrupt */ - if ((ssr_status & 0x0010) && (scr_status & 0x0200)) - sci_br_interrupt(irq, ptr); + if ((ssr_status & 0x0010) && (scr_status & SCI_CTRL_FLAGS_REIE)) + ret = sci_br_interrupt(irq, ptr); - return IRQ_HANDLED; + return ret; } #if defined(CONFIG_CPU_FREQ) && defined(CONFIG_HAVE_CLK) diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index c17e541a07c..6163a45f968 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -166,6 +166,7 @@ #if defined(CONFIG_CPU_SUBTYPE_SH7750) || \ defined(CONFIG_CPU_SUBTYPE_SH7091) || \ defined(CONFIG_CPU_SUBTYPE_SH7750R) || \ + defined(CONFIG_CPU_SUBTYPE_SH7722) || \ defined(CONFIG_CPU_SUBTYPE_SH7750S) || \ defined(CONFIG_CPU_SUBTYPE_SH7751) || \ defined(CONFIG_CPU_SUBTYPE_SH7751R) || \ -- cgit v1.2.3 From cbafe312ef4a263e9aa36786bc67e1e6d959872b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Fri, 31 Oct 2008 00:40:19 -0700 Subject: bpa10x: free sk_buff with kfree_skb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inspired by Sergio Luis' similar patches, I finally found a case which is trivial enough that spatch won't choke on it. Signed-off-by: Ilpo Järvinen Acked-by: Marcel Holtmann Signed-off-by: David S. Miller --- drivers/bluetooth/bpa10x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 32f3a8ed8d3..b936d8ce272 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -443,8 +443,8 @@ static void bpa10x_destruct(struct hci_dev *hdev) BT_DBG("%s", hdev->name); - kfree(data->rx_skb[0]); - kfree(data->rx_skb[1]); + kfree_skb(data->rx_skb[0]); + kfree_skb(data->rx_skb[1]); kfree(data); } -- cgit v1.2.3 From a1f64819fe9f136c98d572794a35a7e377c951ef Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 30 Oct 2008 01:41:56 +0100 Subject: firewire: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers Signed-off-by: Stefan Richter --- drivers/firewire/fw-device.c | 14 ++++++-------- drivers/firewire/fw-ohci.c | 2 +- drivers/firewire/fw-sbp2.c | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 3fccdd48410..6b9be42c7b9 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -587,8 +587,7 @@ static void create_units(struct fw_device *device) unit->device.bus = &fw_bus_type; unit->device.type = &fw_unit_type; unit->device.parent = &device->device; - snprintf(unit->device.bus_id, sizeof(unit->device.bus_id), - "%s.%d", device->device.bus_id, i++); + dev_set_name(&unit->device, "%s.%d", dev_name(&device->device), i++); init_fw_attribute_group(&unit->device, fw_unit_attributes, @@ -711,8 +710,7 @@ static void fw_device_init(struct work_struct *work) device->device.type = &fw_device_type; device->device.parent = device->card->device; device->device.devt = MKDEV(fw_cdev_major, minor); - snprintf(device->device.bus_id, sizeof(device->device.bus_id), - "fw%d", minor); + dev_set_name(&device->device, "fw%d", minor); init_fw_attribute_group(&device->device, fw_device_attributes, @@ -741,13 +739,13 @@ static void fw_device_init(struct work_struct *work) if (device->config_rom_retries) fw_notify("created device %s: GUID %08x%08x, S%d00, " "%d config ROM retries\n", - device->device.bus_id, + dev_name(&device->device), device->config_rom[3], device->config_rom[4], 1 << device->max_speed, device->config_rom_retries); else fw_notify("created device %s: GUID %08x%08x, S%d00\n", - device->device.bus_id, + dev_name(&device->device), device->config_rom[3], device->config_rom[4], 1 << device->max_speed); device->config_rom_retries = 0; @@ -883,12 +881,12 @@ static void fw_device_refresh(struct work_struct *work) FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) goto gone; - fw_notify("refreshed device %s\n", device->device.bus_id); + fw_notify("refreshed device %s\n", dev_name(&device->device)); device->config_rom_retries = 0; goto out; give_up: - fw_notify("giving up on refresh of device %s\n", device->device.bus_id); + fw_notify("giving up on refresh of device %s\n", dev_name(&device->device)); gone: atomic_set(&device->state, FW_DEVICE_SHUTDOWN); fw_device_shutdown(work); diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 8e16bfbdcb3..46610b09041 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -2468,7 +2468,7 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) goto fail_self_id; fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n", - dev->dev.bus_id, version >> 16, version & 0xff); + dev_name(&dev->dev), version >> 16, version & 0xff); return 0; fail_self_id: diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index d334cac5e1f..97df6dac3a8 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -1135,7 +1135,7 @@ static int sbp2_probe(struct device *dev) tgt->unit = unit; kref_init(&tgt->kref); INIT_LIST_HEAD(&tgt->lu_list); - tgt->bus_id = unit->device.bus_id; + tgt->bus_id = dev_name(&unit->device); tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4]; if (fw_device_enable_phys_dma(device) < 0) -- cgit v1.2.3 From 233976e539a93de1320fc7625b24076b1f9e2c9c Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 30 Oct 2008 01:49:20 +0100 Subject: ieee1394: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers Signed-off-by: Stefan Richter --- drivers/ieee1394/hosts.c | 4 ++-- drivers/ieee1394/nodemgr.c | 14 +++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c index 8dd09d85041..237d0c9d69c 100644 --- a/drivers/ieee1394/hosts.c +++ b/drivers/ieee1394/hosts.c @@ -155,11 +155,11 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device)); h->device.parent = dev; set_dev_node(&h->device, dev_to_node(dev)); - snprintf(h->device.bus_id, BUS_ID_SIZE, "fw-host%d", h->id); + dev_set_name(&h->device, "fw-host%d", h->id); h->host_dev.parent = &h->device; h->host_dev.class = &hpsb_host_class; - snprintf(h->host_dev.bus_id, BUS_ID_SIZE, "fw-host%d", h->id); + dev_set_name(&h->host_dev, "fw-host%d", h->id); if (device_register(&h->device)) goto fail; diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 2376b729e87..9e39f73282e 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -826,13 +826,11 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, memcpy(&ne->device, &nodemgr_dev_template_ne, sizeof(ne->device)); ne->device.parent = &host->device; - snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx", - (unsigned long long)(ne->guid)); + dev_set_name(&ne->device, "%016Lx", (unsigned long long)(ne->guid)); ne->node_dev.parent = &ne->device; ne->node_dev.class = &nodemgr_ne_class; - snprintf(ne->node_dev.bus_id, BUS_ID_SIZE, "%016Lx", - (unsigned long long)(ne->guid)); + dev_set_name(&ne->node_dev, "%016Lx", (unsigned long long)(ne->guid)); if (device_register(&ne->device)) goto fail_devreg; @@ -932,13 +930,11 @@ static void nodemgr_register_device(struct node_entry *ne, ud->device.parent = parent; - snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u", - ne->device.bus_id, ud->id); + dev_set_name(&ud->device, "%s-%u", dev_name(&ne->device), ud->id); ud->unit_dev.parent = &ud->device; ud->unit_dev.class = &nodemgr_ud_class; - snprintf(ud->unit_dev.bus_id, BUS_ID_SIZE, "%s-%u", - ne->device.bus_id, ud->id); + dev_set_name(&ud->unit_dev, "%s-%u", dev_name(&ne->device), ud->id); if (device_register(&ud->device)) goto fail_devreg; @@ -953,7 +949,7 @@ static void nodemgr_register_device(struct node_entry *ne, fail_classdevreg: device_unregister(&ud->device); fail_devreg: - HPSB_ERR("Failed to create unit %s", ud->device.bus_id); + HPSB_ERR("Failed to create unit %s", dev_name(&ud->device)); } -- cgit v1.2.3 From 638570b54346f140bc09b986d93e76025d35180f Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 26 Oct 2008 12:03:37 +0100 Subject: ieee1394: raw1394: fix possible deadlock in multithreaded clients Regression in 2.6.28-rc1: When I added the new state_mutex which prevents corruption of raw1394's internal state when accessed by multithreaded client applications, the following possible though highly unlikely deadlock slipped in: Thread A: Thread B: - acquire mmap_sem - raw1394_write() or raw1394_ioctl() - raw1394_mmap() - acquire state_mutex - acquire state_mutex - copy_to/from_user(), possible page fault: acquire mmap_sem The simplest fix is to use mutex_trylock() instead of mutex_lock() in raw1394_mmap(). This changes the behavior under contention in a way which is visible to userspace clients. However, since multithreaded access was entirely buggy before state_mutex was added and libraw1394's documentation advised application programmers to use a handle only in a single thread, this change in behaviour should not be an issue in practice at all. Since we have to use mutex_trylock() in raw1394_mmap() regardless whether /dev/raw1394 was opened with O_NONBLOCK or not, we now use mutex_trylock() unconditionally everywhere for state_mutex, just to have consistent behavior. Reported-by: Johannes Weiner Signed-off-by: Stefan Richter --- drivers/ieee1394/raw1394.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 2cf4ae75bec..4bdfff0a919 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -2268,7 +2268,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer, return -EFAULT; } - mutex_lock(&fi->state_mutex); + if (!mutex_trylock(&fi->state_mutex)) + return -EAGAIN; switch (fi->state) { case opened: @@ -2548,7 +2549,8 @@ static int raw1394_mmap(struct file *file, struct vm_area_struct *vma) struct file_info *fi = file->private_data; int ret; - mutex_lock(&fi->state_mutex); + if (!mutex_trylock(&fi->state_mutex)) + return -EAGAIN; if (fi->iso_state == RAW1394_ISO_INACTIVE) ret = -EINVAL; @@ -2669,7 +2671,8 @@ static long raw1394_ioctl(struct file *file, unsigned int cmd, break; } - mutex_lock(&fi->state_mutex); + if (!mutex_trylock(&fi->state_mutex)) + return -EAGAIN; switch (fi->iso_state) { case RAW1394_ISO_INACTIVE: -- cgit v1.2.3 From 8449fc3ae58bf8ee5acbd2280754cde67b5db128 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 26 Oct 2008 12:02:03 +0100 Subject: ieee1394: dv1394: fix possible deadlock in multithreaded clients Fix a possible though highly unlikely deadlock: Thread A: Thread B: - acquire mmap_sem - dv1394_ioctl/read/write() - dv1394_mmap() - acquire video->mtx - acquire video->mtx - copy_to/from_user(), possible page fault: acquire mmap_sem The simplest fix is to use mutex_trylock() instead of mutex_lock() in dv1394_mmap(). This changes the behavior under contention in a way which is visible to userspace clients. However, my guess is that no clients exist which use mmap vs. ioctl/read/write on the dv1394 character device file interface in concurrent threads. Reported-by: Johannes Weiner Signed-off-by: Stefan Richter --- drivers/ieee1394/dv1394.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index df70f51279d..53329972c7d 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -1270,8 +1270,14 @@ static int dv1394_mmap(struct file *file, struct vm_area_struct *vma) struct video_card *video = file_to_video_card(file); int retval = -EINVAL; - /* serialize mmap */ - mutex_lock(&video->mtx); + /* + * We cannot use the blocking variant mutex_lock here because .mmap + * is called with mmap_sem held, while .ioctl, .read, .write acquire + * video->mtx and subsequently call copy_to/from_user which will + * grab mmap_sem in case of a page fault. + */ + if (!mutex_trylock(&video->mtx)) + return -EAGAIN; if ( ! video_card_initialized(video) ) { retval = do_dv1394_init_default(video); -- cgit v1.2.3 From 0839ccb8ac6a9e2d5e175a4ae9c82b5c574d510d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 30 Oct 2008 19:38:48 -0700 Subject: i915: use io-mapping interfaces instead of a variety of mapping kludges Impact: optimize/clean-up the IO mapping implementation of the i915 DRM driver Switch the i915 device aperture mapping to the io-mapping interface, taking advantage of the cleaner API to extend it across all of the mapping uses, including both pwrite and relocation updates. This dramatically improves performance on 64-bit kernels which were using the same slow path as 32-bit non-HIGHMEM kernels prior to this patch. Signed-off-by: Keith Packard Signed-off-by: Eric Anholt Signed-off-by: Ingo Molnar --- drivers/gpu/drm/i915/i915_drv.h | 3 + drivers/gpu/drm/i915/i915_gem.c | 174 ++++++++++++++++++---------------------- 2 files changed, 83 insertions(+), 94 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f20ffe17df7..126b2f13258 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -31,6 +31,7 @@ #define _I915_DRV_H_ #include "i915_reg.h" +#include /* General customization: */ @@ -246,6 +247,8 @@ typedef struct drm_i915_private { struct { struct drm_mm gtt_space; + struct io_mapping *gtt_mapping; + /** * List of objects currently involved in rendering from the * ringbuffer. diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 17ae330ff26..61183b95b10 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -171,35 +171,50 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, return 0; } -/* - * Try to write quickly with an atomic kmap. Return true on success. - * - * If this fails (which includes a partial write), we'll redo the whole - * thing with the slow version. - * - * This is a workaround for the low performance of iounmap (approximate - * 10% cpu cost on normal 3D workloads). kmap_atomic on HIGHMEM kernels - * happens to let us map card memory without taking IPIs. When the vmap - * rework lands we should be able to dump this hack. +/* This is the fast write path which cannot handle + * page faults in the source data */ -static inline int fast_user_write(unsigned long pfn, char __user *user_data, - int l, int o) + +static inline int +fast_user_write(struct io_mapping *mapping, + loff_t page_base, int page_offset, + char __user *user_data, + int length) { -#ifdef CONFIG_HIGHMEM - unsigned long unwritten; char *vaddr_atomic; + unsigned long unwritten; - vaddr_atomic = kmap_atomic_pfn(pfn, KM_USER0); -#if WATCH_PWRITE - DRM_INFO("pwrite i %d o %d l %d pfn %ld vaddr %p\n", - i, o, l, pfn, vaddr_atomic); -#endif - unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + o, user_data, l); - kunmap_atomic(vaddr_atomic, KM_USER0); - return !unwritten; -#else + vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base); + unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset, + user_data, length); + io_mapping_unmap_atomic(vaddr_atomic); + if (unwritten) + return -EFAULT; + return 0; +} + +/* Here's the write path which can sleep for + * page faults + */ + +static inline int +slow_user_write(struct io_mapping *mapping, + loff_t page_base, int page_offset, + char __user *user_data, + int length) +{ + char __iomem *vaddr; + unsigned long unwritten; + + vaddr = io_mapping_map_wc(mapping, page_base); + if (vaddr == NULL) + return -EFAULT; + unwritten = __copy_from_user(vaddr + page_offset, + user_data, length); + io_mapping_unmap(vaddr); + if (unwritten) + return -EFAULT; return 0; -#endif } static int @@ -208,10 +223,12 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj, struct drm_file *file_priv) { struct drm_i915_gem_object *obj_priv = obj->driver_private; + drm_i915_private_t *dev_priv = dev->dev_private; ssize_t remain; - loff_t offset; + loff_t offset, page_base; char __user *user_data; - int ret = 0; + int page_offset, page_length; + int ret; user_data = (char __user *) (uintptr_t) args->data_ptr; remain = args->size; @@ -235,57 +252,37 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj, obj_priv->dirty = 1; while (remain > 0) { - unsigned long pfn; - int i, o, l; - /* Operation in this page * - * i = page number - * o = offset within page - * l = bytes to copy + * page_base = page offset within aperture + * page_offset = offset within page + * page_length = bytes to copy for this page */ - i = offset >> PAGE_SHIFT; - o = offset & (PAGE_SIZE-1); - l = remain; - if ((o + l) > PAGE_SIZE) - l = PAGE_SIZE - o; - - pfn = (dev->agp->base >> PAGE_SHIFT) + i; - - if (!fast_user_write(pfn, user_data, l, o)) { - unsigned long unwritten; - char __iomem *vaddr; - - vaddr = ioremap_wc(pfn << PAGE_SHIFT, PAGE_SIZE); -#if WATCH_PWRITE - DRM_INFO("pwrite slow i %d o %d l %d " - "pfn %ld vaddr %p\n", - i, o, l, pfn, vaddr); -#endif - if (vaddr == NULL) { - ret = -EFAULT; - goto fail; - } - unwritten = __copy_from_user(vaddr + o, user_data, l); -#if WATCH_PWRITE - DRM_INFO("unwritten %ld\n", unwritten); -#endif - iounmap(vaddr); - if (unwritten) { - ret = -EFAULT; + page_base = (offset & ~(PAGE_SIZE-1)); + page_offset = offset & (PAGE_SIZE-1); + page_length = remain; + if ((page_offset + remain) > PAGE_SIZE) + page_length = PAGE_SIZE - page_offset; + + ret = fast_user_write (dev_priv->mm.gtt_mapping, page_base, + page_offset, user_data, page_length); + + /* If we get a fault while copying data, then (presumably) our + * source page isn't available. In this case, use the + * non-atomic function + */ + if (ret) { + ret = slow_user_write (dev_priv->mm.gtt_mapping, + page_base, page_offset, + user_data, page_length); + if (ret) goto fail; - } } - remain -= l; - user_data += l; - offset += l; + remain -= page_length; + user_data += page_length; + offset += page_length; } -#if WATCH_PWRITE && 1 - i915_gem_clflush_object(obj); - i915_gem_dump_object(obj, args->offset + args->size, __func__, ~0); - i915_gem_clflush_object(obj); -#endif fail: i915_gem_object_unpin(obj); @@ -1503,12 +1500,12 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, struct drm_i915_gem_exec_object *entry) { struct drm_device *dev = obj->dev; + drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_gem_relocation_entry reloc; struct drm_i915_gem_relocation_entry __user *relocs; struct drm_i915_gem_object *obj_priv = obj->driver_private; int i, ret; - uint32_t last_reloc_offset = -1; - void __iomem *reloc_page = NULL; + void __iomem *reloc_page; /* Choose the GTT offset for our buffer and put it there. */ ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment); @@ -1631,26 +1628,11 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, * perform. */ reloc_offset = obj_priv->gtt_offset + reloc.offset; - if (reloc_page == NULL || - (last_reloc_offset & ~(PAGE_SIZE - 1)) != - (reloc_offset & ~(PAGE_SIZE - 1))) { - if (reloc_page != NULL) - iounmap(reloc_page); - - reloc_page = ioremap_wc(dev->agp->base + - (reloc_offset & - ~(PAGE_SIZE - 1)), - PAGE_SIZE); - last_reloc_offset = reloc_offset; - if (reloc_page == NULL) { - drm_gem_object_unreference(target_obj); - i915_gem_object_unpin(obj); - return -ENOMEM; - } - } - + reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, + (reloc_offset & + ~(PAGE_SIZE - 1))); reloc_entry = (uint32_t __iomem *)(reloc_page + - (reloc_offset & (PAGE_SIZE - 1))); + (reloc_offset & (PAGE_SIZE - 1))); reloc_val = target_obj_priv->gtt_offset + reloc.delta; #if WATCH_BUF @@ -1659,6 +1641,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, readl(reloc_entry), reloc_val); #endif writel(reloc_val, reloc_entry); + io_mapping_unmap_atomic(reloc_page); /* Write the updated presumed offset for this entry back out * to the user. @@ -1674,9 +1657,6 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, drm_gem_object_unreference(target_obj); } - if (reloc_page != NULL) - iounmap(reloc_page); - #if WATCH_BUF if (0) i915_gem_dump_object(obj, 128, __func__, ~0); @@ -2518,6 +2498,10 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, if (ret != 0) return ret; + dev_priv->mm.gtt_mapping = io_mapping_create_wc(dev->agp->base, + dev->agp->agp_info.aper_size + * 1024 * 1024); + mutex_lock(&dev->struct_mutex); BUG_ON(!list_empty(&dev_priv->mm.active_list)); BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); @@ -2535,11 +2519,13 @@ int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { + drm_i915_private_t *dev_priv = dev->dev_private; int ret; ret = i915_gem_idle(dev); drm_irq_uninstall(dev); + io_mapping_free(dev_priv->mm.gtt_mapping); return ret; } -- cgit v1.2.3 From 233e70f4228e78eb2f80dc6650f65d3ae3dbf17c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 31 Oct 2008 23:28:30 +0000 Subject: saner FASYNC handling on file close As it is, all instances of ->release() for files that have ->fasync() need to remember to evict file from fasync lists; forgetting that creates a hole and we actually have a bunch that *does* forget. So let's keep our lives simple - let __fput() check FASYNC in file->f_flags and call ->fasync() there if it's been set. And lose that crap in ->release() instances - leaving it there is still valid, but we don't have to bother anymore. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/char/hpet.c | 3 --- drivers/char/ipmi/ipmi_devintf.c | 2 -- drivers/char/ipmi/ipmi_watchdog.c | 1 - drivers/char/random.c | 7 ------- drivers/char/rtc.c | 2 -- drivers/char/sonypi.c | 1 - drivers/gpu/drm/drm_fops.c | 2 -- drivers/hid/usbhid/hiddev.c | 2 -- drivers/ieee1394/dv1394.c | 3 --- drivers/infiniband/core/uverbs_main.c | 2 -- drivers/input/evdev.c | 1 - drivers/input/joydev.c | 1 - drivers/input/misc/hp_sdc_rtc.c | 13 ------------- drivers/input/mousedev.c | 1 - drivers/input/serio/serio_raw.c | 1 - drivers/message/fusion/mptctl.c | 7 ------- drivers/message/i2o/i2o_config.c | 21 +++++---------------- drivers/misc/sony-laptop.c | 1 - drivers/net/tun.c | 2 -- drivers/rtc/rtc-dev.c | 3 --- drivers/scsi/megaraid/megaraid_sas.c | 12 ------------ drivers/scsi/sg.c | 1 - drivers/staging/me4000/me4000.c | 3 --- drivers/telephony/ixj.c | 1 - drivers/uio/uio.c | 3 --- drivers/usb/gadget/inode.c | 1 - 26 files changed, 5 insertions(+), 92 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 408f5f92cb4..53fdc7ff387 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -427,9 +427,6 @@ static int hpet_release(struct inode *inode, struct file *file) if (irq) free_irq(irq, devp); - if (file->f_flags & FASYNC) - hpet_fasync(-1, file, 0); - file->private_data = NULL; return 0; } diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 1d7b429f7ff..41fc11dc921 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -162,8 +162,6 @@ static int ipmi_release(struct inode *inode, struct file *file) if (rv) return rv; - ipmi_fasync (-1, file, 0); - /* FIXME - free the messages in the list. */ kfree(priv); diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 235fab0bdf7..a4d57e31f71 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -870,7 +870,6 @@ static int ipmi_close(struct inode *ino, struct file *filep) clear_bit(0, &ipmi_wdog_open); } - ipmi_fasync(-1, filep, 0); expect_close = 0; return 0; diff --git a/drivers/char/random.c b/drivers/char/random.c index 705a839f179..675076f5fca 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1139,18 +1139,12 @@ static int random_fasync(int fd, struct file *filp, int on) return fasync_helper(fd, filp, on, &fasync); } -static int random_release(struct inode *inode, struct file *filp) -{ - return fasync_helper(-1, filp, 0, &fasync); -} - const struct file_operations random_fops = { .read = random_read, .write = random_write, .poll = random_poll, .unlocked_ioctl = random_ioctl, .fasync = random_fasync, - .release = random_release, }; const struct file_operations urandom_fops = { @@ -1158,7 +1152,6 @@ const struct file_operations urandom_fops = { .write = random_write, .unlocked_ioctl = random_ioctl, .fasync = random_fasync, - .release = random_release, }; /*************************************************************** diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 32dc89720d5..20d6efb6324 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -788,8 +788,6 @@ static int rtc_release(struct inode *inode, struct file *file) } spin_unlock_irq(&rtc_lock); - if (file->f_flags & FASYNC) - rtc_fasync(-1, file, 0); no_irq: #endif diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 85e0eb76eea..2457b07dabd 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -898,7 +898,6 @@ static int sonypi_misc_fasync(int fd, struct file *filp, int on) static int sonypi_misc_release(struct inode *inode, struct file *file) { - sonypi_misc_fasync(-1, file, 0); mutex_lock(&sonypi_device.lock); sonypi_device.open_count--; mutex_unlock(&sonypi_device.lock); diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 0d46627663b..78eeed5caaf 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -406,8 +406,6 @@ int drm_release(struct inode *inode, struct file *filp) if (dev->driver->driver_features & DRIVER_GEM) drm_gem_release(dev, file_priv); - drm_fasync(-1, filp, 0); - mutex_lock(&dev->ctxlist_mutex); if (!list_empty(&dev->ctxlist)) { struct drm_ctx_list *pos, *n; diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 3ac320785fc..83e851a5ed3 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -242,8 +242,6 @@ static int hiddev_release(struct inode * inode, struct file * file) struct hiddev_list *list = file->private_data; unsigned long flags; - hiddev_fasync(-1, file, 0); - spin_lock_irqsave(&list->hiddev->list_lock, flags); list_del(&list->node); spin_unlock_irqrestore(&list->hiddev->list_lock, flags); diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index 2f83543a9df..965cfdb84eb 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -1828,9 +1828,6 @@ static int dv1394_release(struct inode *inode, struct file *file) /* OK to free the DMA buffer, no more mappings can exist */ do_dv1394_shutdown(video, 1); - /* clean up async I/O users */ - dv1394_fasync(-1, file, 0); - /* give someone else a turn */ clear_bit(0, &video->open); diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index d85af1b6702..eb36a81dd09 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -358,8 +358,6 @@ static int ib_uverbs_event_close(struct inode *inode, struct file *filp) } spin_unlock_irq(&file->lock); - ib_uverbs_event_fasync(-1, filp, 0); - if (file->is_async) { ib_unregister_event_handler(&file->uverbs_file->event_handler); kref_put(&file->uverbs_file->ref, ib_uverbs_release_file); diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 3524bef62be..1070db330d3 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -235,7 +235,6 @@ static int evdev_release(struct inode *inode, struct file *file) evdev_ungrab(evdev, client); mutex_unlock(&evdev->mutex); - evdev_fasync(-1, file, 0); evdev_detach_client(evdev, client); kfree(client); diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 65d7077a75a..a85b1485e77 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -244,7 +244,6 @@ static int joydev_release(struct inode *inode, struct file *file) struct joydev_client *client = file->private_data; struct joydev *joydev = client->joydev; - joydev_fasync(-1, file, 0); joydev_detach_client(joydev, client); kfree(client); diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c index 82ec6b1b646..216a559f55e 100644 --- a/drivers/input/misc/hp_sdc_rtc.c +++ b/drivers/input/misc/hp_sdc_rtc.c @@ -71,7 +71,6 @@ static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file, static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait); static int hp_sdc_rtc_open(struct inode *inode, struct file *file); -static int hp_sdc_rtc_release(struct inode *inode, struct file *file); static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on); static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off, @@ -414,17 +413,6 @@ static int hp_sdc_rtc_open(struct inode *inode, struct file *file) return 0; } -static int hp_sdc_rtc_release(struct inode *inode, struct file *file) -{ - /* Turn off interrupts? */ - - if (file->f_flags & FASYNC) { - hp_sdc_rtc_fasync (-1, file, 0); - } - - return 0; -} - static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on) { return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue); @@ -680,7 +668,6 @@ static const struct file_operations hp_sdc_rtc_fops = { .poll = hp_sdc_rtc_poll, .ioctl = hp_sdc_rtc_ioctl, .open = hp_sdc_rtc_open, - .release = hp_sdc_rtc_release, .fasync = hp_sdc_rtc_fasync, }; diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 8137e50ded8..d8c056fe7e9 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -519,7 +519,6 @@ static int mousedev_release(struct inode *inode, struct file *file) struct mousedev_client *client = file->private_data; struct mousedev *mousedev = client->mousedev; - mousedev_fasync(-1, file, 0); mousedev_detach_client(mousedev, client); kfree(client); diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 470770c0926..06bbd0e74c6 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -135,7 +135,6 @@ static int serio_raw_release(struct inode *inode, struct file *file) mutex_lock(&serio_raw_mutex); - serio_raw_fasync(-1, file, 0); serio_raw_cleanup(serio_raw); mutex_unlock(&serio_raw_mutex); diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index f5233f3d9ef..b89f476cd0a 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -559,12 +559,6 @@ mptctl_fasync(int fd, struct file *filep, int mode) return ret; } -static int -mptctl_release(struct inode *inode, struct file *filep) -{ - return fasync_helper(-1, filep, 0, &async_queue); -} - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * MPT ioctl handler @@ -2706,7 +2700,6 @@ mptctl_hp_targetinfo(unsigned long arg) static const struct file_operations mptctl_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .release = mptctl_release, .fasync = mptctl_fasync, .unlocked_ioctl = mptctl_ioctl, #ifdef CONFIG_COMPAT diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index a3fabdbe6ca..f3384c32b9a 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c @@ -1097,28 +1097,17 @@ static int cfg_fasync(int fd, struct file *fp, int on) static int cfg_release(struct inode *inode, struct file *file) { ulong id = (ulong) file->private_data; - struct i2o_cfg_info *p1, *p2; + struct i2o_cfg_info *p, **q; unsigned long flags; lock_kernel(); - p1 = p2 = NULL; - spin_lock_irqsave(&i2o_config_lock, flags); - for (p1 = open_files; p1;) { - if (p1->q_id == id) { - - if (p1->fasync) - cfg_fasync(-1, file, 0); - if (p2) - p2->next = p1->next; - else - open_files = p1->next; - - kfree(p1); + for (q = &open_files; (p = *q) != NULL; q = &p->next) { + if (p->q_id == id) { + *q = p->next; + kfree(p); break; } - p2 = p1; - p1 = p1->next; } spin_unlock_irqrestore(&i2o_config_lock, flags); unlock_kernel(); diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index f483c4221f7..06f07e19dc7 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c @@ -1920,7 +1920,6 @@ static int sonypi_misc_fasync(int fd, struct file *filp, int on) static int sonypi_misc_release(struct inode *inode, struct file *file) { - sonypi_misc_fasync(-1, file, 0); atomic_dec(&sonypi_compat.open_count); return 0; } diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 6daea0c9186..33b6d1b122f 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1070,8 +1070,6 @@ static int tun_chr_close(struct inode *inode, struct file *file) DBG(KERN_INFO "%s: tun_chr_close\n", tun->dev->name); - tun_chr_fasync(-1, file, 0); - rtnl_lock(); /* Detach from net device */ diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 079e9ed907e..ecdea44ae4e 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -446,9 +446,6 @@ static int rtc_dev_release(struct inode *inode, struct file *file) if (rtc->ops->release) rtc->ops->release(rtc->dev.parent); - if (file->f_flags & FASYNC) - rtc_dev_fasync(-1, file, 0); - clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); return 0; } diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index afe1de99876..a454f94623d 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -2987,17 +2987,6 @@ static int megasas_mgmt_open(struct inode *inode, struct file *filep) return 0; } -/** - * megasas_mgmt_release - char node "release" entry point - */ -static int megasas_mgmt_release(struct inode *inode, struct file *filep) -{ - filep->private_data = NULL; - fasync_helper(-1, filep, 0, &megasas_async_queue); - - return 0; -} - /** * megasas_mgmt_fasync - Async notifier registration from applications * @@ -3345,7 +3334,6 @@ megasas_mgmt_compat_ioctl(struct file *file, unsigned int cmd, static const struct file_operations megasas_mgmt_fops = { .owner = THIS_MODULE, .open = megasas_mgmt_open, - .release = megasas_mgmt_release, .fasync = megasas_mgmt_fasync, .unlocked_ioctl = megasas_mgmt_ioctl, #ifdef CONFIG_COMPAT diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 9adf35bd8b5..5103855242a 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -327,7 +327,6 @@ sg_release(struct inode *inode, struct file *filp) if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; SCSI_LOG_TIMEOUT(3, printk("sg_release: %s\n", sdp->disk->disk_name)); - sg_fasync(-1, filp, 0); /* remove filp from async notification list */ if (0 == sg_remove_sfp(sdp, sfp)) { /* Returns 1 when sdp gone */ if (!sdp->detached) { scsi_device_put(sdp->device); diff --git a/drivers/staging/me4000/me4000.c b/drivers/staging/me4000/me4000.c index 0b33773bb4f..cf8b01bcac8 100644 --- a/drivers/staging/me4000/me4000.c +++ b/drivers/staging/me4000/me4000.c @@ -1633,9 +1633,6 @@ static int me4000_release(struct inode *inode_p, struct file *file_p) free_irq(ext_int_context->irq, ext_int_context); - /* Delete the fasync structure and free memory */ - me4000_ext_int_fasync(0, file_p, 0); - /* Mark as unused */ ext_int_context->in_use = 0; } else { diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index 41b6530b8f2..a913efc6966 100644 --- a/drivers/telephony/ixj.c +++ b/drivers/telephony/ixj.c @@ -2328,7 +2328,6 @@ static int ixj_release(struct inode *inode, struct file *file_p) j->rec_codec = j->play_codec = 0; j->rec_frame_size = j->play_frame_size = 0; j->flags.cidsent = j->flags.cidring = 0; - ixj_fasync(-1, file_p, 0); /* remove from list of async notification */ if(j->cardtype == QTI_LINEJACK && !j->readers && !j->writers) { ixj_set_port(j, PORT_PSTN); diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index f9b4647255a..2d2440cd57a 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -367,9 +367,6 @@ static int uio_release(struct inode *inode, struct file *filep) ret = idev->info->release(idev->info, inode); module_put(idev->owner); - - if (filep->f_flags & FASYNC) - ret = uio_fasync(-1, filep, 0); kfree(listener); return ret; } diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index f4585d3e90d..eeb26c0f88e 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1251,7 +1251,6 @@ dev_release (struct inode *inode, struct file *fd) * alternatively, all host requests will time out. */ - fasync_helper (-1, fd, 0, &dev->fasync); kfree (dev->buf); dev->buf = NULL; put_dev (dev); -- cgit v1.2.3 From 76f8bef0db031f03bf286c8bbccfaf83f0b22224 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Fri, 31 Oct 2008 22:50:04 +0800 Subject: remove unused #include 's The file(s) below do not use LINUX_VERSION_CODE nor KERNEL_VERSION. drivers/leds/leds-hp-disk.c drivers/misc/panasonic-laptop.c This patch removes the said #include . Signed-off-by: Huang Weiyi Signed-off-by: Linus Torvalds --- drivers/leds/leds-hp-disk.c | 1 - drivers/misc/panasonic-laptop.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/leds/leds-hp-disk.c b/drivers/leds/leds-hp-disk.c index 74645ab1566..44fa757d825 100644 --- a/drivers/leds/leds-hp-disk.c +++ b/drivers/leds/leds-hp-disk.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff --git a/drivers/misc/panasonic-laptop.c b/drivers/misc/panasonic-laptop.c index a2cb598d8ab..4a1bc64485d 100644 --- a/drivers/misc/panasonic-laptop.c +++ b/drivers/misc/panasonic-laptop.c @@ -116,7 +116,6 @@ * */ -#include #include #include #include -- cgit v1.2.3 From f5ee051e748ae007b972c7e1b6a0588b8ac9ba40 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 1 Nov 2008 18:20:39 +0000 Subject: section fixes for cirrusfb cirrusfb_zorro_unmap() may be called both from __devexit and (on cleanup path) from __devinit. So it needs to be a normal function, same as for cirrusfb_pci_unmap() Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/video/cirrusfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 048b139f0e5..8a8760230bc 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -2049,7 +2049,7 @@ static void cirrusfb_pci_unmap(struct fb_info *info) #endif /* CONFIG_PCI */ #ifdef CONFIG_ZORRO -static void __devexit cirrusfb_zorro_unmap(struct fb_info *info) +static void cirrusfb_zorro_unmap(struct fb_info *info) { struct cirrusfb_info *cinfo = info->par; struct zorro_dev *zdev = to_zorro_dev(info->device); -- cgit v1.2.3 From 9ca68233f2ec12efc950b4d15e9a761308da2b3e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 1 Nov 2008 18:19:59 +0000 Subject: missing dependencies on HAVE_CLK in drivers/mfd Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/mfd/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b550267c8d5..257277394f8 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -81,7 +81,7 @@ config MFD_TMIO config MFD_T7L66XB bool "Support Toshiba T7L66XB" - depends on ARM + depends on ARM && HAVE_CLK select MFD_CORE select MFD_TMIO help @@ -89,7 +89,7 @@ config MFD_T7L66XB config MFD_TC6387XB bool "Support Toshiba TC6387XB" - depends on ARM + depends on ARM && HAVE_CLK select MFD_CORE select MFD_TMIO help -- cgit v1.2.3 From 37b2a1791c8b8d630944afbe0745a08c8e8ae091 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 1 Nov 2008 18:20:19 +0000 Subject: el3_common_init() should be __devinit, not __init Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/net/3c509.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 3a7bc524af3..c7a4f3bcc2b 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -94,7 +94,7 @@ #include #include -static char version[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n"; +static char version[] __devinitdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n"; #ifdef EL3_DEBUG static int el3_debug = EL3_DEBUG; @@ -186,7 +186,7 @@ static int max_interrupt_work = 10; static int nopnp; #endif -static int __init el3_common_init(struct net_device *dev); +static int __devinit el3_common_init(struct net_device *dev); static void el3_common_remove(struct net_device *dev); static ushort id_read_eeprom(int index); static ushort read_eeprom(int ioaddr, int index); @@ -537,7 +537,7 @@ static struct mca_driver el3_mca_driver = { static int mca_registered; #endif /* CONFIG_MCA */ -static int __init el3_common_init(struct net_device *dev) +static int __devinit el3_common_init(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); int err; -- cgit v1.2.3 From af2b0a1ec37c61513d83d2d123658b4ef69d2ce9 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Sat, 1 Nov 2008 12:55:37 -0700 Subject: RDMA/cxgb3: Fix too-big reserved field zeroing in iwch_post_zb_read() The array wqe->read.reserved has only two entries, but iwch_post_zb_read() sets [0], [1], and [2], which is one too many. This is harmless since it runs into the next field, rem_stag, which is initialized correctly immediately after, but we might as well get things right, especially since it makes the code smaller. This was spotted by the Coverity checker (CID 2475). Signed-off-by: Roland Dreier Acked-by: Steve Wise --- drivers/infiniband/hw/cxgb3/iwch_qp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c index 3e4585c2318..19661b2f040 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_qp.c +++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c @@ -745,7 +745,6 @@ int iwch_post_zb_read(struct iwch_qp *qhp) wqe->read.rdmaop = T3_READ_REQ; wqe->read.reserved[0] = 0; wqe->read.reserved[1] = 0; - wqe->read.reserved[2] = 0; wqe->read.rem_stag = cpu_to_be32(1); wqe->read.rem_to = cpu_to_be64(1); wqe->read.local_stag = cpu_to_be32(1); -- cgit v1.2.3 From 60df3de8b1f5ce085049e9e3c83d96643c426158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Thu, 30 Oct 2008 13:02:54 +0200 Subject: pcmcia: fix indentation & braces disagreement - add braces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Broken by d8b0a49da4f2 (pcmcia: deprecate CS_BAD_VCC and CS_BAD_VPP). Signed-off-by: Ilpo Järvinen Signed-off-by: Dominik Brodowski --- drivers/pcmcia/pcmcia_resource.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 76d4a98f095..f5d0ba8e22d 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -302,9 +302,10 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, /* We only allow changing Vpp1 and Vpp2 to the same value */ if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { - if (mod->Vpp1 != mod->Vpp2) + if (mod->Vpp1 != mod->Vpp2) { ds_dbg(s, 0, "Vpp1 and Vpp2 must be the same\n"); return -EINVAL; + } s->socket.Vpp = mod->Vpp1; if (s->ops->set_socket(s, &s->socket)) { dev_printk(KERN_WARNING, &s->dev, -- cgit v1.2.3 From abdd5a0301a6306d6465ceca9de8e732b2fedaa5 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Sat, 1 Nov 2008 21:30:50 -0700 Subject: IRDA: remove double inclusion of module.h Signed-off-by: Alexander Beregalov Signed-off-by: David S. Miller --- drivers/net/irda/ks959-sir.c | 1 - drivers/net/irda/ksdazzle-sir.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/ks959-sir.c b/drivers/net/irda/ks959-sir.c index 2482d61662a..2e67ae015d9 100644 --- a/drivers/net/irda/ks959-sir.c +++ b/drivers/net/irda/ks959-sir.c @@ -118,7 +118,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/irda/ksdazzle-sir.c b/drivers/net/irda/ksdazzle-sir.c index 1e0de93fd61..3843b5faba8 100644 --- a/drivers/net/irda/ksdazzle-sir.c +++ b/drivers/net/irda/ksdazzle-sir.c @@ -82,7 +82,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 3e879f61434632ca099804713099f8f1627f929e Mon Sep 17 00:00:00 2001 From: Komuro Date: Sun, 2 Nov 2008 19:33:24 +0900 Subject: pcmcia: setup resource information for pseudo multifunction devices. Setup "io" and "irq" for pseudo multifunction devices. Signed-off-by: Komuro Signed-off-by: Dominik Brodowski --- drivers/pcmcia/ds.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 79566025549..00eee1435dc 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -668,6 +668,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) if (p_dev->func == tmp_dev->func) { p_dev->function_config = tmp_dev->function_config; + p_dev->io = tmp_dev->io; + p_dev->irq = tmp_dev->irq; kref_get(&p_dev->function_config->ref); } -- cgit v1.2.3 From 70d9d15833864e7120c3ffcfdbd6fa61f5f9726a Mon Sep 17 00:00:00 2001 From: Will Newton Date: Tue, 28 Oct 2008 10:52:36 +0000 Subject: drivers/net/smc911x.c: Fix lockdep warning on xmit. dev_kfree_skb should not be called with irqs disabled, use dev_kfree_skb_irq instead. The warning caused looks like this: ====================================================== [ INFO: hard-safe -> hard-unsafe lock order detected ] 2.6.28-rc1 #273 ------------------------------------------------------ swapper/0 [HC0[0]:SC1[2]:HE0:SE0] is trying to acquire: (clock-AF_INET){-..+}, at: [<4015c17c>] _sock_def_write_space+0x28/0xd8 and this task is already holding: (&lp->lock){++..}, at: [<4013f230>] _smc911x_hard_start_xmit+0x30/0x4b8 which would create a new lock dependency: (&lp->lock){++..} -> (clock-AF_INET){-..+} Signed-off-by: Will Newton Signed-off-by: Jeff Garzik --- drivers/net/smc911x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index f59c7772f34..5051554ff05 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -499,7 +499,7 @@ static void smc911x_hardware_send_pkt(struct net_device *dev) #else SMC_PUSH_DATA(lp, buf, len); dev->trans_start = jiffies; - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); #endif if (!lp->tx_throttle) { netif_wake_queue(dev); -- cgit v1.2.3 From 2509698687e2d8265a19d800f7daa6f87790a529 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sat, 1 Nov 2008 11:46:06 +0100 Subject: pcmcia: struct device - replace bus_id with dev_name(), dev_set_name() Signed-Off-By: Kay Sievers Acked-by: Greg Kroah-Hartman Signed-off-by: Dominik Brodowski --- drivers/pcmcia/cs.c | 2 +- drivers/pcmcia/ds.c | 9 ++++----- drivers/pcmcia/rsrc_nonstatic.c | 6 +++--- 3 files changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index c68c5d33828..5d0e60e09d3 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -226,7 +226,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) /* set proper values in socket->dev */ dev_set_drvdata(&socket->dev, socket); socket->dev.class = &pcmcia_socket_class; - snprintf(socket->dev.bus_id, BUS_ID_SIZE, "pcmcia_socket%u", socket->sock); + dev_set_name(&socket->dev, "pcmcia_socket%u", socket->sock); /* base address = 0, map = 0 */ socket->cis_mem.flags = 0; diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 00eee1435dc..47cab31ff6e 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -622,7 +622,6 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f { struct pcmcia_device *p_dev, *tmp_dev; unsigned long flags; - int bus_id_len; s = pcmcia_get_socket(s); if (!s) @@ -650,12 +649,12 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f /* by default don't allow DMA */ p_dev->dma_mask = DMA_MASK_NONE; p_dev->dev.dma_mask = &p_dev->dma_mask; - bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no); - - p_dev->devname = kmalloc(6 + bus_id_len + 1, GFP_KERNEL); + dev_set_name(&p_dev->dev, "%d.%d", p_dev->socket->sock, p_dev->device_no); + if (!dev_name(&p_dev->dev)) + goto err_free; + p_dev->devname = kasprintf(GFP_KERNEL, "pcmcia%s", dev_name(&p_dev->dev)); if (!p_dev->devname) goto err_free; - sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id); ds_dev_dbg(3, &p_dev->dev, "devname is %s\n", p_dev->devname); spin_lock_irqsave(&pcmcia_dev_list_lock, flags); diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 17f4ecf1c0c..9ca22c7aafb 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -71,7 +71,7 @@ static DEFINE_MUTEX(rsrc_mutex); ======================================================================*/ static struct resource * -make_resource(resource_size_t b, resource_size_t n, int flags, char *name) +make_resource(resource_size_t b, resource_size_t n, int flags, const char *name) { struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); @@ -624,7 +624,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star static struct resource *nonstatic_find_io_region(unsigned long base, int num, unsigned long align, struct pcmcia_socket *s) { - struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.bus_id); + struct resource *res = make_resource(0, num, IORESOURCE_IO, dev_name(&s->dev)); struct socket_data *s_data = s->resource_data; struct pcmcia_align_data data; unsigned long min = base; @@ -658,7 +658,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num, static struct resource * nonstatic_find_mem_region(u_long base, u_long num, u_long align, int low, struct pcmcia_socket *s) { - struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.bus_id); + struct resource *res = make_resource(0, num, IORESOURCE_MEM, dev_name(&s->dev)); struct socket_data *s_data = s->resource_data; struct pcmcia_align_data data; unsigned long min, max; -- cgit v1.2.3 From e689597fe890cf22e23195037aa668c39b25ae4b Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 2 Nov 2008 19:55:45 +0100 Subject: pcmcia: add braces in error path Signed-off-by: Dominik Brodowski --- drivers/pcmcia/cistpl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index dcce9f5d846..4a110b7b267 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -351,10 +351,11 @@ int verify_cis_cache(struct pcmcia_socket *s) char *buf; buf = kmalloc(256, GFP_KERNEL); - if (buf == NULL) + if (buf == NULL) { dev_printk(KERN_WARNING, &s->dev, "no memory for verifying CIS\n"); return -ENOMEM; + } list_for_each_entry(cis, &s->cis_cache, node) { int len = cis->len; -- cgit v1.2.3 From 9bd27cba1aeacb6b12d05f4e5ed6361072f08fe0 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sun, 2 Nov 2008 21:40:07 +0100 Subject: ide-cd: fix DMA alignment regression e5318b531b008c79d2a0c0df06a7b8628da38e2f ("ide: use the dma safe check for REQ_TYPE_ATA_PC") introduced a regression which caused some ATAPI drives to turn off DMA for REQ_TYPE_BLOCK_PC commands while burning and thus degrading performance and ultimately causing an excessive amount of underruns. The issue is documented also in: http://bugzilla.kernel.org/show_bug.cgi?id=11742. Signed-off-by: Borislav Petkov Cc: FUJITA Tomonori Tested-by: Valerio Passini [bart: fixup patch description per comments from Sergei Shtylyov] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-cd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 48b5eda3ab4..42ab6d8715f 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1250,7 +1250,8 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) * separate masks. */ alignment = queue_dma_alignment(q) | q->dma_pad_mask; - if ((unsigned long)buf & alignment || rq->data_len & alignment + if ((unsigned long)buf & alignment + || rq->data_len & q->dma_pad_mask || object_is_on_stack(buf)) drive->dma = 0; } -- cgit v1.2.3 From ccd32e221c3e3797ac56305c554ad8b07c13c815 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 2 Nov 2008 21:40:08 +0100 Subject: ide: Switch to a common address Signed-off-by: Alan Cox Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/alim15x3.c | 2 +- drivers/ide/hpt366.c | 2 +- drivers/ide/ide-disk.c | 2 +- drivers/ide/ide-iops.c | 2 +- drivers/ide/ide-pci-generic.c | 2 +- drivers/ide/ide-proc.c | 2 +- drivers/ide/it821x.c | 2 +- drivers/ide/jmicron.c | 2 +- drivers/ide/piix.c | 2 +- drivers/ide/scc_pata.c | 2 +- drivers/ide/siimage.c | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c index daf9dce39e5..e56c7b72f9e 100644 --- a/drivers/ide/alim15x3.c +++ b/drivers/ide/alim15x3.c @@ -5,7 +5,7 @@ * * Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org) * May be copied or modified under the terms of the GNU General Public License - * Copyright (C) 2002 Alan Cox + * Copyright (C) 2002 Alan Cox * ALi (now ULi M5228) support by Clear Zhang * Copyright (C) 2007 MontaVista Software, Inc. * Copyright (C) 2007 Bartlomiej Zolnierkiewicz diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index a7909e9c720..f5afd46ed51 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c @@ -52,7 +52,7 @@ * different clocks on read/write. This requires overloading rw_disk and * other deeply crazy things. Thanks to for * keeping me sane. - * Alan Cox + * Alan Cox * * - fix the clock turnaround code: it was writing to the wrong ports when * called for the secondary channel, caching the current clock mode per- diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index e5adebe8ac2..eb9fac4d0f0 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -2,7 +2,7 @@ * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) * Copyright (C) 1998-2002 Linux ATA Development * Andre Hedrick - * Copyright (C) 2003 Red Hat + * Copyright (C) 2003 Red Hat * Copyright (C) 2003-2005, 2007 Bartlomiej Zolnierkiewicz */ diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index bb7a1ed8094..5d6ba14e211 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2000-2002 Andre Hedrick - * Copyright (C) 2003 Red Hat + * Copyright (C) 2003 Red Hat * */ diff --git a/drivers/ide/ide-pci-generic.c b/drivers/ide/ide-pci-generic.c index 474f96a7c07..bddae2b329a 100644 --- a/drivers/ide/ide-pci-generic.c +++ b/drivers/ide/ide-pci-generic.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2001-2002 Andre Hedrick - * Portions (C) Copyright 2002 Red Hat Inc + * Portions (C) Copyright 2002 Red Hat Inc * * 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 diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index c31d0dd7a53..f3cddd1b2f8 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -1,6 +1,6 @@ /* * Copyright (C) 1997-1998 Mark Lord - * Copyright (C) 2003 Red Hat + * Copyright (C) 2003 Red Hat * * Some code was moved here from ide.c, see it for original copyrights. */ diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c index 995e18bb313..ef004089761 100644 --- a/drivers/ide/it821x.c +++ b/drivers/ide/it821x.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Red Hat + * Copyright (C) 2004 Red Hat * Copyright (C) 2007 Bartlomiej Zolnierkiewicz * * May be copied or modified under the terms of the GNU General Public License diff --git a/drivers/ide/jmicron.c b/drivers/ide/jmicron.c index 9a68433cf46..bf2be6431b2 100644 --- a/drivers/ide/jmicron.c +++ b/drivers/ide/jmicron.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2006 Red Hat + * Copyright (C) 2006 Red Hat * * May be copied or modified under the terms of the GNU General Public License */ diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c index d63f9fdca76..61d2d920a5c 100644 --- a/drivers/ide/piix.c +++ b/drivers/ide/piix.c @@ -1,7 +1,7 @@ /* * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-2000 Andre Hedrick - * Copyright (C) 2003 Red Hat Inc + * Copyright (C) 2003 Red Hat * Copyright (C) 2006-2007 MontaVista Software, Inc. * * May be copied or modified under the terms of the GNU General Public License diff --git a/drivers/ide/scc_pata.c b/drivers/ide/scc_pata.c index f26aa5d54ef..0f48f9dacfa 100644 --- a/drivers/ide/scc_pata.c +++ b/drivers/ide/scc_pata.c @@ -5,7 +5,7 @@ * * This code is based on drivers/ide/pci/siimage.c: * Copyright (C) 2001-2002 Andre Hedrick - * Copyright (C) 2003 Red Hat + * Copyright (C) 2003 Red Hat * * 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 diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c index c3107df7773..7d622d20bc4 100644 --- a/drivers/ide/siimage.c +++ b/drivers/ide/siimage.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2001-2002 Andre Hedrick - * Copyright (C) 2003 Red Hat + * Copyright (C) 2003 Red Hat * Copyright (C) 2007-2008 MontaVista Software, Inc. * Copyright (C) 2007-2008 Bartlomiej Zolnierkiewicz * -- cgit v1.2.3 From 630a8b2500c8d04e87e597c4afa5e1fafff04591 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sun, 2 Nov 2008 21:40:09 +0100 Subject: tx4938ide: Check minimum cycle time and SHWT range (v2) SHWT value is used as address valid to -CSx assertion and -CSx to -DIOx assertion setup time, and contrarywise, -DIOx to -CSx release and -CSx release to address invalid hold time, so it actualy applies 4 times and so constitutes -DIOx recovery time. Check requirement of the recovery time and cycle time. Also check SHWT maximum value. Suggested-by: Sergei Shtylyov Signed-off-by: Atsushi Nemoto Cc: ralf@linux-mips.org Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/tx4938ide.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c index fa660f931a1..9c518e72270 100644 --- a/drivers/ide/tx4938ide.c +++ b/drivers/ide/tx4938ide.c @@ -39,10 +39,17 @@ static void tx4938ide_tune_ebusc(unsigned int ebus_ch, /* Address-valid to DIOR/DIOW setup */ shwt = DIV_ROUND_UP(t->setup, cycle); + /* -DIOx recovery time (SHWT * 4) and cycle time requirement */ + while ((shwt * 4 + wt + (wt ? 2 : 3)) * cycle < t->cycle) + shwt++; + if (shwt > 7) { + pr_warning("tx4938ide: SHWT violation (%d)\n", shwt); + shwt = 7; + } pr_debug("tx4938ide: ebus %d, bus cycle %dns, WT %d, SHWT %d\n", ebus_ch, cycle, wt, shwt); - __raw_writeq((cr & ~(0x3f007ull)) | (wt << 12) | shwt, + __raw_writeq((cr & ~0x3f007ull) | (wt << 12) | shwt, &tx4938_ebuscptr->cr[ebus_ch]); } -- cgit v1.2.3 From 9d4eb0a33e620a85e36f66cf895d2bea6d556eac Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sun, 2 Nov 2008 21:40:09 +0100 Subject: tx4938ide: Do not call devm_ioremap for whole 128KB Call devm_ioremap() for CS0 and CS1 separetely. And some style cleanups. Suggested-by: Sergei Shtylyov Signed-off-by: Atsushi Nemoto Cc: ralf@linux-mips.org Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/tx4938ide.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c index 9c518e72270..796289cf97e 100644 --- a/drivers/ide/tx4938ide.c +++ b/drivers/ide/tx4938ide.c @@ -235,7 +235,7 @@ static int __init tx4938ide_probe(struct platform_device *pdev) struct resource *res; struct tx4938ide_platform_info *pdata = pdev->dev.platform_data; int irq, ret, i; - unsigned long mapbase; + unsigned long mapbase, mapctl; struct ide_port_info d = tx4938ide_port_info; irq = platform_get_irq(pdev, 0); @@ -249,38 +249,43 @@ static int __init tx4938ide_probe(struct platform_device *pdev) res->end - res->start + 1, "tx4938ide")) return -EBUSY; mapbase = (unsigned long)devm_ioremap(&pdev->dev, res->start, - res->end - res->start + 1); - if (!mapbase) + 8 << pdata->ioport_shift); + mapctl = (unsigned long)devm_ioremap(&pdev->dev, + res->start + 0x10000 + + (6 << pdata->ioport_shift), + 1 << pdata->ioport_shift); + if (!mapbase || !mapctl) return -EBUSY; memset(&hw, 0, sizeof(hw)); if (pdata->ioport_shift) { unsigned long port = mapbase; + unsigned long ctl = mapctl; hw.io_ports_array[0] = port; #ifdef __BIG_ENDIAN port++; + ctl++; #endif for (i = 1; i <= 7; i++) hw.io_ports_array[i] = port + (i << pdata->ioport_shift); - hw.io_ports.ctl_addr = - port + 0x10000 + (6 << pdata->ioport_shift); + hw.io_ports.ctl_addr = ctl; } else - ide_std_init_ports(&hw, mapbase, mapbase + 0x10006); + ide_std_init_ports(&hw, mapbase, mapctl); hw.irq = irq; hw.dev = &pdev->dev; - pr_info("TX4938 IDE interface (base %#lx, irq %d)\n", mapbase, hw.irq); + pr_info("TX4938 IDE interface (base %#lx, ctl %#lx, irq %d)\n", + mapbase, mapctl, hw.irq); if (pdata->gbus_clock) tx4938ide_tune_ebusc(pdata->ebus_ch, pdata->gbus_clock, 0); else d.port_ops = NULL; ret = ide_host_add(&d, hws, &host); - if (ret) - return ret; - platform_set_drvdata(pdev, host); - return 0; + if (!ret) + platform_set_drvdata(pdev, host); + return ret; } static int __exit tx4938ide_remove(struct platform_device *pdev) -- cgit v1.2.3 From 7afa05350c42d8427f2d8f6112b64ab0812f3289 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sun, 2 Nov 2008 21:40:10 +0100 Subject: tx4938ide: Avoid underflow on calculation of a wait cycle Make 'wt' variable signed while it can be negative during calculation. Suggested-by: Sergei Shtylyov Signed-off-by: Atsushi Nemoto Cc: sshtylyov@ru.mvista.com Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/tx4938ide.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c index 796289cf97e..9120063e8f8 100644 --- a/drivers/ide/tx4938ide.c +++ b/drivers/ide/tx4938ide.c @@ -26,12 +26,13 @@ static void tx4938ide_tune_ebusc(unsigned int ebus_ch, unsigned int sp = (cr >> 4) & 3; unsigned int clock = gbus_clock / (4 - sp); unsigned int cycle = 1000000000 / clock; - unsigned int wt, shwt; + unsigned int shwt; + int wt; /* Minimum DIOx- active time */ wt = DIV_ROUND_UP(t->act8b, cycle) - 2; /* IORDY setup time: 35ns */ - wt = max(wt, DIV_ROUND_UP(35, cycle)); + wt = max_t(int, wt, DIV_ROUND_UP(35, cycle)); /* actual wait-cycle is max(wt & ~1, 1) */ if (wt > 2 && (wt & 1)) wt++; -- cgit v1.2.3 From 52ebb438e952c674e5a5c131292589db9bcf169b Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sun, 2 Nov 2008 21:40:10 +0100 Subject: ide-gd: re-get capacity on revalidate We need to re-get a removable media's capacity when revalidating the disk so that its partitions get rescanned by the block layer. Signed-off-by: Borislav Petkov Cc: Tejun Heo Cc: axboe@kernel.dk Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-gd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c index 7b666285437..b8078b3231f 100644 --- a/drivers/ide/ide-gd.c +++ b/drivers/ide/ide-gd.c @@ -281,7 +281,12 @@ static int ide_gd_media_changed(struct gendisk *disk) static int ide_gd_revalidate_disk(struct gendisk *disk) { struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); - set_capacity(disk, ide_gd_capacity(idkp->drive)); + ide_drive_t *drive = idkp->drive; + + if (ide_gd_media_changed(disk)) + drive->disk_ops->get_capacity(drive); + + set_capacity(disk, ide_gd_capacity(drive)); return 0; } -- cgit v1.2.3 From 5a125c3c79167e78ba44efef03af7090ef28eeaf Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 22 Oct 2008 21:40:13 -0700 Subject: i915: Add GEM ioctl to get available aperture size. This will let userland know when to submit its batchbuffers, before they get too big to fit in the aperture. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_dma.c | 1 + drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_gem.c | 22 ++++++++++++++++++++++ 3 files changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 01de536e021..256e22963ae 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -960,6 +960,7 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0), DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0), DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0), + DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 901e80cf581..cc8a9f3f7a6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -502,6 +502,8 @@ int i915_gem_set_tiling(struct drm_device *dev, void *data, struct drm_file *file_priv); int i915_gem_get_tiling(struct drm_device *dev, void *data, struct drm_file *file_priv); +int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); void i915_gem_load(struct drm_device *dev); int i915_gem_proc_init(struct drm_minor *minor); void i915_gem_proc_cleanup(struct drm_minor *minor); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 17ae330ff26..c1733ac4a7f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -79,6 +79,28 @@ i915_gem_init_ioctl(struct drm_device *dev, void *data, return 0; } +int +i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_get_aperture *args = data; + struct drm_i915_gem_object *obj_priv; + + if (!(dev->driver->driver_features & DRIVER_GEM)) + return -ENODEV; + + args->aper_size = dev->gtt_total; + args->aper_available_size = args->aper_size; + + list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) { + if (obj_priv->pin_count > 0) + args->aper_available_size -= obj_priv->obj->size; + } + + return 0; +} + /** * Creates a new mm object and returns a handle to it. -- cgit v1.2.3 From 5880ff19fa29466cb9d7e293710e6aebecfecdd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Thu, 30 Oct 2008 13:39:43 +0200 Subject: RDMA/nes: Reindent mis-indented spinlocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ilpo Järvinen Signed-off-by: Roland Dreier --- drivers/infiniband/hw/nes/nes_verbs.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 932e56fcf77..ffdd141efe3 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -220,14 +220,14 @@ static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw, if (nesqp->ibqp_state > IB_QPS_RTS) return -EINVAL; - spin_lock_irqsave(&nesqp->lock, flags); + spin_lock_irqsave(&nesqp->lock, flags); head = nesqp->hwqp.sq_head; qsize = nesqp->hwqp.sq_tail; /* Check for SQ overflow */ if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) { - spin_unlock_irqrestore(&nesqp->lock, flags); + spin_unlock_irqrestore(&nesqp->lock, flags); return -EINVAL; } @@ -269,7 +269,7 @@ static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw, nes_write32(nesdev->regs+NES_WQE_ALLOC, (1 << 24) | 0x00800000 | nesqp->hwqp.qp_id); - spin_unlock_irqrestore(&nesqp->lock, flags); + spin_unlock_irqrestore(&nesqp->lock, flags); return 0; } @@ -3212,7 +3212,7 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, if (nesqp->ibqp_state > IB_QPS_RTS) return -EINVAL; - spin_lock_irqsave(&nesqp->lock, flags); + spin_lock_irqsave(&nesqp->lock, flags); head = nesqp->hwqp.sq_head; @@ -3337,7 +3337,7 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, (counter << 24) | 0x00800000 | nesqp->hwqp.qp_id); } - spin_unlock_irqrestore(&nesqp->lock, flags); + spin_unlock_irqrestore(&nesqp->lock, flags); if (err) *bad_wr = ib_wr; @@ -3368,7 +3368,7 @@ static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr, if (nesqp->ibqp_state > IB_QPS_RTS) return -EINVAL; - spin_lock_irqsave(&nesqp->lock, flags); + spin_lock_irqsave(&nesqp->lock, flags); head = nesqp->hwqp.rq_head; @@ -3421,7 +3421,7 @@ static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr, nes_write32(nesdev->regs+NES_WQE_ALLOC, (counter<<24) | nesqp->hwqp.qp_id); } - spin_unlock_irqrestore(&nesqp->lock, flags); + spin_unlock_irqrestore(&nesqp->lock, flags); if (err) *bad_wr = ib_wr; @@ -3453,7 +3453,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) nes_debug(NES_DBG_CQ, "\n"); - spin_lock_irqsave(&nescq->lock, flags); + spin_lock_irqsave(&nescq->lock, flags); head = nescq->hw_cq.cq_head; cq_size = nescq->hw_cq.cq_size; @@ -3562,7 +3562,7 @@ static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) nes_debug(NES_DBG_CQ, "Reporting %u completions for CQ%u.\n", cqe_count, nescq->hw_cq.cq_number); - spin_unlock_irqrestore(&nescq->lock, flags); + spin_unlock_irqrestore(&nescq->lock, flags); return cqe_count; } -- cgit v1.2.3 From 35c6d6942c966e6d74ea801d8b5007d7f900ce92 Mon Sep 17 00:00:00 2001 From: Chien Tung Date: Sun, 2 Nov 2008 21:37:35 -0800 Subject: RDMA/nes: Correct handling of PBL resources * Roll back allocated structures on failures. * Use GFP_ATOMIC instead of GFP_KERNEL since we are holding a lock. * Acquire nesadapter->pbl_lock when modifying PBL counters. * Decrement PBL counters on deallocation. Signed-off-by: Chien Tung Signed-off-by: Roland Dreier --- drivers/infiniband/hw/nes/nes_verbs.c | 44 ++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index ffdd141efe3..a8c2193a026 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -349,7 +349,7 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, if (nesfmr->nesmr.pbls_used > nesadapter->free_4kpbl) { spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); ret = -ENOMEM; - goto failed_vpbl_alloc; + goto failed_vpbl_avail; } else { nesadapter->free_4kpbl -= nesfmr->nesmr.pbls_used; } @@ -357,7 +357,7 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, if (nesfmr->nesmr.pbls_used > nesadapter->free_256pbl) { spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); ret = -ENOMEM; - goto failed_vpbl_alloc; + goto failed_vpbl_avail; } else { nesadapter->free_256pbl -= nesfmr->nesmr.pbls_used; } @@ -391,14 +391,14 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, goto failed_vpbl_alloc; } - nesfmr->root_vpbl.leaf_vpbl = kzalloc(sizeof(*nesfmr->root_vpbl.leaf_vpbl)*1024, GFP_KERNEL); + nesfmr->leaf_pbl_cnt = nesfmr->nesmr.pbls_used-1; + nesfmr->root_vpbl.leaf_vpbl = kzalloc(sizeof(*nesfmr->root_vpbl.leaf_vpbl)*1024, GFP_ATOMIC); if (!nesfmr->root_vpbl.leaf_vpbl) { spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); ret = -ENOMEM; goto failed_leaf_vpbl_alloc; } - nesfmr->leaf_pbl_cnt = nesfmr->nesmr.pbls_used-1; nes_debug(NES_DBG_MR, "two level pbl, root_vpbl.pbl_vbase=%p" " leaf_pbl_cnt=%d root_vpbl.leaf_vpbl=%p\n", nesfmr->root_vpbl.pbl_vbase, nesfmr->leaf_pbl_cnt, nesfmr->root_vpbl.leaf_vpbl); @@ -519,6 +519,16 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, nesfmr->root_vpbl.pbl_pbase); failed_vpbl_alloc: + if (nesfmr->nesmr.pbls_used != 0) { + spin_lock_irqsave(&nesadapter->pbl_lock, flags); + if (nesfmr->nesmr.pbl_4k) + nesadapter->free_4kpbl += nesfmr->nesmr.pbls_used; + else + nesadapter->free_256pbl += nesfmr->nesmr.pbls_used; + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + } + +failed_vpbl_avail: kfree(nesfmr); failed_fmr_alloc: @@ -534,18 +544,14 @@ static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd, */ static int nes_dealloc_fmr(struct ib_fmr *ibfmr) { + unsigned long flags; struct nes_mr *nesmr = to_nesmr_from_ibfmr(ibfmr); struct nes_fmr *nesfmr = to_nesfmr(nesmr); struct nes_vnic *nesvnic = to_nesvnic(ibfmr->device); struct nes_device *nesdev = nesvnic->nesdev; - struct nes_mr temp_nesmr = *nesmr; + struct nes_adapter *nesadapter = nesdev->nesadapter; int i = 0; - temp_nesmr.ibmw.device = ibfmr->device; - temp_nesmr.ibmw.pd = ibfmr->pd; - temp_nesmr.ibmw.rkey = ibfmr->rkey; - temp_nesmr.ibmw.uobject = NULL; - /* free the resources */ if (nesfmr->leaf_pbl_cnt == 0) { /* single PBL case */ @@ -561,8 +567,24 @@ static int nes_dealloc_fmr(struct ib_fmr *ibfmr) pci_free_consistent(nesdev->pcidev, 8192, nesfmr->root_vpbl.pbl_vbase, nesfmr->root_vpbl.pbl_pbase); } + nesmr->ibmw.device = ibfmr->device; + nesmr->ibmw.pd = ibfmr->pd; + nesmr->ibmw.rkey = ibfmr->rkey; + nesmr->ibmw.uobject = NULL; + + if (nesfmr->nesmr.pbls_used != 0) { + spin_lock_irqsave(&nesadapter->pbl_lock, flags); + if (nesfmr->nesmr.pbl_4k) { + nesadapter->free_4kpbl += nesfmr->nesmr.pbls_used; + WARN_ON(nesadapter->free_4kpbl > nesadapter->max_4kpbl); + } else { + nesadapter->free_256pbl += nesfmr->nesmr.pbls_used; + WARN_ON(nesadapter->free_256pbl > nesadapter->max_256pbl); + } + spin_unlock_irqrestore(&nesadapter->pbl_lock, flags); + } - return nes_dealloc_mw(&temp_nesmr.ibmw); + return nes_dealloc_mw(&nesmr->ibmw); } -- cgit v1.2.3 From 2e369544ac14de7bd0d76b369c1f6110eefbea8a Mon Sep 17 00:00:00 2001 From: Vadim Makhervaks Date: Sun, 2 Nov 2008 21:39:17 -0800 Subject: RDMA/nes: Fix CQ allocation scheme for multicast receive queue apps Fix CQ allocation for multicast receive queue applications. Before this patch, the CQ was not lined up with the right NIC. Signed-off-by: Vadim Makhervaks Signed-off-by: Chien Tung Signed-off-by: Roland Dreier --- drivers/infiniband/hw/nes/nes_verbs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index a8c2193a026..d36c9a0bf1b 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1617,7 +1617,7 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries, nes_ucontext->mcrqf = req.mcrqf; if (nes_ucontext->mcrqf) { if (nes_ucontext->mcrqf & 0x80000000) - nescq->hw_cq.cq_number = nesvnic->nic.qp_id + 12 + (nes_ucontext->mcrqf & 0xf) - 1; + nescq->hw_cq.cq_number = nesvnic->nic.qp_id + 28 + 2 * ((nes_ucontext->mcrqf & 0xf) - 1); else if (nes_ucontext->mcrqf & 0x40000000) nescq->hw_cq.cq_number = nes_ucontext->mcrqf & 0xffff; else -- cgit v1.2.3 From 633693660045b3e46a63ed618eb38a54339fbcc0 Mon Sep 17 00:00:00 2001 From: Chien Tung Date: Sun, 2 Nov 2008 21:40:55 -0800 Subject: RDMA/nes: Mitigate compatibility issue regarding PCIe write credits Under heavy load, there is an compatibility issue regarding PCIe write credits with certain chipsets. It can be mitigated by limiting read requests to 256 Bytes. This workaround is always enabled for Tbird2 on Gladius. We also add a module parameter to enable workaround for non-Gladius cards. Signed-off-by: Chien Tung Signed-off-by: Roland Dreier --- drivers/infiniband/hw/nes/nes.c | 16 ++++++++++++++++ drivers/infiniband/hw/nes/nes_hw.h | 1 + 2 files changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index a2b04d62b1a..aa1dc41f04c 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c @@ -95,6 +95,10 @@ unsigned int wqm_quanta = 0x10000; module_param(wqm_quanta, int, 0644); MODULE_PARM_DESC(wqm_quanta, "WQM quanta"); +static unsigned int limit_maxrdreqsz; +module_param(limit_maxrdreqsz, bool, 0644); +MODULE_PARM_DESC(limit_maxrdreqsz, "Limit max read request size to 256 Bytes"); + LIST_HEAD(nes_adapter_list); static LIST_HEAD(nes_dev_list); @@ -588,6 +592,18 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i nesdev->nesadapter->port_count; } + if ((limit_maxrdreqsz || + ((nesdev->nesadapter->phy_type[0] == NES_PHY_TYPE_GLADIUS) && + (hw_rev == NE020_REV1))) && + (pcie_get_readrq(pcidev) > 256)) { + if (pcie_set_readrq(pcidev, 256)) + printk(KERN_ERR PFX "Unable to set max read request" + " to 256 bytes\n"); + else + nes_debug(NES_DBG_INIT, "Max read request size set" + " to 256 bytes\n"); + } + tasklet_init(&nesdev->dpc_tasklet, nes_dpc, (unsigned long)nesdev); /* bring up the Control QP */ diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index 610b9d85959..bc0b4de0445 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h @@ -40,6 +40,7 @@ #define NES_PHY_TYPE_ARGUS 4 #define NES_PHY_TYPE_PUMA_1G 5 #define NES_PHY_TYPE_PUMA_10G 6 +#define NES_PHY_TYPE_GLADIUS 7 #define NES_MULTICAST_PF_MAX 8 -- cgit v1.2.3 From 55c8eb6c8eaa5009eed1557b296da5d4ea9c369a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 3 Nov 2008 00:04:24 -0800 Subject: SMC91x: Fix compilation on some platforms. This reverts 51ac3beffd4afaea4350526cf01fe74aaff25eff ('SMC91x: delete unused local variable "lp"') and adds __maybe_unused markers to these (potentially) unused variables. The issue is that in some configurations SMC_IO_SHIFT evaluates to '(lp->io_shift)', but in some others it's plain '0'. Based upon a build failure report from Manuel Lauss. Signed-off-by: David S. Miller --- drivers/net/smc91x.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 6f9895d4e5b..fc80f250da3 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -2060,6 +2060,7 @@ static int smc_request_attrib(struct platform_device *pdev, struct net_device *ndev) { struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib"); + struct smc_local *lp __maybe_unused = netdev_priv(ndev); if (!res) return 0; @@ -2074,6 +2075,7 @@ static void smc_release_attrib(struct platform_device *pdev, struct net_device *ndev) { struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib"); + struct smc_local *lp __maybe_unused = netdev_priv(ndev); if (res) release_mem_region(res->start, ATTRIB_SIZE); -- cgit v1.2.3 From 7385d595751874854a6729fbaaa7f793480bbb67 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 2 Nov 2008 17:49:59 +0300 Subject: fs_enet: fix polling 1. compile fix for irqreturn_t type change 2. restore ->poll_controller after CONFIG_PPC_CPM_NEW_BINDING transition Signed-off-by: Alexey Dobriyan Signed-off-by: Jeff Garzik --- drivers/net/fs_enet/fs_enet-main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index cb51c1fb033..a6f49d02578 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -1099,7 +1099,9 @@ static int __devinit fs_enet_probe(struct of_device *ofdev, ndev->stop = fs_enet_close; ndev->get_stats = fs_enet_get_stats; ndev->set_multicast_list = fs_set_multicast_list; - +#ifdef CONFIG_NET_POLL_CONTROLLER + ndev->poll_controller = fs_enet_netpoll; +#endif if (fpi->use_napi) netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi, fpi->napi_weight); @@ -1209,7 +1211,7 @@ static void __exit fs_cleanup(void) static void fs_enet_netpoll(struct net_device *dev) { disable_irq(dev->irq); - fs_enet_interrupt(dev->irq, dev, NULL); + fs_enet_interrupt(dev->irq, dev); enable_irq(dev->irq); } #endif -- cgit v1.2.3 From 1d19ecfc65ed01bac7a58f83004057ad704ee7cc Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Sun, 2 Nov 2008 20:30:33 -0800 Subject: net: kconfig cleanup The bool kconfig option added to ixgbe and myri10ge for DCA is ambigous, so this patch adds a description to the kconfig option. Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f749b40f954..11f143f4adf 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2010,9 +2010,13 @@ config IGB_LRO If in doubt, say N. config IGB_DCA - bool "Enable DCA" + bool "Direct Cache Access (DCA) Support" default y depends on IGB && DCA && !(IGB=y && DCA=m) + ---help--- + Say Y here if you want to use Direct Cache Access (DCA) in the + driver. DCA is a method for warming the CPU cache before data + is used, with the intent of lessening the impact of cache misses. source "drivers/net/ixp2000/Kconfig" @@ -2437,9 +2441,13 @@ config IXGBE will be called ixgbe. config IXGBE_DCA - bool + bool "Direct Cache Access (DCA) Support" default y depends on IXGBE && DCA && !(IXGBE=y && DCA=m) + ---help--- + Say Y here if you want to use Direct Cache Access (DCA) in the + driver. DCA is a method for warming the CPU cache before data + is used, with the intent of lessening the impact of cache misses. config IXGB tristate "Intel(R) PRO/10GbE support" @@ -2489,9 +2497,13 @@ config MYRI10GE will be called myri10ge. config MYRI10GE_DCA - bool + bool "Direct Cache Access (DCA) Support" default y depends on MYRI10GE && DCA && !(MYRI10GE=y && DCA=m) + ---help--- + Say Y here if you want to use Direct Cache Access (DCA) in the + driver. DCA is a method for warming the CPU cache before data + is used, with the intent of lessening the impact of cache misses. config NETXEN_NIC tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC" -- cgit v1.2.3 From ee04448d8871e71f55520d62cf6adbf5dd403c99 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sat, 1 Nov 2008 06:32:20 +0100 Subject: mv643xx_eth: fix SMI bus access timeouts The mv643xx_eth mii bus implementation uses wait_event_timeout() to wait for SMI completion interrupts. If wait_event_timeout() would return zero, mv643xx_eth would conclude that the SMI access timed out, but this is not necessarily true -- wait_event_timeout() can also return zero in the case where the SMI completion interrupt did happen in time but where it took longer than the requested timeout for the process performing the SMI access to be scheduled again. This would lead to occasional SMI access timeouts when the system would be under heavy load. The fix is to ignore the return value of wait_event_timeout(), and to re-check the SMI done bit after wait_event_timeout() returns to determine whether or not the SMI access timed out. Signed-off-by: Lennert Buytenhek Signed-off-by: Jeff Garzik --- drivers/net/mv643xx_eth.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index a9c8c08044b..b9dcdbd369f 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1066,9 +1066,12 @@ static int smi_wait_ready(struct mv643xx_eth_shared_private *msp) return 0; } - if (!wait_event_timeout(msp->smi_busy_wait, smi_is_done(msp), - msecs_to_jiffies(100))) - return -ETIMEDOUT; + if (!smi_is_done(msp)) { + wait_event_timeout(msp->smi_busy_wait, smi_is_done(msp), + msecs_to_jiffies(100)); + if (!smi_is_done(msp)) + return -ETIMEDOUT; + } return 0; } -- cgit v1.2.3 From bffadffd43d438c3143b8d172a463de89345b836 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Tue, 28 Oct 2008 14:44:11 +0800 Subject: PCI: fix VPD limit quirk for Broadcom 5708S VPD quirks need to be called after the VPD capability is initialized. Since VPD initialization now runs after pci_fixup_header (due to the capabilities consolidation), VPD quirks should be done at pci_fixup_final stage correspondingly. Tested-by: Eric Dumazet Signed-off-by: Yu Zhao Signed-off-by: Jesse Barnes --- drivers/pci/quirks.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index bbf66ea8fd8..5049a47030a 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1692,24 +1692,24 @@ static void __devinit quirk_brcm_570x_limit_vpd(struct pci_dev *dev) } } -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, - PCI_DEVICE_ID_NX2_5706, - quirk_brcm_570x_limit_vpd); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, - PCI_DEVICE_ID_NX2_5706S, - quirk_brcm_570x_limit_vpd); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, - PCI_DEVICE_ID_NX2_5708, - quirk_brcm_570x_limit_vpd); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, - PCI_DEVICE_ID_NX2_5708S, - quirk_brcm_570x_limit_vpd); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, - PCI_DEVICE_ID_NX2_5709, - quirk_brcm_570x_limit_vpd); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, - PCI_DEVICE_ID_NX2_5709S, - quirk_brcm_570x_limit_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_NX2_5706, + quirk_brcm_570x_limit_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_NX2_5706S, + quirk_brcm_570x_limit_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_NX2_5708, + quirk_brcm_570x_limit_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_NX2_5708S, + quirk_brcm_570x_limit_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_NX2_5709, + quirk_brcm_570x_limit_vpd); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, + PCI_DEVICE_ID_NX2_5709S, + quirk_brcm_570x_limit_vpd); #ifdef CONFIG_PCI_MSI /* Some chipsets do not support MSI. We cannot easily rely on setting -- cgit v1.2.3 From f5dafca52d366ef8c6c86cbdfecc71a9a78b63a6 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 29 Oct 2008 22:35:12 -0700 Subject: PCI: remove excess kernel-doc notation Fix pci/rom.c kernel-doc function notation: Warning(drivers/pci/rom.c:110): Excess function parameter or struct member 'return' description in 'pci_map_rom' Warning(drivers/pci/rom.c:177): Excess function parameter or struct member 'return' description in 'pci_map_rom_copy' Signed-off-by: Randy Dunlap Signed-off-by: Jesse Barnes --- drivers/pci/rom.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index 1f5f6143f35..132a78159b6 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c @@ -100,7 +100,8 @@ size_t pci_get_rom_size(void __iomem *rom, size_t size) * pci_map_rom - map a PCI ROM to kernel space * @pdev: pointer to pci device struct * @size: pointer to receive size of pci window over ROM - * @return: kernel virtual pointer to image of ROM + * + * Return: kernel virtual pointer to image of ROM * * Map a PCI ROM into kernel space. If ROM is boot video ROM, * the shadow BIOS copy will be returned instead of the @@ -167,7 +168,8 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) * pci_map_rom_copy - map a PCI ROM to kernel space, create a copy * @pdev: pointer to pci device struct * @size: pointer to receive size of pci window over ROM - * @return: kernel virtual pointer to image of ROM + * + * Return: kernel virtual pointer to image of ROM * * Map a PCI ROM into kernel space. If ROM is boot video ROM, * the shadow BIOS copy will be returned instead of the -- cgit v1.2.3 From 88e7df0b7ee717f9db3333fb1248827bbdb2d4d3 Mon Sep 17 00:00:00 2001 From: Ed Swierk Date: Mon, 3 Nov 2008 14:41:16 -0800 Subject: PCI: fix range check on mmapped sysfs resource files pci_mmap_fits() returns the wrong answer if the sysfs resource file size is not a multiple of the page size. vm_end and vm_start are already page-aligned, so size - start < nr, causing mmap() to return EINVAL. Signed-off-by: Ed Swierk Signed-off-by: Andrew Morton Signed-off-by: Jesse Barnes --- drivers/pci/pci-sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 110022d7868..5d72866897a 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -575,7 +575,7 @@ static int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; start = vma->vm_pgoff; - size = pci_resource_len(pdev, resno) >> PAGE_SHIFT; + size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1; if (start < size && size - start >= nr) return 1; WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n", -- cgit v1.2.3 From 9a0354405feb0f8bd460349a93db05e4cca8d166 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 3 Nov 2008 16:45:55 -0800 Subject: bnx2x: Removing the PMF indication when unloading When the PMF flag is set, the driver can access the HW freely. When the driver is unloaded, it should not access the HW. The problem caused fatal errors when "ethtool -i" was called after the calling instance was unloaded and another instance was already loaded Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index fce745148ff..61152e149e6 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6481,6 +6481,7 @@ load_int_disable: bnx2x_free_irq(bp); load_error: bnx2x_free_mem(bp); + bp->port.pmf = 0; /* TBD we really need to reset the chip if we want to recover from this */ @@ -6791,6 +6792,7 @@ unload_error: /* Report UNLOAD_DONE to MCP */ if (!BP_NOMCP(bp)) bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE); + bp->port.pmf = 0; /* Free SKBs, SGEs, TPA pool and driver internals */ bnx2x_free_skbs(bp); -- cgit v1.2.3 From 7d96567ac0527703cf1b80043fc0ebd7f21a10ad Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 3 Nov 2008 16:46:19 -0800 Subject: bnx2x: PCI configuration bug on big-endian The current code read nothing but zeros on big-endian (wrong part of the 32bits). This caused poor performance on big-endian machines. Though this issue did not cause the system to crash, the performance is significantly better with the fix so I view it as critical bug fix. Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_init.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2x_init.h b/drivers/net/bnx2x_init.h index 130927cfc75..a6c0b3abba2 100644 --- a/drivers/net/bnx2x_init.h +++ b/drivers/net/bnx2x_init.h @@ -564,14 +564,15 @@ static const struct arb_line write_arb_addr[NUM_WR_Q-1] = { static void bnx2x_init_pxp(struct bnx2x *bp) { + u16 devctl; int r_order, w_order; u32 val, i; pci_read_config_word(bp->pdev, - bp->pcie_cap + PCI_EXP_DEVCTL, (u16 *)&val); - DP(NETIF_MSG_HW, "read 0x%x from devctl\n", (u16)val); - w_order = ((val & PCI_EXP_DEVCTL_PAYLOAD) >> 5); - r_order = ((val & PCI_EXP_DEVCTL_READRQ) >> 12); + bp->pcie_cap + PCI_EXP_DEVCTL, &devctl); + DP(NETIF_MSG_HW, "read 0x%x from devctl\n", devctl); + w_order = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5); + r_order = ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12); if (r_order > MAX_RD_ORD) { DP(NETIF_MSG_HW, "read order of %d order adjusted to %d\n", -- cgit v1.2.3 From 12b56ea89e70d4b04f2f5199750310e82894ebbd Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 3 Nov 2008 16:46:40 -0800 Subject: bnx2x: Calling netif_carrier_off at the end of the probe netif_carrier_off was called too early at the probe. In case of failure or simply bad timing, this can cause a fatal error since linkwatch_event might run too soon. Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 61152e149e6..5b013d8457c 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -10206,8 +10206,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, return -ENOMEM; } - netif_carrier_off(dev); - bp = netdev_priv(dev); bp->msglevel = debug; @@ -10231,6 +10229,8 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, goto init_one_exit; } + netif_carrier_off(dev); + bp->common.name = board_info[ent->driver_data].name; printk(KERN_INFO "%s: %s (%c%d) PCI-E x%d %s found at mem %lx," " IRQ %d, ", dev->name, bp->common.name, -- cgit v1.2.3 From ca8eac55fa554043c57fd18d595ca356e752833e Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 3 Nov 2008 16:46:58 -0800 Subject: bnx2x: Version Update Updating the version Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 5b013d8457c..600210d7eff 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -59,8 +59,8 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.45.22" -#define DRV_MODULE_RELDATE "2008/09/09" +#define DRV_MODULE_VERSION "1.45.23" +#define DRV_MODULE_RELDATE "2008/11/03" #define BNX2X_BC_VER 0x040200 /* Time in jiffies before concluding the transmitter is hung */ -- cgit v1.2.3 From 19ecb6ba800765743bb4525c66562f0d30993f8d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 3 Nov 2008 17:05:16 -0800 Subject: niu: Use pci_ioremap_bar(). Signed-off-by: David S. Miller --- drivers/net/niu.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/niu.c b/drivers/net/niu.c index ebc81270290..9acb5d70a3a 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -8667,7 +8667,6 @@ static void __devinit niu_device_announce(struct niu *np) static int __devinit niu_pci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { - unsigned long niureg_base, niureg_len; union niu_parent_id parent_id; struct net_device *dev; struct niu *np; @@ -8758,10 +8757,7 @@ static int __devinit niu_pci_init_one(struct pci_dev *pdev, dev->features |= (NETIF_F_SG | NETIF_F_HW_CSUM); - niureg_base = pci_resource_start(pdev, 0); - niureg_len = pci_resource_len(pdev, 0); - - np->regs = ioremap_nocache(niureg_base, niureg_len); + np->regs = pci_ioremap_bar(pdev, 0); if (!np->regs) { dev_err(&pdev->dev, PFX "Cannot map device registers, " "aborting.\n"); -- cgit v1.2.3 From c2d06fe338912ee56c2ddd7de5574d5396ed8050 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 11 Sep 2008 10:56:00 +0800 Subject: intel_menlow: don't set max_state a negative value max_state is unsigned long. don't set max_state a negative value Cc : Thomas Sujith Cc : Roel Kluin Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/misc/intel_menlow.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c index e00a2756e97..124b37ddb5c 100644 --- a/drivers/misc/intel_menlow.c +++ b/drivers/misc/intel_menlow.c @@ -71,6 +71,9 @@ static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev, if (ACPI_FAILURE(status)) return -EFAULT; + if (!value) + return -EINVAL; + *max_state = value - 1; return 0; } @@ -121,7 +124,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev, if (memory_get_int_max_bandwidth(cdev, &max_state)) return -EFAULT; - if (max_state < 0 || state > max_state) + if (state > max_state) return -EINVAL; arg_list.count = 1; -- cgit v1.2.3 From cadef677e4a9b9c1d069675043767df486782986 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Fri, 31 Oct 2008 08:03:55 +0100 Subject: sata_promise: add ATA engine reset to reset ops Promise ATA engines need to be reset when errors occur. That's currently done for errors detected by sata_promise itself, but it's not done for errors like timeouts detected outside of the low-level driver. The effect of this omission is that a timeout tends to result in a sequence of failed COMRESETs after which libata EH gives up and disables the port. At that point the port's ATA engine hangs and even reloading the driver will not resume it. To fix this, make sata_promise override ->hardreset on SATA ports with code which calls pdc_reset_port() on the port in question before calling libata's hardreset. PATA ports don't use ->hardreset, so for those we override ->softreset instead. Signed-off-by: Mikael Pettersson Signed-off-by: Jeff Garzik --- drivers/ata/sata_promise.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 750d8cdc00c..ba9a2570a74 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -153,6 +153,10 @@ static void pdc_freeze(struct ata_port *ap); static void pdc_sata_freeze(struct ata_port *ap); static void pdc_thaw(struct ata_port *ap); static void pdc_sata_thaw(struct ata_port *ap); +static int pdc_pata_softreset(struct ata_link *link, unsigned int *class, + unsigned long deadline); +static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline); static void pdc_error_handler(struct ata_port *ap); static void pdc_post_internal_cmd(struct ata_queued_cmd *qc); static int pdc_pata_cable_detect(struct ata_port *ap); @@ -186,6 +190,7 @@ static struct ata_port_operations pdc_sata_ops = { .scr_read = pdc_sata_scr_read, .scr_write = pdc_sata_scr_write, .port_start = pdc_sata_port_start, + .hardreset = pdc_sata_hardreset, }; /* First-generation chips need a more restrictive ->check_atapi_dma op */ @@ -200,6 +205,7 @@ static struct ata_port_operations pdc_pata_ops = { .freeze = pdc_freeze, .thaw = pdc_thaw, .port_start = pdc_common_port_start, + .softreset = pdc_pata_softreset, }; static const struct ata_port_info pdc_port_info[] = { @@ -693,6 +699,20 @@ static void pdc_sata_thaw(struct ata_port *ap) readl(host_mmio + hotplug_offset); /* flush */ } +static int pdc_pata_softreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + pdc_reset_port(link->ap); + return ata_sff_softreset(link, class, deadline); +} + +static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + pdc_reset_port(link->ap); + return sata_sff_hardreset(link, class, deadline); +} + static void pdc_error_handler(struct ata_port *ap) { if (!(ap->pflags & ATA_PFLAG_FROZEN)) -- cgit v1.2.3 From 554d491de112a378b4d1a705bb93b58bcd444a70 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Sun, 2 Nov 2008 22:18:52 +0100 Subject: sata_via: restore vt*_prepare_host error handling commit b9d5b89b487517cbd4cb4702da829e07ef9e4432 (sata_via: fix support for 5287) accidently (?) removed vt*_prepare_host error handling - restore it catched by gcc: drivers/ata/sata_via.c: In function 'svia_init_one': drivers/ata/sata_via.c:567: warning: 'host' may be used uninitialized in this function Signed-off-by: Marcin Slusarz Cc: Tejun Heo Cc: Joseph Chan Cc: Jeff Garzik Signed-off-by: Jeff Garzik --- drivers/ata/sata_via.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 62367fe4d5d..c18935f0bda 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -602,8 +602,10 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rc = vt8251_prepare_host(pdev, &host); break; default: - return -EINVAL; + rc = -EINVAL; } + if (rc) + return rc; svia_configure(pdev); -- cgit v1.2.3 From 3c324283e6cdb79210cf7975c3e40d3ba3e672b2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 3 Nov 2008 12:37:49 +0900 Subject: sata_nv: fix generic, nf2/3 detection regression All three flavors of sata_nv's are different in how their hardreset behaves. * generic: Hardreset is not reliable. Link often doesn't come online after hardreset. * nf2/3: A little bit better - link comes online with longer debounce timing. However, nf2/3 can't reliable wait for the first D2H Register FIS, so it can't wait for device readiness or classify the device after hardreset. Follow-up SRST required. * ck804: Hardreset finally works. The core layer change to prefer hardreset and follow up changes exposed the above issues and caused various detection regressions for all three flavors. This patch, hopefully, fixes all the known issues and should make sata_nv error handling more reliable. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/sata_nv.c | 53 ++++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index fae3841de0d..6f146061432 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -307,10 +307,10 @@ static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); static void nv_nf2_freeze(struct ata_port *ap); static void nv_nf2_thaw(struct ata_port *ap); +static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline); static void nv_ck804_freeze(struct ata_port *ap); static void nv_ck804_thaw(struct ata_port *ap); -static int nv_hardreset(struct ata_link *link, unsigned int *class, - unsigned long deadline); static int nv_adma_slave_config(struct scsi_device *sdev); static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc); static void nv_adma_qc_prep(struct ata_queued_cmd *qc); @@ -405,17 +405,8 @@ static struct scsi_host_template nv_swncq_sht = { .slave_configure = nv_swncq_slave_config, }; -/* OSDL bz3352 reports that some nv controllers can't determine device - * signature reliably and nv_hardreset is implemented to work around - * the problem. This was reported on nf3 and it's unclear whether any - * other controllers are affected. However, the workaround has been - * applied to all variants and there isn't much to gain by trying to - * find out exactly which ones are affected at this point especially - * because NV has moved over to ahci for newer controllers. - */ static struct ata_port_operations nv_common_ops = { .inherits = &ata_bmdma_port_ops, - .hardreset = nv_hardreset, .scr_read = nv_scr_read, .scr_write = nv_scr_write, }; @@ -429,12 +420,22 @@ static struct ata_port_operations nv_generic_ops = { .hardreset = ATA_OP_NULL, }; +/* OSDL bz3352 reports that nf2/3 controllers can't determine device + * signature reliably. Also, the following thread reports detection + * failure on cold boot with the standard debouncing timing. + * + * http://thread.gmane.org/gmane.linux.ide/34098 + * + * Debounce with hotplug timing and request follow-up SRST. + */ static struct ata_port_operations nv_nf2_ops = { .inherits = &nv_common_ops, .freeze = nv_nf2_freeze, .thaw = nv_nf2_thaw, + .hardreset = nv_nf2_hardreset, }; +/* CK804 finally gets hardreset right */ static struct ata_port_operations nv_ck804_ops = { .inherits = &nv_common_ops, .freeze = nv_ck804_freeze, @@ -443,7 +444,7 @@ static struct ata_port_operations nv_ck804_ops = { }; static struct ata_port_operations nv_adma_ops = { - .inherits = &nv_common_ops, + .inherits = &nv_ck804_ops, .check_atapi_dma = nv_adma_check_atapi_dma, .sff_tf_read = nv_adma_tf_read, @@ -467,7 +468,7 @@ static struct ata_port_operations nv_adma_ops = { }; static struct ata_port_operations nv_swncq_ops = { - .inherits = &nv_common_ops, + .inherits = &nv_generic_ops, .qc_defer = ata_std_qc_defer, .qc_prep = nv_swncq_qc_prep, @@ -1553,6 +1554,17 @@ static void nv_nf2_thaw(struct ata_port *ap) iowrite8(mask, scr_addr + NV_INT_ENABLE); } +static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class, + unsigned long deadline) +{ + bool online; + int rc; + + rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline, + &online, NULL); + return online ? -EAGAIN : rc; +} + static void nv_ck804_freeze(struct ata_port *ap) { void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR]; @@ -1605,21 +1617,6 @@ static void nv_mcp55_thaw(struct ata_port *ap) ata_sff_thaw(ap); } -static int nv_hardreset(struct ata_link *link, unsigned int *class, - unsigned long deadline) -{ - int rc; - - /* SATA hardreset fails to retrieve proper device signature on - * some controllers. Request follow up SRST. For more info, - * see http://bugzilla.kernel.org/show_bug.cgi?id=3352 - */ - rc = sata_sff_hardreset(link, class, deadline); - if (rc) - return rc; - return -EAGAIN; -} - static void nv_adma_error_handler(struct ata_port *ap) { struct nv_adma_port_priv *pp = ap->private_data; -- cgit v1.2.3 From a464189de350b050aa8f334bd4cc53ed406e56dd Mon Sep 17 00:00:00 2001 From: Elias Oltmanns Date: Mon, 3 Nov 2008 19:01:08 +0900 Subject: libata: Fix a potential race condition in ata_scsi_park_show() Peter Moulder has pointed out that there is a slight chance that a negative value might be passed to jiffies_to_msecs() in ata_scsi_park_show(). This is fixed by saving the value of jiffies in a local variable, thus also reducing code since the volatile variable jiffies is accessed only once. Signed-off-by: Elias Oltmanns Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-scsi.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index bbb30d882f0..3fa75eac135 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -190,7 +190,7 @@ static ssize_t ata_scsi_park_show(struct device *device, struct ata_port *ap; struct ata_link *link; struct ata_device *dev; - unsigned long flags; + unsigned long flags, now; unsigned int uninitialized_var(msecs); int rc = 0; @@ -208,10 +208,11 @@ static ssize_t ata_scsi_park_show(struct device *device, } link = dev->link; + now = jiffies; if (ap->pflags & ATA_PFLAG_EH_IN_PROGRESS && link->eh_context.unloaded_mask & (1 << dev->devno) && - time_after(dev->unpark_deadline, jiffies)) - msecs = jiffies_to_msecs(dev->unpark_deadline - jiffies); + time_after(dev->unpark_deadline, now)) + msecs = jiffies_to_msecs(dev->unpark_deadline - now); else msecs = 0; -- cgit v1.2.3 From 6a87e42e955ff27e07a77f65f8f077dc7c4171e1 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 3 Nov 2008 19:01:09 +0900 Subject: libata: implement ATA_HORKAGE_ATAPI_MOD16_DMA and apply it libata always uses PIO for ATAPI commands when the number of bytes to transfer isn't multiple of 16 but quantum DAT72 chokes on odd bytes PIO transfers. Implement a horkage to skip the mod16 check and apply it to the quantum device. This is reported by John Clark in the following thread. http://thread.gmane.org/gmane.linux.ide/34748 Signed-off-by: Tejun Heo Cc: John Clark Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 82af7011f2d..91b478f2055 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4024,6 +4024,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Weird ATAPI devices */ { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, + { "QUANTUM DAT DAT72-000", NULL, ATA_HORKAGE_ATAPI_MOD16_DMA }, /* Devices we expect to fail diagnostics */ @@ -4444,7 +4445,8 @@ int atapi_check_dma(struct ata_queued_cmd *qc) /* Don't allow DMA if it isn't multiple of 16 bytes. Quite a * few ATAPI devices choke on such DMA requests. */ - if (unlikely(qc->nbytes & 15)) + if (!(qc->dev->horkage & ATA_HORKAGE_ATAPI_MOD16_DMA) && + unlikely(qc->nbytes & 15)) return 1; if (ap->ops->check_atapi_dma) -- cgit v1.2.3 From 299246f9a2a4c5c531863d72bad7ebd0de213de9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 3 Nov 2008 19:27:07 +0900 Subject: libata: mask off DET when restoring SControl for detach libata restores SControl on detach; however, trying to restore non-zero DET can cause undeterministic behavior including PMP device going offline till power cycling. Mask off DET when restoring SControl. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 91b478f2055..622350d9b2e 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5936,7 +5936,7 @@ static void ata_port_detach(struct ata_port *ap) * to us. Restore SControl and disable all existing devices. */ __ata_port_for_each_link(link, ap) { - sata_scr_write(link, SCR_CONTROL, link->saved_scontrol); + sata_scr_write(link, SCR_CONTROL, link->saved_scontrol & 0xff0); ata_link_for_each_dev(dev, link) ata_dev_disable(dev); } -- cgit v1.2.3 From 54074d59320581a6d7e4f4dd405e8cac1d174b75 Mon Sep 17 00:00:00 2001 From: Jianjun Kong Date: Tue, 4 Nov 2008 21:47:07 +0800 Subject: drivers: remove duplicated #include Signed-off-by: Jianjun Kong Signed-off-by: Linus Torvalds --- drivers/mtd/onenand/omap2.c | 1 - drivers/net/atl1e/atl1e.h | 1 - drivers/net/ucc_geth_ethtool.c | 1 - drivers/pnp/interface.c | 1 - drivers/sbus/char/jsflash.c | 1 - drivers/staging/echo/echo.c | 1 - drivers/staging/me4000/me4000.c | 1 - drivers/xen/balloon.c | 1 - 8 files changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 8387e05daae..e39b21d3e16 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/atl1e/atl1e.h b/drivers/net/atl1e/atl1e.h index b645fa0f3f6..c49550d507a 100644 --- a/drivers/net/atl1e/atl1e.h +++ b/drivers/net/atl1e/atl1e.h @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ucc_geth_ethtool.c index cfbbfee5583..85f38a6b6a4 100644 --- a/drivers/net/ucc_geth_ethtool.c +++ b/drivers/net/ucc_geth_ethtool.c @@ -37,7 +37,6 @@ #include #include #include -#include #include "ucc_geth.h" #include "ucc_geth_mii.h" diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index 478a4a739c0..c3f1c8e9d25 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c index 2bec9ccc029..a9a9893a5f9 100644 --- a/drivers/sbus/char/jsflash.c +++ b/drivers/sbus/char/jsflash.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include diff --git a/drivers/staging/echo/echo.c b/drivers/staging/echo/echo.c index b8f2c5e9dee..fd4007e329e 100644 --- a/drivers/staging/echo/echo.c +++ b/drivers/staging/echo/echo.c @@ -106,7 +106,6 @@ #include /* We're doing kernel work */ #include -#include #include #include "bit_operations.h" diff --git a/drivers/staging/me4000/me4000.c b/drivers/staging/me4000/me4000.c index cf8b01bcac8..0394e270927 100644 --- a/drivers/staging/me4000/me4000.c +++ b/drivers/staging/me4000/me4000.c @@ -39,7 +39,6 @@ #include #include #include -#include /* Include-File for the Meilhaus ME-4000 I/O board */ #include "me4000.h" diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 8c83abc7340..a0fb5eac407 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -41,7 +41,6 @@ #include #include #include -#include #include #include -- cgit v1.2.3 From 7b0f5df4c88bac46fe749d36d905fc7ad0296587 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 4 Nov 2008 11:18:56 -0800 Subject: mlx4_core: Fix unused variable warning Fix drivers/net/mlx4/profile.c:55: warning: 'res_name' defined but not used by making mlx4_dbg() always use all of its parameters, regardless of whether CONFIG_MLX4_DEBUG is set or not. Reported-by: Alexander Beregalov Signed-off-by: Roland Dreier --- drivers/net/mlx4/mlx4.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index fa431fad0ee..56a2e213fe6 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h @@ -87,6 +87,9 @@ enum { #ifdef CONFIG_MLX4_DEBUG extern int mlx4_debug_level; +#else /* CONFIG_MLX4_DEBUG */ +#define mlx4_debug_level (0) +#endif /* CONFIG_MLX4_DEBUG */ #define mlx4_dbg(mdev, format, arg...) \ do { \ @@ -94,12 +97,6 @@ extern int mlx4_debug_level; dev_printk(KERN_DEBUG, &mdev->pdev->dev, format, ## arg); \ } while (0) -#else /* CONFIG_MLX4_DEBUG */ - -#define mlx4_dbg(mdev, format, arg...) do { (void) mdev; } while (0) - -#endif /* CONFIG_MLX4_DEBUG */ - #define mlx4_err(mdev, format, arg...) \ dev_err(&mdev->pdev->dev, format, ## arg) #define mlx4_info(mdev, format, arg...) \ -- cgit v1.2.3 From fce4d58353e449a1ac637fc8d2b994e0fcc55312 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 2 Nov 2008 07:26:51 +0000 Subject: powerpc/ps3: Fix compile error in ps3-lpm.c Compiling with CONFIG_SMP = n and CONFIG_PS3_LPM != n gives this error: drivers/ps3/ps3-lpm.c:838: error: implicit declaration of function 'get_hard_smp_processor_id' This fixes it. We have to include rather than because the UP definition of get_hard_smp_processor_id() is in , and only includes if CONFIG_SMP = y. Signed-off-by: Alexey Dobriyan Acked-by: Geoff Levand Signed-off-by: Paul Mackerras --- drivers/ps3/ps3-lpm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/ps3/ps3-lpm.c b/drivers/ps3/ps3-lpm.c index 85edf945ab8..204158cf7a5 100644 --- a/drivers/ps3/ps3-lpm.c +++ b/drivers/ps3/ps3-lpm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 467622ef2acb01986eab37ef96c3632b3ea35999 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Sat, 1 Nov 2008 04:19:11 -0700 Subject: [MTD] [NOR] Fix cfi_send_gen_cmd handling of x16 devices in x8 mode (v4) For "unlock" cycles to 16bit devices in 8bit compatibility mode we need to use the byte addresses 0xaaa and 0x555. These effectively match the word address 0x555 and 0x2aa, except the latter has its low bit set. Most chips don't care about the value of the 'A-1' pin in x8 mode, but some -- like the ST M29W320D -- do. So we need to be careful to set it where appropriate. cfi_send_gen_cmd is only ever passed addresses where the low byte is 0x00, 0x55 or 0xaa. Of those, only addresses ending 0xaa are affected by this patch, by masking in the extra low bit when the device is known to be in compatibility mode. [dwmw2: Do it only when (cmd_ofs & 0xff) == 0xaa] v4: Fix stupid typo in cfi_build_cmd_addr that failed to compile I'm writing this patch way to late at night. v3: Bring all of the work back into cfi_build_cmd_addr including calling of map_bankwidth(map) and cfi_interleave(cfi) So every caller doesn't need to. v2: Only modified the address if we our device_type is larger than our bus width. Cc: stable@kernel.org Signed-off-by: Eric W. Biederman Signed-off-by: David Woodhouse --- drivers/mtd/chips/cfi_cmdset_0002.c | 13 ------------- drivers/mtd/chips/jedec_probe.c | 10 ++++------ 2 files changed, 4 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 3e6f5d8609e..d74ec46aa03 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -406,19 +406,6 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) /* Set the default CFI lock/unlock addresses */ cfi->addr_unlock1 = 0x555; cfi->addr_unlock2 = 0x2aa; - /* Modify the unlock address if we are in compatibility mode */ - if ( /* x16 in x8 mode */ - ((cfi->device_type == CFI_DEVICETYPE_X8) && - (cfi->cfiq->InterfaceDesc == - CFI_INTERFACE_X8_BY_X16_ASYNC)) || - /* x32 in x16 mode */ - ((cfi->device_type == CFI_DEVICETYPE_X16) && - (cfi->cfiq->InterfaceDesc == - CFI_INTERFACE_X16_BY_X32_ASYNC))) - { - cfi->addr_unlock1 = 0xaaa; - cfi->addr_unlock2 = 0x555; - } } /* CFI mode */ else if (cfi->cfi_mode == CFI_MODE_JEDEC) { diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index f84ab618214..2f3f2f719ba 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -1808,9 +1808,7 @@ static inline u32 jedec_read_mfr(struct map_info *map, uint32_t base, * several first banks can contain 0x7f instead of actual ID */ do { - uint32_t ofs = cfi_build_cmd_addr(0 + (bank << 8), - cfi_interleave(cfi), - cfi->device_type); + uint32_t ofs = cfi_build_cmd_addr(0 + (bank << 8), map, cfi); mask = (1 << (cfi->device_type * 8)) - 1; result = map_read(map, base + ofs); bank++; @@ -1824,7 +1822,7 @@ static inline u32 jedec_read_id(struct map_info *map, uint32_t base, { map_word result; unsigned long mask; - u32 ofs = cfi_build_cmd_addr(1, cfi_interleave(cfi), cfi->device_type); + u32 ofs = cfi_build_cmd_addr(1, map, cfi); mask = (1 << (cfi->device_type * 8)) -1; result = map_read(map, base + ofs); return result.x[0] & mask; @@ -2067,8 +2065,8 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, } /* Ensure the unlock addresses we try stay inside the map */ - probe_offset1 = cfi_build_cmd_addr(cfi->addr_unlock1, cfi_interleave(cfi), cfi->device_type); - probe_offset2 = cfi_build_cmd_addr(cfi->addr_unlock2, cfi_interleave(cfi), cfi->device_type); + probe_offset1 = cfi_build_cmd_addr(cfi->addr_unlock1, map, cfi); + probe_offset2 = cfi_build_cmd_addr(cfi->addr_unlock2, map, cfi); if ( ((base + probe_offset1 + map_bankwidth(map)) >= map->size) || ((base + probe_offset2 + map_bankwidth(map)) >= map->size)) goto retry; -- cgit v1.2.3 From 6b0eea21efed26f92e18741e54a3121cf5cd197e Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 24 Oct 2008 09:21:05 +0900 Subject: [SCSI] megaraid: fix mega_internal_command oops scsi_cmnd->cmnd was changed from a static array to a pointer post 2.6.25. It breaks mega_internal_command(): static int mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) { ... scb = &adapter->int_scb; memset(scb, 0, sizeof(scb_t)); scmd = &adapter->int_scmd; memset(scmd, 0, sizeof(Scsi_Cmnd)); sdev = kzalloc(sizeof(struct scsi_device), GFP_KERNEL); scmd->device = sdev; scmd->device->host = adapter->host; scmd->host_scribble = (void *)scb; scmd->cmnd[0] = MEGA_INTERNAL_CMD; mega_internal_command() uses scsi_cmnd allocated internally so scmd->cmnd is NULL here. This patch adds a static array for cdb to adapter_t and uses it here. This also uses scsi_allocate_command/scsi_free_command, the recommended way to allocate struct scsi_cmnd since the driver might use sense_buffer in struct scsi_cmnd. Signed-off-by: FUJITA Tomonori Reviewed-by: Boaz Harrosh Tested-by: Pascal Terjan Reported-by: Pascal Terjan Acked-by: "Yang, Bo" Signed-off-by: James Bottomley --- drivers/scsi/megaraid.c | 11 ++++++++--- drivers/scsi/megaraid.h | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 28c9da7d4a5..7dc62deb408 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -4402,6 +4402,10 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) scb_t *scb; int rval; + scmd = scsi_allocate_command(GFP_KERNEL); + if (!scmd) + return -ENOMEM; + /* * The internal commands share one command id and hence are * serialized. This is so because we want to reserve maximum number of @@ -4412,12 +4416,11 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) scb = &adapter->int_scb; memset(scb, 0, sizeof(scb_t)); - scmd = &adapter->int_scmd; - memset(scmd, 0, sizeof(Scsi_Cmnd)); - sdev = kzalloc(sizeof(struct scsi_device), GFP_KERNEL); scmd->device = sdev; + memset(adapter->int_cdb, 0, sizeof(adapter->int_cdb)); + scmd->cmnd = adapter->int_cdb; scmd->device->host = adapter->host; scmd->host_scribble = (void *)scb; scmd->cmnd[0] = MEGA_INTERNAL_CMD; @@ -4456,6 +4459,8 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) mutex_unlock(&adapter->int_mtx); + scsi_free_command(GFP_KERNEL, scmd); + return rval; } diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h index ee70bd4ae4b..795201fa0b4 100644 --- a/drivers/scsi/megaraid.h +++ b/drivers/scsi/megaraid.h @@ -888,8 +888,8 @@ typedef struct { u8 sglen; /* f/w supported scatter-gather list length */ + unsigned char int_cdb[MAX_COMMAND_SIZE]; scb_t int_scb; - Scsi_Cmnd int_scmd; struct mutex int_mtx; /* To synchronize the internal commands */ struct completion int_waitq; /* wait queue for internal -- cgit v1.2.3 From 821b3996001508e872582dcafc7575021f122728 Mon Sep 17 00:00:00 2001 From: Lalit Chandivade Date: Fri, 24 Oct 2008 15:13:44 -0700 Subject: [SCSI] qla2xxx: Correct Atmel flash-part handling. Use correct block size (4K) for erase command 0x20 for Atmel Flash. Use dword addresses for determining sector boundary. Cc: Stable Tree Signed-off-by: Lalit Chandivade Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 1 - drivers/scsi/qla2xxx/qla_sup.c | 19 +++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index f25f41a499e..b97194096d8 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2547,7 +2547,6 @@ typedef struct scsi_qla_host { uint8_t fcode_revision[16]; uint32_t fw_revision[4]; - uint16_t fdt_odd_index; uint32_t fdt_wrt_disable; uint32_t fdt_erase_cmd; uint32_t fdt_block_size; diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 90a13211717..e4af678eb2d 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -722,6 +722,7 @@ done: static void qla2xxx_get_fdt_info(scsi_qla_host_t *ha) { +#define FLASH_BLK_SIZE_4K 0x1000 #define FLASH_BLK_SIZE_32K 0x8000 #define FLASH_BLK_SIZE_64K 0x10000 const char *loc, *locations[] = { "MID", "FDT" }; @@ -755,7 +756,6 @@ qla2xxx_get_fdt_info(scsi_qla_host_t *ha) loc = locations[1]; mid = le16_to_cpu(fdt->man_id); fid = le16_to_cpu(fdt->id); - ha->fdt_odd_index = mid == 0x1f; ha->fdt_wrt_disable = fdt->wrt_disable_bits; ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd); ha->fdt_block_size = le32_to_cpu(fdt->block_size); @@ -788,8 +788,7 @@ no_flash_data: ha->fdt_block_size = FLASH_BLK_SIZE_64K; break; case 0x1f: /* Atmel 26DF081A. */ - ha->fdt_odd_index = 1; - ha->fdt_block_size = FLASH_BLK_SIZE_64K; + ha->fdt_block_size = FLASH_BLK_SIZE_4K; ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0320); ha->fdt_unprotect_sec_cmd = flash_conf_to_access_addr(0x0339); ha->fdt_protect_sec_cmd = flash_conf_to_access_addr(0x0336); @@ -801,9 +800,9 @@ no_flash_data: } done: DEBUG2(qla_printk(KERN_DEBUG, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x " - "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", loc, mid, fid, + "pro=%x upro=%x wrtd=0x%x blk=0x%x.\n", loc, mid, fid, ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd, - ha->fdt_unprotect_sec_cmd, ha->fdt_odd_index, ha->fdt_wrt_disable, + ha->fdt_unprotect_sec_cmd, ha->fdt_wrt_disable, ha->fdt_block_size)); } @@ -987,13 +986,9 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, qla24xx_unprotect_flash(ha); for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { - if (ha->fdt_odd_index) { - findex = faddr << 2; - fdata = findex & sec_mask; - } else { - findex = faddr; - fdata = (findex & sec_mask) << 2; - } + + findex = faddr; + fdata = (findex & sec_mask) << 2; /* Are we at the beginning of a sector? */ if ((findex & rest_addr) == 0) { -- cgit v1.2.3 From 737faece278ffec78612675bc378a4258d8293bb Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 24 Oct 2008 15:13:45 -0700 Subject: [SCSI] qla2xxx: Use pci_disable_rom() to manipulate PCI config space. http://bugzilla.kernel.org/show_bug.cgi?id=9422 Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index a470f2d3270..ecf91ad4027 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -140,7 +140,6 @@ int qla2100_pci_config(scsi_qla_host_t *ha) { uint16_t w; - uint32_t d; unsigned long flags; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; @@ -151,10 +150,7 @@ qla2100_pci_config(scsi_qla_host_t *ha) w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); pci_write_config_word(ha->pdev, PCI_COMMAND, w); - /* Reset expansion ROM address decode enable */ - pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); - d &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); + pci_disable_rom(ha->pdev); /* Get PCI bus information. */ spin_lock_irqsave(&ha->hardware_lock, flags); @@ -174,7 +170,6 @@ int qla2300_pci_config(scsi_qla_host_t *ha) { uint16_t w; - uint32_t d; unsigned long flags = 0; uint32_t cnt; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; @@ -236,10 +231,7 @@ qla2300_pci_config(scsi_qla_host_t *ha) pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); - /* Reset expansion ROM address decode enable */ - pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); - d &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); + pci_disable_rom(ha->pdev); /* Get PCI bus information. */ spin_lock_irqsave(&ha->hardware_lock, flags); @@ -259,7 +251,6 @@ int qla24xx_pci_config(scsi_qla_host_t *ha) { uint16_t w; - uint32_t d; unsigned long flags = 0; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; @@ -281,10 +272,7 @@ qla24xx_pci_config(scsi_qla_host_t *ha) if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP)) pcie_set_readrq(ha->pdev, 2048); - /* Reset expansion ROM address decode enable */ - pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); - d &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); + pci_disable_rom(ha->pdev); ha->chip_revision = ha->pdev->revision; @@ -306,7 +294,6 @@ int qla25xx_pci_config(scsi_qla_host_t *ha) { uint16_t w; - uint32_t d; pci_set_master(ha->pdev); pci_try_set_mwi(ha->pdev); @@ -320,10 +307,7 @@ qla25xx_pci_config(scsi_qla_host_t *ha) if (pci_find_capability(ha->pdev, PCI_CAP_ID_EXP)) pcie_set_readrq(ha->pdev, 2048); - /* Reset expansion ROM address decode enable */ - pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); - d &= ~PCI_ROM_ADDRESS_ENABLE; - pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); + pci_disable_rom(ha->pdev); ha->chip_revision = ha->pdev->revision; -- cgit v1.2.3 From 680d7db88ace53c673e1c437c9b6abcc053e8d6f Mon Sep 17 00:00:00 2001 From: Shyam Sundar Date: Fri, 24 Oct 2008 15:13:46 -0700 Subject: [SCSI] qla2xxx: Do not honour max_vports from firmware for 2G ISPs and below. For 23XX ISPs, max_vports may return an invalid value. Do not honour it. Cc: Stable Tree Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 2 +- drivers/scsi/qla2xxx/qla_mbx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index ecf91ad4027..4218f20f5ed 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -964,7 +964,6 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) &ha->fw_minor_version, &ha->fw_subminor_version, &ha->fw_attributes, &ha->fw_memory_size); - qla2x00_resize_request_q(ha); ha->flags.npiv_supported = 0; if ((IS_QLA24XX(ha) || IS_QLA25XX(ha) || IS_QLA84XX(ha)) && @@ -976,6 +975,7 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) ha->max_npiv_vports = MIN_MULTI_ID_FABRIC - 1; } + qla2x00_resize_request_q(ha); if (ql2xallocfwdump) qla2x00_alloc_fw_dump(ha); diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 36bc6851e23..3402746ec12 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1964,7 +1964,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt, *cur_iocb_cnt = mcp->mb[7]; if (orig_iocb_cnt) *orig_iocb_cnt = mcp->mb[10]; - if (max_npiv_vports) + if (ha->flags.npiv_supported && max_npiv_vports) *max_npiv_vports = mcp->mb[11]; } -- cgit v1.2.3 From 5bff55db3dc4d659f46b4d2fce2f61c1964c2762 Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Fri, 24 Oct 2008 15:13:47 -0700 Subject: [SCSI] qla2xxx: Return a FAILED status when abort mailbox-command fails. Mike Reed noted (https://bugzilla.novell.com/show_bug.cgi?id=421330) that the driver was incorrectly returning a SUCCESS status if the driver's request to the firmware to abort a command failed. By doing so, the mid-layer believed, incorrectly, that the command has completed and has been returned (ultimately clearing scsi_cmnd.request_buffer) yet the driver still has the command. What should correctly happen is a mid-layer escalation (device-reset, etc.) of recovery during which the driver will eventually return the outstanding commands to the mid-layer. Cc: Stable Tree Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 21dd182ad51..35567203ef6 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -728,6 +728,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) if (ha->isp_ops->abort_command(ha, sp)) { DEBUG2(printk("%s(%ld): abort_command " "mbx failed.\n", __func__, ha->host_no)); + ret = FAILED; } else { DEBUG3(printk("%s(%ld): abort_command " "mbx success.\n", __func__, ha->host_no)); -- cgit v1.2.3 From 3869a1728808fc9e075d0091bb03826fa6ed58b0 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 24 Oct 2008 15:13:48 -0700 Subject: [SCSI] qla2xxx: Update version number to 8.02.01-k9. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index be5e299df52..eea6720adf1 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.02.01-k8" +#define QLA2XXX_VERSION "8.02.01-k9" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 2 -- cgit v1.2.3 From 26816f1c2bf59a269917815adb1d972b9fb65e3a Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 4 Nov 2008 16:35:05 +0100 Subject: [SCSI] zfcp: Dont clear reference from SCSI device to unit It is possible that a remote port has a problem, the SCSI device gets deleted after the rport timeout and then the timeout for pending SCSI commands trigger an abort. For this case, don't delete the reference from the SCSI device to the zfcp unit, so that we can still have the reference to issue an abort request. Signed-off-by: Christof Schmitt Signed-off-by: Swen Schillig Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_scsi.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index ca8f85f3dad..e46fd3e9f68 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -24,14 +24,10 @@ char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu) static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) { struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; - WARN_ON(!unit); - if (unit) { - atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); - sdpnt->hostdata = NULL; - unit->device = NULL; - zfcp_erp_unit_failed(unit, 12, NULL); - zfcp_unit_put(unit); - } + atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); + unit->device = NULL; + zfcp_erp_unit_failed(unit, 12, NULL); + zfcp_unit_put(unit); } static int zfcp_scsi_slave_configure(struct scsi_device *sdp) -- cgit v1.2.3 From 45316a86a67934ab499dcfac44c91aa8f39c4c78 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 4 Nov 2008 16:35:06 +0100 Subject: [SCSI] zfcp: fix req_list_locking. The per adapter req_list_lock must be held with interrupts disabled, otherwise we might end up with nice deadlocks as lockdep tells us (see below). zfcp 0.0.1804: QDIO problem occurred. ========================================================= [ INFO: possible irq lock inversion dependency detected ] 2.6.27-rc8-00035-g4a77035-dirty #86 --------------------------------------------------------- swapper/0 just changed the state of lock: (&adapter->erp_lock){++..}, at: [<00000000002c82ae>] zfcp_erp_adapter_reopen+0x4e/0x8c but this lock took another, hard-irq-unsafe lock in the past: (&adapter->req_list_lock){-+..} and interrupts could create inverse lock ordering between them. [tons of backtraces, but only the interesting part follows] the second lock's dependencies: -> (&adapter->req_list_lock){-+..} ops: 2280627634176 { initial-use at: [<0000000000071f10>] __lock_acquire+0x504/0x18bc [<000000000007335c>] lock_acquire+0x94/0xbc [<00000000003d7224>] _spin_lock_irqsave+0x6c/0xb0 [<00000000002cf684>] zfcp_fsf_req_dismiss_all+0x50/0x140 [<00000000002c87ee>] zfcp_erp_adapter_strategy_generic+0x66/0x3d0 [<00000000002c9498>] zfcp_erp_thread+0x88c/0x1318 [<000000000001b0d2>] kernel_thread_starter+0x6/0xc [<000000000001b0cc>] kernel_thread_starter+0x0/0xc in-softirq-W at: [<0000000000072172>] __lock_acquire+0x766/0x18bc [<000000000007335c>] lock_acquire+0x94/0xbc [<00000000003d7224>] _spin_lock_irqsave+0x6c/0xb0 [<00000000002ca73e>] zfcp_qdio_int_resp+0xbe/0x2ac [<000000000027a1d6>] qdio_kick_inbound_handler+0x82/0xa0 [<000000000027daba>] tiqdio_inbound_processing+0x62/0xf8 [<0000000000047ba4>] tasklet_action+0x100/0x1f4 [<0000000000048b5a>] __do_softirq+0xae/0x154 [<0000000000021e4a>] do_softirq+0xea/0xf0 [<00000000000485de>] irq_exit+0xde/0xe8 [<0000000000268c64>] do_IRQ+0x160/0x1fc [<00000000000261a2>] io_return+0x0/0x8 [<000000000001b8f8>] cpu_idle+0x17c/0x224 hardirq-on-W at: [<0000000000072190>] __lock_acquire+0x784/0x18bc [<000000000007335c>] lock_acquire+0x94/0xbc [<00000000003d702c>] _spin_lock+0x5c/0x9c [<00000000002caff6>] zfcp_fsf_req_send+0x3e/0x158 [<00000000002ce7fe>] zfcp_fsf_exchange_config_data+0x106/0x124 [<00000000002c8948>] zfcp_erp_adapter_strategy_generic+0x1c0/0x3d0 [<00000000002c98ea>] zfcp_erp_thread+0xcde/0x1318 [<000000000001b0d2>] kernel_thread_starter+0x6/0xc [<000000000001b0cc>] kernel_thread_starter+0x0/0xc } ... key at: [<0000000000e356c8>] __key.26629+0x0/0x8 Signed-off-by: Heiko Carstens Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 5ae1d497e5e..694d9c9ea7c 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -770,13 +770,14 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) { struct zfcp_adapter *adapter = req->adapter; struct zfcp_qdio_queue *req_q = &adapter->req_q; + unsigned long flags; int idx; /* put allocated FSF request into hash table */ - spin_lock(&adapter->req_list_lock); + spin_lock_irqsave(&adapter->req_list_lock, flags); idx = zfcp_reqlist_hash(req->req_id); list_add_tail(&req->list, &adapter->req_list[idx]); - spin_unlock(&adapter->req_list_lock); + spin_unlock_irqrestore(&adapter->req_list_lock, flags); req->qdio_outb_usage = atomic_read(&req_q->count); req->issued = get_clock(); -- cgit v1.2.3 From 88f2a977870af655296a682fe2a58c822cd25bb2 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 4 Nov 2008 16:35:07 +0100 Subject: [SCSI] zfcp: fix mempool usage for status_read requests When allocating fsf requests without qtcb, store the pointer to the mempool in the fsf requests for later call to mempool_free. This codepath is only used by the status_read requests. Signed-off-by: Christof Schmitt Signed-off-by: Swen Schillig Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 694d9c9ea7c..5e8517fc8b6 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -683,6 +683,7 @@ static struct zfcp_fsf_req *zfcp_fsf_alloc_noqtcb(mempool_t *pool) if (!req) return NULL; memset(req, 0, sizeof(*req)); + req->pool = pool; return req; } -- cgit v1.2.3 From 3765138ae946e6e29b22bf15a9647c600c232639 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 4 Nov 2008 16:35:08 +0100 Subject: [SCSI] zfcp: Fix request list handling in error path Fix the handling of the request list in the error path: - Use irqsave for the lock as in the good path. - Before removing the request, check if it is still in the list, a call to dismiss_all might have changed the list in between. - zfcp_qdio_send does not change the queue counters on failure, trying revert something is wrong, so remove this. Signed-off-by: Christof Schmitt Signed-off-by: Swen Schillig Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 5e8517fc8b6..d024442ee12 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -770,7 +770,6 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_adapter *adapter, static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) { struct zfcp_adapter *adapter = req->adapter; - struct zfcp_qdio_queue *req_q = &adapter->req_q; unsigned long flags; int idx; @@ -780,19 +779,15 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *req) list_add_tail(&req->list, &adapter->req_list[idx]); spin_unlock_irqrestore(&adapter->req_list_lock, flags); - req->qdio_outb_usage = atomic_read(&req_q->count); + req->qdio_outb_usage = atomic_read(&adapter->req_q.count); req->issued = get_clock(); if (zfcp_qdio_send(req)) { - /* Queues are down..... */ del_timer(&req->timer); - spin_lock(&adapter->req_list_lock); - zfcp_reqlist_remove(adapter, req); - spin_unlock(&adapter->req_list_lock); - /* undo changes in request queue made for this request */ - atomic_add(req->sbal_number, &req_q->count); - req_q->first -= req->sbal_number; - req_q->first += QDIO_MAX_BUFFERS_PER_Q; - req_q->first %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */ + spin_lock_irqsave(&adapter->req_list_lock, flags); + /* lookup request again, list might have changed */ + if (zfcp_reqlist_find_safe(adapter, req)) + zfcp_reqlist_remove(adapter, req); + spin_unlock_irqrestore(&adapter->req_list_lock, flags); zfcp_erp_adapter_reopen(adapter, 0, 116, req); return -EIO; } -- cgit v1.2.3 From adc90daffbb454eeae00df92855a88ba79b5b636 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 4 Nov 2008 16:35:09 +0100 Subject: [SCSI] zfcp: Fix cast warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix leftover from last typecast patch: drivers/s390/scsi/zfcp_aux.c: In function ‘zfcp_port_enqueue’: drivers/s390/scsi/zfcp_aux.c:629: warning: format ‘%016llx’ expects type ‘long long unsigned int’, but argument 3 has type ‘u64’ Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 3b56220fb90..3d4e3e3f3fc 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -610,7 +610,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status); atomic_set(&port->refcount, 0); - dev_set_name(&port->sysfs_device, "0x%016llx", wwpn); + dev_set_name(&port->sysfs_device, "0x%016llx", + (unsigned long long)wwpn); port->sysfs_device.parent = &adapter->ccw_device->dev; port->sysfs_device.release = zfcp_sysfs_port_release; -- cgit v1.2.3 From 77fd9494bce3188c20d82e45464ed9b1be83bf98 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 4 Nov 2008 16:35:10 +0100 Subject: [SCSI] zfcp: Wait for port scan to complete when setting adapter online Attaching a unit immediately after setting the adapter online should be possible. The problem right now is that the port_scan runs from a workqueue and has not finished when the set_online call returns and the sysfs structures for the ports are not available yet. Fix that by waiting for the port scan to complete. Signed-off-by: Christof Schmitt Signed-off-by: Swen Schillig Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_ccw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index b04038c7478..951a8d409d1 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -116,7 +116,9 @@ static int zfcp_ccw_set_online(struct ccw_device *ccw_device) zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, 85, NULL); zfcp_erp_wait(adapter); - goto out; + up(&zfcp_data.config_sema); + flush_work(&adapter->scan_work); + return 0; out_scsi_register: zfcp_erp_thread_kill(adapter); -- cgit v1.2.3 From 7ea633ffad0bcb0b3e0deee81997d07f292e7f44 Mon Sep 17 00:00:00 2001 From: Martin Petermann Date: Tue, 4 Nov 2008 16:35:11 +0100 Subject: [SCSI] zfcp: fix erp timeout cleanup for port open requests If an open port fsf request times out (in erp) the corresponding erp_action member of the fsf request need to set to NULL. If the port structure will be removed later-on there will be still a reference in the fsf request to the non existing erp_action otherwise. Signed-off-by: Martin Petermann Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_erp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 9040f738ff3..35364f64da7 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -472,6 +472,7 @@ static void zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *act) ZFCP_STATUS_ERP_TIMEDOUT)) { act->fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; zfcp_rec_dbf_event_action(142, act); + act->fsf_req->erp_action = NULL; } if (act->status & ZFCP_STATUS_ERP_TIMEDOUT) zfcp_rec_dbf_event_action(143, act); -- cgit v1.2.3 From d94ce6c6e99252ab2ba340b0398c8651713a9f05 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 4 Nov 2008 16:35:12 +0100 Subject: [SCSI] zfcp: Fix hexdump data in s390dbf traces Fix multiple problems found in the hexdump data: - length calculation was wrong, traces were incomplete - FC payloads were dumped in different record than the output function tried to read - minor fixes in output - allow complete RSCN traces (up to 1024 bytes according to spec) Signed-off-by: Christof Schmitt Signed-off-by: Swen Schillig Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_dbf.c | 42 ++++++++++++++++-------------------------- drivers/s390/scsi/zfcp_dbf.h | 8 ++------ 2 files changed, 18 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 060f5f2352e..31012d58cfb 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -30,7 +30,7 @@ static void zfcp_dbf_hexdump(debug_info_t *dbf, void *to, int to_len, dump->offset = offset; dump->size = min(from_len - offset, room); memcpy(dump->data, from + offset, dump->size); - debug_event(dbf, level, dump, dump->size); + debug_event(dbf, level, dump, dump->size + sizeof(*dump)); } } @@ -108,7 +108,7 @@ static int zfcp_dbf_view_header(debug_info_t *id, struct debug_view *view, t.tv_sec, t.tv_nsec); zfcp_dbf_out(&p, "cpu", "%02i", entry->id.fields.cpuid); } else { - zfcp_dbf_outd(&p, NULL, dump->data, dump->size, dump->offset, + zfcp_dbf_outd(&p, "", dump->data, dump->size, dump->offset, dump->total_size); if ((dump->offset + dump->size) == dump->total_size) p += sprintf(p, "\n"); @@ -366,6 +366,7 @@ static void zfcp_hba_dbf_view_response(char **p, break; zfcp_dbf_out(p, "scsi_cmnd", "0x%0Lx", r->u.fcp.cmnd); zfcp_dbf_out(p, "scsi_serial", "0x%016Lx", r->u.fcp.serial); + p += sprintf(*p, "\n"); break; case FSF_QTCB_OPEN_PORT_WITH_DID: @@ -465,7 +466,8 @@ static int zfcp_hba_dbf_view_format(debug_info_t *id, struct debug_view *view, else if (strncmp(r->tag, "berr", ZFCP_DBF_TAG_SIZE) == 0) zfcp_hba_dbf_view_berr(&p, &r->u.berr); - p += sprintf(p, "\n"); + if (strncmp(r->tag, "resp", ZFCP_DBF_TAG_SIZE) != 0) + p += sprintf(p, "\n"); return p - out_buf; } @@ -880,6 +882,7 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) struct ct_hdr *hdr = sg_virt(ct->req); struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf; struct zfcp_san_dbf_record_ct_request *oct = &r->u.ct_req; + int level = 3; unsigned long flags; spin_lock_irqsave(&adapter->san_dbf_lock, flags); @@ -896,9 +899,10 @@ void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) oct->options = hdr->options; oct->max_res_size = hdr->max_res_size; oct->len = min((int)ct->req->length - (int)sizeof(struct ct_hdr), - ZFCP_DBF_CT_PAYLOAD); - memcpy(oct->payload, (void *)hdr + sizeof(struct ct_hdr), oct->len); - debug_event(adapter->san_dbf, 3, r, sizeof(*r)); + ZFCP_DBF_SAN_MAX_PAYLOAD); + debug_event(adapter->san_dbf, level, r, sizeof(*r)); + zfcp_dbf_hexdump(adapter->san_dbf, r, sizeof(*r), level, + (void *)hdr + sizeof(struct ct_hdr), oct->len); spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); } @@ -914,6 +918,7 @@ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) struct ct_hdr *hdr = sg_virt(ct->resp); struct zfcp_san_dbf_record *r = &adapter->san_dbf_buf; struct zfcp_san_dbf_record_ct_response *rct = &r->u.ct_resp; + int level = 3; unsigned long flags; spin_lock_irqsave(&adapter->san_dbf_lock, flags); @@ -929,9 +934,10 @@ void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) rct->expl = hdr->reason_code_expl; rct->vendor_unique = hdr->vendor_unique; rct->len = min((int)ct->resp->length - (int)sizeof(struct ct_hdr), - ZFCP_DBF_CT_PAYLOAD); - memcpy(rct->payload, (void *)hdr + sizeof(struct ct_hdr), rct->len); - debug_event(adapter->san_dbf, 3, r, sizeof(*r)); + ZFCP_DBF_SAN_MAX_PAYLOAD); + debug_event(adapter->san_dbf, level, r, sizeof(*r)); + zfcp_dbf_hexdump(adapter->san_dbf, r, sizeof(*r), level, + (void *)hdr + sizeof(struct ct_hdr), rct->len); spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); } @@ -954,7 +960,7 @@ static void zfcp_san_dbf_event_els(const char *tag, int level, rec->u.els.ls_code = ls_code; debug_event(adapter->san_dbf, level, rec, sizeof(*rec)); zfcp_dbf_hexdump(adapter->san_dbf, rec, sizeof(*rec), level, - buffer, min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD)); + buffer, min(buflen, ZFCP_DBF_SAN_MAX_PAYLOAD)); spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); } @@ -1008,8 +1014,6 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view, char *out_buf, const char *in_buf) { struct zfcp_san_dbf_record *r = (struct zfcp_san_dbf_record *)in_buf; - char *buffer = NULL; - int buflen = 0, total = 0; char *p = out_buf; if (strncmp(r->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0) @@ -1029,9 +1033,6 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view, zfcp_dbf_out(&p, "gs_subtype", "0x%02x", ct->gs_subtype); zfcp_dbf_out(&p, "options", "0x%02x", ct->options); zfcp_dbf_out(&p, "max_res_size", "0x%04x", ct->max_res_size); - total = ct->len; - buffer = ct->payload; - buflen = min(total, ZFCP_DBF_CT_PAYLOAD); } else if (strncmp(r->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) { struct zfcp_san_dbf_record_ct_response *ct = &r->u.ct_resp; zfcp_dbf_out(&p, "cmd_rsp_code", "0x%04x", ct->cmd_rsp_code); @@ -1039,23 +1040,12 @@ static int zfcp_san_dbf_view_format(debug_info_t *id, struct debug_view *view, zfcp_dbf_out(&p, "reason_code", "0x%02x", ct->reason_code); zfcp_dbf_out(&p, "reason_code_expl", "0x%02x", ct->expl); zfcp_dbf_out(&p, "vendor_unique", "0x%02x", ct->vendor_unique); - total = ct->len; - buffer = ct->payload; - buflen = min(total, ZFCP_DBF_CT_PAYLOAD); } else if (strncmp(r->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 || strncmp(r->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 || strncmp(r->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) { struct zfcp_san_dbf_record_els *els = &r->u.els; zfcp_dbf_out(&p, "ls_code", "0x%02x", els->ls_code); - total = els->len; - buffer = els->payload; - buflen = min(total, ZFCP_DBF_ELS_PAYLOAD); } - - zfcp_dbf_outd(&p, "payload", buffer, buflen, 0, total); - if (buflen == total) - p += sprintf(p, "\n"); - return p - out_buf; } diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index e8f450801fe..5d6b2dff855 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -163,8 +163,6 @@ struct zfcp_san_dbf_record_ct_request { u8 options; u16 max_res_size; u32 len; -#define ZFCP_DBF_CT_PAYLOAD 24 - u8 payload[ZFCP_DBF_CT_PAYLOAD]; } __attribute__ ((packed)); struct zfcp_san_dbf_record_ct_response { @@ -174,15 +172,11 @@ struct zfcp_san_dbf_record_ct_response { u8 expl; u8 vendor_unique; u32 len; - u8 payload[ZFCP_DBF_CT_PAYLOAD]; } __attribute__ ((packed)); struct zfcp_san_dbf_record_els { u8 ls_code; u32 len; -#define ZFCP_DBF_ELS_PAYLOAD 32 -#define ZFCP_DBF_ELS_MAX_PAYLOAD 1024 - u8 payload[ZFCP_DBF_ELS_PAYLOAD]; } __attribute__ ((packed)); struct zfcp_san_dbf_record { @@ -196,6 +190,8 @@ struct zfcp_san_dbf_record { struct zfcp_san_dbf_record_ct_response ct_resp; struct zfcp_san_dbf_record_els els; } u; +#define ZFCP_DBF_SAN_MAX_PAYLOAD 1024 + u8 payload[32]; } __attribute__ ((packed)); struct zfcp_scsi_dbf_record { -- cgit v1.2.3 From 939c2288c35132fe340b2694c7d02cacf7593723 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 4 Nov 2008 19:47:19 -0600 Subject: [SCSI] scsi_error regression: Fix idempotent command handling Drivers want to be able to return DID_TRANSPORT_DISRUPTED and have it do the right thing for commands like tape and passthrouh as far as retries go. The LLDs previously used DID_BUS_BUSY or DID_ERROR which followed the cmd->retries limit, but DID_TRANSPORT_DISRUPTED was skipping that check so it could have caused a problem with tape commands. This patch has DID_TRANSPORT_DISRUPTED check the cmd->retries/cmd->allowed. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 94ed262bdf0..386361778eb 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1340,9 +1340,10 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) * LLD/transport was disrupted during processing of the IO. * The transport class is now blocked/blocking, * and the transport will decide what to do with the IO - * based on its timers and recovery capablilities. + * based on its timers and recovery capablilities if + * there are enough retries. */ - return ADD_TO_MLQUEUE; + goto maybe_retry; case DID_TRANSPORT_FAILFAST: /* * The transport decided to failfast the IO (most likely -- cgit v1.2.3 From 7f3abf5c7c9a9febdd643b9d4005382144525475 Mon Sep 17 00:00:00 2001 From: Vladimir Sokolovsky Date: Wed, 5 Nov 2008 10:56:52 -0800 Subject: IB/mlx4: Set umem field to NULL in mlx4_ib_alloc_fast_reg_mr() Set mr->umem to NULL in mlx4_ib_alloc_fast_reg_mr(). Otherwise ib_dereg_mr() may invoke ib_umem_release() on a random pointer value and get an oops. Signed-off-by: Vladimir Sokolovsky Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/mr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c index 87f5c5a87b9..8e4d26d56a9 100644 --- a/drivers/infiniband/hw/mlx4/mr.c +++ b/drivers/infiniband/hw/mlx4/mr.c @@ -205,6 +205,7 @@ struct ib_mr *mlx4_ib_alloc_fast_reg_mr(struct ib_pd *pd, goto err_mr; mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; + mr->umem = NULL; return &mr->ibmr; -- cgit v1.2.3 From cb3ac42b8af357fdd9ad838234245b39e5bdb7fe Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 6 Nov 2008 17:28:01 +1100 Subject: md: revert the recent addition of a call to the BLKRRPART ioctl. It turns out that it is only safe to call blkdev_ioctl when the device is actually open (as ->bd_disk is set to NULL on last close). And it is quite possible for do_md_stop to be called when the device is not open. So discard the call to blkdev_ioctl(BLKRRPART) which was added in commit 934d9c23b4c7e31840a895ba4b7e88d6413c81f3 It is just as easy to call this ioctl from userspace when needed (on mdadm -S) so leave it out of the kernel Signed-off-by: NeilBrown --- drivers/md/md.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index 9abf6ed1653..1b1d32694f6 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3884,7 +3884,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) if (mode == 0) { mdk_rdev_t *rdev; struct list_head *tmp; - struct block_device *bdev; printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); @@ -3941,11 +3940,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) mddev->degraded = 0; mddev->barriers_work = 0; mddev->safemode = 0; - bdev = bdget_disk(mddev->gendisk, 0); - if (bdev) { - blkdev_ioctl(bdev, 0, BLKRRPART, 0); - bdput(bdev); - } kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); } else if (mddev->pers) -- cgit v1.2.3 From a53a6c85756339f82ff19e001e90cfba2d6299a8 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 6 Nov 2008 17:28:20 +1100 Subject: md: fix bug in raid10 recovery. Adding a spare to a raid10 doesn't cause recovery to start. This is due to an silly type in commit 6c2fce2ef6b4821c21b5c42c7207cb9cf8c87eda and so is a bug in 2.6.27 and .28-rc. Thanks to Thomas Backlund for bisecting to find this. Cc: Thomas Backlund Cc: stable@kernel.org Signed-off-by: NeilBrown --- drivers/md/raid10.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index da5129a24b1..970a96ef9b1 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1137,7 +1137,7 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) if (!enough(conf)) return -EINVAL; - if (rdev->raid_disk) + if (rdev->raid_disk >= 0) first = last = rdev->raid_disk; if (rdev->saved_raid_disk >= 0 && -- cgit v1.2.3 From f1cd14ae52985634d0389e934eba25b5ecf24565 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Thu, 6 Nov 2008 19:41:24 +1100 Subject: md: linear: Fix a division by zero bug for very small arrays. We currently oops with a divide error on starting a linear software raid array consisting of at least two very small (< 500K) devices. The bug is caused by the calculation of the hash table size which tries to compute sector_div(sz, base) with "base" being zero due to the small size of the component devices of the array. Fix this by requiring the hash spacing to be at least one which implies that also "base" is non-zero. This bug has existed since about 2.6.14. Cc: stable@kernel.org Signed-off-by: Andre Noll Signed-off-by: NeilBrown --- drivers/md/linear.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 190147c79e7..3b90c5c924e 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -148,6 +148,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) min_sectors = conf->array_sectors; sector_div(min_sectors, PAGE_SIZE/sizeof(struct dev_info *)); + if (min_sectors == 0) + min_sectors = 1; /* min_sectors is the minimum spacing that will fit the hash * table in one PAGE. This may be much smaller than needed. -- cgit v1.2.3 From b954f6f63e7938a11de5bd15cb5cbcac7423cf97 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Wed, 5 Nov 2008 22:18:41 +0200 Subject: [WATCHDOG] SAM9 watchdog - update for moved headers The architecture header files were recently moved from include/asm-arm/mach-at91/ to arch/arm/mach-at91/include/mach/. The SAM9 watchdog driver still includes a header from the old location. Signed-off-by: Andrew Victor Signed-off-by: Wim Van Sebroeck Signed-off-by: Andrew Morton --- drivers/watchdog/at91sam9_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index b4babfc3158..b1da287f90e 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -30,7 +30,7 @@ #include #include -#include +#include #define DRV_NAME "AT91SAM9 Watchdog" -- cgit v1.2.3 From f0e625c1aa24e861c224fb778c377b2ddb443d2b Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Wed, 5 Nov 2008 22:36:35 +0200 Subject: [WATCHDOG] SAM9 watchdog - supported on all SAM9 and CAP9 processors The SAM9 watchdog driver is usable on the whole family of AT91SAM9 and CAP9 processors. Update the configuration to indicate this and allow the driver to be selected. Signed-off-by: Andrew Victor Signed-off-by: Wim Van Sebroeck Signed-off-by: Andrew Morton --- drivers/watchdog/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 1a22fe782a2..4fd3fa5546b 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -67,11 +67,11 @@ config AT91RM9200_WATCHDOG system when the timeout is reached. config AT91SAM9X_WATCHDOG - tristate "AT91SAM9X watchdog" - depends on WATCHDOG && (ARCH_AT91SAM9260 || ARCH_AT91SAM9261) + tristate "AT91SAM9X / AT91CAP9 watchdog" + depends on ARCH_AT91 && !ARCH_AT91RM9200 help - Watchdog timer embedded into AT91SAM9X chips. This will reboot your - system when the timeout is reached. + Watchdog timer embedded into AT91SAM9X and AT91CAP9 chips. This will + reboot your system when the timeout is reached. config 21285_WATCHDOG tristate "DC21285 watchdog" -- cgit v1.2.3 From b77bcb07897f1a9cd9d1d78691896dcdb0fd1a22 Mon Sep 17 00:00:00 2001 From: Zoltan Sogor Date: Wed, 29 Oct 2008 09:50:02 +0100 Subject: UBI: fix EBADMSG handling 'ubi_io_read_data()' may return EBADMSG in case of an ECC error, and we should not panic because of this. We have CRC32 checksum and may check the data. So just ignore the EBADMSG error. This patch also fixes a minor spelling error at the same time. Signed-off-by: Zoltan Sogor Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/eba.c | 2 +- drivers/mtd/ubi/scan.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index e04bcf1dff8..d8966bae0e0 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -1022,7 +1022,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, } /* - * OK, now the LEB is locked and we can safely start moving iy. Since + * OK, now the LEB is locked and we can safely start moving it. Since * this function utilizes thie @ubi->peb1_buf buffer which is shared * with some other functions, so lock the buffer by taking the * @ubi->buf_mutex. diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 4f2daa5bbec..41d47e1cf15 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -320,7 +320,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, } err = ubi_io_read_data(ubi, buf, pnum, 0, len); - if (err && err != UBI_IO_BITFLIPS) + if (err && err != UBI_IO_BITFLIPS && err != -EBADMSG) goto out_free_buf; data_crc = be32_to_cpu(vid_hdr->data_crc); -- cgit v1.2.3 From 2ad49887150894b9ed6a87a76b409adceee6b074 Mon Sep 17 00:00:00 2001 From: Vitaliy Gusev Date: Wed, 5 Nov 2008 18:27:18 +0300 Subject: UBI: Don't exit from ubi_thread until kthread_should_stop() is true If ubi_thread() exits but kthread_should_stop() is not true then kthread_stop() will never return and cleanup thread will forever stay in "D" state. Signed-off-by: Vitaliy Gusev Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/wl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 05d70937b54..dcb6dac1dc5 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1396,7 +1396,8 @@ int ubi_thread(void *u) ubi_msg("%s: %d consecutive failures", ubi->bgt_name, WL_MAX_FAILURES); ubi_ro_mode(ubi); - break; + ubi->thread_enabled = 0; + continue; } } else failures = 0; -- cgit v1.2.3 From 5704d626e7c770ef4a984a697bac7eff07420a39 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 5 Nov 2008 16:17:42 -0700 Subject: ACPI: remove comments about debug layer/level to use I don't think there's any point in cluttering the code with these. Better to improve the documentation so *anybody* can figure out what layer & level to use. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_root.c | 6 ------ drivers/acpi/video.c | 6 ------ 2 files changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 1b8f67d21d5..642554b1b60 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -376,15 +376,9 @@ static int acpi_pci_root_remove(struct acpi_device *device, int type) static int __init acpi_pci_root_init(void) { - if (acpi_pci_disabled) return 0; - /* DEBUG: - acpi_dbg_layer = ACPI_PCI_COMPONENT; - acpi_dbg_level = 0xFFFFFFFF; - */ - if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0) return -ENODEV; diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index a29b0ccac65..bf0c26a7368 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -2094,12 +2094,6 @@ static int __init acpi_video_init(void) { int result = 0; - - /* - acpi_dbg_level = 0xFFFFFFFF; - acpi_dbg_layer = 0x08000000; - */ - acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); if (!acpi_video_dir) return -ENODEV; -- cgit v1.2.3 From 5b881479af4352791e5004b74e3639f1416c5fe4 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 5 Nov 2008 16:17:47 -0700 Subject: ACPI: SBS: remove useless acpi_cm_sbs_init() initcall acpi_cm_sbs_init() doesn't do anything, so we can just remove it. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/cm_sbs.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c index 4441e84b28a..80d5c88e68c 100644 --- a/drivers/acpi/cm_sbs.c +++ b/drivers/acpi/cm_sbs.c @@ -105,9 +105,3 @@ void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param) return; } EXPORT_SYMBOL(acpi_unlock_battery_dir); - -static int __init acpi_cm_sbs_init(void) -{ - return 0; -} -subsys_initcall(acpi_cm_sbs_init); -- cgit v1.2.3 From fefe5ab3d67b0ade6200fec5ed6f2812cbcbb658 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 5 Nov 2008 16:17:58 -0700 Subject: ACPI: remove CONFIG_ACPI_POWER Remove CONFIG_ACPI_POWER. It was always set the same as CONFIG_ACPI, and it had no menu label, so there was no way to set it to anything other than "y". The interfaces under CONFIG_ACPI_POWER (acpi_device_sleep_wake(), acpi_power_transition(), etc) are called unconditionally from the ACPI core, so we already depend on it always being present. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 4 ---- drivers/acpi/Makefile | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index f4f63291750..4fa7866a9a5 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -341,10 +341,6 @@ config ACPI_PCI_SLOT help you correlate PCI bus addresses with the physical geography of your slots. If you are unsure, say N. -config ACPI_POWER - bool - default y - config ACPI_SYSTEM bool default y diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index d91c027ece8..8017f63920c 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -51,7 +51,7 @@ obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o obj-$(CONFIG_ACPI_CONTAINER) += container.o obj-$(CONFIG_ACPI_THERMAL) += thermal.o -obj-$(CONFIG_ACPI_POWER) += power.o +obj-y += power.o obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o obj-$(CONFIG_ACPI_DEBUG) += debug.o obj-$(CONFIG_ACPI_NUMA) += numa.o -- cgit v1.2.3 From 8950d89acaa8c353869e681772479d7955ae6f7a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 5 Nov 2008 16:18:03 -0700 Subject: ACPI: remove CONFIG_ACPI_EC Remove CONFIG_ACPI_EC. It was always set the same as CONFIG_ACPI, and it had no menu label, so there was no way to set it to anything other than "y". Per section 6.5.4 of the ACPI 3.0b specification, OSPM must make Embedded Controller operation regions, accessed via the Embedded Controllers described in ECDT, available before executing any control method. The ECDT table is optional, but if it is present, the above text means that the EC it describes is a required part of the ACPI subsystem, so CONFIG_ACPI_EC=n wouldn't make sense. Signed-off-by: Bjorn Helgaas Acked-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 8 -------- drivers/acpi/Makefile | 2 +- drivers/acpi/bus.c | 3 +-- drivers/char/sonypi.c | 4 ++-- drivers/misc/Kconfig | 4 ++-- 5 files changed, 6 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 4fa7866a9a5..90cb2a823b5 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -324,14 +324,6 @@ config ACPI_DEBUG_FUNC_TRACE ACPI Debug Statements slow down ACPI processing. Function trace is about half of the penalty and is rarely useful. -config ACPI_EC - bool - default y - help - This driver is required on some systems for the proper operation of - the battery and thermal drivers. If you are compiling for a - mobile system, say Y. - config ACPI_PCI_SLOT tristate "PCI slot detection driver" default n diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 8017f63920c..fc622316a7d 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -39,7 +39,7 @@ obj-y += sleep/ obj-y += bus.o glue.o obj-y += scan.o # Keep EC driver first. Initialization of others depend on it. -obj-$(CONFIG_ACPI_EC) += ec.o +obj-y += ec.o obj-$(CONFIG_ACPI_AC) += ac.o obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_BUTTON) += button.o diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index c797c6473f3..765fd1c56cd 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -774,7 +774,7 @@ static int __init acpi_bus_init(void) "Unable to initialize ACPI OS objects\n"); goto error1; } -#ifdef CONFIG_ACPI_EC + /* * ACPI 2.0 requires the EC driver to be loaded and work before * the EC device is found in the namespace (i.e. before acpi_initialize_objects() @@ -785,7 +785,6 @@ static int __init acpi_bus_init(void) */ status = acpi_ec_ecdt_probe(); /* Ignore result. Not having an ECDT is not fatal. */ -#endif status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); if (ACPI_FAILURE(status)) { diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 85e0eb76eea..1b128d1e215 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -523,7 +523,7 @@ static int acpi_driver_registered; static int sonypi_ec_write(u8 addr, u8 value) { -#ifdef CONFIG_ACPI_EC +#ifdef CONFIG_ACPI if (SONYPI_ACPI_ACTIVE) return ec_write(addr, value); #endif @@ -539,7 +539,7 @@ static int sonypi_ec_write(u8 addr, u8 value) static int sonypi_ec_read(u8 addr, u8 *value) { -#ifdef CONFIG_ACPI_EC +#ifdef CONFIG_ACPI if (SONYPI_ACPI_ACTIVE) return ec_read(addr, value); #endif diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 9494400e8fd..4494ad27cbf 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -230,7 +230,7 @@ config HP_WMI config MSI_LAPTOP tristate "MSI Laptop Extras" depends on X86 - depends on ACPI_EC + depends on ACPI depends on BACKLIGHT_CLASS_DEVICE ---help--- This is a driver for laptops built by MSI (MICRO-STAR @@ -260,7 +260,7 @@ config PANASONIC_LAPTOP config COMPAL_LAPTOP tristate "Compal Laptop Extras" depends on X86 - depends on ACPI_EC + depends on ACPI depends on BACKLIGHT_CLASS_DEVICE ---help--- This is a driver for laptops built by Compal: -- cgit v1.2.3 From 934f6c3f8e7f5d6a6d07ae2df283fd02393019dd Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 6 Nov 2008 15:49:04 -0500 Subject: Revert "ath5k: honor FIF_BCN_PRBRESP_PROMISC in STA mode" Unfortunately, the result was that mac80211 didn't see all the beacons it actually wanted to see. This caused lost associations. Hopefully we can revisit this when mac80211 is less greedy about seeing beacons directly... This reverts commit 063279062a8c530cc90fb77797db16c49c905b26. Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 9e47d727e22..cfd4d052d66 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -2942,8 +2942,10 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, sc->opmode != NL80211_IFTYPE_MESH_POINT && test_bit(ATH_STAT_PROMISC, sc->status)) rfilt |= AR5K_RX_FILTER_PROM; - if (sc->opmode == NL80211_IFTYPE_ADHOC) + if (sc->opmode == NL80211_IFTYPE_STATION || + sc->opmode == NL80211_IFTYPE_ADHOC) { rfilt |= AR5K_RX_FILTER_BEACON; + } /* Set filters */ ath5k_hw_set_rx_filter(ah,rfilt); -- cgit v1.2.3 From 502c12e1ef14967e08dabb04c674cf0f000e8f7e Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Thu, 23 Oct 2008 23:48:54 -0700 Subject: iwlwifi: clear scanning bits upon failure In iwl_bg_request_scan function, if we could not send a scan command it will go to done. In done it does the right thing to call mac80211 with scan complete, but the problem is STATUS_SCAN_HW is still set causing any future scan to fail. Fix by clearing the scanning status bits if scan fails. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-scan.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 3b0bee331a3..c89365e2ca5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -896,6 +896,13 @@ static void iwl_bg_request_scan(struct work_struct *data) return; done: + /* Cannot perform scan. Make sure we clear scanning + * bits from status so next scan request can be performed. + * If we don't clear scanning status bit here all next scan + * will fail + */ + clear_bit(STATUS_SCAN_HW, &priv->status); + clear_bit(STATUS_SCANNING, &priv->status); /* inform mac80211 scan aborted */ queue_work(priv->workqueue, &priv->scan_completed); mutex_unlock(&priv->mutex); -- cgit v1.2.3 From 964d2777438bf7687324243d38ade538d9bbfe3c Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 30 Oct 2008 14:12:21 -0400 Subject: iwlagn: avoid sleep in softirq context __ieee80211_tasklet_handler -> __ieee80211_rx -> __ieee80211_rx_handle_packet -> ieee80211_invoke_rx_handlers -> ieee80211_rx_h_decrypt -> ieee80211_crypto_tkip_decrypt -> ieee80211_tkip_decrypt_data -> iwl4965_mac_update_tkip_key -> iwl_scan_cancel_timeout -> msleep Ooops! Avoid the sleep by changing iwl_scan_cancel_timeout with iwl_scan_cancel and simply returning on failure if the scan persists. This will cause hardware decryption to fail and we'll handle a few more frames with software decryption. Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 321dbc8c034..8d690a0eb1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3252,7 +3252,11 @@ static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw, return; } - iwl_scan_cancel_timeout(priv, 100); + if (iwl_scan_cancel(priv)) { + /* cancel scan failed, just live w/ bad key and rely + briefly on SW decryption */ + return; + } key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK); key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); -- cgit v1.2.3 From 0feec9dfe7b8880ab3b4c38d7cc4107dd706ea7f Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Sat, 1 Nov 2008 17:03:48 +0000 Subject: zd1211rw: Add 2 device IDs 07fa/1196 Bewan BWIFI-USB54AR: Tested by night1308, this device is a ZD1211B with an AL2230S radio. 0ace/b215 HP 802.11abg: Tested by Robert Philippe Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index a60ae86bd5c..a3ccd8c1c71 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -61,6 +61,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 }, /* ZD1211B */ { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B }, @@ -82,6 +83,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0cde, 0x001a), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0586, 0x340a), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B }, /* "Driverless" devices that need ejecting */ { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, -- cgit v1.2.3 From c793033945bea23d7a6e0d8d94b2da6603e02af2 Mon Sep 17 00:00:00 2001 From: Bob Copeland Date: Mon, 3 Nov 2008 22:14:00 -0500 Subject: ath5k: correct handling of rx status fields ath5k_rx_status fields rs_antenna and rs_more are u8s, but we were setting them with bitwise ANDs of 32-bit values. As a consequence, jumbo frames would not be discarded as intended. Then, because the hw rate value of such frames is zero, and, since "ath5k: rates cleanup", we do not fall back to the basic rate, such packets would trigger the following WARN_ON: ------------[ cut here ]------------ WARNING: at net/mac80211/rx.c:2192 __ieee80211_rx+0x4d/0x57e [mac80211]() Modules linked in: ath5k af_packet sha256_generic aes_i586 aes_generic cbc loop i915 drm binfmt_misc acpi_cpufreq fan container nls_utf8 hfsplus dm_crypt dm_mod kvm_intel kvm fuse sbp2 snd_hda_intel snd_pcm_oss snd_pcm snd_mixer_oss snd_seq_dummy snd_seq_oss arc4 joydev hid_apple ecb snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq snd_timer snd_seq_device usbhid appletouch mac80211 sky2 snd ehci_hcd ohci1394 bitrev crc32 sr_mod cdrom rtc sg uhci_hcd snd_page_alloc cfg80211 ieee1394 thermal ac battery processor button evdev unix [last unloaded: ath5k] Pid: 0, comm: swapper Tainted: G W 2.6.28-rc2-wl #14 Call Trace: [] warn_on_slowpath+0x41/0x5b [] ? sched_debug_show+0x31e/0x9c6 [] ? vprintk+0x369/0x389 [] ? _spin_unlock_irqrestore+0x54/0x58 [] ? try_to_wake_up+0x14f/0x15a [] __ieee80211_rx+0x4d/0x57e [mac80211] [] ath5k_tasklet_rx+0x5a1/0x5e4 [ath5k] [] ? clockevents_program_event+0xd4/0xe3 [] tasklet_action+0x94/0xfd [] __do_softirq+0x8c/0x13e [] do_softirq+0x39/0x55 [] irq_exit+0x46/0x85 [] do_IRQ+0x9a/0xb2 [] common_interrupt+0x28/0x30 [] ? acpi_idle_enter_bm+0x2ad/0x31b [processor] [] cpuidle_idle_call+0x65/0x9a [] cpu_idle+0x76/0xa6 [] rest_init+0x62/0x64 Signed-off-by: Bob Copeland Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/desc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath5k/desc.c b/drivers/net/wireless/ath5k/desc.c index dd1374052ba..5e362a7a362 100644 --- a/drivers/net/wireless/ath5k/desc.c +++ b/drivers/net/wireless/ath5k/desc.c @@ -531,10 +531,10 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL); rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE); - rs->rs_antenna = rx_status->rx_status_0 & - AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA; - rs->rs_more = rx_status->rx_status_0 & - AR5K_5210_RX_DESC_STATUS0_MORE; + rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, + AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA); + rs->rs_more = !!(rx_status->rx_status_0 & + AR5K_5210_RX_DESC_STATUS0_MORE); /* TODO: this timestamp is 13 bit, later on we assume 15 bit */ rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); @@ -607,10 +607,10 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); - rs->rs_antenna = rx_status->rx_status_0 & - AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA; - rs->rs_more = rx_status->rx_status_0 & - AR5K_5212_RX_DESC_STATUS0_MORE; + rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, + AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA); + rs->rs_more = !!(rx_status->rx_status_0 & + AR5K_5212_RX_DESC_STATUS0_MORE); rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); rs->rs_status = 0; -- cgit v1.2.3 From 2420ebc104d38567ee977a3c15dc675a9dd3b07c Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Tue, 4 Nov 2008 12:21:34 -0800 Subject: iwl3945: clear scanning bits upon failure This patch ensures we clear any scan status bit when an error occurs while sending the scan command. It is the implementation of patch: "iwlwifi: clear scanning bits upon failure" for iwl3945. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d15a2c99795..b9eac5551d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6273,6 +6273,14 @@ static void iwl3945_bg_request_scan(struct work_struct *data) return; done: + /* can not perform scan make sure we clear scanning + * bits from status so next scan request can be performed. + * if we dont clear scanning status bit here all next scan + * will fail + */ + clear_bit(STATUS_SCAN_HW, &priv->status); + clear_bit(STATUS_SCANNING, &priv->status); + /* inform mac80211 scan aborted */ queue_work(priv->workqueue, &priv->scan_completed); mutex_unlock(&priv->mutex); -- cgit v1.2.3 From 14b5433606289dbc5b6fd70ced11462f80e95003 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Tue, 4 Nov 2008 12:21:35 -0800 Subject: iwl3945: do not send scan command if channel count zero Do not send scan command if no channels to scan. This avoids a Microcode error as reported in: http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1650 http://bugzilla.kernel.org/show_bug.cgi?id=11806 http://marc.info/?l=linux-wireless&m=122437145211886&w=2 Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index b9eac5551d8..81dfcb88285 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6256,6 +6256,11 @@ static void iwl3945_bg_request_scan(struct work_struct *data) n_probes, (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + if (scan->channel_count == 0) { + IWL_DEBUG_SCAN("channel count %d\n", scan->channel_count); + goto done; + } + cmd.len += le16_to_cpu(scan->tx_cmd.len) + scan->channel_count * sizeof(struct iwl3945_scan_channel); cmd.data = scan; -- cgit v1.2.3 From d54bc4e3fc5c56600a13c9ebc0a7e1077ac05d59 Mon Sep 17 00:00:00 2001 From: "Zhu, Yi" Date: Tue, 4 Nov 2008 12:21:36 -0800 Subject: iwl3945: fix deadlock on suspend This patch fixes iwl3945 deadlock during suspend by moving notify_mac out of iwl3945 mutex. This is a portion of the same fix for iwlwifi by Tomas. Signed-off-by: Zhu Yi Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 81dfcb88285..285b53e7e26 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5768,7 +5768,6 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) if (priv->error_recovering) iwl3945_error_recovery(priv); - ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); return; restart: @@ -6013,6 +6012,7 @@ static void iwl3945_bg_alive_start(struct work_struct *data) mutex_lock(&priv->mutex); iwl3945_alive_start(priv); mutex_unlock(&priv->mutex); + ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); } static void iwl3945_bg_rf_kill(struct work_struct *work) -- cgit v1.2.3 From 77ca7286d10b798e4907af941f29672bf484db77 Mon Sep 17 00:00:00 2001 From: Mike Miller Date: Thu, 6 Nov 2008 12:53:14 -0800 Subject: cciss: new hardware support Add support for 2 new SAS/SATA controllers. Signed-off-by: Mike Miller Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/cciss.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 4023885353e..00048bd26e7 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -96,6 +96,8 @@ static const struct pci_device_id cciss_pci_device_id[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3245}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3247}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324A}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324B}, {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, {0,} @@ -133,6 +135,8 @@ static struct board_type products[] = { {0x3245103C, "Smart Array P410i", &SA5_access}, {0x3247103C, "Smart Array P411", &SA5_access}, {0x3249103C, "Smart Array P812", &SA5_access}, + {0x324A103C, "Smart Array P712m", &SA5_access}, + {0x324B103C, "Smart Array P711m", &SA5_access}, {0xFFFF103C, "Unknown Smart Array", &SA5_access}, }; -- cgit v1.2.3 From 2197d18ded232ef6eef63cce57b6b21eddf1b7b6 Mon Sep 17 00:00:00 2001 From: Andrey Borzenkov Date: Thu, 6 Nov 2008 12:53:15 -0800 Subject: cpqarry: fix return value of cpqarray_init() As reported by Dick Gevers on Compaq ProLiant: Oct 13 18:06:51 dvgcpl kernel: Compaq SMART2 Driver (v 2.6.0) Oct 13 18:06:51 dvgcpl kernel: sys_init_module: 'cpqarray'->init suspiciously returned 1, it should follow 0/-E convention Oct 13 18:06:51 dvgcpl kernel: sys_init_module: loading module anyway... Oct 13 18:06:51 dvgcpl kernel: Pid: 315, comm: modprobe Not tainted 2.6.27-desktop-0.rc8.2mnb #1 Oct 13 18:06:51 dvgcpl kernel: [] ? printk+0x18/0x1e Oct 13 18:06:51 dvgcpl kernel: [] sys_init_module+0x155/0x1c0 Oct 13 18:06:51 dvgcpl kernel: [] syscall_call+0x7/0xb Oct 13 18:06:51 dvgcpl kernel: ======================= Make it return 0 on success and -ENODEV if no array was found. Reported-by: Dick Gevers Signed-off-by: Andrey Borzenkov Cc: Jens Axboe Cc: Greg Kroah-Hartman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/cpqarray.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 47d233c6d0b..5d39df14ed9 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -567,7 +567,12 @@ static int __init cpqarray_init(void) num_cntlrs_reg++; } - return(num_cntlrs_reg); + if (num_cntlrs_reg) + return 0; + else { + pci_unregister_driver(&cpqarray_pci_driver); + return -ENODEV; + } } /* Function to find the first free pointer into our hba[] array */ -- cgit v1.2.3 From a564738c1c9c7b9ed696bf4116267789201ac8ac Mon Sep 17 00:00:00 2001 From: Wolfgang Kroworsch Date: Thu, 6 Nov 2008 12:53:16 -0800 Subject: vt: incomplete initialization of vc_tab_stop Problem 1 (see patch below): vc_tab_stop is declared as an array of 8 unsigned ints in struct vc_data in include/linux/console_struct.h . In drivers/char/vt.c only 5 of these 8 unsigned ints get initialized leading to unintended tabulator placement on displays with more than 160 columns text. Problem 2 (open): Upcoming displays will have more than 256 columns of text leading to invalid memory access in drivers/char/vt.c during tabulator calculations: if (vc->vc_tab_stop[vc->vc_x >> 5] & (1 << (vc->vc_x & 31))) break; Signed-off-by: Wolfgang Kroworsch Cc: Alan Cox Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/vt.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/vt.c b/drivers/char/vt.c index d8f83e26e4a..a5af6072e2b 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -1644,7 +1644,10 @@ static void reset_terminal(struct vc_data *vc, int do_clear) vc->vc_tab_stop[1] = vc->vc_tab_stop[2] = vc->vc_tab_stop[3] = - vc->vc_tab_stop[4] = 0x01010101; + vc->vc_tab_stop[4] = + vc->vc_tab_stop[5] = + vc->vc_tab_stop[6] = + vc->vc_tab_stop[7] = 0x01010101; vc->vc_bell_pitch = DEFAULT_BELL_PITCH; vc->vc_bell_duration = DEFAULT_BELL_DURATION; @@ -1935,7 +1938,10 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) vc->vc_tab_stop[1] = vc->vc_tab_stop[2] = vc->vc_tab_stop[3] = - vc->vc_tab_stop[4] = 0; + vc->vc_tab_stop[4] = + vc->vc_tab_stop[5] = + vc->vc_tab_stop[6] = + vc->vc_tab_stop[7] = 0; } return; case 'm': -- cgit v1.2.3 From 9e3a4afd5a66f9047e30ba225525e6ff01612dc4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 6 Nov 2008 12:53:18 -0800 Subject: rtc: fix handling of missing tm_year data when reading alarms When fixing up invalid years rtc_read_alarm() was calling rtc_valid_tm() as a boolean but rtc_valid_tm() returns zero on success or a negative number if the time is not valid so the test was inverted. Signed-off-by: Mark Brown Acked-by: Alessandro Zummo Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 7af60b98d8a..a04c1b6b157 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -271,7 +271,7 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year"); do { alarm->time.tm_year++; - } while (!rtc_valid_tm(&alarm->time)); + } while (rtc_valid_tm(&alarm->time) != 0); break; default: -- cgit v1.2.3 From 6e3530fa241ae759313496f67295c9252691ed04 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Thu, 6 Nov 2008 12:53:19 -0800 Subject: hwmon: applesmc: add support for iMac 5 Add temperature sensor support for iMac 5. Signed-off-by: Henrik Rydberg Tested-by: Ricky Campbell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/applesmc.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index bc011da79e1..80d545d3aa1 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -116,6 +116,8 @@ static const char* temperature_sensors_sets[][36] = { /* Set 9: Macbook Pro 3,1 (Santa Rosa) */ { "TALP", "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P", "Th0H", "Th1H", "Th2H", "Tm0P", "Ts0P", NULL }, +/* Set 10: iMac 5,1 */ + { "TA0P", "TC0D", "TC0P", "TG0D", "TH0P", "TO0P", "Tm0P", NULL }, }; /* List of keys used to read/write fan speeds */ @@ -1276,6 +1278,8 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { { .accelerometer = 1, .light = 1, .temperature_set = 8 }, /* MacBook Pro 3: accelerometer, backlight and temperature set 9 */ { .accelerometer = 1, .light = 1, .temperature_set = 9 }, +/* iMac 5: light sensor only, temperature set 10 */ + { .accelerometer = 0, .light = 0, .temperature_set = 10 }, }; /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". @@ -1317,6 +1321,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") }, &applesmc_dmi_data[4]}, + { applesmc_dmi_match, "Apple iMac 5", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "iMac5") }, + &applesmc_dmi_data[10]}, { applesmc_dmi_match, "Apple iMac", { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"iMac") }, -- cgit v1.2.3 From 181209a1d91756bfd83b1d6ce2008cea3ca225b6 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Thu, 6 Nov 2008 12:53:20 -0800 Subject: hwmon: applesmc: add support for Macbook 5 Add accelerometer, backlight and temperature sensor support for the new unibody Macbook 5. Signed-off-by: Henrik Rydberg Tested-by: David M. Lary Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/applesmc.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 80d545d3aa1..074f7f4719f 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -118,6 +118,9 @@ static const char* temperature_sensors_sets[][36] = { "Th0H", "Th1H", "Th2H", "Tm0P", "Ts0P", NULL }, /* Set 10: iMac 5,1 */ { "TA0P", "TC0D", "TC0P", "TG0D", "TH0P", "TO0P", "Tm0P", NULL }, +/* Set 11: Macbook 5,1 */ + { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0P", "TN0D", "TN0P", + "TTF0", "Th0H", "Th1H", "ThFH", "Ts0P", "Ts0S", NULL }, }; /* List of keys used to read/write fan speeds */ @@ -1280,6 +1283,8 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { { .accelerometer = 1, .light = 1, .temperature_set = 9 }, /* iMac 5: light sensor only, temperature set 10 */ { .accelerometer = 0, .light = 0, .temperature_set = 10 }, +/* MacBook 5: accelerometer, backlight and temperature set 11 */ + { .accelerometer = 1, .light = 1, .temperature_set = 11 }, }; /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". @@ -1309,6 +1314,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") }, &applesmc_dmi_data[6]}, + { applesmc_dmi_match, "Apple MacBook 5", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5") }, + &applesmc_dmi_data[11]}, { applesmc_dmi_match, "Apple MacBook", { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") }, -- cgit v1.2.3 From a66603257bf88bbe2c9fd6a97ee5dc24de15d196 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Thu, 6 Nov 2008 12:53:21 -0800 Subject: hwmon: applesmc: add support for Macbook Pro 5 Add accelerometer, backlight and temperature sensor support for the new unibody Macbook Pro 5. Signed-off-by: Henrik Rydberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/applesmc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 074f7f4719f..9f04283beae 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -121,6 +121,10 @@ static const char* temperature_sensors_sets[][36] = { /* Set 11: Macbook 5,1 */ { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0P", "TN0D", "TN0P", "TTF0", "Th0H", "Th1H", "ThFH", "Ts0P", "Ts0S", NULL }, +/* Set 12: Macbook Pro 5,1 */ + { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TG0D", + "TG0F", "TG0H", "TG0P", "TG0T", "TG1H", "TN0D", "TN0P", "TTF0", + "Th2H", "Tm0P", "Ts0P", "Ts0S", NULL }, }; /* List of keys used to read/write fan speeds */ @@ -1285,6 +1289,8 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { { .accelerometer = 0, .light = 0, .temperature_set = 10 }, /* MacBook 5: accelerometer, backlight and temperature set 11 */ { .accelerometer = 1, .light = 1, .temperature_set = 11 }, +/* MacBook Pro 5: accelerometer, backlight and temperature set 12 */ + { .accelerometer = 1, .light = 1, .temperature_set = 12 }, }; /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". @@ -1294,6 +1300,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") }, &applesmc_dmi_data[7]}, + { applesmc_dmi_match, "Apple MacBook Pro 5", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5") }, + &applesmc_dmi_data[12]}, { applesmc_dmi_match, "Apple MacBook Pro 4", { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4") }, -- cgit v1.2.3 From eefc488f96cdde6e152b45675b50bf380b95d99f Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Thu, 6 Nov 2008 12:53:22 -0800 Subject: hwmon: applesmc: add support for iMac 8 Add temperature sensor support for iMac 8. Signed-off-by: Henrik Rydberg Tested-by: Klaus Doblmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/applesmc.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 9f04283beae..be3285912cb 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -125,6 +125,9 @@ static const char* temperature_sensors_sets[][36] = { { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TG0D", "TG0F", "TG0H", "TG0P", "TG0T", "TG1H", "TN0D", "TN0P", "TTF0", "Th2H", "Tm0P", "Ts0P", "Ts0S", NULL }, +/* Set 13: iMac 8,1 */ + { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P", + "TL0P", "TO0P", "TW0P", "Tm0P", "Tp0P", NULL }, }; /* List of keys used to read/write fan speeds */ @@ -1291,6 +1294,8 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { { .accelerometer = 1, .light = 1, .temperature_set = 11 }, /* MacBook Pro 5: accelerometer, backlight and temperature set 12 */ { .accelerometer = 1, .light = 1, .temperature_set = 12 }, +/* iMac 8: light sensor only, temperature set 13 */ + { .accelerometer = 0, .light = 0, .temperature_set = 13 }, }; /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". @@ -1340,6 +1345,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") }, &applesmc_dmi_data[4]}, + { applesmc_dmi_match, "Apple iMac 8", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") }, + &applesmc_dmi_data[13]}, { applesmc_dmi_match, "Apple iMac 5", { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "iMac5") }, -- cgit v1.2.3 From 404443081ce5e6f68b5f7eda16c959835ff200c0 Mon Sep 17 00:00:00 2001 From: Mike Miller Date: Thu, 6 Nov 2008 12:53:24 -0800 Subject: cciss: fix sysfs broken symlink regression Regression introduced by commit 6ae5ce8e8d4de666f31286808d2285aa6a50fa40 ("cciss: remove redundant code"). This patch fixes a broken symlink in sysfs that was introduced by the above commit. We broke it in 2.6.27-rc on or about 20080804. Some installers are broken if this symlink does not exist and they may not detect the logical drives configured on the controller. It does not require being backported into 2.6.26.x or earlier kernels. Signed-off-by: Mike Miller Cc: Jens Axboe Cc: [2.6.27.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/cciss.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 00048bd26e7..dc38368435a 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1370,6 +1370,7 @@ static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk, disk->first_minor = drv_index << NWD_SHIFT; disk->fops = &cciss_fops; disk->private_data = &h->drv[drv_index]; + disk->driverfs_dev = &h->pdev->dev; /* Set up queue information */ blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask); -- cgit v1.2.3 From 22bece00dc1f28dd3374c55e464c9f02eb642876 Mon Sep 17 00:00:00 2001 From: Mike Miller Date: Thu, 6 Nov 2008 12:53:25 -0800 Subject: cciss: fix regression firmware not displayed in procfs This regression was introduced by commit 6ae5ce8e8d4de666f31286808d2285aa6a50fa40 ("cciss: remove redundant code"). This patch fixes a regression where the controller firmware version is not displayed in procfs. The previous patch would be called anytime something changed. This will get called only once for each controller. Signed-off-by: Mike Miller Cc: FUJITA Tomonori Cc: Jens Axboe Cc: [2.6.27.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/cciss.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index dc38368435a..12de1fdaa6c 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -3409,7 +3409,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, int i; int j = 0; int rc; - int dac; + int dac, return_code; + InquiryData_struct *inq_buff = NULL; i = alloc_cciss_hba(); if (i < 0) @@ -3515,6 +3516,25 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, /* Turn the interrupts on so we can service requests */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON); + /* Get the firmware version */ + inq_buff = kzalloc(sizeof(InquiryData_struct), GFP_KERNEL); + if (inq_buff == NULL) { + printk(KERN_ERR "cciss: out of memory\n"); + goto clean4; + } + + return_code = sendcmd_withirq(CISS_INQUIRY, i, inq_buff, + sizeof(InquiryData_struct), 0, 0 , 0, TYPE_CMD); + if (return_code == IO_OK) { + hba[i]->firm_ver[0] = inq_buff->data_byte[32]; + hba[i]->firm_ver[1] = inq_buff->data_byte[33]; + hba[i]->firm_ver[2] = inq_buff->data_byte[34]; + hba[i]->firm_ver[3] = inq_buff->data_byte[35]; + } else { /* send command failed */ + printk(KERN_WARNING "cciss: unable to determine firmware" + " version of controller\n"); + } + cciss_procinit(i); hba[i]->cciss_max_sectors = 2048; @@ -3525,6 +3545,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, return 1; clean4: + kfree(inq_buff); #ifdef CONFIG_CISS_SCSI_TAPE kfree(hba[i]->scsi_rejects.complete); #endif -- cgit v1.2.3 From 17a1217e12d8c8434f8a3deef7bf980c724a6ac7 Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Thu, 6 Nov 2008 12:53:29 -0800 Subject: fbdev: add new framebuffer driver for Fujitsu MB862xx GDCs Add a framebuffer driver for the Fujitsu Carmine/Coral-P(A)/Lime graphics controllers. Lime GDC support is known to work on PPC440EPx based lwmon5 and MPC8544E based socrates embedded boards, both equipped with Lime GDC. Carmine/Coral-P PCI GDC support is known to work on PPC440EPx based Sequoia board and also on x86 platform. Signed-off-by: Anatolij Gustschin Cc: Dmitry Baryshkov Cc: Anton Vorontsov Cc: Matteo Fortini Cc: Krzysztof Helt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/Kconfig | 32 ++ drivers/video/Makefile | 1 + drivers/video/mb862xx/Makefile | 5 + drivers/video/mb862xx/mb862xx_reg.h | 138 +++++ drivers/video/mb862xx/mb862xxfb.c | 1061 +++++++++++++++++++++++++++++++++++ drivers/video/mb862xx/mb862xxfb.h | 83 +++ 6 files changed, 1320 insertions(+) create mode 100644 drivers/video/mb862xx/Makefile create mode 100644 drivers/video/mb862xx/mb862xx_reg.h create mode 100644 drivers/video/mb862xx/mb862xxfb.c create mode 100644 drivers/video/mb862xx/mb862xxfb.h (limited to 'drivers') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 0f13448c6f7..3f3ce13fef4 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2083,6 +2083,38 @@ config FB_METRONOME controller. The pre-release name for this device was 8track and could also have been called by some vendors as PVI-nnnn. +config FB_MB862XX + tristate "Fujitsu MB862xx GDC support" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for Fujitsu Carmine/Coral-P(A)/Lime controllers. + +config FB_MB862XX_PCI_GDC + bool "Carmine/Coral-P(A) GDC" + depends on PCI && FB_MB862XX + ---help--- + This enables framebuffer support for Fujitsu Carmine/Coral-P(A) + PCI graphics controller devices. + +config FB_MB862XX_LIME + bool "Lime GDC" + depends on FB_MB862XX + depends on OF && !FB_MB862XX_PCI_GDC + select FB_FOREIGN_ENDIAN + select FB_LITTLE_ENDIAN + ---help--- + Framebuffer support for Fujitsu Lime GDC on host CPU bus. + +config FB_PRE_INIT_FB + bool "Don't reinitialize, use bootloader's GDC/Display configuration" + depends on FB_MB862XX_LIME + ---help--- + Select this option if display contents should be inherited as set by + the bootloader. + source "drivers/video/omap/Kconfig" source "drivers/video/backlight/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 248bddc8d0b..e39e33e797d 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -122,6 +122,7 @@ obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o obj-$(CONFIG_FB_OMAP) += omap/ obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o obj-$(CONFIG_FB_CARMINE) += carminefb.o +obj-$(CONFIG_FB_MB862XX) += mb862xx/ # Platform or fallback drivers go here obj-$(CONFIG_FB_UVESA) += uvesafb.o diff --git a/drivers/video/mb862xx/Makefile b/drivers/video/mb862xx/Makefile new file mode 100644 index 00000000000..07664814bb1 --- /dev/null +++ b/drivers/video/mb862xx/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the MB862xx framebuffer driver +# + +obj-$(CONFIG_FB_MB862XX) := mb862xxfb.o diff --git a/drivers/video/mb862xx/mb862xx_reg.h b/drivers/video/mb862xx/mb862xx_reg.h new file mode 100644 index 00000000000..2ba65e11850 --- /dev/null +++ b/drivers/video/mb862xx/mb862xx_reg.h @@ -0,0 +1,138 @@ +/* + * Fujitsu MB862xx Graphics Controller Registers/Bits + */ + +#ifndef _MB862XX_REG_H +#define _MB862XX_REG_H + +#ifdef MB862XX_MMIO_BOTTOM +#define MB862XX_MMIO_BASE 0x03fc0000 +#else +#define MB862XX_MMIO_BASE 0x01fc0000 +#endif +#define MB862XX_I2C_BASE 0x0000c000 +#define MB862XX_DISP_BASE 0x00010000 +#define MB862XX_CAP_BASE 0x00018000 +#define MB862XX_DRAW_BASE 0x00030000 +#define MB862XX_GEO_BASE 0x00038000 +#define MB862XX_PIO_BASE 0x00038000 +#define MB862XX_MMIO_SIZE 0x40000 + +/* Host interface/pio registers */ +#define GC_IST 0x00000020 +#define GC_IMASK 0x00000024 +#define GC_SRST 0x0000002c +#define GC_CCF 0x00000038 +#define GC_CID 0x000000f0 +#define GC_REVISION 0x00000084 + +#define GC_CCF_CGE_100 0x00000000 +#define GC_CCF_CGE_133 0x00040000 +#define GC_CCF_CGE_166 0x00080000 +#define GC_CCF_COT_100 0x00000000 +#define GC_CCF_COT_133 0x00010000 +#define GC_CID_CNAME_MSK 0x0000ff00 +#define GC_CID_VERSION_MSK 0x000000ff + +/* define enabled interrupts hereby */ +#define GC_INT_EN 0x00000000 + +/* Memory interface mode register */ +#define GC_MMR 0x0000fffc + +/* Display Controller registers */ +#define GC_DCM0 0x00000000 +#define GC_HTP 0x00000004 +#define GC_HDB_HDP 0x00000008 +#define GC_VSW_HSW_HSP 0x0000000c +#define GC_VTR 0x00000010 +#define GC_VDP_VSP 0x00000014 +#define GC_WY_WX 0x00000018 +#define GC_WH_WW 0x0000001c +#define GC_L0M 0x00000020 +#define GC_L0OA0 0x00000024 +#define GC_L0DA0 0x00000028 +#define GC_L0DY_L0DX 0x0000002c +#define GC_DCM1 0x00000100 +#define GC_L0EM 0x00000110 +#define GC_L0WY_L0WX 0x00000114 +#define GC_L0WH_L0WW 0x00000118 +#define GC_DCM2 0x00000104 +#define GC_DCM3 0x00000108 +#define GC_CPM_CUTC 0x000000a0 +#define GC_CUOA0 0x000000a4 +#define GC_CUY0_CUX0 0x000000a8 +#define GC_CUOA1 0x000000ac +#define GC_CUY1_CUX1 0x000000b0 +#define GC_L0PAL0 0x00000400 + +#define GC_CPM_CEN0 0x00100000 +#define GC_CPM_CEN1 0x00200000 + +#define GC_DCM01_ESY 0x00000004 +#define GC_DCM01_SC 0x00003f00 +#define GC_DCM01_RESV 0x00004000 +#define GC_DCM01_CKS 0x00008000 +#define GC_DCM01_L0E 0x00010000 +#define GC_DCM01_DEN 0x80000000 +#define GC_L0M_L0C_8 0x00000000 +#define GC_L0M_L0C_16 0x80000000 +#define GC_L0EM_L0EC_24 0x40000000 +#define GC_L0M_L0W_UNIT 64 + +#define GC_DISP_REFCLK_400 400 + +/* Carmine specific */ +#define MB86297_DRAW_BASE 0x00020000 +#define MB86297_DISP0_BASE 0x00100000 +#define MB86297_DISP1_BASE 0x00140000 +#define MB86297_WRBACK_BASE 0x00180000 +#define MB86297_CAP0_BASE 0x00200000 +#define MB86297_CAP1_BASE 0x00280000 +#define MB86297_DRAMCTRL_BASE 0x00300000 +#define MB86297_CTRL_BASE 0x00400000 +#define MB86297_I2C_BASE 0x00500000 + +#define GC_CTRL_STATUS 0x00000000 +#define GC_CTRL_INT_MASK 0x00000004 +#define GC_CTRL_CLK_ENABLE 0x0000000c +#define GC_CTRL_SOFT_RST 0x00000010 + +#define GC_CTRL_CLK_EN_DRAM 0x00000001 +#define GC_CTRL_CLK_EN_2D3D 0x00000002 +#define GC_CTRL_CLK_EN_DISP0 0x00000020 +#define GC_CTRL_CLK_EN_DISP1 0x00000040 + +#define GC_2D3D_REV 0x000004b4 +#define GC_RE_REVISION 0x24240200 + +/* define enabled interrupts hereby */ +#define GC_CARMINE_INT_EN 0x00000004 + +/* DRAM controller */ +#define GC_DCTL_MODE_ADD 0x00000000 +#define GC_DCTL_SETTIME1_EMODE 0x00000004 +#define GC_DCTL_REFRESH_SETTIME2 0x00000008 +#define GC_DCTL_RSV0_STATES 0x0000000C +#define GC_DCTL_RSV2_RSV1 0x00000010 +#define GC_DCTL_DDRIF2_DDRIF1 0x00000014 +#define GC_DCTL_IOCONT1_IOCONT0 0x00000024 + +#define GC_DCTL_STATES_MSK 0x0000000f +#define GC_DCTL_INIT_WAIT_CNT 3000 +#define GC_DCTL_INIT_WAIT_INTERVAL 1 + +/* DRAM ctrl values for Carmine PCI Eval. board */ +#define GC_EVB_DCTL_MODE_ADD 0x012105c3 +#define GC_EVB_DCTL_MODE_ADD_AFT_RST 0x002105c3 +#define GC_EVB_DCTL_SETTIME1_EMODE 0x47498000 +#define GC_EVB_DCTL_REFRESH_SETTIME2 0x00422a22 +#define GC_EVB_DCTL_RSV0_STATES 0x00200003 +#define GC_EVB_DCTL_RSV0_STATES_AFT_RST 0x00200002 +#define GC_EVB_DCTL_RSV2_RSV1 0x0000000f +#define GC_EVB_DCTL_DDRIF2_DDRIF1 0x00556646 +#define GC_EVB_DCTL_IOCONT1_IOCONT0 0x05550555 + +#define GC_DISP_REFCLK_533 533 + +#endif diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c new file mode 100644 index 00000000000..38718d95fbb --- /dev/null +++ b/drivers/video/mb862xx/mb862xxfb.c @@ -0,0 +1,1061 @@ +/* + * drivers/mb862xx/mb862xxfb.c + * + * Fujitsu Carmine/Coral-P(A)/Lime framebuffer driver + * + * (C) 2008 Anatolij Gustschin + * DENX Software Engineering + * + * 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. + * + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#if defined(CONFIG_PPC_OF) +#include +#endif +#include "mb862xxfb.h" +#include "mb862xx_reg.h" + +#define NR_PALETTE 256 +#define MB862XX_MEM_SIZE 0x1000000 +#define CORALP_MEM_SIZE 0x4000000 +#define CARMINE_MEM_SIZE 0x8000000 +#define DRV_NAME "mb862xxfb" + +#if defined(CONFIG_LWMON5) +static struct mb862xx_gc_mode lwmon5_gc_mode = { + /* Mode for Sharp LQ104V1DG61 TFT LCD Panel */ + { "640x480", 60, 640, 480, 40000, 48, 16, 32, 11, 96, 2, 0, 0, 0 }, + /* 16 bits/pixel, 32MB, 100MHz, SDRAM memory mode value */ + 16, 0x2000000, GC_CCF_COT_100, 0x414fb7f2 +}; +#endif + +#if defined(CONFIG_SOCRATES) +static struct mb862xx_gc_mode socrates_gc_mode = { + /* Mode for Prime View PM070WL4 TFT LCD Panel */ + { "800x480", 45, 800, 480, 40000, 86, 42, 33, 10, 128, 2, 0, 0, 0 }, + /* 16 bits/pixel, 16MB, 133MHz, SDRAM memory mode value */ + 16, 0x1000000, GC_CCF_COT_133, 0x4157ba63 +}; +#endif + +/* Helpers */ +static inline int h_total(struct fb_var_screeninfo *var) +{ + return var->xres + var->left_margin + + var->right_margin + var->hsync_len; +} + +static inline int v_total(struct fb_var_screeninfo *var) +{ + return var->yres + var->upper_margin + + var->lower_margin + var->vsync_len; +} + +static inline int hsp(struct fb_var_screeninfo *var) +{ + return var->xres + var->right_margin - 1; +} + +static inline int vsp(struct fb_var_screeninfo *var) +{ + return var->yres + var->lower_margin - 1; +} + +static inline int d_pitch(struct fb_var_screeninfo *var) +{ + return var->xres * var->bits_per_pixel / 8; +} + +static inline unsigned int chan_to_field(unsigned int chan, + struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +static int mb862xxfb_setcolreg(unsigned regno, + unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info) +{ + struct mb862xxfb_par *par = info->par; + unsigned int val; + + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + if (regno < 16) { + val = chan_to_field(red, &info->var.red); + val |= chan_to_field(green, &info->var.green); + val |= chan_to_field(blue, &info->var.blue); + par->pseudo_palette[regno] = val; + } + break; + case FB_VISUAL_PSEUDOCOLOR: + if (regno < 256) { + val = (red >> 8) << 16; + val |= (green >> 8) << 8; + val |= blue >> 8; + outreg(disp, GC_L0PAL0 + (regno * 4), val); + } + break; + default: + return 1; /* unsupported type */ + } + return 0; +} + +static int mb862xxfb_check_var(struct fb_var_screeninfo *var, + struct fb_info *fbi) +{ + unsigned long tmp; + + if (fbi->dev) + dev_dbg(fbi->dev, "%s\n", __func__); + + /* check if these values fit into the registers */ + if (var->hsync_len > 255 || var->vsync_len > 255) + return -EINVAL; + + if ((var->xres + var->right_margin) >= 4096) + return -EINVAL; + + if ((var->yres + var->lower_margin) > 4096) + return -EINVAL; + + if (h_total(var) > 4096 || v_total(var) > 4096) + return -EINVAL; + + if (var->xres_virtual > 4096 || var->yres_virtual > 4096) + return -EINVAL; + + if (var->bits_per_pixel <= 8) + var->bits_per_pixel = 8; + else if (var->bits_per_pixel <= 16) + var->bits_per_pixel = 16; + else if (var->bits_per_pixel <= 32) + var->bits_per_pixel = 32; + + /* + * can cope with 8,16 or 24/32bpp if resulting + * pitch is divisible by 64 without remainder + */ + if (d_pitch(&fbi->var) % GC_L0M_L0W_UNIT) { + int r; + + var->bits_per_pixel = 0; + do { + var->bits_per_pixel += 8; + r = d_pitch(&fbi->var) % GC_L0M_L0W_UNIT; + } while (r && var->bits_per_pixel <= 32); + + if (d_pitch(&fbi->var) % GC_L0M_L0W_UNIT) + return -EINVAL; + } + + /* line length is going to be 128 bit aligned */ + tmp = (var->xres * var->bits_per_pixel) / 8; + if ((tmp & 15) != 0) + return -EINVAL; + + /* set r/g/b positions and validate bpp */ + switch (var->bits_per_pixel) { + case 8: + var->red.length = var->bits_per_pixel; + var->green.length = var->bits_per_pixel; + var->blue.length = var->bits_per_pixel; + var->red.offset = 0; + var->green.offset = 0; + var->blue.offset = 0; + var->transp.length = 0; + break; + case 16: + var->red.length = 5; + var->green.length = 5; + var->blue.length = 5; + var->red.offset = 10; + var->green.offset = 5; + var->blue.offset = 0; + var->transp.length = 0; + break; + case 24: + case 32: + var->transp.length = 8; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + var->transp.offset = 24; + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + break; + default: + return -EINVAL; + } + return 0; +} + +/* + * set display parameters + */ +static int mb862xxfb_set_par(struct fb_info *fbi) +{ + struct mb862xxfb_par *par = fbi->par; + unsigned long reg, sc; + + dev_dbg(par->dev, "%s\n", __func__); + + if (par->pre_init) + return 0; + + /* disp off */ + reg = inreg(disp, GC_DCM1); + reg &= ~GC_DCM01_DEN; + outreg(disp, GC_DCM1, reg); + + /* set display reference clock div. */ + sc = par->refclk / (1000000 / fbi->var.pixclock) - 1; + reg = inreg(disp, GC_DCM1); + reg &= ~(GC_DCM01_CKS | GC_DCM01_RESV | GC_DCM01_SC); + reg |= sc << 8; + outreg(disp, GC_DCM1, reg); + dev_dbg(par->dev, "SC 0x%lx\n", sc); + + /* disp dimension, format */ + reg = pack(d_pitch(&fbi->var) / GC_L0M_L0W_UNIT, + (fbi->var.yres - 1)); + if (fbi->var.bits_per_pixel == 16) + reg |= GC_L0M_L0C_16; + outreg(disp, GC_L0M, reg); + + if (fbi->var.bits_per_pixel == 32) { + reg = inreg(disp, GC_L0EM); + outreg(disp, GC_L0EM, reg | GC_L0EM_L0EC_24); + } + outreg(disp, GC_WY_WX, 0); + reg = pack(fbi->var.yres - 1, fbi->var.xres); + outreg(disp, GC_WH_WW, reg); + outreg(disp, GC_L0OA0, 0); + outreg(disp, GC_L0DA0, 0); + outreg(disp, GC_L0DY_L0DX, 0); + outreg(disp, GC_L0WY_L0WX, 0); + outreg(disp, GC_L0WH_L0WW, reg); + + /* both HW-cursors off */ + reg = inreg(disp, GC_CPM_CUTC); + reg &= ~(GC_CPM_CEN0 | GC_CPM_CEN1); + outreg(disp, GC_CPM_CUTC, reg); + + /* timings */ + reg = pack(fbi->var.xres - 1, fbi->var.xres - 1); + outreg(disp, GC_HDB_HDP, reg); + reg = pack((fbi->var.yres - 1), vsp(&fbi->var)); + outreg(disp, GC_VDP_VSP, reg); + reg = ((fbi->var.vsync_len - 1) << 24) | + pack((fbi->var.hsync_len - 1), hsp(&fbi->var)); + outreg(disp, GC_VSW_HSW_HSP, reg); + outreg(disp, GC_HTP, pack(h_total(&fbi->var) - 1, 0)); + outreg(disp, GC_VTR, pack(v_total(&fbi->var) - 1, 0)); + + /* display on */ + reg = inreg(disp, GC_DCM1); + reg |= GC_DCM01_DEN | GC_DCM01_L0E; + reg &= ~GC_DCM01_ESY; + outreg(disp, GC_DCM1, reg); + return 0; +} + +static int mb862xxfb_pan(struct fb_var_screeninfo *var, + struct fb_info *info) +{ + struct mb862xxfb_par *par = info->par; + unsigned long reg; + + reg = pack(var->yoffset, var->xoffset); + outreg(disp, GC_L0WY_L0WX, reg); + + reg = pack(var->yres_virtual, var->xres_virtual); + outreg(disp, GC_L0WH_L0WW, reg); + return 0; +} + +static int mb862xxfb_blank(int mode, struct fb_info *fbi) +{ + struct mb862xxfb_par *par = fbi->par; + unsigned long reg; + + dev_dbg(fbi->dev, "blank mode=%d\n", mode); + + switch (mode) { + case FB_BLANK_POWERDOWN: + reg = inreg(disp, GC_DCM1); + reg &= ~GC_DCM01_DEN; + outreg(disp, GC_DCM1, reg); + break; + case FB_BLANK_UNBLANK: + reg = inreg(disp, GC_DCM1); + reg |= GC_DCM01_DEN; + outreg(disp, GC_DCM1, reg); + break; + case FB_BLANK_NORMAL: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + default: + return 1; + } + return 0; +} + +/* framebuffer ops */ +static struct fb_ops mb862xxfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = mb862xxfb_check_var, + .fb_set_par = mb862xxfb_set_par, + .fb_setcolreg = mb862xxfb_setcolreg, + .fb_blank = mb862xxfb_blank, + .fb_pan_display = mb862xxfb_pan, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +/* initialize fb_info data */ +static int mb862xxfb_init_fbinfo(struct fb_info *fbi) +{ + struct mb862xxfb_par *par = fbi->par; + struct mb862xx_gc_mode *mode = par->gc_mode; + unsigned long reg; + + fbi->fbops = &mb862xxfb_ops; + fbi->pseudo_palette = par->pseudo_palette; + fbi->screen_base = par->fb_base; + fbi->screen_size = par->mapped_vram; + + strcpy(fbi->fix.id, DRV_NAME); + fbi->fix.smem_start = (unsigned long)par->fb_base_phys; + fbi->fix.smem_len = par->mapped_vram; + fbi->fix.mmio_start = (unsigned long)par->mmio_base_phys; + fbi->fix.mmio_len = par->mmio_len; + fbi->fix.accel = FB_ACCEL_NONE; + fbi->fix.type = FB_TYPE_PACKED_PIXELS; + fbi->fix.type_aux = 0; + fbi->fix.xpanstep = 1; + fbi->fix.ypanstep = 1; + fbi->fix.ywrapstep = 0; + + reg = inreg(disp, GC_DCM1); + if (reg & GC_DCM01_DEN && reg & GC_DCM01_L0E) { + /* get the disp mode from active display cfg */ + unsigned long sc = ((reg & GC_DCM01_SC) >> 8) + 1; + unsigned long hsp, vsp, ht, vt; + + dev_dbg(par->dev, "using bootloader's disp. mode\n"); + fbi->var.pixclock = (sc * 1000000) / par->refclk; + fbi->var.xres = (inreg(disp, GC_HDB_HDP) & 0x0fff) + 1; + reg = inreg(disp, GC_VDP_VSP); + fbi->var.yres = ((reg >> 16) & 0x0fff) + 1; + vsp = (reg & 0x0fff) + 1; + fbi->var.xres_virtual = fbi->var.xres; + fbi->var.yres_virtual = fbi->var.yres; + reg = inreg(disp, GC_L0EM); + if (reg & GC_L0EM_L0EC_24) { + fbi->var.bits_per_pixel = 32; + } else { + reg = inreg(disp, GC_L0M); + if (reg & GC_L0M_L0C_16) + fbi->var.bits_per_pixel = 16; + else + fbi->var.bits_per_pixel = 8; + } + reg = inreg(disp, GC_VSW_HSW_HSP); + fbi->var.hsync_len = ((reg & 0xff0000) >> 16) + 1; + fbi->var.vsync_len = ((reg & 0x3f000000) >> 24) + 1; + hsp = (reg & 0xffff) + 1; + ht = ((inreg(disp, GC_HTP) & 0xfff0000) >> 16) + 1; + fbi->var.right_margin = hsp - fbi->var.xres; + fbi->var.left_margin = ht - hsp - fbi->var.hsync_len; + vt = ((inreg(disp, GC_VTR) & 0xfff0000) >> 16) + 1; + fbi->var.lower_margin = vsp - fbi->var.yres; + fbi->var.upper_margin = vt - vsp - fbi->var.vsync_len; + } else if (mode) { + dev_dbg(par->dev, "using supplied mode\n"); + fb_videomode_to_var(&fbi->var, (struct fb_videomode *)mode); + fbi->var.bits_per_pixel = mode->def_bpp ? mode->def_bpp : 8; + } else { + int ret; + + ret = fb_find_mode(&fbi->var, fbi, "640x480-16@60", + NULL, 0, NULL, 16); + if (ret == 0 || ret == 4) { + dev_err(par->dev, + "failed to get initial mode\n"); + return -EINVAL; + } + } + + fbi->var.xoffset = 0; + fbi->var.yoffset = 0; + fbi->var.grayscale = 0; + fbi->var.nonstd = 0; + fbi->var.height = -1; + fbi->var.width = -1; + fbi->var.accel_flags = 0; + fbi->var.vmode = FB_VMODE_NONINTERLACED; + fbi->var.activate = FB_ACTIVATE_NOW; + fbi->flags = FBINFO_DEFAULT | +#ifdef __BIG_ENDIAN + FBINFO_FOREIGN_ENDIAN | +#endif + FBINFO_HWACCEL_XPAN | + FBINFO_HWACCEL_YPAN; + + /* check and possibly fix bpp */ + if ((fbi->fbops->fb_check_var)(&fbi->var, fbi)) + dev_err(par->dev, "check_var() failed on initial setup?\n"); + + fbi->fix.visual = fbi->var.bits_per_pixel == 8 ? + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; + fbi->fix.line_length = (fbi->var.xres_virtual * + fbi->var.bits_per_pixel) / 8; + return 0; +} + +/* + * show some display controller and cursor registers + */ +static ssize_t mb862xxfb_show_dispregs(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct fb_info *fbi = dev_get_drvdata(dev); + struct mb862xxfb_par *par = fbi->par; + char *ptr = buf; + unsigned int reg; + + for (reg = GC_DCM0; reg <= GC_L0DY_L0DX; reg += 4) + ptr += sprintf(ptr, "%08x = %08x\n", + reg, inreg(disp, reg)); + + for (reg = GC_CPM_CUTC; reg <= GC_CUY1_CUX1; reg += 4) + ptr += sprintf(ptr, "%08x = %08x\n", + reg, inreg(disp, reg)); + + for (reg = GC_DCM1; reg <= GC_L0WH_L0WW; reg += 4) + ptr += sprintf(ptr, "%08x = %08x\n", + reg, inreg(disp, reg)); + + return ptr - buf; +} + +static DEVICE_ATTR(dispregs, 0444, mb862xxfb_show_dispregs, NULL); + +irqreturn_t mb862xx_intr(int irq, void *dev_id) +{ + struct mb862xxfb_par *par = (struct mb862xxfb_par *) dev_id; + unsigned long reg_ist, mask; + + if (!par) + return IRQ_NONE; + + if (par->type == BT_CARMINE) { + /* Get Interrupt Status */ + reg_ist = inreg(ctrl, GC_CTRL_STATUS); + mask = inreg(ctrl, GC_CTRL_INT_MASK); + if (reg_ist == 0) + return IRQ_HANDLED; + + reg_ist &= mask; + if (reg_ist == 0) + return IRQ_HANDLED; + + /* Clear interrupt status */ + outreg(ctrl, 0x0, reg_ist); + } else { + /* Get status */ + reg_ist = inreg(host, GC_IST); + mask = inreg(host, GC_IMASK); + + reg_ist &= mask; + if (reg_ist == 0) + return IRQ_HANDLED; + + /* Clear status */ + outreg(host, GC_IST, ~reg_ist); + } + return IRQ_HANDLED; +} + +#if defined(CONFIG_FB_MB862XX_LIME) +/* + * GDC (Lime, Coral(B/Q), Mint, ...) on host bus + */ +static int mb862xx_gdc_init(struct mb862xxfb_par *par) +{ + unsigned long ccf, mmr; + unsigned long ver, rev; + + if (!par) + return -ENODEV; + +#if defined(CONFIG_FB_PRE_INIT_FB) + par->pre_init = 1; +#endif + par->host = par->mmio_base; + par->i2c = par->mmio_base + MB862XX_I2C_BASE; + par->disp = par->mmio_base + MB862XX_DISP_BASE; + par->cap = par->mmio_base + MB862XX_CAP_BASE; + par->draw = par->mmio_base + MB862XX_DRAW_BASE; + par->geo = par->mmio_base + MB862XX_GEO_BASE; + par->pio = par->mmio_base + MB862XX_PIO_BASE; + + par->refclk = GC_DISP_REFCLK_400; + + ver = inreg(host, GC_CID); + rev = inreg(pio, GC_REVISION); + if ((ver == 0x303) && (rev & 0xffffff00) == 0x20050100) { + dev_info(par->dev, "Fujitsu Lime v1.%d found\n", + (int)rev & 0xff); + par->type = BT_LIME; + ccf = par->gc_mode ? par->gc_mode->ccf : GC_CCF_COT_100; + mmr = par->gc_mode ? par->gc_mode->mmr : 0x414fb7f2; + } else { + dev_info(par->dev, "? GDC, CID/Rev.: 0x%lx/0x%lx \n", ver, rev); + return -ENODEV; + } + + if (!par->pre_init) { + outreg(host, GC_CCF, ccf); + udelay(200); + outreg(host, GC_MMR, mmr); + udelay(10); + } + + /* interrupt status */ + outreg(host, GC_IST, 0); + outreg(host, GC_IMASK, GC_INT_EN); + return 0; +} + +static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev, + const struct of_device_id *id) +{ + struct device_node *np = ofdev->node; + struct device *dev = &ofdev->dev; + struct mb862xxfb_par *par; + struct fb_info *info; + struct resource res; + resource_size_t res_size; + unsigned long ret = -ENODEV; + + if (of_address_to_resource(np, 0, &res)) { + dev_err(dev, "Invalid address\n"); + return -ENXIO; + } + + info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev); + if (info == NULL) { + dev_err(dev, "cannot allocate framebuffer\n"); + return -ENOMEM; + } + + par = info->par; + par->info = info; + par->dev = dev; + + par->irq = irq_of_parse_and_map(np, 0); + if (par->irq == NO_IRQ) { + dev_err(dev, "failed to map irq\n"); + ret = -ENODEV; + goto fbrel; + } + + res_size = 1 + res.end - res.start; + par->res = request_mem_region(res.start, res_size, DRV_NAME); + if (par->res == NULL) { + dev_err(dev, "Cannot claim framebuffer/mmio\n"); + ret = -ENXIO; + goto irqdisp; + } + +#if defined(CONFIG_LWMON5) + par->gc_mode = &lwmon5_gc_mode; +#endif + +#if defined(CONFIG_SOCRATES) + par->gc_mode = &socrates_gc_mode; +#endif + + par->fb_base_phys = res.start; + par->mmio_base_phys = res.start + MB862XX_MMIO_BASE; + par->mmio_len = MB862XX_MMIO_SIZE; + if (par->gc_mode) + par->mapped_vram = par->gc_mode->max_vram; + else + par->mapped_vram = MB862XX_MEM_SIZE; + + par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram); + if (par->fb_base == NULL) { + dev_err(dev, "Cannot map framebuffer\n"); + goto rel_reg; + } + + par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len); + if (par->mmio_base == NULL) { + dev_err(dev, "Cannot map registers\n"); + goto fb_unmap; + } + + dev_dbg(dev, "fb phys 0x%llx 0x%lx\n", + (u64)par->fb_base_phys, (ulong)par->mapped_vram); + dev_dbg(dev, "mmio phys 0x%llx 0x%lx, (irq = %d)\n", + (u64)par->mmio_base_phys, (ulong)par->mmio_len, par->irq); + + if (mb862xx_gdc_init(par)) + goto io_unmap; + + if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED, + DRV_NAME, (void *)par)) { + dev_err(dev, "Cannot request irq\n"); + goto io_unmap; + } + + mb862xxfb_init_fbinfo(info); + + if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) { + dev_err(dev, "Could not allocate cmap for fb_info.\n"); + goto free_irq; + } + + if ((info->fbops->fb_set_par)(info)) + dev_err(dev, "set_var() failed on initial setup?\n"); + + if (register_framebuffer(info)) { + dev_err(dev, "failed to register framebuffer\n"); + goto rel_cmap; + } + + dev_set_drvdata(dev, info); + + if (device_create_file(dev, &dev_attr_dispregs)) + dev_err(dev, "Can't create sysfs regdump file\n"); + return 0; + +rel_cmap: + fb_dealloc_cmap(&info->cmap); +free_irq: + outreg(host, GC_IMASK, 0); + free_irq(par->irq, (void *)par); +io_unmap: + iounmap(par->mmio_base); +fb_unmap: + iounmap(par->fb_base); +rel_reg: + release_mem_region(res.start, res_size); +irqdisp: + irq_dispose_mapping(par->irq); +fbrel: + dev_set_drvdata(dev, NULL); + framebuffer_release(info); + return ret; +} + +static int __devexit of_platform_mb862xx_remove(struct of_device *ofdev) +{ + struct fb_info *fbi = dev_get_drvdata(&ofdev->dev); + struct mb862xxfb_par *par = fbi->par; + resource_size_t res_size = 1 + par->res->end - par->res->start; + unsigned long reg; + + dev_dbg(fbi->dev, "%s release\n", fbi->fix.id); + + /* display off */ + reg = inreg(disp, GC_DCM1); + reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E); + outreg(disp, GC_DCM1, reg); + + /* disable interrupts */ + outreg(host, GC_IMASK, 0); + + free_irq(par->irq, (void *)par); + irq_dispose_mapping(par->irq); + + device_remove_file(&ofdev->dev, &dev_attr_dispregs); + + unregister_framebuffer(fbi); + fb_dealloc_cmap(&fbi->cmap); + + iounmap(par->mmio_base); + iounmap(par->fb_base); + + dev_set_drvdata(&ofdev->dev, NULL); + release_mem_region(par->res->start, res_size); + framebuffer_release(fbi); + return 0; +} + +/* + * common types + */ +static struct of_device_id __devinitdata of_platform_mb862xx_tbl[] = { + { .compatible = "fujitsu,MB86276", }, + { .compatible = "fujitsu,lime", }, + { .compatible = "fujitsu,MB86277", }, + { .compatible = "fujitsu,mint", }, + { .compatible = "fujitsu,MB86293", }, + { .compatible = "fujitsu,MB86294", }, + { .compatible = "fujitsu,coral", }, + { /* end */ } +}; + +static struct of_platform_driver of_platform_mb862xxfb_driver = { + .owner = THIS_MODULE, + .name = DRV_NAME, + .match_table = of_platform_mb862xx_tbl, + .probe = of_platform_mb862xx_probe, + .remove = __devexit_p(of_platform_mb862xx_remove), +}; +#endif + +#if defined(CONFIG_FB_MB862XX_PCI_GDC) +static int coralp_init(struct mb862xxfb_par *par) +{ + int cn, ver; + + par->host = par->mmio_base; + par->i2c = par->mmio_base + MB862XX_I2C_BASE; + par->disp = par->mmio_base + MB862XX_DISP_BASE; + par->cap = par->mmio_base + MB862XX_CAP_BASE; + par->draw = par->mmio_base + MB862XX_DRAW_BASE; + par->geo = par->mmio_base + MB862XX_GEO_BASE; + par->pio = par->mmio_base + MB862XX_PIO_BASE; + + par->refclk = GC_DISP_REFCLK_400; + + ver = inreg(host, GC_CID); + cn = (ver & GC_CID_CNAME_MSK) >> 8; + ver = ver & GC_CID_VERSION_MSK; + if (cn == 3) { + dev_info(par->dev, "Fujitsu Coral-%s GDC Rev.%d found\n",\ + (ver == 6) ? "P" : (ver == 8) ? "PA" : "?", + par->pdev->revision); + outreg(host, GC_CCF, GC_CCF_CGE_166 | GC_CCF_COT_133); + udelay(200); + outreg(host, GC_MMR, GC_MMR_CORALP_EVB_VAL); + udelay(10); + /* Clear interrupt status */ + outreg(host, GC_IST, 0); + } else { + return -ENODEV; + } + return 0; +} + +static int init_dram_ctrl(struct mb862xxfb_par *par) +{ + unsigned long i = 0; + + /* + * Set io mode first! Spec. says IC may be destroyed + * if not set to SSTL2/LVCMOS before init. + */ + outreg(dram_ctrl, GC_DCTL_IOCONT1_IOCONT0, GC_EVB_DCTL_IOCONT1_IOCONT0); + + /* DRAM init */ + outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD); + outreg(dram_ctrl, GC_DCTL_SETTIME1_EMODE, GC_EVB_DCTL_SETTIME1_EMODE); + outreg(dram_ctrl, GC_DCTL_REFRESH_SETTIME2, + GC_EVB_DCTL_REFRESH_SETTIME2); + outreg(dram_ctrl, GC_DCTL_RSV2_RSV1, GC_EVB_DCTL_RSV2_RSV1); + outreg(dram_ctrl, GC_DCTL_DDRIF2_DDRIF1, GC_EVB_DCTL_DDRIF2_DDRIF1); + outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES); + + /* DLL reset done? */ + while ((inreg(dram_ctrl, GC_DCTL_RSV0_STATES) & GC_DCTL_STATES_MSK)) { + udelay(GC_DCTL_INIT_WAIT_INTERVAL); + if (i++ > GC_DCTL_INIT_WAIT_CNT) { + dev_err(par->dev, "VRAM init failed.\n"); + return -EINVAL; + } + } + outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD_AFT_RST); + outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES_AFT_RST); + return 0; +} + +static int carmine_init(struct mb862xxfb_par *par) +{ + unsigned long reg; + + par->ctrl = par->mmio_base + MB86297_CTRL_BASE; + par->i2c = par->mmio_base + MB86297_I2C_BASE; + par->disp = par->mmio_base + MB86297_DISP0_BASE; + par->disp1 = par->mmio_base + MB86297_DISP1_BASE; + par->cap = par->mmio_base + MB86297_CAP0_BASE; + par->cap1 = par->mmio_base + MB86297_CAP1_BASE; + par->draw = par->mmio_base + MB86297_DRAW_BASE; + par->dram_ctrl = par->mmio_base + MB86297_DRAMCTRL_BASE; + par->wrback = par->mmio_base + MB86297_WRBACK_BASE; + + par->refclk = GC_DISP_REFCLK_533; + + /* warm up */ + reg = GC_CTRL_CLK_EN_DRAM | GC_CTRL_CLK_EN_2D3D | GC_CTRL_CLK_EN_DISP0; + outreg(ctrl, GC_CTRL_CLK_ENABLE, reg); + + /* check for engine module revision */ + if (inreg(draw, GC_2D3D_REV) == GC_RE_REVISION) + dev_info(par->dev, "Fujitsu Carmine GDC Rev.%d found\n", + par->pdev->revision); + else + goto err_init; + + reg &= ~GC_CTRL_CLK_EN_2D3D; + outreg(ctrl, GC_CTRL_CLK_ENABLE, reg); + + /* set up vram */ + if (init_dram_ctrl(par) < 0) + goto err_init; + + outreg(ctrl, GC_CTRL_INT_MASK, 0); + return 0; + +err_init: + outreg(ctrl, GC_CTRL_CLK_ENABLE, 0); + return -EINVAL; +} + +static inline int mb862xx_pci_gdc_init(struct mb862xxfb_par *par) +{ + switch (par->type) { + case BT_CORALP: + return coralp_init(par); + case BT_CARMINE: + return carmine_init(par); + default: + return -ENODEV; + } +} + +#define CHIP_ID(id) \ + { PCI_DEVICE(PCI_VENDOR_ID_FUJITSU_LIMITED, id) } + +static struct pci_device_id mb862xx_pci_tbl[] __devinitdata = { + /* MB86295/MB86296 */ + CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALP), + CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALPA), + /* MB86297 */ + CHIP_ID(PCI_DEVICE_ID_FUJITSU_CARMINE), + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, mb862xx_pci_tbl); + +static int __devinit mb862xx_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct mb862xxfb_par *par; + struct fb_info *info; + struct device *dev = &pdev->dev; + int ret; + + ret = pci_enable_device(pdev); + if (ret < 0) { + dev_err(dev, "Cannot enable PCI device\n"); + goto out; + } + + info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev); + if (!info) { + dev_err(dev, "framebuffer alloc failed\n"); + ret = -ENOMEM; + goto dis_dev; + } + + par = info->par; + par->info = info; + par->dev = dev; + par->pdev = pdev; + par->irq = pdev->irq; + + ret = pci_request_regions(pdev, DRV_NAME); + if (ret < 0) { + dev_err(dev, "Cannot reserve region(s) for PCI device\n"); + goto rel_fb; + } + + switch (pdev->device) { + case PCI_DEVICE_ID_FUJITSU_CORALP: + case PCI_DEVICE_ID_FUJITSU_CORALPA: + par->fb_base_phys = pci_resource_start(par->pdev, 0); + par->mapped_vram = CORALP_MEM_SIZE; + par->mmio_base_phys = par->fb_base_phys + MB862XX_MMIO_BASE; + par->mmio_len = MB862XX_MMIO_SIZE; + par->type = BT_CORALP; + break; + case PCI_DEVICE_ID_FUJITSU_CARMINE: + par->fb_base_phys = pci_resource_start(par->pdev, 2); + par->mmio_base_phys = pci_resource_start(par->pdev, 3); + par->mmio_len = pci_resource_len(par->pdev, 3); + par->mapped_vram = CARMINE_MEM_SIZE; + par->type = BT_CARMINE; + break; + default: + /* should never occur */ + goto rel_reg; + } + + par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram); + if (par->fb_base == NULL) { + dev_err(dev, "Cannot map framebuffer\n"); + goto rel_reg; + } + + par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len); + if (par->mmio_base == NULL) { + dev_err(dev, "Cannot map registers\n"); + ret = -EIO; + goto fb_unmap; + } + + dev_dbg(dev, "fb phys 0x%llx 0x%lx\n", + (u64)par->fb_base_phys, (ulong)par->mapped_vram); + dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n", + (u64)par->mmio_base_phys, (ulong)par->mmio_len); + + if (mb862xx_pci_gdc_init(par)) + goto io_unmap; + + if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED | IRQF_SHARED, + DRV_NAME, (void *)par)) { + dev_err(dev, "Cannot request irq\n"); + goto io_unmap; + } + + mb862xxfb_init_fbinfo(info); + + if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) { + dev_err(dev, "Could not allocate cmap for fb_info.\n"); + ret = -ENOMEM; + goto free_irq; + } + + if ((info->fbops->fb_set_par)(info)) + dev_err(dev, "set_var() failed on initial setup?\n"); + + ret = register_framebuffer(info); + if (ret < 0) { + dev_err(dev, "failed to register framebuffer\n"); + goto rel_cmap; + } + + pci_set_drvdata(pdev, info); + + if (device_create_file(dev, &dev_attr_dispregs)) + dev_err(dev, "Can't create sysfs regdump file\n"); + + if (par->type == BT_CARMINE) + outreg(ctrl, GC_CTRL_INT_MASK, GC_CARMINE_INT_EN); + else + outreg(host, GC_IMASK, GC_INT_EN); + + return 0; + +rel_cmap: + fb_dealloc_cmap(&info->cmap); +free_irq: + free_irq(par->irq, (void *)par); +io_unmap: + iounmap(par->mmio_base); +fb_unmap: + iounmap(par->fb_base); +rel_reg: + pci_release_regions(pdev); +rel_fb: + framebuffer_release(info); +dis_dev: + pci_disable_device(pdev); +out: + return ret; +} + +static void __devexit mb862xx_pci_remove(struct pci_dev *pdev) +{ + struct fb_info *fbi = pci_get_drvdata(pdev); + struct mb862xxfb_par *par = fbi->par; + unsigned long reg; + + dev_dbg(fbi->dev, "%s release\n", fbi->fix.id); + + /* display off */ + reg = inreg(disp, GC_DCM1); + reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E); + outreg(disp, GC_DCM1, reg); + + if (par->type == BT_CARMINE) { + outreg(ctrl, GC_CTRL_INT_MASK, 0); + outreg(ctrl, GC_CTRL_CLK_ENABLE, 0); + } else { + outreg(host, GC_IMASK, 0); + } + + device_remove_file(&pdev->dev, &dev_attr_dispregs); + + pci_set_drvdata(pdev, NULL); + unregister_framebuffer(fbi); + fb_dealloc_cmap(&fbi->cmap); + + free_irq(par->irq, (void *)par); + iounmap(par->mmio_base); + iounmap(par->fb_base); + + pci_release_regions(pdev); + framebuffer_release(fbi); + pci_disable_device(pdev); +} + +static struct pci_driver mb862xxfb_pci_driver = { + .name = DRV_NAME, + .id_table = mb862xx_pci_tbl, + .probe = mb862xx_pci_probe, + .remove = __devexit_p(mb862xx_pci_remove), +}; +#endif + +static int __devinit mb862xxfb_init(void) +{ + int ret = -ENODEV; + +#if defined(CONFIG_FB_MB862XX_LIME) + ret = of_register_platform_driver(&of_platform_mb862xxfb_driver); +#endif +#if defined(CONFIG_FB_MB862XX_PCI_GDC) + ret = pci_register_driver(&mb862xxfb_pci_driver); +#endif + return ret; +} + +static void __exit mb862xxfb_exit(void) +{ +#if defined(CONFIG_FB_MB862XX_LIME) + of_unregister_platform_driver(&of_platform_mb862xxfb_driver); +#endif +#if defined(CONFIG_FB_MB862XX_PCI_GDC) + pci_unregister_driver(&mb862xxfb_pci_driver); +#endif +} + +module_init(mb862xxfb_init); +module_exit(mb862xxfb_exit); + +MODULE_DESCRIPTION("Fujitsu MB862xx Framebuffer driver"); +MODULE_AUTHOR("Anatolij Gustschin "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/mb862xx/mb862xxfb.h b/drivers/video/mb862xx/mb862xxfb.h new file mode 100644 index 00000000000..c4c8f4dd221 --- /dev/null +++ b/drivers/video/mb862xx/mb862xxfb.h @@ -0,0 +1,83 @@ +#ifndef __MB862XX_H__ +#define __MB862XX_H__ + +#define PCI_VENDOR_ID_FUJITSU_LIMITED 0x10cf +#define PCI_DEVICE_ID_FUJITSU_CORALP 0x2019 +#define PCI_DEVICE_ID_FUJITSU_CORALPA 0x201e +#define PCI_DEVICE_ID_FUJITSU_CARMINE 0x202b + +#define GC_MMR_CORALP_EVB_VAL 0x11d7fa13 + +enum gdctype { + BT_NONE, + BT_LIME, + BT_MINT, + BT_CORAL, + BT_CORALP, + BT_CARMINE, +}; + +struct mb862xx_gc_mode { + struct fb_videomode def_mode; /* mode of connected display */ + unsigned int def_bpp; /* default depth */ + unsigned long max_vram; /* connected SDRAM size */ + unsigned long ccf; /* gdc clk */ + unsigned long mmr; /* memory mode for SDRAM */ +}; + +/* private data */ +struct mb862xxfb_par { + struct fb_info *info; /* fb info head */ + struct device *dev; + struct pci_dev *pdev; + struct resource *res; /* framebuffer/mmio resource */ + + resource_size_t fb_base_phys; /* fb base, 36-bit PPC440EPx */ + resource_size_t mmio_base_phys; /* io base addr */ + void __iomem *fb_base; /* remapped framebuffer */ + void __iomem *mmio_base; /* remapped registers */ + size_t mapped_vram; /* length of remapped vram */ + size_t mmio_len; /* length of register region */ + + void __iomem *host; /* relocatable reg. bases */ + void __iomem *i2c; + void __iomem *disp; + void __iomem *disp1; + void __iomem *cap; + void __iomem *cap1; + void __iomem *draw; + void __iomem *geo; + void __iomem *pio; + void __iomem *ctrl; + void __iomem *dram_ctrl; + void __iomem *wrback; + + unsigned int irq; + unsigned int type; /* GDC type */ + unsigned int refclk; /* disp. reference clock */ + struct mb862xx_gc_mode *gc_mode; /* GDC mode init data */ + int pre_init; /* don't init display if 1 */ + + u32 pseudo_palette[16]; +}; + +#if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC) +#error "Select Lime GDC or CoralP/Carmine support, but not both together" +#endif +#if defined(CONFIG_FB_MB862XX_LIME) +#define gdc_read __raw_readl +#define gdc_write __raw_writel +#else +#define gdc_read readl +#define gdc_write writel +#endif + +#define inreg(type, off) \ + gdc_read((par->type + (off))) + +#define outreg(type, off, val) \ + gdc_write((val), (par->type + (off))) + +#define pack(a, b) (((a) << 16) | (b)) + +#endif -- cgit v1.2.3 From a684e7d33096892093456dd56a582cfc3bfad648 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 6 Nov 2008 12:53:37 -0800 Subject: fbdev: fix fb_compat_ioctl() deadlocks commit 3e680aae4e53ab54cdbb0c29257dae0cbb158e1c ("fb: convert lock/unlock_kernel() into local fb mutex") introduced several deadlocks in the fb_compat_ioctl() path, as mutex_lock() doesn't allow recursion, unlike lock_kernel(). This broke frame buffer applications on 64-bit systems with a 32-bit userland. commit 120a37470c2831fea49fdebaceb5a7039f700ce6 ("framebuffer compat_ioctl deadlock") fixed one of the deadlocks. This patch fixes the remaining deadlocks: - Revert commit 120a37470c2831fea49fdebaceb5a7039f700ce6, - Extract the core logic of fb_ioctl() into a new function do_fb_ioctl(), - Change all callsites of fb_ioctl() where info->lock is already held to call do_fb_ioctl() instead, - Add sparse annotations to all routines that take info->lock. Signed-off-by: Geert Uytterhoeven Cc: Mikulas Patocka Cc: Krzysztof Helt Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/fbmem.c | 63 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 6048b55f287..1d5ae39cb27 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1002,13 +1002,9 @@ fb_blank(struct fb_info *info, int blank) return ret; } -static long -fb_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) +static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, + unsigned long arg) { - struct inode *inode = file->f_path.dentry->d_inode; - int fbidx = iminor(inode); - struct fb_info *info; struct fb_ops *fb; struct fb_var_screeninfo var; struct fb_fix_screeninfo fix; @@ -1018,14 +1014,10 @@ fb_ioctl(struct file *file, unsigned int cmd, void __user *argp = (void __user *)arg; long ret = 0; - info = registered_fb[fbidx]; - mutex_lock(&info->lock); fb = info->fbops; - - if (!fb) { - mutex_unlock(&info->lock); + if (!fb) return -ENODEV; - } + switch (cmd) { case FBIOGET_VSCREENINFO: ret = copy_to_user(argp, &info->var, @@ -1126,6 +1118,21 @@ fb_ioctl(struct file *file, unsigned int cmd, else ret = fb->fb_ioctl(info, cmd, arg); } + return ret; +} + +static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +__acquires(&info->lock) +__releases(&info->lock) +{ + struct inode *inode = file->f_path.dentry->d_inode; + int fbidx = iminor(inode); + struct fb_info *info; + long ret; + + info = registered_fb[fbidx]; + mutex_lock(&info->lock); + ret = do_fb_ioctl(info, cmd, arg); mutex_unlock(&info->lock); return ret; } @@ -1157,8 +1164,8 @@ struct fb_cmap32 { compat_caddr_t transp; }; -static int fb_getput_cmap(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int fb_getput_cmap(struct fb_info *info, unsigned int cmd, + unsigned long arg) { struct fb_cmap_user __user *cmap; struct fb_cmap32 __user *cmap32; @@ -1181,7 +1188,7 @@ static int fb_getput_cmap(struct inode *inode, struct file *file, put_user(compat_ptr(data), &cmap->transp)) return -EFAULT; - err = fb_ioctl(file, cmd, (unsigned long) cmap); + err = do_fb_ioctl(info, cmd, (unsigned long) cmap); if (!err) { if (copy_in_user(&cmap32->start, @@ -1223,8 +1230,8 @@ static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix, return err; } -static int fb_get_fscreeninfo(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd, + unsigned long arg) { mm_segment_t old_fs; struct fb_fix_screeninfo fix; @@ -1235,7 +1242,7 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file, old_fs = get_fs(); set_fs(KERNEL_DS); - err = fb_ioctl(file, cmd, (unsigned long) &fix); + err = do_fb_ioctl(info, cmd, (unsigned long) &fix); set_fs(old_fs); if (!err) @@ -1244,8 +1251,10 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file, return err; } -static long -fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long fb_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +__acquires(&info->lock) +__releases(&info->lock) { struct inode *inode = file->f_path.dentry->d_inode; int fbidx = iminor(inode); @@ -1262,16 +1271,16 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case FBIOPUT_CON2FBMAP: arg = (unsigned long) compat_ptr(arg); case FBIOBLANK: - mutex_unlock(&info->lock); - return fb_ioctl(file, cmd, arg); + ret = do_fb_ioctl(info, cmd, arg); + break; case FBIOGET_FSCREENINFO: - ret = fb_get_fscreeninfo(inode, file, cmd, arg); + ret = fb_get_fscreeninfo(info, cmd, arg); break; case FBIOGETCMAP: case FBIOPUTCMAP: - ret = fb_getput_cmap(inode, file, cmd, arg); + ret = fb_getput_cmap(info, cmd, arg); break; default: @@ -1286,6 +1295,8 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static int fb_mmap(struct file *file, struct vm_area_struct * vma) +__acquires(&info->lock) +__releases(&info->lock) { int fbidx = iminor(file->f_path.dentry->d_inode); struct fb_info *info = registered_fb[fbidx]; @@ -1339,6 +1350,8 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) static int fb_open(struct inode *inode, struct file *file) +__acquires(&info->lock) +__releases(&info->lock) { int fbidx = iminor(inode); struct fb_info *info; @@ -1374,6 +1387,8 @@ out: static int fb_release(struct inode *inode, struct file *file) +__acquires(&info->lock) +__releases(&info->lock) { struct fb_info * const info = file->private_data; -- cgit v1.2.3 From 06a7f058761cd232cab42d5c7da82f7255b51d5b Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 6 Nov 2008 12:53:40 -0800 Subject: atmel_serial: keep clock off when it's not needed The atmel_serial driver is mismanaging its clock by leaving it on at all times ... the whole point of clock management is to leave it off unless it's actively needed, which conserves power!! Although the kernel doesn't actually hang without my fix, it does discard quite a lot of early console output. The result still looks correct: usart users= 1 on 35000000 Hz, for atmel_usart.0 usart users= 0 off 35000000 Hz, for atmel_usart.2 when using ttyS0 as serial console. [haavard.skinnemoen@atmel.com: Make sure clock is enabled early for console] Signed-off-by: David Brownell Signed-off-by: Haavard Skinnemoen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/atmel_serial.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 61fb8b6d19a..d5efd6c7790 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -1258,6 +1258,8 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, atmel_port->clk = clk_get(&pdev->dev, "usart"); clk_enable(atmel_port->clk); port->uartclk = clk_get_rate(atmel_port->clk); + clk_disable(atmel_port->clk); + /* only enable clock when USART is in use */ } atmel_port->use_dma_rx = data->use_dma_rx; @@ -1379,6 +1381,8 @@ static int __init atmel_console_setup(struct console *co, char *options) return -ENODEV; } + clk_enable(atmel_ports[co->index].clk); + UART_PUT_IDR(port, -1); UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN); @@ -1403,7 +1407,7 @@ static struct console atmel_console = { .data = &atmel_uart, }; -#define ATMEL_CONSOLE_DEVICE &atmel_console +#define ATMEL_CONSOLE_DEVICE (&atmel_console) /* * Early console initialization (before VM subsystem initialized). @@ -1534,6 +1538,15 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev) if (ret) goto err_add_port; + if (atmel_is_console_port(&port->uart) + && ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) { + /* + * The serial core enabled the clock for us, so undo + * the clk_enable() in atmel_console_setup() + */ + clk_disable(port->clk); + } + device_init_wakeup(&pdev->dev, 1); platform_set_drvdata(pdev, port); @@ -1544,7 +1557,6 @@ err_add_port: port->rx_ring.buf = NULL; err_alloc_ring: if (!atmel_is_console_port(&port->uart)) { - clk_disable(port->clk); clk_put(port->clk); port->clk = NULL; } @@ -1568,7 +1580,6 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev) /* "port" is allocated statically, so we shouldn't free it */ - clk_disable(atmel_port->clk); clk_put(atmel_port->clk); return ret; -- cgit v1.2.3 From 80bb26d4062657c52862d1b112beead47ff9b793 Mon Sep 17 00:00:00 2001 From: Frans Pop Date: Thu, 6 Nov 2008 12:53:41 -0800 Subject: rtc-cmos: fix boot log message -rtc0: alarms up to one month, y3k, 114 bytes nvram, , hpet irqs irqs +rtc0: alarms up to one month, y3k, 114 bytes nvram, hpet irqs Signed-off-by: Frans Pop Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-cmos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 5549231179a..6cf8e282338 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -794,7 +794,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) goto cleanup2; } - pr_info("%s: alarms up to one %s%s, %zd bytes nvram, %s irqs\n", + pr_info("%s: alarms up to one %s%s, %zd bytes nvram%s\n", cmos_rtc.rtc->dev.bus_id, is_valid_irq(rtc_irq) ? (cmos_rtc.mon_alrm -- cgit v1.2.3 From c1dfda399ace020126547e7d454ba94edc8c8797 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 6 Nov 2008 12:53:42 -0800 Subject: SAM9 watchdog: update for moved headers The architecture header files were recently moved from include/asm-arm/mach-at91/ to arch/arm/mach-at91/include/mach/. The SAM9 watchdog driver still includes a header from the old location. Signed-off-by: Andrew Victor Cc: Wim Van Sebroeck Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/watchdog/at91sam9_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index b4babfc3158..b1da287f90e 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -30,7 +30,7 @@ #include #include -#include +#include #define DRV_NAME "AT91SAM9 Watchdog" -- cgit v1.2.3 From ad93a765c1834db031b5bf1c2baf2a50d0462ca4 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Tue, 4 Nov 2008 14:52:55 -0700 Subject: ACPI: Disambiguate processor declaration type Declaring processors in ACPI namespace can be done using either a "Processor" definition or a "Device" definition (see section 8.4 - Declaring Processors; "Advanced Configuration and Power Interface Specification", Revision 3.0b). Currently the two processor declaration types are conflated. This patch disambiguates the processor declaration's definition type enabling subsequent code to behave uniquely based explicitly on the declaration's type. Signed-off-by: Myron Stowe Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 1 + drivers/acpi/scan.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 24a362f8034..0c670dd297d 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -89,6 +89,7 @@ static int acpi_processor_handle_eject(struct acpi_processor *pr); static const struct acpi_device_id processor_device_ids[] = { + {ACPI_PROCESSOR_OBJECT_HID, 0}, {ACPI_PROCESSOR_HID, 0}, {"", 0}, }; diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a9dda8e0f9f..3fb6e2db585 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1043,7 +1043,7 @@ static void acpi_device_set_id(struct acpi_device *device, hid = ACPI_POWER_HID; break; case ACPI_BUS_TYPE_PROCESSOR: - hid = ACPI_PROCESSOR_HID; + hid = ACPI_PROCESSOR_OBJECT_HID; break; case ACPI_BUS_TYPE_SYSTEM: hid = ACPI_SYSTEM_HID; -- cgit v1.2.3 From b26e9286fb438eb78bcdb68b67a3dbb8bc539125 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Tue, 4 Nov 2008 14:53:00 -0700 Subject: ACPI: Behave uniquely based on processor declaration definition type Associating a Local SAPIC with a processor object is dependent upon the processor object's definition type. CPUs declared as "Processor" should use the Local SAPIC's 'processor_id', and CPUs declared as "Device" should use the 'uid'. Note that for "Processor" declarations, even if a '_UID' child object exists, it has no bearing with respect to mapping Local SAPICs (see section 5.2.11.13 - Local SAPIC Structure; "Advanced Configuration and Power Interface Specification", Revision 3.0b). This patch changes the lsapic mapping logic to rely on the distinction of how the processor object was declared - the mapping can't just try both types of matches regardless of declaration type and rely on one failing as is currently being done. Signed-off-by: Myron Stowe Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 78 ++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 0c670dd297d..bc332fc28d7 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -410,7 +410,7 @@ static int acpi_processor_remove_fs(struct acpi_device *device) /* Use the acpiid in MADT to map cpus in case of SMP */ #ifndef CONFIG_SMP -static int get_cpu_id(acpi_handle handle, u32 acpi_id) {return -1;} +static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id) { return -1; } #else static struct acpi_table_madt *madt; @@ -429,27 +429,35 @@ static int map_lapic_id(struct acpi_subtable_header *entry, } static int map_lsapic_id(struct acpi_subtable_header *entry, - u32 acpi_id, int *apic_id) + int device_declaration, u32 acpi_id, int *apic_id) { struct acpi_madt_local_sapic *lsapic = (struct acpi_madt_local_sapic *)entry; + u32 tmp = (lsapic->id << 8) | lsapic->eid; + /* Only check enabled APICs*/ - if (lsapic->lapic_flags & ACPI_MADT_ENABLED) { - /* First check against id */ - if (lsapic->processor_id == acpi_id) { - *apic_id = (lsapic->id << 8) | lsapic->eid; - return 1; - /* Check against optional uid */ - } else if (entry->length >= 16 && - lsapic->uid == acpi_id) { - *apic_id = lsapic->uid; - return 1; - } - } + if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED)) + return 0; + + /* Device statement declaration type */ + if (device_declaration) { + if (entry->length < 16) + printk(KERN_ERR PREFIX + "Invalid LSAPIC with Device type processor (SAPIC ID %#x)\n", + tmp); + else if (lsapic->uid == acpi_id) + goto found; + /* Processor statement declaration type */ + } else if (lsapic->processor_id == acpi_id) + goto found; + return 0; +found: + *apic_id = tmp; + return 1; } -static int map_madt_entry(u32 acpi_id) +static int map_madt_entry(int type, u32 acpi_id) { unsigned long madt_end, entry; int apic_id = -1; @@ -470,7 +478,7 @@ static int map_madt_entry(u32 acpi_id) if (map_lapic_id(header, acpi_id, &apic_id)) break; } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { - if (map_lsapic_id(header, acpi_id, &apic_id)) + if (map_lsapic_id(header, type, acpi_id, &apic_id)) break; } entry += header->length; @@ -478,7 +486,7 @@ static int map_madt_entry(u32 acpi_id) return apic_id; } -static int map_mat_entry(acpi_handle handle, u32 acpi_id) +static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; @@ -501,7 +509,7 @@ static int map_mat_entry(acpi_handle handle, u32 acpi_id) if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { map_lapic_id(header, acpi_id, &apic_id); } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { - map_lsapic_id(header, acpi_id, &apic_id); + map_lsapic_id(header, type, acpi_id, &apic_id); } exit: @@ -510,14 +518,14 @@ exit: return apic_id; } -static int get_cpu_id(acpi_handle handle, u32 acpi_id) +static int get_cpu_id(acpi_handle handle, int type, u32 acpi_id) { int i; int apic_id = -1; - apic_id = map_mat_entry(handle, acpi_id); + apic_id = map_mat_entry(handle, type, acpi_id); if (apic_id == -1) - apic_id = map_madt_entry(acpi_id); + apic_id = map_madt_entry(type, acpi_id); if (apic_id == -1) return apic_id; @@ -533,15 +541,16 @@ static int get_cpu_id(acpi_handle handle, u32 acpi_id) Driver Interface -------------------------------------------------------------------------- */ -static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) +static int acpi_processor_get_info(struct acpi_device *device) { acpi_status status = 0; union acpi_object object = { 0 }; struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; - int cpu_index; + struct acpi_processor *pr; + int cpu_index, device_declaration = 0; static int cpu0_initialized; - + pr = acpi_driver_data(device); if (!pr) return -EINVAL; @@ -562,22 +571,23 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No bus mastering arbitration control\n")); - /* Check if it is a Device with HID and UID */ - if (has_uid) { + if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_HID)) { + /* + * Declared with "Device" statement; match _UID. + * Note that we don't handle string _UIDs yet. + */ unsigned long long value; status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, NULL, &value); if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Evaluating processor _UID\n"); + printk(KERN_ERR PREFIX + "Evaluating processor _UID [%#x]\n", status); return -ENODEV; } + device_declaration = 1; pr->acpi_id = value; } else { - /* - * Evalute the processor object. Note that it is common on SMP to - * have the first (boot) processor with a valid PBLK address while - * all others have a NULL address. - */ + /* Declared with "Processor" statement; match ProcessorID */ status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Evaluating processor object\n"); @@ -590,7 +600,7 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) */ pr->acpi_id = object.processor.proc_id; } - cpu_index = get_cpu_id(pr->handle, pr->acpi_id); + cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id); /* Handle UP system running SMP kernel, with no LAPIC in MADT */ if (!cpu0_initialized && (cpu_index == -1) && @@ -662,7 +672,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) pr = acpi_driver_data(device); - result = acpi_processor_get_info(pr, device->flags.unique_id); + result = acpi_processor_get_info(device); if (result) { /* Processor is physically not present */ return 0; -- cgit v1.2.3 From 5b53ed69158eeff115004f246193d07a083445f6 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Tue, 4 Nov 2008 14:53:05 -0700 Subject: ACPI: 80 column adherence and spelling fix (no functional change) Signed-off-by: Myron Stowe Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index bc332fc28d7..b57b1f05cb3 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -595,9 +595,10 @@ static int acpi_processor_get_info(struct acpi_device *device) } /* - * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. - * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c - */ + * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. + * >>> 'acpi_get_processor_id(acpi_id, &id)' in + * arch/xxx/acpi.c + */ pr->acpi_id = object.processor.proc_id; } cpu_index = get_cpu_id(pr->handle, device_declaration, pr->acpi_id); -- cgit v1.2.3 From d65dcdcf0cd55b4be1fd1f5025388e91042d63fc Mon Sep 17 00:00:00 2001 From: "Thomas, Sujith" Date: Wed, 5 Nov 2008 16:15:13 +0530 Subject: intel_menlow: Add comment documenting legal GTHS values Signed-off-by: Sujith Thomas Signed-off-by: Len Brown --- drivers/misc/intel_menlow.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/intel_menlow.c b/drivers/misc/intel_menlow.c index 124b37ddb5c..27b7662955b 100644 --- a/drivers/misc/intel_menlow.c +++ b/drivers/misc/intel_menlow.c @@ -52,6 +52,11 @@ MODULE_LICENSE("GPL"); #define MEMORY_ARG_CUR_BANDWIDTH 1 #define MEMORY_ARG_MAX_BANDWIDTH 0 +/* + * GTHS returning 'n' would mean that [0,n-1] states are supported + * In that case max_cstate would be n-1 + * GTHS returning '0' would mean that no bandwidth control states are supported + */ static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev, unsigned long *max_state) { -- cgit v1.2.3 From d17cb18a07c587b8f9ff174a1bf6d03413eabe64 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 6 Nov 2008 20:51:59 -0500 Subject: Revert "ACPI: Ingore the RESET_REG_SUP bit when using ACPI reset mechanism" This reverts commit 8fd145917fb62368a9b80db59562c20576238f5a. http://bugzilla.kernel.org/show_bug.cgi?id=11942 Signed-off-by: Len Brown --- drivers/acpi/reboot.c | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c index 755baf2ca70..a6b662c00b6 100644 --- a/drivers/acpi/reboot.c +++ b/drivers/acpi/reboot.c @@ -15,28 +15,9 @@ void acpi_reboot(void) rr = &acpi_gbl_FADT.reset_register; - /* - * Is the ACPI reset register supported? - * - * According to ACPI 3.0, FADT.flags.RESET_REG_SUP indicates - * whether the ACPI reset mechanism is supported. - * - * However, some boxes have this bit clear, yet a valid - * ACPI_RESET_REG & RESET_VALUE, and ACPI reboot is the only - * mechanism that works for them after S3. - * - * This suggests that other operating systems may not be checking - * the RESET_REG_SUP bit, and are using other means to decide - * whether to use the ACPI reboot mechanism or not. - * - * So when acpi reboot is requested, - * only the reset_register is checked. If the following - * conditions are met, it indicates that the reset register is supported. - * a. reset_register is not zero - * b. the access width is eight - * c. the bit_offset is zero - */ - if (!(rr->address) || rr->bit_width != 8 || rr->bit_offset != 0) + /* Is the reset register supported? */ + if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || + rr->bit_width != 8 || rr->bit_offset != 0) return; reset_value = acpi_gbl_FADT.reset_value; -- cgit v1.2.3 From 0794469da3f7b2093575cbdfc1108308dd3641ce Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 30 Oct 2008 01:18:59 +0100 Subject: ACPI: struct device - replace bus_id with dev_name(), dev_set_name() This patch is part of a larger patch series which will remove the "char bus_id[20]" name string from struct device. The device name is managed in the kobject anyway, and without any size limitation, and just needlessly copied into "struct device". To set and read the device name dev_name(dev) and dev_set_name(dev) must be used. If your code uses static kobjects, which it shouldn't do, "const char *init_name" can be used to statically provide the name the registered device should have. At registration time, the init_name field is cleared, to enforce the use of dev_name(dev) to access the device name at a later time. We need to get rid of all occurrences of bus_id in the entire tree to be able to enable the new interface. Please apply this patch, and possibly convert any remaining remaining occurrences of bus_id. We want to submit a patch to -next, which will remove bus_id from "struct device", to find the remaining pieces to convert, and finally switch over to the new api, which will remove the 20 bytes array and does no longer have a size limitation. Acked-by: Greg Kroah-Hartman Signed-Off-By: Kay Sievers Signed-off-by: Len Brown --- drivers/acpi/ac.c | 2 +- drivers/acpi/battery.c | 2 +- drivers/acpi/processor_core.c | 6 +++--- drivers/acpi/scan.c | 8 ++++---- drivers/acpi/sleep/proc.c | 4 ++-- drivers/acpi/thermal.c | 8 ++++---- drivers/acpi/wmi.c | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index d72a1b6c8a9..2d467326d9e 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -242,7 +242,7 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) acpi_ac_get_state(ac); acpi_bus_generate_proc_event(device, event, (u32) ac->state); acpi_bus_generate_netlink_event(device->pnp.device_class, - device->dev.bus_id, event, + dev_name(&device->dev), event, (u32) ac->state); #ifdef CONFIG_ACPI_SYSFS_POWER kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index b2133e89ad9..e68f2187ed6 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -782,7 +782,7 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) acpi_bus_generate_proc_event(device, event, acpi_battery_present(battery)); acpi_bus_generate_netlink_event(device->pnp.device_class, - device->dev.bus_id, event, + dev_name(&device->dev), event, acpi_battery_present(battery)); #ifdef CONFIG_ACPI_SYSFS_POWER /* acpi_batter_update could remove power_supply object */ diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 24a362f8034..cf7e8856a4c 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -761,20 +761,20 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) acpi_bus_generate_proc_event(device, event, pr->performance_platform_limit); acpi_bus_generate_netlink_event(device->pnp.device_class, - device->dev.bus_id, event, + dev_name(&device->dev), event, pr->performance_platform_limit); break; case ACPI_PROCESSOR_NOTIFY_POWER: acpi_processor_cst_has_changed(pr); acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, - device->dev.bus_id, event, 0); + dev_name(&device->dev), event, 0); break; case ACPI_PROCESSOR_NOTIFY_THROTTLING: acpi_processor_tstate_has_changed(pr); acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, - device->dev.bus_id, event, 0); + dev_name(&device->dev), event, 0); default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a9dda8e0f9f..4dd1f31930b 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -109,8 +109,7 @@ static int acpi_bus_hot_remove_device(void *context) return 0; ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Hot-removing device %s...\n", device->dev.bus_id)); - + "Hot-removing device %s...\n", dev_name(&device->dev))); if (acpi_bus_trim(device, 1)) { printk(KERN_ERR PREFIX @@ -460,7 +459,7 @@ static int acpi_device_register(struct acpi_device *device, acpi_device_bus_id->instance_no = 0; list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list); } - sprintf(device->dev.bus_id, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no); + dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no); if (device->parent) { list_add_tail(&device->node, &device->parent->children); @@ -484,7 +483,8 @@ static int acpi_device_register(struct acpi_device *device, result = acpi_device_setup_files(device); if(result) - printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", device->dev.bus_id); + printk(KERN_ERR PREFIX "Error creating sysfs interface for device %s\n", + dev_name(&device->dev)); device->removal_type = ACPI_BUS_REMOVAL_NORMAL; return 0; diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 631ee2ee2ca..64e591ba86f 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c @@ -366,8 +366,8 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) dev->wakeup.state.enabled ? "enabled" : "disabled"); if (ldev) seq_printf(seq, "%s:%s", - ldev->bus ? ldev->bus->name : "no-bus", - ldev->bus_id); + dev_name(ldev) ? ldev->bus->name : "no-bus", + dev_name(ldev)); seq_printf(seq, "\n"); put_device(ldev); diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index ad6cae938f0..462b1687885 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -576,7 +576,7 @@ static int acpi_thermal_critical(struct acpi_thermal *tz) acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled); acpi_bus_generate_netlink_event(tz->device->pnp.device_class, - tz->device->dev.bus_id, + dev_name(&tz->device->dev), ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled); @@ -605,7 +605,7 @@ static int acpi_thermal_hot(struct acpi_thermal *tz) acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_HOT, tz->trips.hot.flags.enabled); acpi_bus_generate_netlink_event(tz->device->pnp.device_class, - tz->device->dev.bus_id, + dev_name(&tz->device->dev), ACPI_THERMAL_NOTIFY_HOT, tz->trips.hot.flags.enabled); @@ -1592,14 +1592,14 @@ static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data) acpi_thermal_check(tz); acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, - device->dev.bus_id, event, 0); + dev_name(&device->dev), event, 0); break; case ACPI_THERMAL_NOTIFY_DEVICES: acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES); acpi_thermal_check(tz); acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, - device->dev.bus_id, event, 0); + dev_name(&device->dev), event, 0); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, diff --git a/drivers/acpi/wmi.c b/drivers/acpi/wmi.c index 47cd7baf9b1..8a8b377712c 100644 --- a/drivers/acpi/wmi.c +++ b/drivers/acpi/wmi.c @@ -660,7 +660,7 @@ static void acpi_wmi_notify(acpi_handle handle, u32 event, void *data) wblock->handler(event, wblock->handler_data); acpi_bus_generate_netlink_event( - device->pnp.device_class, device->dev.bus_id, + device->pnp.device_class, dev_name(&device->dev), event, 0); break; } -- cgit v1.2.3 From afeb12b7478fee31888e7c34804bee2f658e7765 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 29 Oct 2008 14:13:20 -0700 Subject: fujitsu-laptop: fix section mismatch warning Could fix a bug in a hotplug add scenario. WARNING: drivers/misc/fujitsu-laptop.o(.text+0xbde): Section mismatch in reference from the function acpi_fujitsu_add() to the variable .init.data:fujitsu_dmi_table The function acpi_fujitsu_add() references the variable __initdata fujitsu_dmi_table. This is often because acpi_fujitsu_add lacks a __initdata annotation or the annotation of fujitsu_dmi_table is wrong. Signed-off-by: Randy Dunlap Acked-by: Jonathan Woithe Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/misc/fujitsu-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c index d2cf0bfe316..9124fcdc4d0 100644 --- a/drivers/misc/fujitsu-laptop.c +++ b/drivers/misc/fujitsu-laptop.c @@ -473,7 +473,7 @@ static int dmi_check_cb_p8010(const struct dmi_system_id *id) return 0; } -static struct dmi_system_id __initdata fujitsu_dmi_table[] = { +static struct dmi_system_id fujitsu_dmi_table[] = { { .ident = "Fujitsu Siemens S6410", .matches = { -- cgit v1.2.3 From 14a63ba821ac2a0f5166789b31241c0b7eb147d9 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Wed, 29 Oct 2008 14:13:22 -0700 Subject: ACPI: use macro to replace hard number Impact: cleanup Use MACRO for rev 3 fadt id instead of 3 directly. Signed-off-by: Yinghai Lu Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/tables/tbfadt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c index 2c7885e7ffb..2817158fb6a 100644 --- a/drivers/acpi/tables/tbfadt.c +++ b/drivers/acpi/tables/tbfadt.c @@ -304,7 +304,7 @@ static void acpi_tb_convert_fadt(void) * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at * offset 45, 55, 95, and the word located at offset 109, 110. */ - if (acpi_gbl_FADT.header.revision < 3) { + if (acpi_gbl_FADT.header.revision < FADT2_REVISION_ID) { acpi_gbl_FADT.preferred_profile = 0; acpi_gbl_FADT.pstate_control = 0; acpi_gbl_FADT.cst_control = 0; -- cgit v1.2.3 From 4feba70a2c1a1a0c96909f657f48b2e11e682370 Mon Sep 17 00:00:00 2001 From: Peter Gruber Date: Mon, 27 Oct 2008 23:59:36 -0400 Subject: ACPI: avoid empty file name in sysfs Since commit bc45b1d39a925b56796bebf8a397a0491489d85c acpi tables are allowed to have an empty signature and /sys/firmware/acpi/tables uses the signature as filename. Applications using naive recursion through /sys loop forever. A possible solution would be: (replacing the zero length filename with the string "NULL") http://bugzilla.kernel.org/show_bug.cgi?id=11539 Acked-by: Zhang Rui Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/system.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 1d74171b794..62ec75e7912 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -78,9 +78,15 @@ static ssize_t acpi_table_show(struct kobject *kobj, container_of(bin_attr, struct acpi_table_attr, attr); struct acpi_table_header *table_header = NULL; acpi_status status; + char name[ACPI_NAME_SIZE]; + + if (strncmp(table_attr->name, "NULL", 4)) + memcpy(name, table_attr->name, ACPI_NAME_SIZE); + else + memcpy(name, "\0\0\0\0", 4); status = - acpi_get_table(table_attr->name, table_attr->instance, + acpi_get_table(name, table_attr->instance, &table_header); if (ACPI_FAILURE(status)) return -ENODEV; @@ -95,21 +101,24 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr, struct acpi_table_header *header = NULL; struct acpi_table_attr *attr = NULL; - memcpy(table_attr->name, table_header->signature, ACPI_NAME_SIZE); + if (table_header->signature[0] != '\0') + memcpy(table_attr->name, table_header->signature, + ACPI_NAME_SIZE); + else + memcpy(table_attr->name, "NULL", 4); list_for_each_entry(attr, &acpi_table_attr_list, node) { - if (!memcmp(table_header->signature, attr->name, - ACPI_NAME_SIZE)) + if (!memcmp(table_attr->name, attr->name, ACPI_NAME_SIZE)) if (table_attr->instance < attr->instance) table_attr->instance = attr->instance; } table_attr->instance++; if (table_attr->instance > 1 || (table_attr->instance == 1 && - !acpi_get_table(table_header-> - signature, 2, - &header))) - sprintf(table_attr->name + 4, "%d", table_attr->instance); + !acpi_get_table + (table_header->signature, 2, &header))) + sprintf(table_attr->name + ACPI_NAME_SIZE, "%d", + table_attr->instance); table_attr->attr.size = 0; table_attr->attr.read = acpi_table_show; -- cgit v1.2.3 From c1adbb9681c30e984272b66623c4d5774b3981e1 Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Wed, 5 Nov 2008 16:53:50 +0200 Subject: mlx4_en: Start port error flow bug fix Tried to deactivate rx ring that wasn't activated, used wrong index. Signed-off-by: Yevgeny Petrilin Signed-off-by: Jeff Garzik --- drivers/net/mlx4/en_netdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index a339afbeed3..a3f732418c4 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -706,7 +706,7 @@ tx_err: mlx4_en_release_rss_steer(priv); rx_err: for (i = 0; i < priv->rx_ring_num; i++) - mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[rx_index]); + mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); cq_err: while (rx_index--) mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]); -- cgit v1.2.3 From db053c6b447d083f3c63e5540b70a3e521b468ca Mon Sep 17 00:00:00 2001 From: Paulius Zaleckas Date: Tue, 4 Nov 2008 13:32:31 +0200 Subject: hso: rfkill type should be WWAN Signed-off-by: Paulius Zaleckas Cc: Denis Joseph Barrow Signed-off-by: Jeff Garzik --- drivers/net/usb/hso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 1164c52e2c0..3f49e8382dd 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2188,7 +2188,7 @@ static void hso_create_rfkill(struct hso_device *hso_dev, char *rfkn; hso_net->rfkill = rfkill_allocate(&interface_to_usbdev(interface)->dev, - RFKILL_TYPE_WLAN); + RFKILL_TYPE_WWAN); if (!hso_net->rfkill) { dev_err(dev, "%s - Out of memory", __func__); return; -- cgit v1.2.3 From 08809b25cf64a7d8deb336b779e527e88830eac9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 1 Nov 2008 18:20:19 +0000 Subject: el3_common_init() should be __devinit, not __init Signed-off-by: Al Viro Signed-off-by: Jeff Garzik --- drivers/net/3c509.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 3a7bc524af3..c7a4f3bcc2b 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -94,7 +94,7 @@ #include #include -static char version[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n"; +static char version[] __devinitdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n"; #ifdef EL3_DEBUG static int el3_debug = EL3_DEBUG; @@ -186,7 +186,7 @@ static int max_interrupt_work = 10; static int nopnp; #endif -static int __init el3_common_init(struct net_device *dev); +static int __devinit el3_common_init(struct net_device *dev); static void el3_common_remove(struct net_device *dev); static ushort id_read_eeprom(int index); static ushort read_eeprom(int ioaddr, int index); @@ -537,7 +537,7 @@ static struct mca_driver el3_mca_driver = { static int mca_registered; #endif /* CONFIG_MCA */ -static int __init el3_common_init(struct net_device *dev) +static int __devinit el3_common_init(struct net_device *dev) { struct el3_private *lp = netdev_priv(dev); int err; -- cgit v1.2.3 From cd17fa7b8f1dd24b23c464ebcb14e7c058e15097 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 3 Nov 2008 23:08:04 +0000 Subject: sfc: Correct address of gPXE boot configuration in EEPROM Due to a hardware bug, the originally assigned range cannot reliably be used for boot configuration and must not be modifiable through ethtool. Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index fa98af58223..cd0d0873d97 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -174,8 +174,8 @@ static struct efx_ethtool_stat efx_ethtool_stats[] = { /* EEPROM range with gPXE configuration */ #define EFX_ETHTOOL_EEPROM_MAGIC 0xEFAB -#define EFX_ETHTOOL_EEPROM_MIN 0x100U -#define EFX_ETHTOOL_EEPROM_MAX 0x400U +#define EFX_ETHTOOL_EEPROM_MIN 0x800U +#define EFX_ETHTOOL_EEPROM_MAX 0x1800U /************************************************************************** * -- cgit v1.2.3 From 939a9516416ad8ccec27aa05bd19236c550c0c03 Mon Sep 17 00:00:00 2001 From: Jonathan McDowell Date: Tue, 4 Nov 2008 07:51:38 +0000 Subject: [netdrvr] usb/hso: Cleanup rfkill error handling Yup, this appears to be the problem, thanks. I think &hso_net->net->dev is more intuitive for the error message, so I've used that. I've also added missing line endings on the error messages and set our local rfkill structure element to NULL on failure so we don't try to call rfkill_unregister on driver removal if we failed to register at all. The patch below Works For Me (TM); the device is detected fine, can be removed without problems and connects ok. I'll have a prod at why the rfkill stuff isn't working next, but I believe this cleanup of the error handling is appropriate no matter what the issue with registration is. Signed-Off-By: Jonathan McDowell Signed-off-by: Jeff Garzik --- drivers/net/usb/hso.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 3f49e8382dd..8e90891f0e4 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2184,19 +2184,20 @@ static void hso_create_rfkill(struct hso_device *hso_dev, struct usb_interface *interface) { struct hso_net *hso_net = dev2net(hso_dev); - struct device *dev = hso_dev->dev; + struct device *dev = &hso_net->net->dev; char *rfkn; hso_net->rfkill = rfkill_allocate(&interface_to_usbdev(interface)->dev, RFKILL_TYPE_WWAN); if (!hso_net->rfkill) { - dev_err(dev, "%s - Out of memory", __func__); + dev_err(dev, "%s - Out of memory\n", __func__); return; } rfkn = kzalloc(20, GFP_KERNEL); if (!rfkn) { rfkill_free(hso_net->rfkill); - dev_err(dev, "%s - Out of memory", __func__); + hso_net->rfkill = NULL; + dev_err(dev, "%s - Out of memory\n", __func__); return; } snprintf(rfkn, 20, "hso-%d", @@ -2209,7 +2210,8 @@ static void hso_create_rfkill(struct hso_device *hso_dev, kfree(rfkn); hso_net->rfkill->name = NULL; rfkill_free(hso_net->rfkill); - dev_err(dev, "%s - Failed to register rfkill", __func__); + hso_net->rfkill = NULL; + dev_err(dev, "%s - Failed to register rfkill\n", __func__); return; } } -- cgit v1.2.3 From 8638545c3668231675dcf8f46afa7ed5930a6b02 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 7 Nov 2008 16:03:46 +0000 Subject: trivial: dmi_scan typo As we've lost our trivial maintainer for the moment I'll send this directly. Only touches a comment Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/firmware/dmi_scan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 3e526b6d00c..8daf4793ac3 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -81,9 +81,9 @@ static void dmi_table(u8 *buf, int len, int num, 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 + * We want to know the total length (formatted 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])) -- cgit v1.2.3 From 54e7ff9d6249ba88e393d7fbc8008da9279723be Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 7 Nov 2008 16:07:02 +0000 Subject: trivial: MPT fusion - remove long dead code This triggers false bug reports as it does a bogus kmalloc with locks held but is never really compiled into the kernel. Closes #8329 Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/message/fusion/mptlan.c | 108 ---------------------------------------- 1 file changed, 108 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index a1abf95cf75..603ffd008c7 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -77,12 +77,6 @@ MODULE_VERSION(my_VERSION); * Fusion MPT LAN private structures */ -struct NAA_Hosed { - u16 NAA; - u8 ieee[FC_ALEN]; - struct NAA_Hosed *next; -}; - struct BufferControl { struct sk_buff *skb; dma_addr_t dma; @@ -159,11 +153,6 @@ static u8 LanCtx = MPT_MAX_PROTOCOL_DRIVERS; static u32 max_buckets_out = 127; static u32 tx_max_out_p = 127 - 16; -#ifdef QLOGIC_NAA_WORKAROUND -static struct NAA_Hosed *mpt_bad_naa = NULL; -DEFINE_RWLOCK(bad_naa_lock); -#endif - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * lan_reply - Handle all data sent from the hardware. @@ -780,30 +769,6 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev) // ctx, skb, skb->data)); mac = skb_mac_header(skb); -#ifdef QLOGIC_NAA_WORKAROUND -{ - struct NAA_Hosed *nh; - - /* Munge the NAA for Tx packets to QLogic boards, which don't follow - RFC 2625. The longer I look at this, the more my opinion of Qlogic - drops. */ - read_lock_irq(&bad_naa_lock); - for (nh = mpt_bad_naa; nh != NULL; nh=nh->next) { - if ((nh->ieee[0] == mac[0]) && - (nh->ieee[1] == mac[1]) && - (nh->ieee[2] == mac[2]) && - (nh->ieee[3] == mac[3]) && - (nh->ieee[4] == mac[4]) && - (nh->ieee[5] == mac[5])) { - cur_naa = nh->NAA; - dlprintk ((KERN_INFO "mptlan/sdu_send: using NAA value " - "= %04x.\n", cur_naa)); - break; - } - } - read_unlock_irq(&bad_naa_lock); -} -#endif pTrans->TransactionDetails[0] = cpu_to_le32((cur_naa << 16) | (mac[0] << 8) | @@ -1572,79 +1537,6 @@ mpt_lan_type_trans(struct sk_buff *skb, struct net_device *dev) fcllc = (struct fcllc *)skb->data; -#ifdef QLOGIC_NAA_WORKAROUND -{ - u16 source_naa = fch->stype, found = 0; - - /* Workaround for QLogic not following RFC 2625 in regards to the NAA - value. */ - - if ((source_naa & 0xF000) == 0) - source_naa = swab16(source_naa); - - if (fcllc->ethertype == htons(ETH_P_ARP)) - dlprintk ((KERN_INFO "mptlan/type_trans: got arp req/rep w/ naa of " - "%04x.\n", source_naa)); - - if ((fcllc->ethertype == htons(ETH_P_ARP)) && - ((source_naa >> 12) != MPT_LAN_NAA_RFC2625)){ - struct NAA_Hosed *nh, *prevnh; - int i; - - dlprintk ((KERN_INFO "mptlan/type_trans: ARP Req/Rep from " - "system with non-RFC 2625 NAA value (%04x).\n", - source_naa)); - - write_lock_irq(&bad_naa_lock); - for (prevnh = nh = mpt_bad_naa; nh != NULL; - prevnh=nh, nh=nh->next) { - if ((nh->ieee[0] == fch->saddr[0]) && - (nh->ieee[1] == fch->saddr[1]) && - (nh->ieee[2] == fch->saddr[2]) && - (nh->ieee[3] == fch->saddr[3]) && - (nh->ieee[4] == fch->saddr[4]) && - (nh->ieee[5] == fch->saddr[5])) { - found = 1; - dlprintk ((KERN_INFO "mptlan/type_trans: ARP Re" - "q/Rep w/ bad NAA from system already" - " in DB.\n")); - break; - } - } - - if ((!found) && (nh == NULL)) { - - nh = kmalloc(sizeof(struct NAA_Hosed), GFP_KERNEL); - dlprintk ((KERN_INFO "mptlan/type_trans: ARP Req/Rep w/" - " bad NAA from system not yet in DB.\n")); - - if (nh != NULL) { - nh->next = NULL; - if (!mpt_bad_naa) - mpt_bad_naa = nh; - if (prevnh) - prevnh->next = nh; - - nh->NAA = source_naa; /* Set the S_NAA value. */ - for (i = 0; i < FC_ALEN; i++) - nh->ieee[i] = fch->saddr[i]; - dlprintk ((KERN_INFO "Got ARP from %02x:%02x:%02x:%02x:" - "%02x:%02x with non-compliant S_NAA value.\n", - fch->saddr[0], fch->saddr[1], fch->saddr[2], - fch->saddr[3], fch->saddr[4],fch->saddr[5])); - } else { - printk (KERN_ERR "mptlan/type_trans: Unable to" - " kmalloc a NAA_Hosed struct.\n"); - } - } else if (!found) { - printk (KERN_ERR "mptlan/type_trans: found not" - " set, but nh isn't null. Evil " - "funkiness abounds.\n"); - } - write_unlock_irq(&bad_naa_lock); - } -} -#endif /* Strip the SNAP header from ARP packets since we don't * pass them through to the 802.2/SNAP layers. -- cgit v1.2.3 From d21cf3c16b1191f3154a51e0b20c82bf851cc553 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Mon, 3 Nov 2008 14:26:40 -0500 Subject: ACPI EC: Fix regression due to use of uninitialized variable breakage introduced by following patch commit 27663c5855b10af9ec67bc7dfba001426ba21222 Author: Matthew Wilcox Date: Fri Oct 10 02:22:59 2008 -0400 acpi_evaluate_integer() does not clear passed variable if there is an error at evaluation. So if we ignore error, we must supply initialized variable. http://bugzilla.kernel.org/show_bug.cgi?id=11917 Signed-off-by: Alexey Starikovskiy Tested-by: Alan Jenkins Signed-off-by: Len Brown --- drivers/acpi/ec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ef42316f89f..523ac5b229a 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -736,7 +736,7 @@ static acpi_status ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) { acpi_status status; - unsigned long long tmp; + unsigned long long tmp = 0; struct acpi_ec *ec = context; status = acpi_walk_resources(handle, METHOD_NAME__CRS, @@ -751,6 +751,7 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) return status; ec->gpe = tmp; /* Use the global lock for all EC transactions? */ + tmp = 0; acpi_evaluate_integer(handle, "_GLK", NULL, &tmp); ec->global_lock = tmp; ec->handle = handle; -- cgit v1.2.3 From 89595b8f2850a080d290bf778ec933ea1d99f78e Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 7 Nov 2008 16:57:45 -0700 Subject: ACPI: consolidate ACPI_*_COMPONENT definitions in acpi_drivers.h Move all the component definitions for drivers to a single shared place, include/acpi/acpi_drivers.h. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/ac.c | 1 - drivers/acpi/acpi_memhotplug.c | 1 - drivers/acpi/battery.c | 1 - drivers/acpi/button.c | 1 - drivers/acpi/cm_sbs.c | 1 - drivers/acpi/container.c | 1 - drivers/acpi/fan.c | 1 - drivers/acpi/power.c | 3 +-- drivers/acpi/processor_core.c | 1 - drivers/acpi/processor_idle.c | 1 - drivers/acpi/processor_perflib.c | 2 +- drivers/acpi/processor_thermal.c | 1 - drivers/acpi/processor_throttling.c | 2 +- drivers/acpi/thermal.c | 1 - drivers/acpi/video.c | 1 - 15 files changed, 3 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index d72a1b6c8a9..5cdd713a0ea 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -37,7 +37,6 @@ #include #include -#define ACPI_AC_COMPONENT 0x00020000 #define ACPI_AC_CLASS "ac_adapter" #define ACPI_AC_DEVICE_NAME "AC Adapter" #define ACPI_AC_FILE_STATE "state" diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 71d21c51c45..63a17b55b39 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -32,7 +32,6 @@ #include #include -#define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000UL #define ACPI_MEMORY_DEVICE_CLASS "memory" #define ACPI_MEMORY_DEVICE_HID "PNP0C80" #define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device" diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index b2133e89ad9..47f6e38fa6c 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -46,7 +46,6 @@ #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF -#define ACPI_BATTERY_COMPONENT 0x00040000 #define ACPI_BATTERY_CLASS "battery" #define ACPI_BATTERY_DEVICE_NAME "Battery" #define ACPI_BATTERY_NOTIFY_STATUS 0x80 diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index cb046c3fc3f..fd7ca289cb0 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -33,7 +33,6 @@ #include #include -#define ACPI_BUTTON_COMPONENT 0x00080000 #define ACPI_BUTTON_CLASS "button" #define ACPI_BUTTON_FILE_INFO "info" #define ACPI_BUTTON_FILE_STATE "state" diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c index 80d5c88e68c..307963bd104 100644 --- a/drivers/acpi/cm_sbs.c +++ b/drivers/acpi/cm_sbs.c @@ -34,7 +34,6 @@ ACPI_MODULE_NAME("cm_sbs"); #define ACPI_AC_CLASS "ac_adapter" #define ACPI_BATTERY_CLASS "battery" -#define ACPI_SBS_COMPONENT 0x00080000 #define _COMPONENT ACPI_SBS_COMPONENT static struct proc_dir_entry *acpi_ac_dir; static struct proc_dir_entry *acpi_battery_dir; diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c index 134818b265a..17020c12623 100644 --- a/drivers/acpi/container.c +++ b/drivers/acpi/container.c @@ -41,7 +41,6 @@ #define INSTALL_NOTIFY_HANDLER 1 #define UNINSTALL_NOTIFY_HANDLER 2 -#define ACPI_CONTAINER_COMPONENT 0x01000000 #define _COMPONENT ACPI_CONTAINER_COMPONENT ACPI_MODULE_NAME("container"); diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 60d54d1f6b1..eaaee1660bd 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -34,7 +34,6 @@ #include #include -#define ACPI_FAN_COMPONENT 0x00200000 #define ACPI_FAN_CLASS "fan" #define ACPI_FAN_FILE_STATE "state" diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index a1718e56103..81f583f8098 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -44,9 +44,8 @@ #include #include -#define _COMPONENT ACPI_POWER_COMPONENT +#define _COMPONENT ACPI_POWER_COMPONENT ACPI_MODULE_NAME("power"); -#define ACPI_POWER_COMPONENT 0x00800000 #define ACPI_POWER_CLASS "power_resource" #define ACPI_POWER_DEVICE_NAME "Power Resource" #define ACPI_POWER_FILE_INFO "info" diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 24a362f8034..105e0ff8384 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -59,7 +59,6 @@ #include #include -#define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" #define ACPI_PROCESSOR_DEVICE_NAME "Processor" #define ACPI_PROCESSOR_FILE_INFO "info" diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 81b40ed5379..5f8d746a9b8 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -59,7 +59,6 @@ #include #include -#define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_idle"); diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index dbcf260ea93..0d7b772bef5 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -44,9 +44,9 @@ #endif #include +#include #include -#define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" #define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" #define _COMPONENT ACPI_PROCESSOR_COMPONENT diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index ef34b18f95c..b1eb376fae4 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -40,7 +40,6 @@ #include #include -#define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_thermal"); diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 3da2df93d92..a0c38c94a8a 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -38,9 +38,9 @@ #include #include +#include #include -#define ACPI_PROCESSOR_COMPONENT 0x01000000 #define ACPI_PROCESSOR_CLASS "processor" #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_throttling"); diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index ad6cae938f0..a6da1d9918c 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -47,7 +47,6 @@ #include #include -#define ACPI_THERMAL_COMPONENT 0x04000000 #define ACPI_THERMAL_CLASS "thermal_zone" #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone" #define ACPI_THERMAL_FILE_STATE "state" diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bf0c26a7368..a3aad30d39f 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -41,7 +41,6 @@ #include #include -#define ACPI_VIDEO_COMPONENT 0x08000000 #define ACPI_VIDEO_CLASS "video" #define ACPI_VIDEO_BUS_NAME "Video Bus" #define ACPI_VIDEO_DEVICE_NAME "Video Device" -- cgit v1.2.3 From bdd7279919f682da8752fb47784a1ee302f8b7ea Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 7 Nov 2008 16:57:55 -0700 Subject: ACPI: add driver component definitions to sysfs debug_layers /sys/module/acpi/parameters/debug_layers used to contain only the debug layers defined by the ACPI CA. This patch adds the additional layer definitions for ACPI drivers. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/debug.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index abf36b4b1d1..c4839689200 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c @@ -44,6 +44,21 @@ static const struct acpi_dlayer acpi_debug_layers[] = { ACPI_DEBUG_INIT(ACPI_CA_DISASSEMBLER), ACPI_DEBUG_INIT(ACPI_COMPILER), ACPI_DEBUG_INIT(ACPI_TOOLS), + + ACPI_DEBUG_INIT(ACPI_BUS_COMPONENT), + ACPI_DEBUG_INIT(ACPI_AC_COMPONENT), + ACPI_DEBUG_INIT(ACPI_BATTERY_COMPONENT), + ACPI_DEBUG_INIT(ACPI_BUTTON_COMPONENT), + ACPI_DEBUG_INIT(ACPI_SBS_COMPONENT), + ACPI_DEBUG_INIT(ACPI_FAN_COMPONENT), + ACPI_DEBUG_INIT(ACPI_PCI_COMPONENT), + ACPI_DEBUG_INIT(ACPI_POWER_COMPONENT), + ACPI_DEBUG_INIT(ACPI_CONTAINER_COMPONENT), + ACPI_DEBUG_INIT(ACPI_SYSTEM_COMPONENT), + ACPI_DEBUG_INIT(ACPI_THERMAL_COMPONENT), + ACPI_DEBUG_INIT(ACPI_MEMORY_DEVICE_COMPONENT), + ACPI_DEBUG_INIT(ACPI_VIDEO_COMPONENT), + ACPI_DEBUG_INIT(ACPI_PROCESSOR_COMPONENT), }; static const struct acpi_dlevel acpi_debug_levels[] = { -- cgit v1.2.3 From 87b586088ef953c602680e5aff8ab83a2e299498 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 7 Nov 2008 16:58:00 -0700 Subject: ACPI: turn off all debug output by default When CONFIG_ACPI_DEBUG=y, the default acpi_dbg_layer and acpi_dbg_level values built into the ACPI CA have some debug output enabled. We'd rather be quiet unless the user actually specified the acpi.debug_level argument. This enables distros to ship with CONFIG_ACPI_DEBUG=y without inundating users with debug output. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/bus.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 765fd1c56cd..7edf6d913c1 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -688,6 +688,14 @@ void __init acpi_early_init(void) if (acpi_disabled) return; + /* + * ACPI CA initializes acpi_dbg_level to non-zero, which means + * we get debug output merely by turning on CONFIG_ACPI_DEBUG. + * Turn it off so we don't get output unless the user specifies + * acpi.debug_level. + */ + acpi_dbg_level = 0; + printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION); /* enable workarounds, unless strict ACPI spec. compliance */ -- cgit v1.2.3 From a0d84a92df43b7206b9c1330a2cccf109cf0a41a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 7 Nov 2008 16:58:05 -0700 Subject: ACPI: update debug parameter documentation Reformat acpi.debug_layer and acpi.debug_level documentation so it's more readable, add some clues about how to figure out the mask bits that enable a specific ACPI_DEBUG_PRINT statement, and include some useful examples. Move the list of masks to Documentation/acpi/debug.txt (these are copies of the authoritative values in acoutput.h and acpi_drivers.h). Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 90cb2a823b5..b0243fd55ac 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -312,9 +312,13 @@ config ACPI_DEBUG bool "Debug Statements" default n help - The ACPI driver can optionally report errors with a great deal - of verbosity. Saying Y enables these statements. This will increase - your kernel size by around 50K. + The ACPI subsystem can produce debug output. Saying Y enables this + output and increases the kernel size by around 50K. + + Use the acpi.debug_layer and acpi.debug_level kernel command-line + parameters documented in Documentation/acpi/debug.txt and + Documentation/kernel-parameters.txt to control the type and + amount of debug output. config ACPI_DEBUG_FUNC_TRACE bool "Additionally enable ACPI function tracing" -- cgit v1.2.3 From a1a8d334f9e8c89a15bba8f34e443a37c29079c3 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 31 Jul 2008 23:02:28 +0200 Subject: Delete an unwanted return statement at evgpe.c Len's tree branch release-2.6.27, found an unwanted return statement at evgpe.c. (git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6 release-2.6.27) Signed-of-by Lin Ming Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/events/evgpe.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index c5e53aae86f..f45c74fe745 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c @@ -289,8 +289,6 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) */ status = acpi_hw_low_disable_gpe(gpe_event_info); return_ACPI_STATUS(status); - - return_ACPI_STATUS(AE_OK); } /******************************************************************************* -- cgit v1.2.3 From 22c13f9d8179f4c9caecfcb60a95214562b9addc Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 1 Aug 2008 17:37:54 +0200 Subject: ACPI: video: Ignore devices that aren't present in hardware This is a reimplemention of commit 0119509c4fbc9adcef1472817fda295334612976 from Matthew Garrett This patch got removed because of a regression: ThinkPads with a Intel graphics card and an Integrated Graphics Device BIOS implementation stopped working. In fact, they only worked because the ACPI device of the discrete, the wrong one, got used (via int10). So ACPI functions were poking on the wrong hardware used which is a sever bug. The next patch provides support for above ThinkPads to be able to switch brightness via the legacy thinkpad_acpi driver and automatically detect when to use it. Original commit message from Matthew Garrett: Vendors often ship machines with a choice of integrated or discrete graphics, and use the same DSDT for both. As a result, the ACPI video module will locate devices that may not exist on this specific platform. Attempt to determine whether the device exists or not, and abort the device creation if it doesn't. http://bugzilla.kernel.org/show_bug.cgi?id=9614 Signed-off-by: Thomas Renninger Acked-by: Zhang Rui Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/glue.c | 40 ++++++++++++++++++++++++++++++++++++++++ drivers/acpi/video.c | 7 ++++++- 2 files changed, 46 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 24649ada08d..adec3d15810 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -140,6 +140,46 @@ struct device *acpi_get_physical_device(acpi_handle handle) EXPORT_SYMBOL(acpi_get_physical_device); +/* ToDo: When a PCI bridge is found, return the PCI device behind the bridge + * This should work in general, but did not on a Lenovo T61 for the + * graphics card. But this must be fixed when the PCI device is + * bound and the kernel device struct is attached to the acpi device + * Note: A success call will increase reference count by one + * Do call put_device(dev) on the returned device then + */ +struct device *acpi_get_physical_pci_device(acpi_handle handle) +{ + struct device *dev; + long long device_id; + acpi_status status; + + status = + acpi_evaluate_integer(handle, "_ADR", NULL, &device_id); + + if (ACPI_FAILURE(status)) + return NULL; + + /* We need to attempt to determine whether the _ADR refers to a + PCI device or not. There's no terribly good way to do this, + so the best we can hope for is to assume that there'll never + be a device in the host bridge */ + if (device_id >= 0x10000) { + /* It looks like a PCI device. Does it exist? */ + dev = acpi_get_physical_device(handle); + } else { + /* It doesn't look like a PCI device. Does its parent + exist? */ + acpi_handle phandle; + if (acpi_get_parent(handle, &phandle)) + return NULL; + dev = acpi_get_physical_device(phandle); + } + if (!dev) + return NULL; + return dev; +} +EXPORT_SYMBOL(acpi_get_physical_pci_device); + static int acpi_bind_one(struct device *dev, acpi_handle handle) { struct acpi_device *acpi_dev; diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index a29b0ccac65..6597c2a37c3 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -842,11 +842,16 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) static int acpi_video_bus_check(struct acpi_video_bus *video) { acpi_status status = -ENOENT; - + struct device *dev; if (!video) return -EINVAL; + dev = acpi_get_physical_pci_device(video->device->handle); + if (!dev) + return -ENODEV; + put_device(dev); + /* Since there is no HID, CID and so on for VGA driver, we have * to check well known required nodes. */ -- cgit v1.2.3 From c3d6de698c84efdbdd3781b7058bcc339ab43da8 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 1 Aug 2008 17:37:55 +0200 Subject: ACPI video: if no ACPI backlight support, use vendor drivers If an ACPI graphics device supports backlight brightness functions (cmp. with latest ACPI spec Appendix B), let the ACPI video driver control backlight and switch backlight control off in vendor specific ACPI drivers (asus_acpi, thinkpad_acpi, eeepc, fujitsu_laptop, msi_laptop, sony_laptop, acer-wmi). Currently it is possible to load above drivers and let both poke on the brightness HW registers, the video and vendor specific ACPI drivers -> bad. This patch provides the basic support to check for BIOS capabilities before driver loading time. Driver specific modifications are in separate follow up patches. "acpi_backlight=vendor" Prever vendor driver over ACPI driver for backlight. "acpi_backlight=video" (default) Prever ACPI driver over vendor driver for backlight. Signed-off-by: Thomas Renninger Acked-by: Zhang Rui Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/Makefile | 4 + drivers/acpi/scan.c | 32 +----- drivers/acpi/video.c | 28 +++-- drivers/acpi/video_detect.c | 268 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 289 insertions(+), 43 deletions(-) create mode 100644 drivers/acpi/video_detect.c (limited to 'drivers') diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index d91c027ece8..c03810aa19c 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -46,6 +46,10 @@ obj-$(CONFIG_ACPI_BUTTON) += button.o obj-$(CONFIG_ACPI_FAN) += fan.o obj-$(CONFIG_ACPI_DOCK) += dock.o obj-$(CONFIG_ACPI_VIDEO) += video.o +ifdef CONFIG_ACPI_VIDEO +obj-y += video_detect.o +endif + obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index a9dda8e0f9f..556b182001c 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -919,36 +919,6 @@ static void acpi_device_get_busid(struct acpi_device *device, } } -static int -acpi_video_bus_match(struct acpi_device *device) -{ - acpi_handle h_dummy; - - if (!device) - return -EINVAL; - - /* Since there is no HID, CID for ACPI Video drivers, we have - * to check well known required nodes for each feature we support. - */ - - /* Does this device able to support video switching ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy))) - return 0; - - /* Does this device able to retrieve a video ROM ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy))) - return 0; - - /* Does this device able to configure which video head to be POSTed ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) && - ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy))) - return 0; - - return -ENODEV; -} - /* * acpi_bay_match - see if a device is an ejectable driver bay * @@ -1031,7 +1001,7 @@ static void acpi_device_set_id(struct acpi_device *device, will get autoloaded and the device might still match against another driver. */ - if (ACPI_SUCCESS(acpi_video_bus_match(device))) + if (acpi_is_video_device(device)) cid_add = ACPI_VIDEO_HID; else if (ACPI_SUCCESS(acpi_bay_match(device))) cid_add = ACPI_BAY_HID; diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 6597c2a37c3..2097c399dd0 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -739,7 +739,8 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) device->cap._DSS = 1; } - max_level = acpi_video_init_brightness(device); + if (acpi_video_backlight_support()) + max_level = acpi_video_init_brightness(device); if (device->cap._BCL && device->cap._BCM && max_level > 0) { int result; @@ -785,18 +786,21 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) printk(KERN_ERR PREFIX "Create sysfs link\n"); } - if (device->cap._DCS && device->cap._DSS){ - static int count = 0; - char *name; - name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); - if (!name) - return; - sprintf(name, "acpi_video%d", count++); - device->output_dev = video_output_register(name, - NULL, device, &acpi_output_properties); - kfree(name); + + if (acpi_video_display_switch_support()) { + + if (device->cap._DCS && device->cap._DSS) { + static int count; + char *name; + name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); + if (!name) + return; + sprintf(name, "acpi_video%d", count++); + device->output_dev = video_output_register(name, + NULL, device, &acpi_output_properties); + kfree(name); + } } - return; } /* diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c new file mode 100644 index 00000000000..70b1e91ae2a --- /dev/null +++ b/drivers/acpi/video_detect.c @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2008 SuSE Linux Products GmbH + * Thomas Renninger + * + * May be copied or modified under the terms of the GNU General Public License + * + * video_detect.c: + * Provides acpi_is_video_device() for early scanning of ACPI devices in scan.c + * There a Linux specific (Spec does not provide a HID for video devices) is + * assinged + * + * After PCI devices are glued with ACPI devices + * acpi_get_physical_pci_device() can be called to identify ACPI graphics + * devices for which a real graphics card is plugged in + * + * Now acpi_video_get_capabilities() can be called to check which + * capabilities the graphics cards plugged in support. The check for general + * video capabilities will be triggered by the first caller of + * acpi_video_get_capabilities(NULL); which will happen when the first + * backlight (or display output) switching supporting driver calls: + * acpi_video_backlight_support(); + * + * Depending on whether ACPI graphics extensions (cmp. ACPI spec Appendix B) + * are available, video.ko should be used to handle the device. + * + * Otherwise vendor specific drivers like thinkpad_acpi, asus_acpi, + * sony_acpi,... can take care about backlight brightness and display output + * switching. + * + * If CONFIG_ACPI_VIDEO is neither set as "compiled in" (y) nor as a module (m) + * this file will not be compiled, acpi_video_get_capabilities() and + * acpi_video_backlight_support() will always return 0 and vendor specific + * drivers always can handle backlight. + * + */ + +#include +#include + +ACPI_MODULE_NAME("video"); +#define ACPI_VIDEO_COMPONENT 0x08000000 +#define _COMPONENT ACPI_VIDEO_COMPONENT + +static long acpi_video_support; +static bool acpi_video_caps_checked; + +static acpi_status +acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context, + void **retyurn_value) +{ + long *cap = context; + acpi_handle h_dummy; + + if (ACPI_SUCCESS(acpi_get_handle(handle, "_BCM", &h_dummy)) && + ACPI_SUCCESS(acpi_get_handle(handle, "_BCL", &h_dummy))) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight " + "support\n")); + *cap |= ACPI_VIDEO_BACKLIGHT; + /* We have backlight support, no need to scan further */ + return AE_CTRL_TERMINATE; + } + return 0; +} + +/* Returns true if the device is a video device which can be handled by + * video.ko. + * The device will get a Linux specific CID added in scan.c to + * identify the device as an ACPI graphics device + * Be aware that the graphics device may not be physically present + * Use acpi_video_get_capabilities() to detect general ACPI video + * capabilities of present cards + */ +long acpi_is_video_device(struct acpi_device *device) +{ + acpi_handle h_dummy; + long video_caps = 0; + + if (!device) + return 0; + + /* Does this device able to support video switching ? */ + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy))) + video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING; + + /* Does this device able to retrieve a video ROM ? */ + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy))) + video_caps |= ACPI_VIDEO_ROM_AVAILABLE; + + /* Does this device able to configure which video head to be POSTed ? */ + if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) && + ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy))) + video_caps |= ACPI_VIDEO_DEVICE_POSTING; + + /* Only check for backlight functionality if one of the above hit. */ + if (video_caps) + acpi_walk_namespace(ACPI_TYPE_DEVICE, device->handle, + ACPI_UINT32_MAX, acpi_backlight_cap_match, + &video_caps, NULL); + + return video_caps; +} +EXPORT_SYMBOL(acpi_is_video_device); + +static acpi_status +find_video(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + long *cap = context; + struct device *dev; + struct acpi_device *acpi_dev; + + const struct acpi_device_id video_ids[] = { + {ACPI_VIDEO_HID, 0}, + {"", 0}, + }; + if (acpi_bus_get_device(handle, &acpi_dev)) + return AE_OK; + + if (!acpi_match_device_ids(acpi_dev, video_ids)) { + dev = acpi_get_physical_pci_device(handle); + if (!dev) + return AE_OK; + put_device(dev); + *cap |= acpi_is_video_device(acpi_dev); + } + return AE_OK; +} + +/* + * Returns the video capabilities of a specific ACPI graphics device + * + * if NULL is passed as argument all ACPI devices are enumerated and + * all graphics capabilities of physically present devices are + * summerized and returned. This is cached and done only once. + */ +long acpi_video_get_capabilities(acpi_handle graphics_handle) +{ + long caps = 0; + struct acpi_device *tmp_dev; + acpi_status status; + + if (acpi_video_caps_checked && graphics_handle == NULL) + return acpi_video_support; + + if (!graphics_handle) { + /* Only do the global walk through all graphics devices once */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_video, + &caps, NULL); + /* There might be boot param flags set already... */ + acpi_video_support |= caps; + acpi_video_caps_checked = 1; + /* Add blacklists here. Be careful to use the right *DMI* bits + * to still be able to override logic via boot params, e.g.: + * + * if (dmi_name_in_vendors("XY")) { + * acpi_video_support |= + * ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR; + * acpi_video_support |= + * ACPI_VIDEO_BACKLIGHT_DMI_VENDOR; + *} + */ + } else { + status = acpi_bus_get_device(graphics_handle, &tmp_dev); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Invalid device")); + return 0; + } + acpi_walk_namespace(ACPI_TYPE_DEVICE, graphics_handle, + ACPI_UINT32_MAX, find_video, + &caps, NULL); + } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "We have 0x%lX video support %s %s\n", + graphics_handle ? caps : acpi_video_support, + graphics_handle ? "on device " : "in general", + graphics_handle ? acpi_device_bid(tmp_dev) : "")); + return caps; +} +EXPORT_SYMBOL(acpi_video_get_capabilities); + +/* Returns true if video.ko can do backlight switching */ +int acpi_video_backlight_support(void) +{ + /* + * We must check whether the ACPI graphics device is physically plugged + * in. Therefore this must be called after binding PCI and ACPI devices + */ + if (!acpi_video_caps_checked) + acpi_video_get_capabilities(NULL); + + /* First check for boot param -> highest prio */ + if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR) + return 0; + else if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO) + return 1; + + /* Then check for DMI blacklist -> second highest prio */ + if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_DMI_VENDOR) + return 0; + else if (acpi_video_support & ACPI_VIDEO_BACKLIGHT_DMI_VIDEO) + return 1; + + /* Then go the default way */ + return acpi_video_support & ACPI_VIDEO_BACKLIGHT; +} +EXPORT_SYMBOL(acpi_video_backlight_support); + +/* + * Returns true if video.ko can do display output switching. + * This does not work well/at all with binary graphics drivers + * which disable system io ranges and do it on their own. + */ +int acpi_video_display_switch_support(void) +{ + if (!acpi_video_caps_checked) + acpi_video_get_capabilities(NULL); + + if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR) + return 0; + else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO) + return 1; + + if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR) + return 0; + else if (acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO) + return 1; + + return acpi_video_support & ACPI_VIDEO_OUTPUT_SWITCHING; +} +EXPORT_SYMBOL(acpi_video_display_switch_support); + +/* + * Use acpi_display_output=vendor/video or acpi_backlight=vendor/video + * To force that backlight or display output switching is processed by vendor + * specific acpi drivers or video.ko driver. + */ +int __init acpi_backlight(char *str) +{ + if (str == NULL || *str == '\0') + return 1; + else { + if (!strcmp("vendor", str)) + acpi_video_support |= + ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR; + if (!strcmp("video", str)) + acpi_video_support |= + ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO; + } + return 1; +} +__setup("acpi_backlight=", acpi_backlight); + +int __init acpi_display_output(char *str) +{ + if (str == NULL || *str == '\0') + return 1; + else { + if (!strcmp("vendor", str)) + acpi_video_support |= + ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR; + if (!strcmp("video", str)) + acpi_video_support |= + ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO; + } + return 1; +} +__setup("acpi_display_output=", acpi_display_output); -- cgit v1.2.3 From febf2d95a71cd594182e4b3defb0e0ffdfe61482 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 1 Aug 2008 17:37:56 +0200 Subject: Acer-WMI: fingers off backlight if video.ko is serving this functionality Signed-off-by: Thomas Renninger Acked-by: Zhang Rui Signed-off-by: Andi Kleen Acked-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/misc/acer-wmi.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c index 0532a2de2ce..94c9f911824 100644 --- a/drivers/misc/acer-wmi.c +++ b/drivers/misc/acer-wmi.c @@ -1297,6 +1297,12 @@ static int __init acer_wmi_init(void) set_quirks(); + if (!acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { + interface->capability &= ~ACER_CAP_BRIGHTNESS; + printk(ACER_INFO "Brightness must be controlled by " + "generic video driver\n"); + } + if (platform_driver_register(&acer_platform_driver)) { printk(ACER_ERR "Unable to register platform driver.\n"); goto error_platform_register; -- cgit v1.2.3 From 6766fec3669d5053b987e111afb348b885237bfc Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 1 Aug 2008 17:37:57 +0200 Subject: asus-acpi: fingers off backlight if video.ko is serving this functionality Signed-off-by: Thomas Renninger Acked-by: Zhang Rui Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/misc/asus-laptop.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index a9d5228724a..8fb8b359104 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c @@ -1208,9 +1208,13 @@ static int __init asus_laptop_init(void) dev = acpi_get_physical_device(hotk->device->handle); - result = asus_backlight_init(dev); - if (result) - goto fail_backlight; + if (!acpi_video_backlight_support()) { + result = asus_backlight_init(dev); + if (result) + goto fail_backlight; + } else + printk(ASUS_INFO "Brightness ignored, must be controlled by " + "ACPI video driver\n"); result = asus_led_init(dev); if (result) -- cgit v1.2.3 From 29454f17124c655236d2972dad21907e15ca294b Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 1 Aug 2008 17:37:58 +0200 Subject: compal: fingers off backlight if video.ko is serving this functionality Signed-off-by: Thomas Renninger Acked-by: Zhang Rui Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/misc/compal-laptop.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/compal-laptop.c b/drivers/misc/compal-laptop.c index 344b790a625..11003bba10d 100644 --- a/drivers/misc/compal-laptop.c +++ b/drivers/misc/compal-laptop.c @@ -326,12 +326,14 @@ static int __init compal_init(void) /* Register backlight stuff */ - compalbl_device = backlight_device_register("compal-laptop", NULL, NULL, - &compalbl_ops); - if (IS_ERR(compalbl_device)) - return PTR_ERR(compalbl_device); + if (!acpi_video_backlight_support()) { + compalbl_device = backlight_device_register("compal-laptop", NULL, NULL, + &compalbl_ops); + if (IS_ERR(compalbl_device)) + return PTR_ERR(compalbl_device); - compalbl_device->props.max_brightness = COMPAL_LCD_LEVEL_MAX-1; + compalbl_device->props.max_brightness = COMPAL_LCD_LEVEL_MAX-1; + } ret = platform_driver_register(&compal_driver); if (ret) -- cgit v1.2.3 From a2bf8c01048f855fbf65a8fc41460aef71ca39dc Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 1 Aug 2008 17:37:59 +0200 Subject: eeepc-laptop: fingers off backlight if video.ko is serving this functionality Signed-off-by: Thomas Renninger Acked-by: Zhang Rui Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/misc/eeepc-laptop.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c index 9ef98b2d503..02fe2b8b893 100644 --- a/drivers/misc/eeepc-laptop.c +++ b/drivers/misc/eeepc-laptop.c @@ -825,9 +825,15 @@ static int __init eeepc_laptop_init(void) return -ENODEV; } dev = acpi_get_physical_device(ehotk->device->handle); - result = eeepc_backlight_init(dev); - if (result) - goto fail_backlight; + + if (!acpi_video_backlight_support()) { + result = eeepc_backlight_init(dev); + if (result) + goto fail_backlight; + } else + printk(EEEPC_INFO "Backlight controlled by ACPI video " + "driver\n"); + result = eeepc_hwmon_init(dev); if (result) goto fail_hwmon; -- cgit v1.2.3 From 7d5c89a615c5dae039094a3cf4a56fe6aab81765 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 1 Aug 2008 17:38:00 +0200 Subject: fujitsu-laptop: fingers off backlight if video.ko is serving this functionality Signed-off-by: Thomas Renninger Acked-by: Zhang Rui Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/misc/fujitsu-laptop.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c index d2cf0bfe316..1070dc1bc18 100644 --- a/drivers/misc/fujitsu-laptop.c +++ b/drivers/misc/fujitsu-laptop.c @@ -990,16 +990,16 @@ static int __init fujitsu_init(void) /* Register backlight stuff */ - fujitsu->bl_device = - backlight_device_register("fujitsu-laptop", NULL, NULL, - &fujitsubl_ops); - if (IS_ERR(fujitsu->bl_device)) - return PTR_ERR(fujitsu->bl_device); - - max_brightness = fujitsu->max_brightness; - - fujitsu->bl_device->props.max_brightness = max_brightness - 1; - fujitsu->bl_device->props.brightness = fujitsu->brightness_level; + if (!acpi_video_backlight_support()) { + fujitsu->bl_device = + backlight_device_register("fujitsu-laptop", NULL, NULL, + &fujitsubl_ops); + if (IS_ERR(fujitsu->bl_device)) + return PTR_ERR(fujitsu->bl_device); + max_brightness = fujitsu->max_brightness; + fujitsu->bl_device->props.max_brightness = max_brightness - 1; + fujitsu->bl_device->props.brightness = fujitsu->brightness_level; + } ret = platform_driver_register(&fujitsupf_driver); if (ret) @@ -1035,7 +1035,8 @@ fail_hotkey: fail_backlight: - backlight_device_unregister(fujitsu->bl_device); + if (fujitsu->bl_device) + backlight_device_unregister(fujitsu->bl_device); fail_platform_device2: @@ -1062,7 +1063,8 @@ static void __exit fujitsu_cleanup(void) &fujitsupf_attribute_group); platform_device_unregister(fujitsu->pf_device); platform_driver_unregister(&fujitsupf_driver); - backlight_device_unregister(fujitsu->bl_device); + if (fujitsu->bl_device) + backlight_device_unregister(fujitsu->bl_device); acpi_bus_unregister_driver(&acpi_fujitsu_driver); -- cgit v1.2.3 From a598c82f39892069a8f6693459b1179fd9ef30e1 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 1 Aug 2008 17:38:01 +0200 Subject: msi-laptop: fingers off backlight if video.ko is serving this functionality Signed-off-by: Thomas Renninger Acked-by: Zhang Rui Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/misc/msi-laptop.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c index de898c6938f..759763d18e4 100644 --- a/drivers/misc/msi-laptop.c +++ b/drivers/misc/msi-laptop.c @@ -347,12 +347,16 @@ static int __init msi_init(void) /* Register backlight stuff */ - msibl_device = backlight_device_register("msi-laptop-bl", NULL, NULL, - &msibl_ops); - if (IS_ERR(msibl_device)) - return PTR_ERR(msibl_device); - - msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1; + if (acpi_video_backlight_support()) { + printk(KERN_INFO "MSI: Brightness ignored, must be controlled " + "by ACPI video driver\n"); + } else { + msibl_device = backlight_device_register("msi-laptop-bl", NULL, + NULL, &msibl_ops); + if (IS_ERR(msibl_device)) + return PTR_ERR(msibl_device); + msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1; + } ret = platform_driver_register(&msipf_driver); if (ret) -- cgit v1.2.3 From 540b8bb9c33935183ceb5bed466a42ad72b2af56 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 1 Aug 2008 17:38:02 +0200 Subject: sony-laptop: fingers off backlight if video.ko is serving this functionality Signed-off-by: Thomas Renninger Acked-by: Zhang Rui Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/misc/sony-laptop.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 06f07e19dc7..7bcb81002dc 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c @@ -1038,7 +1038,11 @@ static int sony_nc_add(struct acpi_device *device) goto outinput; } - if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", &handle))) { + if (!acpi_video_backlight_support()) { + printk(KERN_INFO DRV_PFX "Sony: Brightness ignored, must be " + "controlled by ACPI video driver\n"); + } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", + &handle))) { sony_backlight_device = backlight_device_register("sony", NULL, NULL, &sony_backlight_ops); -- cgit v1.2.3 From 2dba1b5d87e08a294da5cdfa4d32908000e9b085 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 1 Aug 2008 17:38:03 +0200 Subject: thinkpad_acpi: fingers off backlight if video.ko is serving this functionality Signed-off-by: Thomas Renninger Acked-by: Zhang Rui Acked-by: Henrique de Moraes Holschuh Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/misc/thinkpad_acpi.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 4db1cf9078d..7a4a26b0edd 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -4932,16 +4932,25 @@ static int __init brightness_init(struct ibm_init_struct *iibm) */ b = tpacpi_check_std_acpi_brightness_support(); if (b > 0) { - if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { - printk(TPACPI_NOTICE - "Lenovo BIOS switched to ACPI backlight " - "control mode\n"); - } - if (brightness_enable > 1) { - printk(TPACPI_NOTICE - "standard ACPI backlight interface " - "available, not loading native one...\n"); - return 1; + + if (acpi_video_backlight_support()) { + if (brightness_enable > 1) { + printk(TPACPI_NOTICE + "Standard ACPI backlight interface " + "available, not loading native one.\n"); + return 1; + } else if (brightness_enable == 1) { + printk(TPACPI_NOTICE + "Backlight control force enabled, even if standard " + "ACPI backlight interface is available\n"); + } + } else { + if (brightness_enable > 1) { + printk(TPACPI_NOTICE + "Standard ACPI backlight interface not " + "available, thinkpad_acpi native " + "brightness control enabled\n"); + } } } -- cgit v1.2.3 From 0c4b95455f250c7006af00208aefdf0f93f63144 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 7 Nov 2008 21:12:17 -0800 Subject: Staging: only build the tree if we really want to This Kconfig change allows the common 'make allmodconfig' and 'make allyesconfig' build options to skip the staging tree, which is probably what you want to have happen anyway. This makes the linux-next developer's life a lot easier so he doesn't have to worry about changes that break the staging tree, that's for me to worry about... Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index e1654f59eb7..0a49cd788a7 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -21,7 +21,23 @@ menuconfig STAGING If in doubt, say N here. -if STAGING + +config STAGING_EXCLUDE_BUILD + bool "Exclude Staging drivers from being built" + default y + ---help--- + Are you sure you really want to build the staging drivers? + They taint your kernel, don't live up to the normal Linux + kernel quality standards, are a bit crufty around the edges, + and might go off and kick your dog when you aren't paying + attention. + + Say N here to be able to select and build the Staging drivers. + This option is primarily here to prevent them from being built + when selecting 'make allyesconfg' and 'make allmodconfig' so + don't be all that put off, your dog will be just fine. + +if !STAGING_EXCLUDE_BUILD source "drivers/staging/et131x/Kconfig" @@ -45,4 +61,4 @@ source "drivers/staging/at76_usb/Kconfig" source "drivers/staging/poch/Kconfig" -endif # STAGING +endif # !STAGING_EXCLUDE_BUILD -- cgit v1.2.3 From b8f6ec2e61f650fd1a316a207a00965bcb8805d4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 29 Oct 2008 10:44:55 -0700 Subject: Staging: make usbip depend on CONFIG_NET Thanks to Randy Dunlap for finding this problem. Reported-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/usbip/Kconfig b/drivers/staging/usbip/Kconfig index 7426235ccc4..217fb7e62c2 100644 --- a/drivers/staging/usbip/Kconfig +++ b/drivers/staging/usbip/Kconfig @@ -1,6 +1,6 @@ config USB_IP_COMMON tristate "USB IP support (EXPERIMENTAL)" - depends on USB && EXPERIMENTAL + depends on USB && NET && EXPERIMENTAL default N ---help--- This enables pushing USB packets over IP to allow remote -- cgit v1.2.3 From 0a0e9e0cb90170f95b4351597fd5c0e65fab6bc5 Mon Sep 17 00:00:00 2001 From: Matthias Fuchs Date: Wed, 5 Nov 2008 21:53:56 +0100 Subject: powerpc: Fix Book-E watchdog timer interval setting This patch fixes the setting of the Book-E watchdog timer interval setup on initialization and by ioctl(). On initialization the period bits have to be masked before setting a new period. In WDIOC_SETTIMEOUT ioctl we have to use the correct mask. Signed-off-by: Matthias Fuchs Acked-by: Timur Tabi Signed-off-by: Kumar Gala --- drivers/watchdog/booke_wdt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index c3b78a76f17..225398fd504 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c @@ -42,8 +42,10 @@ u32 booke_wdt_period = WDT_PERIOD_DEFAULT; #ifdef CONFIG_FSL_BOOKE #define WDTP(x) ((((63-x)&0x3)<<30)|(((63-x)&0x3c)<<15)) +#define WDTP_MASK (WDTP(0)) #else #define WDTP(x) (TCR_WP(x)) +#define WDTP_MASK (TCR_WP_MASK) #endif static DEFINE_SPINLOCK(booke_wdt_lock); @@ -65,6 +67,7 @@ static void __booke_wdt_enable(void *data) /* clear status before enabling watchdog */ __booke_wdt_ping(NULL); val = mfspr(SPRN_TCR); + val &= ~WDTP_MASK; val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); mtspr(SPRN_TCR, val); @@ -114,7 +117,7 @@ static long booke_wdt_ioctl(struct file *file, case WDIOC_SETTIMEOUT: if (get_user(booke_wdt_period, p)) return -EFAULT; - mtspr(SPRN_TCR, (mfspr(SPRN_TCR) & ~WDTP(0)) | + mtspr(SPRN_TCR, (mfspr(SPRN_TCR) & ~WDTP_MASK) | WDTP(booke_wdt_period)); return 0; case WDIOC_GETTIMEOUT: -- cgit v1.2.3 From 493890e75d98810a3470b4aae23be628ee5e9667 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 26 Oct 2008 12:37:25 +0100 Subject: mmc: increase SD write timeout for crappy cards It seems that some cards are slightly out of spec and occasionally will not be able to complete a write in the alloted 250 ms [1]. Incease the timeout slightly to allow even these cards to function properly. [1] http://lkml.org/lkml/2008/9/23/390 Signed-off-by: Pierre Ossman --- drivers/mmc/core/core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 044d84eeed7..f7284b905eb 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -280,7 +280,11 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) (card->host->ios.clock / 1000); if (data->flags & MMC_DATA_WRITE) - limit_us = 250000; + /* + * The limit is really 250 ms, but that is + * insufficient for some crappy cards. + */ + limit_us = 300000; else limit_us = 100000; -- cgit v1.2.3 From d1b268630875a7713b5d468a0c03403c5b721c8e Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sat, 8 Nov 2008 21:37:46 +0100 Subject: mmc: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-Off-By: Kay Sievers Signed-off-by: Pierre Ossman --- drivers/mmc/core/bus.c | 3 +-- drivers/mmc/core/host.c | 5 ++--- drivers/mmc/core/sdio_bus.c | 3 +-- drivers/mmc/host/mmc_spi.c | 2 +- drivers/mmc/host/sdhci.c | 2 +- drivers/mmc/host/tifm_sd.c | 16 ++++++++-------- 6 files changed, 14 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 0d9b2d6f9eb..f210a8ee686 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -216,8 +216,7 @@ int mmc_add_card(struct mmc_card *card) int ret; const char *type; - snprintf(card->dev.bus_id, sizeof(card->dev.bus_id), - "%s:%04x", mmc_hostname(card->host), card->rca); + dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); switch (card->type) { case MMC_TYPE_MMC: diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 6da80fd4d97..5e945e64ead 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -73,8 +73,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) if (err) goto free; - snprintf(host->class_dev.bus_id, BUS_ID_SIZE, - "mmc%d", host->index); + dev_set_name(&host->class_dev, "mmc%d", host->index); host->parent = dev; host->class_dev.parent = dev; @@ -121,7 +120,7 @@ int mmc_add_host(struct mmc_host *host) WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) && !host->ops->enable_sdio_irq); - led_trigger_register_simple(host->class_dev.bus_id, &host->led); + led_trigger_register_simple(dev_name(&host->class_dev), &host->led); err = device_add(&host->class_dev); if (err) diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 233d0f9b3c4..46284b52739 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -239,8 +239,7 @@ int sdio_add_func(struct sdio_func *func) { int ret; - snprintf(func->dev.bus_id, sizeof(func->dev.bus_id), - "%s:%d", mmc_card_id(func->card), func->num); + dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num); ret = device_add(&func->dev); if (ret == 0) diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 07faf5412a1..ad00e163231 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -1348,7 +1348,7 @@ static int mmc_spi_probe(struct spi_device *spi) goto fail_add_host; dev_info(&spi->dev, "SD/MMC host %s%s%s%s%s\n", - mmc->class_dev.bus_id, + dev_name(&mmc->class_dev), host->dma_dev ? "" : ", no DMA", (host->pdata && host->pdata->get_ro) ? "" : ", no WP", diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 30f64b1f235..4d010a984be 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1733,7 +1733,7 @@ int sdhci_add_host(struct sdhci_host *host) mmc_add_host(mmc); printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s%s\n", - mmc_hostname(mmc), host->hw_name, mmc_dev(mmc)->bus_id, + mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), (host->flags & SDHCI_USE_ADMA)?"A":"", (host->flags & SDHCI_USE_DMA)?"DMA":"PIO"); diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index 13844843e8d..82554ddec6b 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c @@ -632,7 +632,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) if (host->req) { printk(KERN_ERR "%s : unfinished request detected\n", - sock->dev.bus_id); + dev_name(&sock->dev)); mrq->cmd->error = -ETIMEDOUT; goto err_out; } @@ -672,7 +672,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE)) { printk(KERN_ERR "%s : scatterlist map failed\n", - sock->dev.bus_id); + dev_name(&sock->dev)); mrq->cmd->error = -ENOMEM; goto err_out; } @@ -684,7 +684,7 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) : PCI_DMA_FROMDEVICE); if (host->sg_len < 1) { printk(KERN_ERR "%s : scatterlist map failed\n", - sock->dev.bus_id); + dev_name(&sock->dev)); tifm_unmap_sg(sock, &host->bounce_buf, 1, r_data->flags & MMC_DATA_WRITE ? PCI_DMA_TODEVICE @@ -748,7 +748,7 @@ static void tifm_sd_end_cmd(unsigned long data) if (!mrq) { printk(KERN_ERR " %s : no request to complete?\n", - sock->dev.bus_id); + dev_name(&sock->dev)); spin_unlock_irqrestore(&sock->lock, flags); return; } @@ -789,7 +789,7 @@ static void tifm_sd_abort(unsigned long data) printk(KERN_ERR "%s : card failed to respond for a long period of time " "(%x, %x)\n", - host->dev->dev.bus_id, host->req->cmd->opcode, host->cmd_flags); + dev_name(&host->dev->dev), host->req->cmd->opcode, host->cmd_flags); tifm_eject(host->dev); } @@ -906,7 +906,7 @@ static int tifm_sd_initialize_host(struct tifm_sd *host) if (rc) { printk(KERN_ERR "%s : controller failed to reset\n", - sock->dev.bus_id); + dev_name(&sock->dev)); return -ENODEV; } @@ -933,7 +933,7 @@ static int tifm_sd_initialize_host(struct tifm_sd *host) if (rc) { printk(KERN_ERR "%s : card not ready - probe failed on initialization\n", - sock->dev.bus_id); + dev_name(&sock->dev)); return -ENODEV; } @@ -954,7 +954,7 @@ static int tifm_sd_probe(struct tifm_dev *sock) if (!(TIFM_SOCK_STATE_OCCUPIED & readl(sock->addr + SOCK_PRESENT_STATE))) { printk(KERN_WARNING "%s : card gone, unexpectedly\n", - sock->dev.bus_id); + dev_name(&sock->dev)); return rc; } -- cgit v1.2.3 From bbda14dfba26bd4ca5dc74f672518bc42120d765 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 30 Oct 2008 15:57:05 +0100 Subject: regulator: Use menuconfig in Kconfig Use menuconfig instead of flat configs so that you can disable/enable regulator items with one selection. Also, use depends instead of reverse selections to make life easier, too. Signed-off-by: Takashi Iwai Signed-off-by: Liam Girdwood --- drivers/regulator/Kconfig | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 4dada6ee111..39360e2a454 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -1,6 +1,4 @@ -menu "Voltage and Current regulators" - -config REGULATOR +menuconfig REGULATOR bool "Voltage and Current Regulator Support" default n help @@ -23,21 +21,20 @@ config REGULATOR If unsure, say no. +if REGULATOR + config REGULATOR_DEBUG bool "Regulator debug support" - depends on REGULATOR help Say yes here to enable debugging support. config REGULATOR_FIXED_VOLTAGE tristate default n - select REGULATOR config REGULATOR_VIRTUAL_CONSUMER tristate "Virtual regulator consumer support" default n - select REGULATOR help This driver provides a virtual consumer for the voltage and current regulator API which provides sysfs controls for @@ -49,7 +46,6 @@ config REGULATOR_VIRTUAL_CONSUMER config REGULATOR_BQ24022 tristate "TI bq24022 Dual Input 1-Cell Li-Ion Charger IC" default n - select REGULATOR help This driver controls a TI bq24022 Charger attached via GPIOs. The provided current regulator can enable/disable @@ -59,7 +55,6 @@ config REGULATOR_BQ24022 config REGULATOR_WM8350 tristate "Wolfson Microelectroncis WM8350 AudioPlus PMIC" depends on MFD_WM8350 - select REGULATOR help This driver provides support for the voltage and current regulators of the WM8350 AudioPlus PMIC. @@ -67,7 +62,6 @@ config REGULATOR_WM8350 config REGULATOR_WM8400 tristate "Wolfson Microelectroncis WM8400 AudioPlus PMIC" depends on MFD_WM8400 - select REGULATOR help This driver provides support for the voltage regulators of the WM8400 AudioPlus PMIC. @@ -75,9 +69,8 @@ config REGULATOR_WM8400 config REGULATOR_DA903X tristate "Support regulators on Dialog Semiconductor DA9030/DA9034 PMIC" depends on PMIC_DA903X - select REGULATOR help Say y here to support the BUCKs and LDOs regulators found on Dialog Semiconductor DA9030/DA9034 PMIC. -endmenu +endif -- cgit v1.2.3 From 980fc29f20f5cfb8cef29ddfccecb685f299ada4 Mon Sep 17 00:00:00 2001 From: Marc Pignat Date: Thu, 6 Nov 2008 11:44:34 +0100 Subject: pcmcia: add another pata/ide ID Support for Apacer photo steno pro card. Signed-off-by: Marc Pignat Signed-off-by: Dominik Brodowski CC: Alan Cox Date: Sun, 9 Nov 2008 12:47:04 -0800 Subject: Don't ask twice about not including staging drivers The "Exclude staging drivers" question is there so that we don't build staging drivers for allyesconfig or allnoconfig settings, but it's very irritating when you've already said "no" to staging drivers earlier. There is absolutely no point in declining twice - once you've declined the staging drivers, you're done. So make the second question depend on the first question having been answered in the affirmative. Signed-off-by: Linus Torvalds --- drivers/staging/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 0a49cd788a7..c95b286a123 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -23,7 +23,7 @@ menuconfig STAGING config STAGING_EXCLUDE_BUILD - bool "Exclude Staging drivers from being built" + bool "Exclude Staging drivers from being built" if STAGING default y ---help--- Are you sure you really want to build the staging drivers? -- cgit v1.2.3 From b1769450da0eeae2d95aae5496acbdf4c6ba89b2 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 9 Nov 2008 21:47:47 +0100 Subject: pcmcia: ensure correct logging in do_io_probe Signed-off-by: Dominik Brodowski --- drivers/pcmcia/cs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 5d0e60e09d3..0660ad18258 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -186,12 +186,6 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) spin_lock_init(&socket->lock); - if (socket->resource_ops->init) { - ret = socket->resource_ops->init(socket); - if (ret) - return (ret); - } - /* try to obtain a socket number [yes, it gets ugly if we * register more than 2^sizeof(unsigned int) pcmcia * sockets... but the socket number is deprecated @@ -239,6 +233,12 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) mutex_init(&socket->skt_mutex); spin_lock_init(&socket->thread_lock); + if (socket->resource_ops->init) { + ret = socket->resource_ops->init(socket); + if (ret) + goto err; + } + tsk = kthread_run(pccardd, socket, "pccardd"); if (IS_ERR(tsk)) { ret = PTR_ERR(tsk); -- cgit v1.2.3 From 9a6558371bcd01c2973b7638181db4ccc34eab4f Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 9 Nov 2008 12:45:10 -0800 Subject: regression: disable timer peek-ahead for 2.6.28 It's showing up as regressions; disabling it very likely just papers over an underlying issue, but time is running out for 2.6.28, lets get back to this for 2.6.29 Fixes: #11826 and #11893 Signed-off-by: Arjan van de Ven Signed-off-by: Linus Torvalds --- drivers/cpuidle/cpuidle.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 5bed73329ef..8504a210855 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -65,12 +65,14 @@ static void cpuidle_idle_call(void) return; } +#if 0 + /* shows regressions, re-enable for 2.6.29 */ /* * run any timers that can be run now, at this point * before calculating the idle duration etc. */ hrtimer_peek_ahead_timers(); - +#endif /* ask the governor for the next state */ next_state = cpuidle_curr_governor->select(dev); if (need_resched()) -- cgit v1.2.3 From 8a8bc22332ee6ea49137508467a76aa7f4367719 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 10 Nov 2008 14:48:21 +0900 Subject: libata: revert convert-to-block-tagging patches This patch reverts the following three commits which convert libata to use block layer tagging. 43a49cbdf31e812c0d8f553d433b09b421f5d52c e013e13bf605b9e6b702adffbe2853cfc60e7806 2fca5ccf97d2c28bcfce44f5b07d85e74e3cd18e Although using block layer tagging is the right direction, due to the tight coupling among tag number, data structure allocation and hardware command slot allocation, libata doesn't work correctly with the current conversion. The biggest problem is guaranteeing that tag 0 is always used for non-NCQ commands. Due to the way blk-tag is implemented and how SCSI starts and finishes requests, such guarantee can't be made. I'm not sure whether this would actually break any low level driver but it doesn't look like a good idea to break such assumption given the frailty of ATA controllers. So, for the time being, keep using the old dumb in-libata qc allocation. Signed-off-by: Tejun Heo Cc: Jens Axobe Cc: Jeff Garzik Signed-off-by: Linus Torvalds --- drivers/ata/libata-core.c | 66 ++++++++++++++++++++++++++++++++++++++++++----- drivers/ata/libata-scsi.c | 23 ++--------------- drivers/ata/libata.h | 19 ++------------ 3 files changed, 64 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 622350d9b2e..0cd3ad49713 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1712,6 +1712,8 @@ unsigned ata_exec_internal_sg(struct ata_device *dev, else tag = 0; + if (test_and_set_bit(tag, &ap->qc_allocated)) + BUG(); qc = __ata_qc_from_tag(ap, tag); qc->tag = tag; @@ -4562,6 +4564,37 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) #endif /* __BIG_ENDIAN */ } +/** + * ata_qc_new - Request an available ATA command, for queueing + * @ap: Port associated with device @dev + * @dev: Device from whom we request an available command structure + * + * LOCKING: + * None. + */ + +static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) +{ + struct ata_queued_cmd *qc = NULL; + unsigned int i; + + /* no command while frozen */ + if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) + return NULL; + + /* the last tag is reserved for internal command. */ + for (i = 0; i < ATA_MAX_QUEUE - 1; i++) + if (!test_and_set_bit(i, &ap->qc_allocated)) { + qc = __ata_qc_from_tag(ap, i); + break; + } + + if (qc) + qc->tag = i; + + return qc; +} + /** * ata_qc_new_init - Request an available ATA command, and initialize it * @dev: Device from whom we request an available command structure @@ -4571,20 +4604,16 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) * None. */ -struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag) +struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev) { struct ata_port *ap = dev->link->ap; struct ata_queued_cmd *qc; - if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) - return NULL; - - qc = __ata_qc_from_tag(ap, tag); + qc = ata_qc_new(ap); if (qc) { qc->scsicmd = NULL; qc->ap = ap; qc->dev = dev; - qc->tag = tag; ata_qc_reinit(qc); } @@ -4592,6 +4621,31 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag) return qc; } +/** + * ata_qc_free - free unused ata_queued_cmd + * @qc: Command to complete + * + * Designed to free unused ata_queued_cmd object + * in case something prevents using it. + * + * LOCKING: + * spin_lock_irqsave(host lock) + */ +void ata_qc_free(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + unsigned int tag; + + WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */ + + qc->flags = 0; + tag = qc->tag; + if (likely(ata_tag_valid(tag))) { + qc->tag = ATA_TAG_POISON; + clear_bit(tag, &ap->qc_allocated); + } +} + void __ata_qc_complete(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 3fa75eac135..47c7afcb36f 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -709,11 +709,7 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev, { struct ata_queued_cmd *qc; - if (cmd->request->tag != -1) - qc = ata_qc_new_init(dev, cmd->request->tag); - else - qc = ata_qc_new_init(dev, 0); - + qc = ata_qc_new_init(dev); if (qc) { qc->scsicmd = cmd; qc->scsidone = done; @@ -1108,17 +1104,7 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id)); depth = min(ATA_MAX_QUEUE - 1, depth); - - /* - * If this device is behind a port multiplier, we have - * to share the tag map between all devices on that PMP. - * Set up the shared tag map here and we get automatic. - */ - if (dev->link->ap->pmp_link) - scsi_init_shared_tag_map(sdev->host, ATA_MAX_QUEUE - 1); - - scsi_set_tag_type(sdev, MSG_SIMPLE_TAG); - scsi_activate_tcq(sdev, depth); + scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth); } return 0; @@ -1958,11 +1944,6 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf) hdr[1] |= (1 << 7); memcpy(rbuf, hdr, sizeof(hdr)); - - /* if ncq, set tags supported */ - if (ata_id_has_ncq(args->id)) - rbuf[7] |= (1 << 1); - memcpy(&rbuf[8], "ATA ", 8); ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16); ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4); diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index d3831d39bda..fe2839e5877 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -74,7 +74,7 @@ extern struct ata_link *ata_dev_phys_link(struct ata_device *dev); extern void ata_force_cbl(struct ata_port *ap); extern u64 ata_tf_to_lba(const struct ata_taskfile *tf); extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf); -extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag); +extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, unsigned int tag); @@ -103,6 +103,7 @@ extern int ata_dev_configure(struct ata_device *dev); extern int sata_down_spd_limit(struct ata_link *link); extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel); extern void ata_sg_clean(struct ata_queued_cmd *qc); +extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_issue(struct ata_queued_cmd *qc); extern void __ata_qc_complete(struct ata_queued_cmd *qc); extern int atapi_check_dma(struct ata_queued_cmd *qc); @@ -118,22 +119,6 @@ extern struct ata_port *ata_port_alloc(struct ata_host *host); extern void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy); extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm); -/** - * ata_qc_free - free unused ata_queued_cmd - * @qc: Command to complete - * - * Designed to free unused ata_queued_cmd object - * in case something prevents using it. - * - * LOCKING: - * spin_lock_irqsave(host lock) - */ -static inline void ata_qc_free(struct ata_queued_cmd *qc) -{ - qc->flags = 0; - qc->tag = ATA_TAG_POISON; -} - /* libata-acpi.c */ #ifdef CONFIG_ATA_ACPI extern void ata_acpi_associate_sata_port(struct ata_port *ap); -- cgit v1.2.3 From 9581483444d002e0b3807d9e66f552f372a6fc5e Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 6 Nov 2008 01:37:00 +0000 Subject: SSB: hide empty sub menu If the target system cannot support SSB, then don't show the menu option as it'll simply be an empty submenu. Signed-off-by: Mike Frysinger Signed-off-by: David S. Miller --- drivers/ssb/Kconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig index 307b1f62d94..b1b947edcf0 100644 --- a/drivers/ssb/Kconfig +++ b/drivers/ssb/Kconfig @@ -1,10 +1,11 @@ -menu "Sonics Silicon Backplane" - config SSB_POSSIBLE bool depends on HAS_IOMEM && HAS_DMA default y +menu "Sonics Silicon Backplane" + depends on SSB_POSSIBLE + config SSB tristate "Sonics Silicon Backplane support" depends on SSB_POSSIBLE -- cgit v1.2.3 From c3d4f44f50b65b0b0290e357f8739cfb3f4bcaca Mon Sep 17 00:00:00 2001 From: Maciej Sosnowski Date: Fri, 7 Nov 2008 01:45:52 +0000 Subject: [1/4] I/OAT: fix channel resources free for not allocated channels If the ioatdma driver is loaded but not used it does not allocate descriptors. Before it frees channel resources it should first be sure that they have been previously allocated. Cc: Signed-off-by: Maciej Sosnowski Tested-by: Tom Picard Signed-off-by: Dan Williams Signed-off-by: David S. Miller --- drivers/dma/ioat_dma.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index b0438c4f0c3..dbb8bbb83a3 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c @@ -807,6 +807,12 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan) struct ioat_desc_sw *desc, *_desc; int in_use_descs = 0; + /* Before freeing channel resources first check + * if they have been previously allocated for this channel. + */ + if (ioat_chan->desccount == 0) + return; + tasklet_disable(&ioat_chan->cleanup_task); ioat_dma_memcpy_cleanup(ioat_chan); @@ -869,6 +875,7 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan) ioat_chan->last_completion = ioat_chan->completion_addr = 0; ioat_chan->pending = 0; ioat_chan->dmacount = 0; + ioat_chan->desccount = 0; ioat_chan->watchdog_completion = 0; ioat_chan->last_compl_desc_addr_hw = 0; ioat_chan->watchdog_tcp_cookie = -- cgit v1.2.3 From c2c0b4c5434c0a25f7f7796b29155d53805909f5 Mon Sep 17 00:00:00 2001 From: Maciej Sosnowski Date: Fri, 7 Nov 2008 01:46:33 +0000 Subject: [2/4] I/OAT: fix dma_pin_iovec_pages() error handling Error handling needs to be modified in dma_pin_iovec_pages(). It should return NULL instead of ERR_PTR (pinned_list is checked for NULL in tcp_recvmsg() to determine if iovec pages have been successfully pinned down). In case of error for the first iovec, local_list->nr_iovecs needs to be initialized. Cc: Signed-off-by: Maciej Sosnowski Signed-off-by: David S. Miller --- drivers/dma/iovlock.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/iovlock.c b/drivers/dma/iovlock.c index e763d723e4c..9f6fe46a9b8 100644 --- a/drivers/dma/iovlock.c +++ b/drivers/dma/iovlock.c @@ -55,7 +55,6 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) int nr_iovecs = 0; int iovec_len_used = 0; int iovec_pages_used = 0; - long err; /* don't pin down non-user-based iovecs */ if (segment_eq(get_fs(), KERNEL_DS)) @@ -72,23 +71,21 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) local_list = kmalloc(sizeof(*local_list) + (nr_iovecs * sizeof (struct dma_page_list)) + (iovec_pages_used * sizeof (struct page*)), GFP_KERNEL); - if (!local_list) { - err = -ENOMEM; + if (!local_list) goto out; - } /* list of pages starts right after the page list array */ pages = (struct page **) &local_list->page_list[nr_iovecs]; + local_list->nr_iovecs = 0; + for (i = 0; i < nr_iovecs; i++) { struct dma_page_list *page_list = &local_list->page_list[i]; len -= iov[i].iov_len; - if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) { - err = -EFAULT; + if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) goto unpin; - } page_list->nr_pages = num_pages_spanned(&iov[i]); page_list->base_address = iov[i].iov_base; @@ -109,10 +106,8 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) NULL); up_read(¤t->mm->mmap_sem); - if (ret != page_list->nr_pages) { - err = -ENOMEM; + if (ret != page_list->nr_pages) goto unpin; - } local_list->nr_iovecs = i + 1; } @@ -122,7 +117,7 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) unpin: dma_unpin_iovec_pages(local_list); out: - return ERR_PTR(err); + return NULL; } void dma_unpin_iovec_pages(struct dma_pinned_list *pinned_list) -- cgit v1.2.3 From 12ccea24e309d815d058cdc6ee8bf2c4b85f0c5f Mon Sep 17 00:00:00 2001 From: Maciej Sosnowski Date: Fri, 7 Nov 2008 01:46:55 +0000 Subject: [3/4] I/OAT: fix async_tx.callback checking async_tx.callback should be checked for the first not the last descriptor in the chain. Cc: Signed-off-by: Maciej Sosnowski Signed-off-by: David S. Miller --- drivers/dma/ioat_dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index dbb8bbb83a3..ecd743f7cc6 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c @@ -525,7 +525,7 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx) } hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS; - if (new->async_tx.callback) { + if (first->async_tx.callback) { hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN; if (first != new) { /* move callback into to last desc */ @@ -617,7 +617,7 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx) } hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_CP_STS; - if (new->async_tx.callback) { + if (first->async_tx.callback) { hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN; if (first != new) { /* move callback into to last desc */ -- cgit v1.2.3 From 1207e795568a368928dfd23d6817e47f2e8097e3 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 7 Nov 2008 01:47:17 +0000 Subject: [4/4] dca: fixup initialization dependency Mark dca_init as a subsys_initcall since it needs to be ready to go before dependent drivers start registering themselves. Cc: Reported-and-tested-by: Mark Rustad Acked-by: Maciej Sosnowski Signed-off-by: Dan Williams Signed-off-by: David S. Miller --- drivers/dca/dca-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c index ec249d2db63..d883e1b8bb8 100644 --- a/drivers/dca/dca-core.c +++ b/drivers/dca/dca-core.c @@ -270,6 +270,6 @@ static void __exit dca_exit(void) dca_sysfs_exit(); } -module_init(dca_init); +subsys_initcall(dca_init); module_exit(dca_exit); -- cgit v1.2.3 From 881ee9889c8b98671c5491e43666bf5d4f78a180 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 2 Nov 2008 23:08:44 -0800 Subject: i915: Save/restore MCHBAR_RENDER_STANDBY on GM965/GM45 This register is set by the 2D driver to prevent lockups, and so it needs to be preserved across suspend/resume too. This makes my X200s work. Signed-off-by: Keith Packard Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 3 +++ drivers/gpu/drm/i915/i915_suspend.c | 9 +++++++++ 3 files changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 572dcd0e3e0..be56b0ba88c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -157,6 +157,7 @@ typedef struct drm_i915_private { u32 saveDSPACNTR; u32 saveDSPBCNTR; u32 saveDSPARB; + u32 saveRENDERSTANDBY; u32 savePIPEACONF; u32 savePIPEBCONF; u32 savePIPEASRC; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5c2d9f206d0..0e476eba36e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -527,6 +527,9 @@ #define C0DRB3 0x10206 #define C1DRB3 0x10606 +/** GM965 GM45 render standby register */ +#define MCHBAR_RENDER_STANDBY 0x111B8 + /* * Overlay regs */ diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 603fe742ccd..5ddc6e595c0 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -240,6 +240,10 @@ int i915_save_state(struct drm_device *dev) pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); + /* Render Standby */ + if (IS_I965G(dev) && IS_MOBILE(dev)) + dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY); + /* Display arbitration control */ dev_priv->saveDSPARB = I915_READ(DSPARB); @@ -365,6 +369,11 @@ int i915_restore_state(struct drm_device *dev) pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); + /* Render Standby */ + if (IS_I965G(dev) && IS_MOBILE(dev)) + I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY); + + /* Display arbitration */ I915_WRITE(DSPARB, dev_priv->saveDSPARB); /* Pipe & plane A info */ -- cgit v1.2.3 From ad42ca8f4490de06462aee234ea0083cbd8b46aa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 2 Nov 2008 23:38:20 -0800 Subject: i915: Clean up sarea pointers on leavevt This corresponds to the setup of the sarea pointers in DMA initialization, though neither is exactly the point at which the sarea is set up or torn down. Signed-off-by: Keith Packard Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_dma.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 256e22963ae..79944460d70 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -154,6 +154,9 @@ static int i915_dma_cleanup(struct drm_device * dev) if (I915_NEED_GFX_HWS(dev)) i915_free_hws(dev); + dev_priv->sarea = NULL; + dev_priv->sarea_priv = NULL; + return 0; } -- cgit v1.2.3 From 6a47baa6ce7e6fb5fed8d1fd0af36a96a4ad133f Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Mon, 3 Nov 2008 14:38:17 -0800 Subject: i915: Don't attempt to short-circuit object_wait_rendering by checking domains. This could return early when reading after writing a buffer, if somebody had already put it on the flushing list (write domains are 0, but still active), leading to glReadPixels failure. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b0ec73fa6a9..6b4a2bd2064 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1455,11 +1455,9 @@ i915_gem_object_set_domain_range(struct drm_gem_object *obj, read_domains, write_domain); /* Wait on any GPU rendering to the object to be flushed. */ - if (obj->write_domain & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) { - ret = i915_gem_object_wait_rendering(obj); - if (ret) - return ret; - } + ret = i915_gem_object_wait_rendering(obj); + if (ret) + return ret; if (obj_priv->page_cpu_valid == NULL) { obj_priv->page_cpu_valid = drm_calloc(1, obj->size / PAGE_SIZE, -- cgit v1.2.3 From d3e74d0237b102d34979015fbf6df02ca4413074 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 3 Nov 2008 14:46:17 -0800 Subject: i915: Don't whine when pci_enable_msi() fails. This probably just means the chipset doesn't support MSI, which is fine. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_dma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 79944460d70..9d4278be0ca 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -852,8 +852,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) * be lost or delayed */ if (!IS_I945G(dev) && !IS_I945GM(dev) && !IS_I965GM(dev)) - if (pci_enable_msi(dev->pdev)) - DRM_ERROR("failed to enable MSI\n"); + pci_enable_msi(dev->pdev); intel_opregion_init(dev); -- cgit v1.2.3 From bd95e0a4a6bb9485fe35dda62719663f6ceabae1 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 4 Nov 2008 12:01:24 -0800 Subject: i915: Remove racy delayed vblank swap ioctl. When userland detected that this ioctl was supported (by version number check), it used it in a racy way -- dispatch delayed swap, wait for vblank, continue rendering. As there was no mechanism for it to wait for the swap to finish, sometimes it would render before the swap and garbage would be displayed on the screen. By removing the ioctl and returning -EINVAL, userland returns to its previous, correct rendering path of waiting for a vblank then dispatching a swap. The only path that could have used this ioctl correctly was page flipping, which relied on only one client running and emitting wait-for-vblank-before-rendering in the command stream. That path also falls back correctly, at the performance cost of not being able to queue up rendering before the flip occurs. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_drv.h | 15 -- drivers/gpu/drm/i915/i915_irq.c | 377 ++-------------------------------------- 2 files changed, 14 insertions(+), 378 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index be56b0ba88c..4afbadb1331 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -88,13 +88,6 @@ struct mem_block { struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */ }; -typedef struct _drm_i915_vbl_swap { - struct list_head head; - drm_drawable_t drw_id; - unsigned int pipe; - unsigned int sequence; -} drm_i915_vbl_swap_t; - struct opregion_header; struct opregion_acpi; struct opregion_swsci; @@ -146,10 +139,6 @@ typedef struct drm_i915_private { unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; int vblank_pipe; - spinlock_t swaps_lock; - drm_i915_vbl_swap_t vbl_swaps; - unsigned int swaps_pending; - struct intel_opregion opregion; /* Register state */ @@ -242,9 +231,6 @@ typedef struct drm_i915_private { u8 saveDACDATA[256*3]; /* 256 3-byte colors */ u8 saveCR[37]; - /** Work task for vblank-related ring access */ - struct work_struct vblank_work; - struct { struct drm_mm gtt_space; @@ -445,7 +431,6 @@ extern int i915_irq_wait(struct drm_device *dev, void *data, void i915_user_irq_get(struct drm_device *dev); void i915_user_irq_put(struct drm_device *dev); -extern void i915_vblank_work_handler(struct work_struct *work); extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); extern void i915_driver_irq_preinstall(struct drm_device * dev); extern int i915_driver_irq_postinstall(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 26f48932a51..a75345af62e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -80,211 +80,6 @@ i915_pipe_enabled(struct drm_device *dev, int pipe) return 0; } -/** - * Emit blits for scheduled buffer swaps. - * - * This function will be called with the HW lock held. - * Because this function must grab the ring mutex (dev->struct_mutex), - * it can no longer run at soft irq time. We'll fix this when we do - * the DRI2 swap buffer work. - */ -static void i915_vblank_tasklet(struct drm_device *dev) -{ - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - unsigned long irqflags; - struct list_head *list, *tmp, hits, *hit; - int nhits, nrects, slice[2], upper[2], lower[2], i; - unsigned counter[2]; - struct drm_drawable_info *drw; - drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; - u32 cpp = dev_priv->cpp; - u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD | - XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB) - : XY_SRC_COPY_BLT_CMD; - u32 src_pitch = sarea_priv->pitch * cpp; - u32 dst_pitch = sarea_priv->pitch * cpp; - u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24); - RING_LOCALS; - - mutex_lock(&dev->struct_mutex); - - if (IS_I965G(dev) && sarea_priv->front_tiled) { - cmd |= XY_SRC_COPY_BLT_DST_TILED; - dst_pitch >>= 2; - } - if (IS_I965G(dev) && sarea_priv->back_tiled) { - cmd |= XY_SRC_COPY_BLT_SRC_TILED; - src_pitch >>= 2; - } - - counter[0] = drm_vblank_count(dev, 0); - counter[1] = drm_vblank_count(dev, 1); - - DRM_DEBUG("\n"); - - INIT_LIST_HEAD(&hits); - - nhits = nrects = 0; - - spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); - - /* Find buffer swaps scheduled for this vertical blank */ - list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) { - drm_i915_vbl_swap_t *vbl_swap = - list_entry(list, drm_i915_vbl_swap_t, head); - int pipe = vbl_swap->pipe; - - if ((counter[pipe] - vbl_swap->sequence) > (1<<23)) - continue; - - list_del(list); - dev_priv->swaps_pending--; - drm_vblank_put(dev, pipe); - - spin_unlock(&dev_priv->swaps_lock); - spin_lock(&dev->drw_lock); - - drw = drm_get_drawable_info(dev, vbl_swap->drw_id); - - list_for_each(hit, &hits) { - drm_i915_vbl_swap_t *swap_cmp = - list_entry(hit, drm_i915_vbl_swap_t, head); - struct drm_drawable_info *drw_cmp = - drm_get_drawable_info(dev, swap_cmp->drw_id); - - /* Make sure both drawables are still - * around and have some rectangles before - * we look inside to order them for the - * blts below. - */ - if (drw_cmp && drw_cmp->num_rects > 0 && - drw && drw->num_rects > 0 && - drw_cmp->rects[0].y1 > drw->rects[0].y1) { - list_add_tail(list, hit); - break; - } - } - - spin_unlock(&dev->drw_lock); - - /* List of hits was empty, or we reached the end of it */ - if (hit == &hits) - list_add_tail(list, hits.prev); - - nhits++; - - spin_lock(&dev_priv->swaps_lock); - } - - if (nhits == 0) { - spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); - mutex_unlock(&dev->struct_mutex); - return; - } - - spin_unlock(&dev_priv->swaps_lock); - - i915_kernel_lost_context(dev); - - if (IS_I965G(dev)) { - BEGIN_LP_RING(4); - - OUT_RING(GFX_OP_DRAWRECT_INFO_I965); - OUT_RING(0); - OUT_RING(((sarea_priv->width - 1) & 0xffff) | ((sarea_priv->height - 1) << 16)); - OUT_RING(0); - ADVANCE_LP_RING(); - } else { - BEGIN_LP_RING(6); - - OUT_RING(GFX_OP_DRAWRECT_INFO); - OUT_RING(0); - OUT_RING(0); - OUT_RING(sarea_priv->width | sarea_priv->height << 16); - OUT_RING(sarea_priv->width | sarea_priv->height << 16); - OUT_RING(0); - - ADVANCE_LP_RING(); - } - - sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT; - - upper[0] = upper[1] = 0; - slice[0] = max(sarea_priv->pipeA_h / nhits, 1); - slice[1] = max(sarea_priv->pipeB_h / nhits, 1); - lower[0] = sarea_priv->pipeA_y + slice[0]; - lower[1] = sarea_priv->pipeB_y + slice[0]; - - spin_lock(&dev->drw_lock); - - /* Emit blits for buffer swaps, partitioning both outputs into as many - * slices as there are buffer swaps scheduled in order to avoid tearing - * (based on the assumption that a single buffer swap would always - * complete before scanout starts). - */ - for (i = 0; i++ < nhits; - upper[0] = lower[0], lower[0] += slice[0], - upper[1] = lower[1], lower[1] += slice[1]) { - if (i == nhits) - lower[0] = lower[1] = sarea_priv->height; - - list_for_each(hit, &hits) { - drm_i915_vbl_swap_t *swap_hit = - list_entry(hit, drm_i915_vbl_swap_t, head); - struct drm_clip_rect *rect; - int num_rects, pipe; - unsigned short top, bottom; - - drw = drm_get_drawable_info(dev, swap_hit->drw_id); - - /* The drawable may have been destroyed since - * the vblank swap was queued - */ - if (!drw) - continue; - - rect = drw->rects; - pipe = swap_hit->pipe; - top = upper[pipe]; - bottom = lower[pipe]; - - for (num_rects = drw->num_rects; num_rects--; rect++) { - int y1 = max(rect->y1, top); - int y2 = min(rect->y2, bottom); - - if (y1 >= y2) - continue; - - BEGIN_LP_RING(8); - - OUT_RING(cmd); - OUT_RING(ropcpp | dst_pitch); - OUT_RING((y1 << 16) | rect->x1); - OUT_RING((y2 << 16) | rect->x2); - OUT_RING(sarea_priv->front_offset); - OUT_RING((y1 << 16) | rect->x1); - OUT_RING(src_pitch); - OUT_RING(sarea_priv->back_offset); - - ADVANCE_LP_RING(); - } - } - } - - spin_unlock_irqrestore(&dev->drw_lock, irqflags); - mutex_unlock(&dev->struct_mutex); - - list_for_each_safe(hit, tmp, &hits) { - drm_i915_vbl_swap_t *swap_hit = - list_entry(hit, drm_i915_vbl_swap_t, head); - - list_del(hit); - - drm_free(swap_hit, sizeof(*swap_hit), DRM_MEM_DRIVER); - } -} - /* Called from drm generic code, passed a 'crtc', which * we use as a pipe index */ @@ -322,40 +117,6 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) return count; } -void -i915_vblank_work_handler(struct work_struct *work) -{ - drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, - vblank_work); - struct drm_device *dev = dev_priv->dev; - unsigned long irqflags; - - if (dev->lock.hw_lock == NULL) { - i915_vblank_tasklet(dev); - return; - } - - spin_lock_irqsave(&dev->tasklet_lock, irqflags); - dev->locked_tasklet_func = i915_vblank_tasklet; - spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); - - /* Try to get the lock now, if this fails, the lock - * holder will execute the tasklet during unlock - */ - if (!drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT)) - return; - - dev->lock.lock_time = jiffies; - atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); - - spin_lock_irqsave(&dev->tasklet_lock, irqflags); - dev->locked_tasklet_func = NULL; - spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); - - i915_vblank_tasklet(dev); - drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT); -} - irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; @@ -433,9 +194,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) if (iir & I915_ASLE_INTERRUPT) opregion_asle_intr(dev); - if (vblank && dev_priv->swaps_pending > 0) - schedule_work(&dev_priv->vblank_work); - return IRQ_HANDLED; } @@ -696,123 +454,21 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data, int i915_vblank_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_vblank_swap_t *swap = data; - drm_i915_vbl_swap_t *vbl_swap, *vbl_old; - unsigned int pipe, seqtype, curseq; - unsigned long irqflags; - struct list_head *list; - int ret; - - if (!dev_priv || !dev_priv->sarea_priv) { - DRM_ERROR("%s called with no initialization\n", __func__); - return -EINVAL; - } - - if (dev_priv->sarea_priv->rotation) { - DRM_DEBUG("Rotation not supported\n"); - return -EINVAL; - } - - if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE | - _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) { - DRM_ERROR("Invalid sequence type 0x%x\n", swap->seqtype); - return -EINVAL; - } - - pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0; - - seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE); - - if (!(dev_priv->vblank_pipe & (1 << pipe))) { - DRM_ERROR("Invalid pipe %d\n", pipe); - return -EINVAL; - } - - spin_lock_irqsave(&dev->drw_lock, irqflags); - - if (!drm_get_drawable_info(dev, swap->drawable)) { - spin_unlock_irqrestore(&dev->drw_lock, irqflags); - DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable); - return -EINVAL; - } - - spin_unlock_irqrestore(&dev->drw_lock, irqflags); - - /* - * We take the ref here and put it when the swap actually completes - * in the tasklet. + /* The delayed swap mechanism was fundamentally racy, and has been + * removed. The model was that the client requested a delayed flip/swap + * from the kernel, then waited for vblank before continuing to perform + * rendering. The problem was that the kernel might wake the client + * up before it dispatched the vblank swap (since the lock has to be + * held while touching the ringbuffer), in which case the client would + * clear and start the next frame before the swap occurred, and + * flicker would occur in addition to likely missing the vblank. + * + * In the absence of this ioctl, userland falls back to a correct path + * of waiting for a vblank, then dispatching the swap on its own. + * Context switching to userland and back is plenty fast enough for + * meeting the requirements of vblank swapping. */ - ret = drm_vblank_get(dev, pipe); - if (ret) - return ret; - curseq = drm_vblank_count(dev, pipe); - - if (seqtype == _DRM_VBLANK_RELATIVE) - swap->sequence += curseq; - - if ((curseq - swap->sequence) <= (1<<23)) { - if (swap->seqtype & _DRM_VBLANK_NEXTONMISS) { - swap->sequence = curseq + 1; - } else { - DRM_DEBUG("Missed target sequence\n"); - drm_vblank_put(dev, pipe); - return -EINVAL; - } - } - - vbl_swap = drm_calloc(1, sizeof(*vbl_swap), DRM_MEM_DRIVER); - - if (!vbl_swap) { - DRM_ERROR("Failed to allocate memory to queue swap\n"); - drm_vblank_put(dev, pipe); - return -ENOMEM; - } - - vbl_swap->drw_id = swap->drawable; - vbl_swap->pipe = pipe; - vbl_swap->sequence = swap->sequence; - - spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); - - list_for_each(list, &dev_priv->vbl_swaps.head) { - vbl_old = list_entry(list, drm_i915_vbl_swap_t, head); - - if (vbl_old->drw_id == swap->drawable && - vbl_old->pipe == pipe && - vbl_old->sequence == swap->sequence) { - spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); - drm_vblank_put(dev, pipe); - drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER); - DRM_DEBUG("Already scheduled\n"); - return 0; - } - } - - if (dev_priv->swaps_pending >= 10) { - DRM_DEBUG("Too many swaps queued\n"); - DRM_DEBUG(" pipe 0: %d pipe 1: %d\n", - drm_vblank_count(dev, 0), - drm_vblank_count(dev, 1)); - - list_for_each(list, &dev_priv->vbl_swaps.head) { - vbl_old = list_entry(list, drm_i915_vbl_swap_t, head); - DRM_DEBUG("\tdrw %x pipe %d seq %x\n", - vbl_old->drw_id, vbl_old->pipe, - vbl_old->sequence); - } - spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); - drm_vblank_put(dev, pipe); - drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER); - return -EBUSY; - } - - list_add_tail(&vbl_swap->head, &dev_priv->vbl_swaps.head); - dev_priv->swaps_pending++; - - spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); - - return 0; + return -EINVAL; } /* drm_dma.h hooks @@ -831,11 +487,6 @@ int i915_driver_irq_postinstall(struct drm_device *dev) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int ret, num_pipes = 2; - spin_lock_init(&dev_priv->swaps_lock); - INIT_LIST_HEAD(&dev_priv->vbl_swaps.head); - INIT_WORK(&dev_priv->vblank_work, i915_vblank_work_handler); - dev_priv->swaps_pending = 0; - /* Set initial unmasked IRQs to just the selected vblank pipes. */ dev_priv->irq_mask_reg = ~0; -- cgit v1.2.3 From 5d8e6bb7a20b6206e1fe44565efc383a941b81fa Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 4 Nov 2008 18:36:29 -0800 Subject: drm: Remove infrastructure for supporting i915's vblank swapping. It's not used in any other drivers, and doesn't look like it will be from drm.git master. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_irq.c | 80 ---------------------------------------------- drivers/gpu/drm/drm_lock.c | 9 ------ drivers/gpu/drm/drm_stub.c | 1 - 3 files changed, 90 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 212a94f715b..15c8dabc3e9 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -280,8 +280,6 @@ int drm_irq_uninstall(struct drm_device * dev) drm_vblank_cleanup(dev); - dev->locked_tasklet_func = NULL; - return 0; } EXPORT_SYMBOL(drm_irq_uninstall); @@ -699,81 +697,3 @@ void drm_handle_vblank(struct drm_device *dev, int crtc) drm_vbl_send_signals(dev, crtc); } EXPORT_SYMBOL(drm_handle_vblank); - -/** - * Tasklet wrapper function. - * - * \param data DRM device in disguise. - * - * Attempts to grab the HW lock and calls the driver callback on success. On - * failure, leave the lock marked as contended so the callback can be called - * from drm_unlock(). - */ -static void drm_locked_tasklet_func(unsigned long data) -{ - struct drm_device *dev = (struct drm_device *)data; - unsigned long irqflags; - void (*tasklet_func)(struct drm_device *); - - spin_lock_irqsave(&dev->tasklet_lock, irqflags); - tasklet_func = dev->locked_tasklet_func; - spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); - - if (!tasklet_func || - !drm_lock_take(&dev->lock, - DRM_KERNEL_CONTEXT)) { - return; - } - - dev->lock.lock_time = jiffies; - atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); - - spin_lock_irqsave(&dev->tasklet_lock, irqflags); - tasklet_func = dev->locked_tasklet_func; - dev->locked_tasklet_func = NULL; - spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); - - if (tasklet_func != NULL) - tasklet_func(dev); - - drm_lock_free(&dev->lock, - DRM_KERNEL_CONTEXT); -} - -/** - * Schedule a tasklet to call back a driver hook with the HW lock held. - * - * \param dev DRM device. - * \param func Driver callback. - * - * This is intended for triggering actions that require the HW lock from an - * interrupt handler. The lock will be grabbed ASAP after the interrupt handler - * completes. Note that the callback may be called from interrupt or process - * context, it must not make any assumptions about this. Also, the HW lock will - * be held with the kernel context or any client context. - */ -void drm_locked_tasklet(struct drm_device *dev, void (*func)(struct drm_device *)) -{ - unsigned long irqflags; - static DECLARE_TASKLET(drm_tasklet, drm_locked_tasklet_func, 0); - - if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ) || - test_bit(TASKLET_STATE_SCHED, &drm_tasklet.state)) - return; - - spin_lock_irqsave(&dev->tasklet_lock, irqflags); - - if (dev->locked_tasklet_func) { - spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); - return; - } - - dev->locked_tasklet_func = func; - - spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); - - drm_tasklet.data = (unsigned long)dev; - - tasklet_hi_schedule(&drm_tasklet); -} -EXPORT_SYMBOL(drm_locked_tasklet); diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 888159e03d2..1cfa72031f8 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -154,8 +154,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_lock *lock = data; - unsigned long irqflags; - void (*tasklet_func)(struct drm_device *); if (lock->context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", @@ -163,13 +161,6 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) return -EINVAL; } - spin_lock_irqsave(&dev->tasklet_lock, irqflags); - tasklet_func = dev->locked_tasklet_func; - dev->locked_tasklet_func = NULL; - spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); - if (tasklet_func != NULL) - tasklet_func(dev); - atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); /* kernel_context_switch isn't used by any of the x86 drm diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index 141e33004a7..66c96ec6667 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -92,7 +92,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, spin_lock_init(&dev->count_lock); spin_lock_init(&dev->drw_lock); - spin_lock_init(&dev->tasklet_lock); spin_lock_init(&dev->lock.spinlock); init_timer(&dev->timer); mutex_init(&dev->struct_mutex); -- cgit v1.2.3 From 78538bf14995a136c2d9a22159ada49937359119 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 11 Nov 2008 17:56:16 +1000 Subject: drm/radeon: map registers at load time Now that the radeon driver has suspend/resume functions, it needs to map its registers at load time or it will likely crash if a suspend operation occurs before the driver has been initialized. This patch moves the register mapping code from firstopen to load and makes the mapping into a _DRM_DRIVER one so that the core won't remove it at lastclose time. Fixes (at least partially) kernel bz #11891. Signed-off-by: Jesse Barnes Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_cp.c | 15 +++++++++------ drivers/gpu/drm/radeon/radeon_drv.h | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 073894824e6..abdc1ae3846 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -1751,6 +1751,12 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) else dev_priv->flags |= RADEON_IS_PCI; + ret = drm_addmap(dev, drm_get_resource_start(dev, 2), + drm_get_resource_len(dev, 2), _DRM_REGISTERS, + _DRM_READ_ONLY | _DRM_DRIVER, &dev_priv->mmio); + if (ret != 0) + return ret; + DRM_DEBUG("%s card detected\n", ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); return ret; @@ -1767,12 +1773,6 @@ int radeon_driver_firstopen(struct drm_device *dev) dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; - ret = drm_addmap(dev, drm_get_resource_start(dev, 2), - drm_get_resource_len(dev, 2), _DRM_REGISTERS, - _DRM_READ_ONLY, &dev_priv->mmio); - if (ret != 0) - return ret; - dev_priv->fb_aper_offset = drm_get_resource_start(dev, 0); ret = drm_addmap(dev, dev_priv->fb_aper_offset, drm_get_resource_len(dev, 0), _DRM_FRAME_BUFFER, @@ -1788,6 +1788,9 @@ int radeon_driver_unload(struct drm_device *dev) drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); + + drm_rmmap(dev, dev_priv->mmio); + drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); dev->dev_private = NULL; diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 02f5575ba39..7a183789be9 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -287,7 +287,6 @@ typedef struct drm_radeon_private { unsigned long gart_textures_offset; drm_local_map_t *sarea; - drm_local_map_t *mmio; drm_local_map_t *cp_ring; drm_local_map_t *ring_rptr; drm_local_map_t *gart_textures; @@ -318,6 +317,7 @@ typedef struct drm_radeon_private { int num_gb_pipes; int track_flush; + drm_local_map_t *mmio; } drm_radeon_private_t; typedef struct drm_radeon_buf_priv { -- cgit v1.2.3 From bd6b52a17b9af630c38bb4f89609be5654d71e1e Mon Sep 17 00:00:00 2001 From: Qinghuang Feng Date: Sat, 8 Nov 2008 16:32:02 +0800 Subject: [libata] pata_cs553*.c: cleanup kernel-doc No arguments named @deadline in cs5535_cable_detect() and cs5536_cable_detect(). Remove them. Signed-off-by: Qinghuang Feng Signed-off-by: Jeff Garzik --- drivers/ata/pata_cs5535.c | 1 - drivers/ata/pata_cs5536.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c index 1b2d4a0f5f7..8b236af84c2 100644 --- a/drivers/ata/pata_cs5535.c +++ b/drivers/ata/pata_cs5535.c @@ -72,7 +72,6 @@ /** * cs5535_cable_detect - detect cable type * @ap: Port to detect on - * @deadline: deadline jiffies for the operation * * Perform cable detection for ATA66 capable cable. Return a libata * cable type. diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c index 73f8332cb67..afed9297619 100644 --- a/drivers/ata/pata_cs5536.c +++ b/drivers/ata/pata_cs5536.c @@ -110,7 +110,6 @@ static inline int cs5536_write(struct pci_dev *pdev, int reg, int val) /** * cs5536_cable_detect - detect cable type * @ap: Port to detect on - * @deadline: deadline jiffies for the operation * * Perform cable detection for ATA66 capable cable. Return a libata * cable type. -- cgit v1.2.3 From bc170e656881306d65eb1318c98032e1ab305ee8 Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Thu, 6 Nov 2008 08:03:23 -0500 Subject: [libata] pata_sch: notice attached slave devices I posted this last month, but was prompted to do so again in bz#467457 Add capability flag to support slave devices with pata_sch driver. Signed-off-by: Mark Salter Signed-off-by: Jeff Garzik --- drivers/ata/pata_sch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c index c8cc027789f..6aeeeeb3412 100644 --- a/drivers/ata/pata_sch.c +++ b/drivers/ata/pata_sch.c @@ -83,7 +83,7 @@ static struct ata_port_operations sch_pata_ops = { }; static struct ata_port_info sch_port_info = { - .flags = 0, + .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = ATA_PIO4, /* pio0-4 */ .mwdma_mask = ATA_MWDMA2, /* mwdma0-2 */ .udma_mask = ATA_UDMA5, /* udma0-5 */ -- cgit v1.2.3 From a12d6c9a09c644cb4a35be099eb5124d38e4feb8 Mon Sep 17 00:00:00 2001 From: Marc Pignat Date: Thu, 6 Nov 2008 11:44:34 +0100 Subject: [libata] pata_pcmcia: another memory card support Support for Apacer photo steno pro card. Signed-off-by: Marc Pignat Signed-off-by: Jeff Garzik --- drivers/ata/pata_pcmcia.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 271cb64d429..64b2e2281ee 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -416,6 +416,7 @@ static struct pcmcia_device_id pcmcia_devices[] = { PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), + PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506), PCMCIA_DEVICE_NULL, }; -- cgit v1.2.3 From 44901a96847b9967c057832b185e2f34ee6a14e5 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 4 Nov 2008 10:34:48 -0800 Subject: libata: Avoid overflow in ata_tf_read_block() when tf->hba_lbal > 127 Phillip O'Donnell pointed out that the same sign extension bug that was fixed in commit ba14a9c2 ("libata: Avoid overflow in ata_tf_to_lba48() when tf->hba_lbal > 127") also appears to exist in ata_tf_read_block(). Fix this by adding a cast to u64. Signed-off-by: Roland Dreier Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 0cd3ad49713..4214bfb13bb 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -612,7 +612,7 @@ u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev) if (tf->flags & ATA_TFLAG_LBA48) { block |= (u64)tf->hob_lbah << 40; block |= (u64)tf->hob_lbam << 32; - block |= tf->hob_lbal << 24; + block |= (u64)tf->hob_lbal << 24; } else block |= (tf->device & 0xf) << 24; -- cgit v1.2.3 From 19b723218bde79c60a394a3caee9eb156ac2d356 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 4 Nov 2008 17:08:40 +0900 Subject: libata: fix last_reset timestamp handling ehc->last_reset is used to ensure that resets are not issued too close to each other. It's initialized to jiffies minus one minute on EH entry. However, when new links are initialized after PMP is probed, new links have zero for this timestamp resulting in long wait depending on the current jiffies. This patch makes last_set considered iff ATA_EHI_DID_RESET is set, in which case last_reset is always initialized. As an added precaution, WARN_ON() is added so that warning is printed if last_reset is in future. This problem is spotted and debugged by Shane Huang. Signed-off-by: Tejun Heo Cc: Shane Huang Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 8077bdf5d30..32da9a93ce4 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -610,9 +610,6 @@ void ata_scsi_error(struct Scsi_Host *host) if (ata_ncq_enabled(dev)) ehc->saved_ncq_enabled |= 1 << devno; } - - /* set last reset timestamp to some time in the past */ - ehc->last_reset = jiffies - 60 * HZ; } ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS; @@ -2281,17 +2278,21 @@ int ata_eh_reset(struct ata_link *link, int classify, if (link->flags & ATA_LFLAG_NO_SRST) softreset = NULL; - now = jiffies; - deadline = ata_deadline(ehc->last_reset, ATA_EH_RESET_COOL_DOWN); - if (time_before(now, deadline)) - schedule_timeout_uninterruptible(deadline - now); + /* make sure each reset attemp is at least COOL_DOWN apart */ + if (ehc->i.flags & ATA_EHI_DID_RESET) { + now = jiffies; + WARN_ON(time_after(ehc->last_reset, now)); + deadline = ata_deadline(ehc->last_reset, + ATA_EH_RESET_COOL_DOWN); + if (time_before(now, deadline)) + schedule_timeout_uninterruptible(deadline - now); + } spin_lock_irqsave(ap->lock, flags); ap->pflags |= ATA_PFLAG_RESETTING; spin_unlock_irqrestore(ap->lock, flags); ata_eh_about_to_do(link, NULL, ATA_EH_RESET); - ehc->last_reset = jiffies; ata_link_for_each_dev(dev, link) { /* If we issue an SRST then an ATA drive (not ATAPI) @@ -2379,7 +2380,6 @@ int ata_eh_reset(struct ata_link *link, int classify, /* * Perform reset */ - ehc->last_reset = jiffies; if (ata_is_host_link(link)) ata_eh_freeze_port(ap); @@ -2391,6 +2391,7 @@ int ata_eh_reset(struct ata_link *link, int classify, reset == softreset ? "soft" : "hard"); /* mark that this EH session started with reset */ + ehc->last_reset = jiffies; if (reset == hardreset) ehc->i.flags |= ATA_EHI_DID_HARDRESET; else @@ -2535,7 +2536,7 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_eh_done(link, NULL, ATA_EH_RESET); if (slave) ata_eh_done(slave, NULL, ATA_EH_RESET); - ehc->last_reset = jiffies; + ehc->last_reset = jiffies; /* update to completion time */ ehc->i.action |= ATA_EH_REVALIDATE; rc = 0; -- cgit v1.2.3 From afa21e0584f78964c092981fad94e45d38cda249 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 11 Nov 2008 18:02:12 +1000 Subject: drm/i915: Filter pci devices based on PCI_CLASS_DISPLAY_VGA This fixes hangs on 855-class hardware by avoiding double attachment of the driver due to the stub second head device having the same pci id as the real device. Other DRM drivers probably want this treatment as well, but I'm applying it just to this one for safety. But we should clean up the drm_pciids.h mess now so that each driver has its own pci id list header in its own directory. Lets do that in the next release. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_drv.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 96f416afc3f..3ab1e9cc469 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -266,11 +266,19 @@ int drm_init(struct drm_driver *driver) for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) { pid = (struct pci_device_id *)&driver->pci_driver.id_table[i]; + /* Loop around setting up a DRM device for each PCI device + * matching our ID and device class. If we had the internal + * function that pci_get_subsys and pci_get_class used, we'd + * be able to just pass pid in instead of doing a two-stage + * thing. + */ pdev = NULL; - /* pass back in pdev to account for multiple identical cards */ while ((pdev = pci_get_subsys(pid->vendor, pid->device, pid->subvendor, pid->subdevice, pdev)) != NULL) { + if ((pdev->class & pid->class_mask) != pid->class) + continue; + /* stealth mode requires a manual probe */ pci_dev_get(pdev); drm_get_dev(pdev, pid, driver); -- cgit v1.2.3 From 0baf823a10bd4131f70e9712d1f02de3c247f1df Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 8 Nov 2008 11:44:14 +1000 Subject: drm/i915: Move legacy breadcrumb out of the reserved status page area Addresses in the hardware status page below index 0x20 are reserved for use by the hardware. The legacy breadcrumb was sitting at index 5. Move it to index 0x21, and make sure everyone uses the defined value instead of hard-coded constants. Signed-off-by: Keith Packard Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_dma.c | 10 ++++------ drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_irq.c | 6 ++---- 3 files changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 9d4278be0ca..0d215e38606 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -445,7 +445,7 @@ static void i915_emit_breadcrumb(struct drm_device *dev) BEGIN_LP_RING(4); OUT_RING(MI_STORE_DWORD_INDEX); - OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT); + OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); OUT_RING(dev_priv->counter); OUT_RING(0); ADVANCE_LP_RING(); @@ -576,7 +576,7 @@ static int i915_dispatch_flip(struct drm_device * dev) BEGIN_LP_RING(4); OUT_RING(MI_STORE_DWORD_INDEX); - OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT); + OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); OUT_RING(dev_priv->counter); OUT_RING(0); ADVANCE_LP_RING(); @@ -611,7 +611,6 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u32 *hw_status = dev_priv->hw_status_page; drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) dev_priv->sarea_priv; drm_i915_batchbuffer_t *batch = data; @@ -637,7 +636,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, mutex_unlock(&dev->struct_mutex); if (sarea_priv) - sarea_priv->last_dispatch = (int)hw_status[5]; + sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); return ret; } @@ -645,7 +644,6 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u32 *hw_status = dev_priv->hw_status_page; drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) dev_priv->sarea_priv; drm_i915_cmdbuffer_t *cmdbuf = data; @@ -673,7 +671,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, } if (sarea_priv) - sarea_priv->last_dispatch = (int)hw_status[5]; + sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4afbadb1331..ef1c0b8f8d0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -608,8 +608,9 @@ static inline void opregion_enable_asle(struct drm_device *dev) { return; } * The area from dword 0x20 to 0x3ff is available for driver usage. */ #define READ_HWSP(dev_priv, reg) (((volatile u32*)(dev_priv->hw_status_page))[reg]) -#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, 5) +#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX) #define I915_GEM_HWS_INDEX 0x20 +#define I915_BREADCRUMB_INDEX 0x21 extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a75345af62e..82752d6177a 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -212,12 +212,10 @@ static int i915_emit_irq(struct drm_device * dev) if (dev_priv->sarea_priv) dev_priv->sarea_priv->last_enqueue = dev_priv->counter; - BEGIN_LP_RING(6); + BEGIN_LP_RING(4); OUT_RING(MI_STORE_DWORD_INDEX); - OUT_RING(5 << MI_STORE_DWORD_INDEX_SHIFT); + OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); OUT_RING(dev_priv->counter); - OUT_RING(0); - OUT_RING(0); OUT_RING(MI_USER_INTERRUPT); ADVANCE_LP_RING(); -- cgit v1.2.3 From 8c2f5fa51e1b22db53acf4f3918b6f590b4a35a1 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Mon, 10 Nov 2008 13:58:41 +0100 Subject: myri10ge: fix stop/go ordering even more The doorbell writes may be seen out of order by the firmware if they are in WC memory since the tx spin(un)lock does not flush WC writes. Hence if the "stop" is written on a different CPU than the "go", it is possible that the stop will arrive after the go unless we add an explicit memory barrier (and mmiowb() is not enough). It fixes transmit hangs in multi tx queue mode. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index a5f428bcc0e..b3786709730 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -75,7 +75,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.4.3-1.375" +#define MYRI10GE_VERSION_STR "1.4.3-1.378" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); @@ -1393,6 +1393,7 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index) if (tx->req == tx->done) { tx->queue_active = 0; put_be32(htonl(1), tx->send_stop); + mb(); mmiowb(); } __netif_tx_unlock(dev_queue); @@ -2865,6 +2866,7 @@ again: if ((mgp->dev->real_num_tx_queues > 1) && tx->queue_active == 0) { tx->queue_active = 1; put_be32(htonl(1), tx->send_go); + mb(); mmiowb(); } tx->pkt_start++; -- cgit v1.2.3 From 9f64306b8a3949b74cb11d3b2f613e8a2af20fa6 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Sun, 9 Nov 2008 00:55:28 -0800 Subject: cxgb3 - eeprom read fixes Protect against invalid phy entries in the eeprom. Extend eeprom access timeout. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/t3_hw.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index 968f64be374..9a0898b0dbc 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -572,7 +572,7 @@ struct t3_vpd { u32 pad; /* for multiple-of-4 sizing and alignment */ }; -#define EEPROM_MAX_POLL 4 +#define EEPROM_MAX_POLL 40 #define EEPROM_STAT_ADDR 0x4000 #define VPD_BASE 0xc00 @@ -3690,6 +3690,12 @@ int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, ; pti = &port_types[adapter->params.vpd.port_type[j]]; + if (!pti->phy_prep) { + CH_ALERT(adapter, "Invalid port type index %d\n", + adapter->params.vpd.port_type[j]); + return -EINVAL; + } + ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, ai->mdio_ops); if (ret) -- cgit v1.2.3 From f9ee3882969224aa9f086268020c31819be6ae99 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Sun, 9 Nov 2008 00:55:33 -0800 Subject: cxgb3 - Limit multiqueue setting to msi-x Allow multiqueue setting in MSI-X mode only Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/cxgb3_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 1ace41a13ac..f66367ed693 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -2699,7 +2699,7 @@ static void set_nqsets(struct adapter *adap) int hwports = adap->params.nports; int nqsets = SGE_QSETS; - if (adap->params.rev > 0) { + if (adap->params.rev > 0 && adap->flags & USING_MSIX) { if (hwports == 2 && (hwports * nqsets > SGE_QSETS || num_cpus >= nqsets / hwports)) -- cgit v1.2.3 From cf3760dad576c8dfb4fef4b8a8a08a027bf02583 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Thu, 6 Nov 2008 17:06:42 -0600 Subject: RDMA/cxgb3: deadlock in iw_cxgb3 can cause hang when configuring interface. When the iw_cxgb3 module's cxgb3_client "add" func gets called by the cxgb3 module, the iwarp driver ends up calling the ethtool ops get_drvinfo function in cxgb3 to get the fw version and other info. Currently the iwarp driver grabs the rtnl lock around this down call to serialize. As of 2.6.27 or so, things changed such that the rtnl lock is held around the call to the netdev driver open function. Also the cxgb3_client "add" function doesn't get called if the device is down. So, if you load cxgb3, then load iw_cxgb3, then ifconfig up the device, the iw_cxgb3 add func gets called with the rtnl_lock held. If you load cxgb3, ifconfig up the device, then load iw_cxgb3, the add func gets called without the rtnl_lock held. The former causes the deadlock, the latter does not. In addition, there are iw_cxgb3 sysfs handlers that also can call down into cxgb3 to gather the fw and hw versions. These can be called concurrently on different processors and at any time. Thus we need to push this serialization down in the cxgb3 driver get_drvinfo func. The fix is to remove rtnl lock usage, and use a per-device lock in cxgb3. Signed-off-by: Steve Wise Signed-off-by: Jeff Garzik --- drivers/infiniband/hw/cxgb3/iwch_provider.c | 6 ------ drivers/net/cxgb3/cxgb3_main.c | 2 ++ 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c index ecff9804358..160ef482712 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c @@ -1102,9 +1102,7 @@ static u64 fw_vers_string_to_u64(struct iwch_dev *iwch_dev) char *cp, *next; unsigned fw_maj, fw_min, fw_mic; - rtnl_lock(); lldev->ethtool_ops->get_drvinfo(lldev, &info); - rtnl_unlock(); next = info.fw_version + 1; cp = strsep(&next, "."); @@ -1192,9 +1190,7 @@ static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, ch struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev; PDBG("%s dev 0x%p\n", __func__, dev); - rtnl_lock(); lldev->ethtool_ops->get_drvinfo(lldev, &info); - rtnl_unlock(); return sprintf(buf, "%s\n", info.fw_version); } @@ -1207,9 +1203,7 @@ static ssize_t show_hca(struct device *dev, struct device_attribute *attr, struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev; PDBG("%s dev 0x%p\n", __func__, dev); - rtnl_lock(); lldev->ethtool_ops->get_drvinfo(lldev, &info); - rtnl_unlock(); return sprintf(buf, "%s\n", info.driver); } diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index f66367ed693..2c341f83d32 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1307,8 +1307,10 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) u32 fw_vers = 0; u32 tp_vers = 0; + spin_lock(&adapter->stats_lock); t3_get_fw_version(adapter, &fw_vers); t3_get_tp_version(adapter, &tp_vers); + spin_unlock(&adapter->stats_lock); strcpy(info->driver, DRV_NAME); strcpy(info->version, DRV_VERSION); -- cgit v1.2.3 From 347c8d83cd9f546a8357e1ab12fa6867707975d8 Mon Sep 17 00:00:00 2001 From: "Dasgupta, Romit" Date: Thu, 6 Nov 2008 15:46:18 +0530 Subject: [netdrvr] smc911x: fix for driver resume (and compilation warning) I am trying out suspend, resume on an OMAP3 based board. What I see during resume is that the SMC911x driver resume routing gets stuck after trying to transmit the packet out of the controller. Some debug messages below: --> smc911x_drv_resume eth0: --> smc911x_reset eth0: smc911x_reset timeout waiting for PM restore eth0: --> smc911x_enable eth0: --> smc911x_phy_configure() eth0: --> smc911x_phy_reset() eth0: phy caps=0x782d eth0: phy advertised caps=0x0de1 eth0: --> smc911x_phy_check_media smc911x_phy_read: phyaddr=0x1, phyreg=0x01, phydata=0x7809 smc911x_phy_read: phyaddr=0x1, phyreg=0x01, phydata=0x7809 eth0: link down Restarting tasks ... eth0: --> smc911x_hard_start_xmit eth0: --> smc911x_hardware_send_pkt eth0: --> smc911x_hard_start_xmit eth0: --> smc911x_hardware_send_pkt eth0: --> smc911x_hard_start_xmit eth0: --> smc911x_hardware_send_pkt nfs: server 172.24.190.217 not responding, still trying nfs: server 172.24.190.217 not responding, still trying The following change makes it work fine: (The change within smc911x_drv_probe function was to get rid of a compilation warning). Signed-off-by: Romit Dasgupta Signed-off-by: Jeff Garzik --- drivers/net/smc911x.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 5051554ff05..1f26ab0e798 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -2050,7 +2050,9 @@ err_out: */ static int smc911x_drv_probe(struct platform_device *pdev) { +#ifdef SMC_DYNAMIC_BUS_CONFIG struct smc911x_platdata *pd = pdev->dev.platform_data; +#endif struct net_device *ndev; struct resource *res; struct smc911x_local *lp; @@ -2182,9 +2184,9 @@ static int smc911x_drv_resume(struct platform_device *dev) if (netif_running(ndev)) { smc911x_reset(ndev); - smc911x_enable(ndev); if (lp->phy_type != 0) smc911x_phy_configure(&lp->phy_configure); + smc911x_enable(ndev); netif_device_attach(ndev); } } -- cgit v1.2.3 From 6a13378a56ce06afca9db75f3d4e663fba5f0992 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Sun, 19 Oct 2008 20:10:13 -0300 Subject: V4L/DVB (9337a): HID: Don't allow KWorld radio fm700 be handled by usb hid drivers This device is already handled by radio-si470x driver, and we therefore want usbhid to ignore it. Signed-off-by: Alexey Klimov Acked-by: Tobias Lorenz Signed-off-by: Mauro Carvalho Chehab --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 +++ 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 1903e751565..d3671b4049c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1265,6 +1265,7 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 5cc40429173..f05bcbbbb0d 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -253,6 +253,9 @@ #define USB_VENDOR_ID_KBGEAR 0x084e #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001 +#define USB_VENDOR_ID_KWORLD 0x1b80 +#define USB_DEVICE_ID_KWORLD_RADIO_FM700 0xd700 + #define USB_VENDOR_ID_LABTEC 0x1020 #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006 -- cgit v1.2.3 From 3b37a15c2d75585cc0da49b8e69345af91e227ce Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Mon, 20 Oct 2008 18:14:14 -0300 Subject: V4L/DVB (9346): Optimization: Enable gate in a symmetric/disciplined way, rather than implementing different ways leading to confusion. This allows multiple gate_enable/disable's in the tuner_read/write functions, thereby lesser number of I/O operations throughout, eventually leading to better results. As a side effect demods that detect the STOP bit for auto closing of the gate can be avoided, thereby a very minimal gain in disabling the auto detect feature as well. Improves readability on the device control. Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 5689d1f1d44..8557bf12cfb 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -223,6 +223,8 @@ static void dvb_frontend_init(struct dvb_frontend *fe) if (fe->ops.init) fe->ops.init(fe); if (fe->ops.tuner_ops.init) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); fe->ops.tuner_ops.init(fe); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); -- cgit v1.2.3 From e62b47565a865d77133c88aee6a2a14838aeb9b8 Mon Sep 17 00:00:00 2001 From: Antoine Jacquet Date: Tue, 21 Oct 2008 17:54:51 -0300 Subject: V4L/DVB (9348): dtv5100: add dependency on zl10353 Update Kconfig to add missing dependency on zl10353 for dtv5100 driver. Signed-off-by: Antoine Jacquet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 3c13bcfa638..47488a97a85 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -283,6 +283,7 @@ config DVB_USB_ANYSEE config DVB_USB_DTV5100 tristate "AME DTV-5100 USB2.0 DVB-T support" depends on DVB_USB + select DVB_ZL10353 if !DVB_FE_CUSTOMISE select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE help Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. -- cgit v1.2.3 From 69df96c3dad0704301cdbd665636d8184fb314c6 Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Thu, 23 Oct 2008 09:20:27 -0300 Subject: V4L/DVB (9350): radio-si470x: add support for kworld usb radio This patch add support for new device named KWorld USB FM Radio SnapMusic Mobile 700 (FM700). And changes few lines in comments. Signed-off-by: Alexey Klimov Acked-by: Tobias Lorenz Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/radio-si470x.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index 5920cd30697..a20583c13b6 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c @@ -4,6 +4,7 @@ * Driver for USB radios for the Silicon Labs Si470x FM Radio Receivers: * - Silicon Labs USB FM Radio Reference Design * - ADS/Tech FM Radio Receiver (formerly Instant FM Music) (RDX-155-EF) + * - KWorld USB FM Radio SnapMusic Mobile 700 (FM700) * * Copyright (c) 2008 Tobias Lorenz * @@ -105,6 +106,9 @@ * - afc indication * - more safety checks, let si470x_get_freq return errno * - vidioc behavior corrected according to v4l2 spec + * 2008-10-20 Alexey Klimov + * - add support for KWorld USB FM Radio FM700 + * - blacklisted KWorld radio in hid-core.c and hid-ids.h * * ToDo: * - add firmware download/update support @@ -145,6 +149,8 @@ static struct usb_device_id si470x_usb_driver_id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) }, /* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */ { USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) }, + /* KWorld USB FM Radio SnapMusic Mobile 700 (FM700) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1b80, 0xd700, USB_CLASS_HID, 0, 0) }, /* Terminating entry */ { } }; -- cgit v1.2.3 From a24ddee36ca10a90451552e6620ff7c4ff7e44b5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 23 Oct 2008 09:53:56 -0300 Subject: V4L/DVB (9351): ibmcam: Fix a regression caused by a482f327ff56bc3cf53176a7eb736cea47291a1d As reported by David Ellingsworth: > I'm not sure if it matters or not, but the ibmcam driver in the > Mauro's linux-2.6 git tree in the for_linus branch is currently > broken. uvd is equal to NULL during most of ibmcam_probe. Due to that, an OOPS is generated at dev_info. This patch replaces uvd->dev->dev to dev->dev inside this routine. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: David Ellingsworth --- drivers/media/video/usbvideo/ibmcam.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c index 28421d386f1..c710bcd1df4 100644 --- a/drivers/media/video/usbvideo/ibmcam.c +++ b/drivers/media/video/usbvideo/ibmcam.c @@ -3695,7 +3695,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * unsigned char video_ep = 0; if (debug >= 1) - dev_info(&uvd->dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum); + dev_info(&dev->dev, "ibmcam_probe(%p,%u.)\n", intf, ifnum); /* We don't handle multi-config cameras */ if (dev->descriptor.bNumConfigurations != 1) @@ -3746,7 +3746,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */ break; } - dev_info(&uvd->dev->dev, + dev_info(&dev->dev, "%s USB camera found (model %d, rev. 0x%04x)\n", brand, model, le16_to_cpu(dev->descriptor.bcdDevice)); } while (0); @@ -3754,7 +3754,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * /* Validate found interface: must have one ISO endpoint */ nas = intf->num_altsetting; if (debug > 0) - dev_info(&uvd->dev->dev, "Number of alternate settings=%d.\n", + dev_info(&dev->dev, "Number of alternate settings=%d.\n", nas); if (nas < 2) { err("Too few alternate settings for this camera!"); @@ -3799,7 +3799,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * actInterface = i; maxPS = le16_to_cpu(endpoint->wMaxPacketSize); if (debug > 0) - dev_info(&uvd->dev->dev, + dev_info(&dev->dev, "Active setting=%d. " "maxPS=%d.\n", i, maxPS); } else @@ -3840,7 +3840,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * RESTRICT_TO_RANGE(framerate, 0, 5); break; default: - dev_info(&uvd->dev->dev, "IBM camera: using 320x240\n"); + dev_info(&dev->dev, "IBM camera: using 320x240\n"); size = SIZE_320x240; /* No break here */ case SIZE_320x240: @@ -3869,7 +3869,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id * canvasY = 120; break; default: - dev_info(&uvd->dev->dev, "IBM NetCamera: using 176x144\n"); + dev_info(&dev->dev, "IBM NetCamera: using 176x144\n"); size = SIZE_176x144; /* No break here */ case SIZE_176x144: -- cgit v1.2.3 From c7f09db6852d85e7f76322815051aad1c88d08cf Mon Sep 17 00:00:00 2001 From: Gregor Jasny Date: Thu, 23 Oct 2008 09:55:22 -0300 Subject: V4L/DVB (9352): Add some missing compat32 ioctls This patch adds the missing compat ioctls that are needed to operate Skype in combination with libv4l and a MJPEG only camera. If you think it's trivial enough please submit it to -stable, too. Signed-off-by: Gregor Jasny Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/compat_ioctl32.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c index bd5d9de5a00..e6ca4012b5f 100644 --- a/drivers/media/video/compat_ioctl32.c +++ b/drivers/media/video/compat_ioctl32.c @@ -867,6 +867,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_STREAMON32: case VIDIOC_STREAMOFF32: case VIDIOC_G_PARM: + case VIDIOC_S_PARM: case VIDIOC_G_STD: case VIDIOC_S_STD: case VIDIOC_G_TUNER: @@ -885,6 +886,8 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOC_S_INPUT32: case VIDIOC_TRY_FMT32: case VIDIOC_S_HW_FREQ_SEEK: + case VIDIOC_ENUM_FRAMESIZES: + case VIDIOC_ENUM_FRAMEINTERVALS: ret = do_video_ioctl(file, cmd, arg); break; -- cgit v1.2.3 From 74084d33cb6221a5836a2a4438ec1bcf7a0797b0 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 17 Oct 2008 20:19:29 -0300 Subject: V4L/DVB (9355): de-BKL cafe_ccic.c Remove lock_kernel() call from cafe_ccic.c Commit d56dc61265d2527a63ab5b0f03199a43cd89ca36 added lock_kernel() calls to cafe_ccic.c. But that driver was written with proper locking and does not need the BKL, so take it back out. Signed-off-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cafe_ccic.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index a8c068e1de1..1740b9ebdce 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c @@ -1476,12 +1476,9 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp) { struct cafe_camera *cam; - lock_kernel(); cam = cafe_find_dev(iminor(inode)); - if (cam == NULL) { - unlock_kernel(); + if (cam == NULL) return -ENODEV; - } filp->private_data = cam; mutex_lock(&cam->s_mutex); @@ -1493,7 +1490,6 @@ static int cafe_v4l_open(struct inode *inode, struct file *filp) } (cam->users)++; mutex_unlock(&cam->s_mutex); - unlock_kernel(); return 0; } -- cgit v1.2.3 From d522af581c6abd0e064278345ca638b0553a93fa Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Mon, 20 Oct 2008 17:57:02 -0300 Subject: V4L/DVB (9356): [PATCH] saa7134: fix resource map sanity check conflict Impact: driver could possibly stomp on resources outside of its scope {mchehab@redhat.com: I got two versions of the same patch (identical, except for whitespacing). One authored by Andy Burns and another authored by Suresh Siddha. Due to that, I'm applying the one that has less CodingStyle errors. I'm also adding both comments and the SOB's for both patches, since they are both interesting} Suresh Siddha commented: Alexey Fisher reported: > resource map sanity check conflict: 0xcfeff800 0xcff007ff 0xcfe00000 > 0xcfefffff PCI Bus 0000:01 BAR base is located in the middle of the 4K page and the hardcoded size argument makes the request span two pages causing the conflict. Fix the hard coded size argument in ioremap(). Andy Burns commented: I have already sent this patch on the linux-dvb list, but it didn't get much attention, so re-sending direct, I hope you all don't mind. While attempting to run mythtv in a xen domU, I encountered problems loading the driver for my saa7134 card, with an error from ioremap(). This error was due to the driver allocating an incorrectly sized mmio area, which was trapped by xen's permission checks, but this would go un-noticed on a kernel without xen. My card has a 1K sized mmio area, I've had information that other cards have 2K areas, perhaps others have different sizes, yet the driver always attempts to map 4K. I realise that the granularity of mapping is the page size, which typically would be 4K, but unless the card's base address happens to fall on a 4K boundary (mine does not) then the base+4K will end up spanning two pages, and this is when the error occurs under xen. My patch uses the pci_resource_len macro to determine the size required for the user's particular card, instead of the hardcoded 4K value. I've tested with a couple of printk() inside ioremap() that the start address and size do get rounded to the closest page boundary. With this patch I am able to successfully load the saa7134 driver and run mythtv under xen with my card, subject to correct pollirq settings in case of shared IRQ, I am still seeing occasional DMA panics, which I think are related to swiotlb handling by dom0/domU, usually the panic occurs when changing mux, once tuned to a mux, 12 hour continuous recordings are possible without errors. Reported-by: Alexey Fisher Tested-by: Alexey Fisher Signed-off-by: Suresh Siddha Signed-off-by: Andy Burns Signed-off-by: Ingo Molnar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 24918445294..dfbe08a9ad9 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -941,7 +941,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, dev->name,(unsigned long long)pci_resource_start(pci_dev,0)); goto fail1; } - dev->lmmio = ioremap(pci_resource_start(pci_dev,0), 0x1000); + dev->lmmio = ioremap(pci_resource_start(pci_dev, 0), + pci_resource_len(pci_dev, 0)); dev->bmmio = (__u8 __iomem *)dev->lmmio; if (NULL == dev->lmmio) { err = -EIO; -- cgit v1.2.3 From 0e8bac9791b1539b72b8049b18218eb762d94d71 Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Fri, 24 Oct 2008 10:47:07 -0300 Subject: V4L/DVB (9357): cx88-dvb: Fix Oops in case i2c bus failed to register There already is an report at kernel bugzilla about this issue: http://bugzilla.kernel.org/show_bug.cgi?id=9455 When enabling extra checks for the i2c-bus of cx88 based cards by loading i2c_algo_bit with bit_test=1 this may trigger an oops when loading cx88_dvb. This is caused by the extra check code that detects that the sda-line is stuck high and thus does not register the i2c-bus. cx88-dvb however does not check if the i2c-bus is valid and just uses core->i2c_adap to attach dvb frontend modules. This leads to an oops at the first call to i2c_transfer: $ modprobe i2c_algo_bit bit_test=1 $ modprobe cx8802 cx88/2: cx2388x MPEG-TS Driver Manager version 0.0.6 loaded cx88[0]: quirk: PCIPCI_NATOMA -- set TBFX cx88[0]: subsystem: 0070:9202, board: Hauppauge Nova-S-Plus DVB-S [card=37,autodetected], frontend(s): 1 cx88[0]: TV tuner type 4, Radio tuner type -1 cx88[0]: SDA stuck high! cx88[0]: i2c register FAILED input: cx88 IR (Hauppauge Nova-S-Plus as /class/input/input5 cx88[0]/2: cx2388x 8802 Driver Manager cx88-mpeg driver manager 0000:00:10.2: enabling device (0154 -> 0156) cx88-mpeg driver manager 0000:00:10.2: PCI INT A -> Link[LNKD] -> GSI 9 (level, low) -> IRQ 9 cx88[0]/2: found at 0000:00:10.2, rev: 5, irq: 9, latency: 64, mmio: 0xfb000000 cx8802_probe() allocating 1 frontend(s) cx88/2: cx2388x dvb driver version 0.0.6 loaded cx88/2: registering cx8802 driver, type: dvb access: shared cx88[0]/2: subsystem: 0070:9202, board: Hauppauge Nova-S-Plus DVB-S [card=37] cx88[0]/2: cx2388x based DVB/ATSC card BUG: unable to handle kernel NULL pointer dereference at 00000000 IP: [] :i2c_core:i2c_transfer+0x1f/0x80 *pde = 00000000 Modules linked in: cx88_dvb(+) cx8802 cx88xx ir_common i2c_algo_bit tveeprom videobuf_dvb btcx_risc mga drm ipv6 fscpos eeprom nfsd exportfs stv0299 b2c2_flexcop_pci b2c2_flexcop cx24123 s5h1420 ves1x93 dvb_ttpci dvb_core saa7146_vv saa7146 videobuf_dma_sg videobuf_core videodev v4l1_compat ttpci_eeprom lirc_serial lirc_dev usbhid rtc uhci_hcd 8139too i2c_piix4 i2c_core usbcore evdev Pid: 4249, comm: modprobe Not tainted (2.6.27-gentoo #3) EIP: 0060:[] EFLAGS: 00010296 CPU: 0 EIP is at i2c_transfer+0x1f/0x80 [i2c_core] EAX: 00000000 EBX: ffffffa1 ECX: 00000002 EDX: d6c71e3c ESI: d80cd050 EDI: d8093c00 EBP: d6c71e20 ESP: d6c71e0c DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-dvb.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index cf6c30d4e54..309ca5e6806 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -598,6 +598,11 @@ static int dvb_register(struct cx8802_dev *dev) struct videobuf_dvb_frontend *fe0, *fe1 = NULL; int mfe_shared = 0; /* bus not shared by default */ + if (0 != core->i2c_rc) { + printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name); + goto frontend_detach; + } + /* Get the first frontend */ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1); if (!fe0) -- cgit v1.2.3 From bdb6ee32536b881085a99fabff7bdfe359e3461b Mon Sep 17 00:00:00 2001 From: Thierry MERLE Date: Thu, 23 Oct 2008 17:49:49 -0300 Subject: V4L/DVB (9358): CinergyT2: fix Kconfig typo config\tDVB_USB_CINERGY_T2 causes the make_kconfig.pl to forget to enable by default the compilation of cinergyT2 module. Signed-off-by: Thierry MERLE Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 47488a97a85..62b68c291d9 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -261,7 +261,7 @@ config DVB_USB_DW2102 Say Y here to support the DvbWorld DVB-S/S2 USB2.0 receivers and the TeVii S650. -config DVB_USB_CINERGY_T2 +config DVB_USB_CINERGY_T2 tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver" depends on DVB_USB help -- cgit v1.2.3 From b058e3f39508a3876a4fbf4a92398c817cf82809 Mon Sep 17 00:00:00 2001 From: Rafael Diniz Date: Fri, 24 Oct 2008 23:07:57 -0300 Subject: V4L/DVB (9368): VBI fix for cx88 cards The attached patch fix VBI support cx88 card. I'm running a capture for hours, getting the closed caption from it[1], and it's working perfect - the output is the same of a bttv card. Please apply this patch as soon as possible. [1] - using zvbi-ntsc-cc of zvbi project. Signed-off-by: Rafael Diniz Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-video.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 61265fd04d5..b96ce991d96 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1216,8 +1216,12 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) struct cx8800_fh *fh = priv; struct cx8800_dev *dev = fh->dev; - if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) + /* We should remember that this driver also supports teletext, */ + /* so we have to test if the v4l2_buf_type is VBI capture data. */ + if (unlikely((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && + (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))) return -EINVAL; + if (unlikely(i != fh->type)) return -EINVAL; @@ -1232,8 +1236,10 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) struct cx8800_dev *dev = fh->dev; int err, res; - if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && + (fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)) return -EINVAL; + if (i != fh->type) return -EINVAL; -- cgit v1.2.3 From 8182ff69f8675fc1847a399be4eea5e8118a8dd3 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 24 Oct 2008 15:08:28 -0300 Subject: V4L/DVB (9372): Minor fixes to the saa7110 driver * Apparently the author of the saa7110 driver was confused by the number of outputs returned by DECODER_GET_CAPABILITIES. Of course a decoder chip has no analog ouputs, but it must have at least one digital output. * Fix an off-by-one error when checking the input value of DECODER_SET_INPUT. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7110.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c index adf2ba79496..37860698f78 100644 --- a/drivers/media/video/saa7110.c +++ b/drivers/media/video/saa7110.c @@ -47,7 +47,7 @@ module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); #define SAA7110_MAX_INPUT 9 /* 6 CVBS, 3 SVHS */ -#define SAA7110_MAX_OUTPUT 0 /* its a decoder only */ +#define SAA7110_MAX_OUTPUT 1 /* 1 YUV */ #define SAA7110_NR_REG 0x35 @@ -327,7 +327,7 @@ saa7110_command (struct i2c_client *client, case DECODER_SET_INPUT: v = *(int *) arg; - if (v < 0 || v > SAA7110_MAX_INPUT) { + if (v < 0 || v >= SAA7110_MAX_INPUT) { v4l_dbg(1, debug, client, "input=%d not available\n", v); return -EINVAL; } -- cgit v1.2.3 From f3a3e881b81ae33b786759c7042de974c1e0bbf7 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 25 Oct 2008 23:27:06 -0300 Subject: V4L/DVB (9475): cx18: Disable write retries for registers that always change - part 1. cx18: Disable write retries for registers that always change - part 1. Interrupt related registers will likely not read back the value we just wrote. Disable retries for these registers for now to avoid accidently discarding interrupts. More intelligent read back verification criteria are needed for these and other registers (e.g. GPIO line registers), which will be addressed in subsequent changes. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-io.c | 4 ++-- drivers/media/video/cx18/cx18-irq.c | 6 +++--- drivers/media/video/cx18/cx18-mailbox.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c index 700ab9439c1..31be5e8684d 100644 --- a/drivers/media/video/cx18/cx18-io.c +++ b/drivers/media/video/cx18/cx18-io.c @@ -218,7 +218,7 @@ void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count) void cx18_sw1_irq_enable(struct cx18 *cx, u32 val) { u32 r; - cx18_write_reg(cx, val, SW1_INT_STATUS); + cx18_write_reg_noretry(cx, val, SW1_INT_STATUS); r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI); } @@ -233,7 +233,7 @@ void cx18_sw1_irq_disable(struct cx18 *cx, u32 val) void cx18_sw2_irq_enable(struct cx18 *cx, u32 val) { u32 r; - cx18_write_reg(cx, val, SW2_INT_STATUS); + cx18_write_reg_noretry(cx, val, SW2_INT_STATUS); r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI); } diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index 360330f5463..447fc9c391a 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c @@ -149,9 +149,9 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU; sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask; - cx18_write_reg(cx, sw2&sw2_mask, SW2_INT_STATUS); - cx18_write_reg(cx, sw1&sw1_mask, SW1_INT_STATUS); - cx18_write_reg(cx, hw2&hw2_mask, HW2_INT_CLR_STATUS); + cx18_write_reg_noretry(cx, sw2&sw2_mask, SW2_INT_STATUS); + cx18_write_reg_noretry(cx, sw1&sw1_mask, SW1_INT_STATUS); + cx18_write_reg_noretry(cx, hw2&hw2_mask, HW2_INT_CLR_STATUS); if (sw1 || sw2 || hw2) CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2); diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 9d18dd22de7..87f7c8e2c18 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c @@ -176,7 +176,7 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) cx18_setup_page(cx, SCB_OFFSET); cx18_write_sync(cx, mb->request, &ack_mb->ack); - cx18_write_reg(cx, ack_irq, SW2_INT_SET); + cx18_write_reg_noretry(cx, ack_irq, SW2_INT_SET); return 0; } @@ -225,7 +225,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) } if (info->flags & API_FAST) timeout /= 2; - cx18_write_reg(cx, irq, SW1_INT_SET); + cx18_write_reg_noretry(cx, irq, SW1_INT_SET); while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request) && cnt < 660) { -- cgit v1.2.3 From 6aadf82eb830cf2622f8803fd7f0414299e246d3 Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Tue, 28 Oct 2008 08:48:27 -0300 Subject: V4L/DVB (9482): Documentation, especially regarding audio and informational links This patch adds a recommendation to select SND_USB_AUDIO for listing and adds a documentation file for si470x. Signed-off-by: Tobias Lorenz Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/Kconfig | 14 ++++++++++++++ drivers/media/radio/radio-si470x.c | 13 ------------- 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index 04cd7c04bdd..5189c4eb439 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -355,6 +355,20 @@ config USB_SI470X tristate "Silicon Labs Si470x FM Radio Receiver support" depends on USB && VIDEO_V4L2 ---help--- + This is a driver for USB devices with the Silicon Labs SI470x + chip. Currently these devices are known to work: + - 10c4:818a: Silicon Labs USB FM Radio Reference Design + - 06e1:a155: ADS/Tech FM Radio Receiver (formerly Instant FM Music) + - 1b80:d700: KWorld USB FM Radio SnapMusic Mobile 700 (FM700) + + Sound is provided by the ALSA USB Audio/MIDI driver. Therefore + if you don't want to use the device solely for RDS receiving, + it is recommended to also select SND_USB_AUDIO. + + Please have a look at the documentation, especially on how + to redirect the audio stream from the radio to your sound device: + Documentation/video4linux/si470x.txt + Say Y here if you want to connect this type of radio to your computer's USB port. diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c index a20583c13b6..3e1830293de 100644 --- a/drivers/media/radio/radio-si470x.c +++ b/drivers/media/radio/radio-si470x.c @@ -24,19 +24,6 @@ */ -/* - * User Notes: - * - USB Audio is provided by the alsa snd_usb_audio module. - * For listing you have to redirect the sound, for example using: - * arecord -D hw:1,0 -r96000 -c2 -f S16_LE | artsdsp aplay -B - - * - regarding module parameters in /sys/module/radio_si470x/parameters: - * the contents of read-only files (0444) are not updated, even if - * space, band and de are changed using private video controls - * - increase tune_timeout, if you often get -EIO errors - * - hw_freq_seek returns -EAGAIN, when timed out or band limit is reached - */ - - /* * History: * 2008-01-12 Tobias Lorenz -- cgit v1.2.3 From 6a95ec590647989089b86a6d04c5f064240cb033 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 28 Oct 2008 10:44:12 -0300 Subject: V4L/DVB (9485): ivtv: remove incorrect V4L1 & tvaudio dependency ivtv used tvaudio in the past and at the time tvaudio required V4L1. Since tvaudio is no longer dependent on V4L1 and since ivtv actually no longer uses tvaudio at all, this is no removed from Kconfig. Without this patch ivtv won't be build if V4L1 is disabled. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig index 0069898bdda..d62f2bb5cf0 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/video/ivtv/Kconfig @@ -1,6 +1,6 @@ config VIDEO_IVTV tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" - depends on VIDEO_V4L1 && VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL + depends on VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL depends on INPUT # due to VIDEO_IR select I2C_ALGOBIT select VIDEO_IR @@ -12,7 +12,6 @@ config VIDEO_IVTV select VIDEO_SAA711X select VIDEO_SAA717X select VIDEO_SAA7127 - select VIDEO_TVAUDIO select VIDEO_CS53L32A select VIDEO_M52790 select VIDEO_WM8775 -- cgit v1.2.3 From 7c34158f206dca89c717e6818d04b8db187155a3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 28 Oct 2008 10:45:46 -0300 Subject: V4L/DVB (9486): ivtv/ivtvfb: no longer experimental Remove the EXPERIMENTAL tag. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig index d62f2bb5cf0..c46bfb1569e 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/video/ivtv/Kconfig @@ -1,6 +1,6 @@ config VIDEO_IVTV tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" - depends on VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL + depends on VIDEO_V4L2 && PCI && I2C depends on INPUT # due to VIDEO_IR select I2C_ALGOBIT select VIDEO_IR @@ -31,7 +31,7 @@ config VIDEO_IVTV config VIDEO_FB_IVTV tristate "Conexant cx23415 framebuffer support" - depends on VIDEO_IVTV && FB && EXPERIMENTAL + depends on VIDEO_IVTV && FB select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT -- cgit v1.2.3 From 8268c8f54505e5b952d1705a7bf3b2a218ed26bf Mon Sep 17 00:00:00 2001 From: Daniel J Blueman Date: Mon, 2 Jun 2008 20:05:14 -0300 Subject: V4L/DVB (9492): unplug oops from dvb_frontend_init... When inadvertently hot-unplugging a WT-220U USB DVB-T receiver with 2.6.24, I was met with an oops [1]. The problem is relevant to 2.6.25/26-rc also. dvb_frontend_init() was called either from re-creation of the kdvb-fe0 thread - seems unlikely, or someone called dvb_frontend_reinitialise(), causing this path in the thread - really unlikely, as I can't find any call-site for it. Either way, quite a number of drivers call dvb_usb_generic_rw() [2] without checking the validity of the relevant member in the dvb_usb_device struct - which had changed. Having dvb_usb_generic_rw() sanity-check and fail (rather than loading from 0x120) seems reasonable defensive programming [3], in light of it being called in this way. The problem with this, is that drivers don't check the return code of the init call [4]. Does it make sense to cook a patch which allows the failure to be propagated back up, or am I missing something else? Thanks, Daniel [83711.538485] dvb-usb: bulk message failed: -71 (1/0) [83711.538875] dvb-usb: bulk message failed: -71 (1/0) [83711.538899] usb 7-5: USB disconnect, address 3 [83711.538905] dvb-usb: bulk message failed: -22 (1/0) [83711.538924] dvb-usb: bulk message failed: -22 (1/0) [83711.538943] dvb-usb: bulk message failed: -22 (1/0) [83711.588979] dvb-usb: bulk message failed: -22 (1/0) [83711.589031] dvb-usb: bulk message failed: -22 (1/0) [83711.589078] dvb-usb: bulk message failed: -22 (1/0) [83711.589122] dvb-usb: bulk message failed: -22 (1/0) [83711.589167] dvb-usb: bulk message failed: -22 (1/0) [83711.639233] dvb-usb: bulk message failed: -22 (1/0) [83711.639282] dvb-usb: bulk message failed: -22 (1/0) [83711.639330] dvb-usb: bulk message failed: -22 (1/0) [83711.639374] dvb-usb: bulk message failed: -22 (1/0) [83711.639421] dvb-usb: bulk message failed: -22 (1/0) [83711.658391] dvb-usb: bulk message failed: -22 (1/0) [83768.174281] dvb-usb: bulk message failed: -22 (2/-32512) [83768.174350] Unable to handle kernel NULL pointer dereference<6>dvb-usb: WideView WT-220U PenType Receiver (Typhoon/Freecom) successfully deinitialized and disconnected. [83768.174459] at 0000000000000120 RIP: [83768.174459] [] :dvb_usb:dvb_usb_generic_rw+0x2f/0x1a0 [83768.174580] PGD 0 [83768.174643] Oops: 0000 [1] SMP [83768.174723] CPU 0 [83768.174782] Modules linked in: nfsd auth_rpcgss exportfs nfs lockd nfs_acl sunrpc af_packet xt_length ipt_tos ipt_TOS xt_CLASSIFY sch_sfq sch_htb ipt_MASQUERADE ipt_REDIRECT xt_limit xt_state xt_tcpudp iptable_nat nf_nat nf_conntrack_ipv4 nf_conntrack iptable_mangle iptable_filter ip_tables x_tables xfs sbp2 parport_pc lp parport loop ftdi_sio usbserial evdev dvb_usb_dtt200u dvb_usb dvb_core i2c_core sky2 iTCO_wdt iTCO_vendor_support snd_hda_intel shpchp snd_pcm snd_timer snd_page_alloc snd_hwdep snd pci_hotplug soundcore ipv6 button intel_agp ext3 jbd mbcache sg sd_mod ata_generic pata_acpi ahci ata_piix libata scsi_mod ohci1394 ieee1394 ehci_hcd uhci_hcd usbcore e1000 thermal processor fan fbcon tileblit font bitblit softcursor fuse [83768.176968] Pid: 5732, comm: kdvb-fe-0 Not tainted 2.6.24-16-server #1 [83768.177009] RIP: 0010:[] [] :dvb_usb:dvb_usb_generic_rw+0x2f/0x1a0 [83768.177096] RSP: 0018:ffff810021939df0 EFLAGS: 00010286 [83768.177138] RAX: ffff81003bc7cc00 RBX: 0000000000000001 RCX: 0000000000000000 [83768.177181] RDX: 0000000000000001 RSI: ffff810021939e67 RDI: 0000000000000000 [83768.177223] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 [83768.177267] R10: ffff810001009880 R11: 0000000000000001 R12: ffff81003c10b400 [83768.177311] R13: ffff81003c10b5b0 R14: ffff810021939ec0 R15: 0000000000000000 [83768.177354] FS: 0000000000000000(0000) GS:ffffffff805c3000(0000) knlGS:0000000000000000 [83768.177409] CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b [83768.177449] CR2: 0000000000000120 CR3: 0000000000201000 CR4: 00000000000006e0 [83768.177491] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [83768.177534] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [83768.177576] Process kdvb-fe-0 (pid: 5732, threadinfo ffff810021938000, task ffff81003bd1b7a0) [83768.177629] Stack: ffff81003e9b6828 0000000000000000 ffff8100378369f8 0000000000000000 [83768.177800] ffff81003bd1b7a0 ffff810037836d48 ffff81003bc7cc30 ffff81003c10b400 [83768.177943] ffff81003c10b5b0 ffff810021939ec0 ffff81003c10b5e0 ffffffff88342452 [83768.178054] Call Trace: [83768.178130] [] :dvb_usb_dtt200u:dtt200u_fe_init+0x22/0x30 [83768.178178] [] :dvb_usb:dvb_usb_fe_wakeup+0x3a/0x50 [83768.178229] [] :dvb_core:dvb_frontend_init+0x21/0x70 [83768.178278] [] :dvb_core:dvb_frontend_thread+0x8b/0x370 [83768.178329] [] :dvb_core:dvb_frontend_thread+0x0/0x370 [83768.178382] [] kthread+0x4b/0x80 [83768.178427] [] child_rip+0xa/0x12 [83768.178473] [] kthread+0x0/0x80 [83768.178514] [] child_rip+0x0/0x12 [83768.178557] [83768.178594] [83768.178594] Code: 44 8b 87 20 01 00 00 49 89 f4 45 89 ce 45 85 c0 0f 84 ad 00 [83768.179167] RIP [] :dvb_usb:dvb_usb_generic_rw+0x2f/0x1a0 [83768.179234] RSP [83768.179271] CR2: 0000000000000120 [83768.179419] ---[ end trace dba8483163cb1700 ]--- Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dvb-usb-urb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c index 5cef12a07f7..6fe71c6745e 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c @@ -13,14 +13,14 @@ int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, { int actlen,ret = -ENOMEM; + if (!d || wbuf == NULL || wlen == 0) + return -EINVAL; + if (d->props.generic_bulk_ctrl_endpoint == 0) { err("endpoint for generic control not specified."); return -EINVAL; } - if (wbuf == NULL || wlen == 0) - return -EINVAL; - if ((ret = mutex_lock_interruptible(&d->usb_mutex))) return ret; -- cgit v1.2.3 From dec0c46ac2af9bbc4a2acd56e5bffbf02f20113e Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 29 Oct 2008 21:16:04 -0300 Subject: V4L/DVB (9494): anysee: initialize anysee_usb_mutex statically anysee_usb_mutex is initialized at every time the anysee device is probed. If the second anysee device is probed while anysee_usb_mutex is locked by the first anysee device, the mutex is broken. This patch fixes by initialize anysee_usb_mutex statically rather than initialize at probe time. Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/anysee.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index c786359fba0..cd2edbcaa09 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c @@ -46,7 +46,7 @@ module_param_named(delsys, dvb_usb_anysee_delsys, int, 0644); MODULE_PARM_DESC(delsys, "select delivery mode (0=DVB-C, 1=DVB-T)"); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -static struct mutex anysee_usb_mutex; +static DEFINE_MUTEX(anysee_usb_mutex); static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen, u8 *rbuf, u8 rlen) @@ -456,8 +456,6 @@ static int anysee_probe(struct usb_interface *intf, struct usb_host_interface *alt; int ret; - mutex_init(&anysee_usb_mutex); - /* There is one interface with two alternate settings. Alternate setting 0 is for bulk transfer. Alternate setting 1 is for isochronous transfer. -- cgit v1.2.3 From a2482377c9df89daa0cb94252bd1e8829c0e9c2f Mon Sep 17 00:00:00 2001 From: Frederic CAND Date: Thu, 30 Oct 2008 04:46:42 -0300 Subject: V4L/DVB (9495): cx88-blackbird: bugfix: cx88-blackbird-poll-fix Starts encoder not only on a read call but also on a poll command. Signed-off-by: Frederic CAND Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-blackbird.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index 078be631955..ae77450f126 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1158,6 +1158,10 @@ static unsigned int mpeg_poll(struct file *file, struct poll_table_struct *wait) { struct cx8802_fh *fh = file->private_data; + struct cx8802_dev *dev = fh->dev; + + if (!dev->mpeg_active) + blackbird_start_codec(file, fh); return videobuf_poll_stream(file, &fh->mpegq, wait); } -- cgit v1.2.3 From 9c8e0a260ed7c8935d7ee8dd51cd1971ef516385 Mon Sep 17 00:00:00 2001 From: Frederic CAND Date: Thu, 30 Oct 2008 04:50:05 -0300 Subject: V4L/DVB (9496): cx88-blackbird: bugfix: cx88-blackbird-mpeg-users Allows multiple access to the mpeg device Signed-off-by: Frederic CAND Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-blackbird.c | 8 ++++++-- drivers/media/video/cx88/cx88.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index ae77450f126..d3ae5b4dfca 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1078,7 +1078,7 @@ static int mpeg_open(struct inode *inode, struct file *file) } } - if (blackbird_initialize_codec(dev) < 0) { + if (!atomic_read(&dev->core->mpeg_users) && blackbird_initialize_codec(dev) < 0) { if (drv) drv->request_release(drv); unlock_kernel(); @@ -1109,6 +1109,8 @@ static int mpeg_open(struct inode *inode, struct file *file) fh->mpegq.field); unlock_kernel(); + atomic_inc(&dev->core->mpeg_users); + return 0; } @@ -1118,7 +1120,7 @@ static int mpeg_release(struct inode *inode, struct file *file) struct cx8802_dev *dev = fh->dev; struct cx8802_driver *drv = NULL; - if (dev->mpeg_active) + if (dev->mpeg_active && atomic_read(&dev->core->mpeg_users) == 1) blackbird_stop_codec(dev); cx8802_cancel_buffers(fh->dev); @@ -1138,6 +1140,8 @@ static int mpeg_release(struct inode *inode, struct file *file) if (drv) drv->request_release(drv); + atomic_dec(&dev->core->mpeg_users); + return 0; } diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 76207c2856b..f4240965be3 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -352,6 +352,7 @@ struct cx88_core { /* various v4l controls */ u32 freq; atomic_t users; + atomic_t mpeg_users; /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ struct cx8802_dev *dvbdev; -- cgit v1.2.3 From 1a8dc86db1546f60a25f2b5cd071c0091db87146 Mon Sep 17 00:00:00 2001 From: Darron Broad Date: Thu, 30 Oct 2008 05:05:23 -0300 Subject: V4L/DVB (9499): cx88-mpeg: final fix for analogue only compilation + de-alloc fix Final fix for when analogue only is selected for compilation (ie, !CX88_DVB) This tidies up previous fix and adds missing de-alloc memory leak on fault (eg, if fe1 fails to alloc where fe0 was allocated). Signed-off-by: Darron Broad Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-mpeg.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index a1c435b4b1c..3ebdcd1d83f 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -769,10 +769,6 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, struct cx8802_dev *dev; struct cx88_core *core; int err; -#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE) - struct videobuf_dvb_frontend *demod; - int i; -#endif /* general setup */ core = cx88_core_get(pci_dev); @@ -803,15 +799,21 @@ static int __devinit cx8802_probe(struct pci_dev *pci_dev, mutex_init(&dev->frontends.lock); INIT_LIST_HEAD(&dev->frontends.felist); - if (core->board.num_frontends) - printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, core->board.num_frontends); - - for (i = 1; i <= core->board.num_frontends; i++) { - demod = videobuf_dvb_alloc_frontend(&dev->frontends, i); - if(demod == NULL) { - printk(KERN_ERR "%s() failed to alloc\n", __func__); - err = -ENOMEM; - goto fail_free; + if (core->board.num_frontends) { + struct videobuf_dvb_frontend *fe; + int i; + + printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__, + core->board.num_frontends); + for (i = 1; i <= core->board.num_frontends; i++) { + fe = videobuf_dvb_alloc_frontend(&dev->frontends, i); + if(fe == NULL) { + printk(KERN_ERR "%s() failed to alloc\n", + __func__); + videobuf_dvb_dealloc_frontends(&dev->frontends); + err = -ENOMEM; + goto fail_free; + } } } #endif -- cgit v1.2.3 From 58ae1c23184772a7b2d02a4a82f5515a7820a155 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 3 Nov 2008 08:06:51 -0300 Subject: V4L/DVB (9506): ivtv/cx18: fix test whether modules should be loaded or not. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 4 ++-- drivers/media/video/ivtv/ivtv-driver.c | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 7a1a7830a6b..6a840f2d81a 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -581,10 +581,10 @@ static void cx18_load_and_init_modules(struct cx18 *cx) #ifdef MODULE /* load modules */ -#ifndef CONFIG_MEDIA_TUNER +#ifdef CONFIG_MEDIA_TUNER_MODULE hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER); #endif -#ifndef CONFIG_VIDEO_CS5345 +#ifdef CONFIG_VIDEO_CS5345_MODULE hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345); #endif #endif diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index d36485023b6..b69cc1d55e5 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -875,43 +875,43 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) #ifdef MODULE /* load modules */ -#ifndef CONFIG_MEDIA_TUNER +#ifdef CONFIG_MEDIA_TUNER_MODULE hw = ivtv_request_module(itv, hw, "tuner", IVTV_HW_TUNER); #endif -#ifndef CONFIG_VIDEO_CX25840 +#ifdef CONFIG_VIDEO_CX25840_MODULE hw = ivtv_request_module(itv, hw, "cx25840", IVTV_HW_CX25840); #endif -#ifndef CONFIG_VIDEO_SAA711X +#ifdef CONFIG_VIDEO_SAA711X_MODULE hw = ivtv_request_module(itv, hw, "saa7115", IVTV_HW_SAA711X); #endif -#ifndef CONFIG_VIDEO_SAA7127 +#ifdef CONFIG_VIDEO_SAA7127_MODULE hw = ivtv_request_module(itv, hw, "saa7127", IVTV_HW_SAA7127); #endif -#ifndef CONFIG_VIDEO_SAA717X +#ifdef CONFIG_VIDEO_SAA717X_MODULE hw = ivtv_request_module(itv, hw, "saa717x", IVTV_HW_SAA717X); #endif -#ifndef CONFIG_VIDEO_UPD64031A +#ifdef CONFIG_VIDEO_UPD64031A_MODULE hw = ivtv_request_module(itv, hw, "upd64031a", IVTV_HW_UPD64031A); #endif -#ifndef CONFIG_VIDEO_UPD64083 +#ifdef CONFIG_VIDEO_UPD64083_MODULE hw = ivtv_request_module(itv, hw, "upd64083", IVTV_HW_UPD6408X); #endif -#ifndef CONFIG_VIDEO_MSP3400 +#ifdef CONFIG_VIDEO_MSP3400_MODULE hw = ivtv_request_module(itv, hw, "msp3400", IVTV_HW_MSP34XX); #endif -#ifndef CONFIG_VIDEO_VP27SMPX +#ifdef CONFIG_VIDEO_VP27SMPX_MODULE hw = ivtv_request_module(itv, hw, "vp27smpx", IVTV_HW_VP27SMPX); #endif -#ifndef CONFIG_VIDEO_WM8775 +#ifdef CONFIG_VIDEO_WM8775_MODULE hw = ivtv_request_module(itv, hw, "wm8775", IVTV_HW_WM8775); #endif -#ifndef CONFIG_VIDEO_WM8739 +#ifdef CONFIG_VIDEO_WM8739_MODULE hw = ivtv_request_module(itv, hw, "wm8739", IVTV_HW_WM8739); #endif -#ifndef CONFIG_VIDEO_CS53L32A +#ifdef CONFIG_VIDEO_CS53L32A_MODULE hw = ivtv_request_module(itv, hw, "cs53l32a", IVTV_HW_CS53L32A); #endif -#ifndef CONFIG_VIDEO_M52790 +#ifdef CONFIG_VIDEO_M52790_MODULE hw = ivtv_request_module(itv, hw, "m52790", IVTV_HW_M52790); #endif #endif -- cgit v1.2.3 From f056d29eebd2c8800cf42528ba0470c77a928821 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Fri, 31 Oct 2008 20:49:12 -0300 Subject: V4L/DVB (9510): cx18: Fix write retries for registers that always change - part 2. cx18: Fix write retries for registers that always change - part 2. Some registers, especially interrupt related ones, will never read back the value just written. Modified interrupt register readback checks to make sure the intended effect was achieved. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-io.c | 17 +++++++++++++++-- drivers/media/video/cx18/cx18-io.h | 17 +++++++++++++++++ drivers/media/video/cx18/cx18-irq.c | 19 +++++++++++-------- drivers/media/video/cx18/cx18-mailbox.c | 4 ++-- 4 files changed, 45 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c index 31be5e8684d..220fae8d4ad 100644 --- a/drivers/media/video/cx18/cx18-io.c +++ b/drivers/media/video/cx18/cx18-io.c @@ -88,6 +88,19 @@ void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr) cx18_log_write_retries(cx, i, addr); } +void _cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr, + u32 eval, u32 mask) +{ + int i; + eval &= mask; + for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) { + cx18_writel_noretry(cx, val, addr); + if (eval == (cx18_readl_noretry(cx, addr) & mask)) + break; + } + cx18_log_write_retries(cx, i, addr); +} + void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr) { int i; @@ -218,7 +231,7 @@ void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count) void cx18_sw1_irq_enable(struct cx18 *cx, u32 val) { u32 r; - cx18_write_reg_noretry(cx, val, SW1_INT_STATUS); + cx18_write_reg_expect(cx, val, SW1_INT_STATUS, ~val, val); r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI); } @@ -233,7 +246,7 @@ void cx18_sw1_irq_disable(struct cx18 *cx, u32 val) void cx18_sw2_irq_enable(struct cx18 *cx, u32 val) { u32 r; - cx18_write_reg_noretry(cx, val, SW2_INT_STATUS); + cx18_write_reg_expect(cx, val, SW2_INT_STATUS, ~val, val); r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI); } diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h index 287a5e8bf67..425244453ea 100644 --- a/drivers/media/video/cx18/cx18-io.h +++ b/drivers/media/video/cx18/cx18-io.h @@ -133,6 +133,8 @@ static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr) cx18_writel_noretry(cx, val, addr); } +void _cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr, + u32 eval, u32 mask); static inline void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr) @@ -271,6 +273,21 @@ static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg) cx18_write_reg_noretry(cx, val, reg); } +static inline void _cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg, + u32 eval, u32 mask) +{ + _cx18_writel_expect(cx, val, cx->reg_mem + reg, eval, mask); +} + +static inline void cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg, + u32 eval, u32 mask) +{ + if (cx18_retry_mmio) + _cx18_write_reg_expect(cx, val, reg, eval, mask); + else + cx18_write_reg_noretry(cx, val, reg); +} + static inline u32 cx18_read_reg_noretry(struct cx18 *cx, u32 reg) { diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index 447fc9c391a..a366259bbb7 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c @@ -142,16 +142,19 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) spin_lock(&cx->dma_reg_lock); - hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI); - hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask; - sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK; - sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask; sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU; sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask; + sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK; + sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask; + hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI); + hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask; - cx18_write_reg_noretry(cx, sw2&sw2_mask, SW2_INT_STATUS); - cx18_write_reg_noretry(cx, sw1&sw1_mask, SW1_INT_STATUS); - cx18_write_reg_noretry(cx, hw2&hw2_mask, HW2_INT_CLR_STATUS); + if (sw1) + cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1); + if (sw2) + cx18_write_reg_expect(cx, sw2, SW2_INT_STATUS, ~sw2, sw2); + if (hw2) + cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2); if (sw1 || sw2 || hw2) CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2); @@ -178,5 +181,5 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) hpu_cmd(cx, sw1); spin_unlock(&cx->dma_reg_lock); - return (hw2 | sw1 | sw2) ? IRQ_HANDLED : IRQ_NONE; + return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE; } diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 87f7c8e2c18..851a905376b 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c @@ -176,7 +176,7 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) cx18_setup_page(cx, SCB_OFFSET); cx18_write_sync(cx, mb->request, &ack_mb->ack); - cx18_write_reg_noretry(cx, ack_irq, SW2_INT_SET); + cx18_write_reg_expect(cx, ack_irq, SW2_INT_SET, ack_irq, ack_irq); return 0; } @@ -225,7 +225,7 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[]) } if (info->flags & API_FAST) timeout /= 2; - cx18_write_reg_noretry(cx, irq, SW1_INT_SET); + cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq); while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request) && cnt < 660) { -- cgit v1.2.3 From 4e6b61047db2a77a250b6510bdb3c20c41aee591 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Sat, 1 Nov 2008 01:07:36 -0300 Subject: V4L/DVB (9511): cx18: Mark CX18_CPU_DE_RELEASE_MDL as a slow API call cx18: Mark CX18_CPU_DE_RELEASE_MDL as a slow API call. Give the encoder time to complete the MDL release before destroying the encoder internal task. This avoids an encoder lockup on the next digital capture and error messages about buffers being returned for an inactive encoder task handle. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-mailbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c index 851a905376b..acff7dfb60d 100644 --- a/drivers/media/video/cx18/cx18-mailbox.c +++ b/drivers/media/video/cx18/cx18-mailbox.c @@ -83,7 +83,7 @@ static const struct cx18_api_info api_info[] = { API_ENTRY(CPU, CX18_CPU_DE_SET_MDL_ACK, 0), API_ENTRY(CPU, CX18_CPU_DE_SET_MDL, API_FAST), API_ENTRY(CPU, CX18_APU_RESETAI, API_FAST), - API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, 0), + API_ENTRY(CPU, CX18_CPU_DE_RELEASE_MDL, API_SLOW), API_ENTRY(0, 0, 0), }; -- cgit v1.2.3 From 891bd1331eb378f4a474d2377451a97bb306a451 Mon Sep 17 00:00:00 2001 From: roel kluin Date: Tue, 4 Nov 2008 11:32:59 -0300 Subject: V4L/DVB (9524): af9013: fix bug in status reading - ! has a higher precedence than & Signed-off-by: Roel Kluin Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/af9013.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c index 21c1060cf10..692b68a9e73 100644 --- a/drivers/media/dvb/frontends/af9013.c +++ b/drivers/media/dvb/frontends/af9013.c @@ -1187,7 +1187,7 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status) if (tmp) *status |= FE_HAS_SYNC | FE_HAS_LOCK; - if (!*status & FE_HAS_SIGNAL) { + if (!(*status & FE_HAS_SIGNAL)) { /* AGC lock */ ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp); if (ret) @@ -1196,7 +1196,7 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status) *status |= FE_HAS_SIGNAL; } - if (!*status & FE_HAS_CARRIER) { + if (!(*status & FE_HAS_CARRIER)) { /* CFO lock */ ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp); if (ret) @@ -1205,7 +1205,7 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status) *status |= FE_HAS_CARRIER; } - if (!*status & FE_HAS_CARRIER) { + if (!(*status & FE_HAS_CARRIER)) { /* SFOE lock */ ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp); if (ret) -- cgit v1.2.3 From 349d042f34cc2a663f22cae2390b240934e61014 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Wed, 5 Nov 2008 16:31:24 -0300 Subject: V4L/DVB (9527): af9015: fix compile warnings - use static to avoid compile warnings Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 14 +++++++------- drivers/media/dvb/dvb-usb/af9015.h | 1 - 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index cb0829c038c..847d8fdd9ec 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -31,13 +31,13 @@ #include "mc44s80x.h" #endif -int dvb_usb_af9015_debug; +static int dvb_usb_af9015_debug; module_param_named(debug, dvb_usb_af9015_debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); -int dvb_usb_af9015_remote; +static int dvb_usb_af9015_remote; module_param_named(remote, dvb_usb_af9015_remote, int, 0644); MODULE_PARM_DESC(remote, "select remote"); -int dvb_usb_af9015_dual_mode; +static int dvb_usb_af9015_dual_mode; module_param_named(dual_mode, dvb_usb_af9015_dual_mode, int, 0644); MODULE_PARM_DESC(dual_mode, "enable dual mode"); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -46,7 +46,7 @@ static DEFINE_MUTEX(af9015_usb_mutex); static struct af9015_config af9015_config; static struct dvb_usb_device_properties af9015_properties[2]; -int af9015_properties_count = ARRAY_SIZE(af9015_properties); +static int af9015_properties_count = ARRAY_SIZE(af9015_properties); static struct af9013_config af9015_af9013_config[] = { { @@ -549,7 +549,7 @@ static int af9015_eeprom_dump(struct dvb_usb_device *d) return 0; } -int af9015_download_ir_table(struct dvb_usb_device *d) +static int af9015_download_ir_table(struct dvb_usb_device *d) { int i, packets = 0, ret; u16 addr = 0x9a56; /* ir-table start address */ @@ -999,7 +999,7 @@ static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state) } /* init 2nd I2C adapter */ -int af9015_i2c_init(struct dvb_usb_device *d) +static int af9015_i2c_init(struct dvb_usb_device *d) { int ret; struct af9015_state *state = d->priv; @@ -1419,7 +1419,7 @@ static int af9015_usb_probe(struct usb_interface *intf, return ret; } -void af9015_i2c_exit(struct dvb_usb_device *d) +static void af9015_i2c_exit(struct dvb_usb_device *d) { struct af9015_state *state = d->priv; deb_info("%s: \n", __func__); diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h index 882e8a4b368..6c3c9729331 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/dvb/dvb-usb/af9015.h @@ -27,7 +27,6 @@ #define DVB_USB_LOG_PREFIX "af9015" #include "dvb-usb.h" -extern int dvb_usb_af9015_debug; #define deb_info(args...) dprintk(dvb_usb_af9015_debug, 0x01, args) #define deb_rc(args...) dprintk(dvb_usb_af9015_debug, 0x02, args) #define deb_xfer(args...) dprintk(dvb_usb_af9015_debug, 0x04, args) -- cgit v1.2.3 From 17ff61cb200e8ec0c8e456fbd426c1af63a6e28a Mon Sep 17 00:00:00 2001 From: Frederic CAND Date: Wed, 29 Oct 2008 14:37:49 -0300 Subject: V4L/DVB (9493): kconfig patch Ok I made a patch that converts gspca kconfig file to a more standard= one, with tabs + 2 white spaces, so that if a warning is added it still compiles please find it attached Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/Kconfig | 142 +++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 4d0817471c9..96a16db3d7a 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -3,16 +3,16 @@ menuconfig USB_GSPCA depends on VIDEO_V4L2 default m ---help--- - Say Y here if you want to enable selecting webcams based - on the GSPCA framework. + Say Y here if you want to enable selecting webcams based + on the GSPCA framework. - See for more info. + See for more info. - This driver uses the Video For Linux API. You must say Y or M to - "Video For Linux" to use this driver. + This driver uses the Video For Linux API. You must say Y or M to + "Video For Linux" to use this driver. - To compile this driver as modules, choose M here: the - modules will be called gspca_main. + To compile this driver as modules, choose M here: the + modules will be called gspca_main. if USB_GSPCA && VIDEO_V4L2 @@ -23,190 +23,190 @@ config USB_GSPCA_CONEX tristate "Conexant Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the Conexant chip. + Say Y here if you want support for cameras based on the Conexant chip. - To compile this driver as a module, choose M here: the - module will be called gspca_conex. + To compile this driver as a module, choose M here: the + module will be called gspca_conex. config USB_GSPCA_ETOMS tristate "Etoms USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the Etoms chip. + Say Y here if you want support for cameras based on the Etoms chip. - To compile this driver as a module, choose M here: the - module will be called gspca_etoms. + To compile this driver as a module, choose M here: the + module will be called gspca_etoms. config USB_GSPCA_FINEPIX tristate "Fujifilm FinePix USB V4L2 driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the FinePix chip. + Say Y here if you want support for cameras based on the FinePix chip. - To compile this driver as a module, choose M here: the - module will be called gspca_finepix. + To compile this driver as a module, choose M here: the + module will be called gspca_finepix. config USB_GSPCA_MARS tristate "Mars USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the Mars chip. + Say Y here if you want support for cameras based on the Mars chip. - To compile this driver as a module, choose M here: the - module will be called gspca_mars. + To compile this driver as a module, choose M here: the + module will be called gspca_mars. config USB_GSPCA_OV519 tristate "OV519 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the OV519 chip. + Say Y here if you want support for cameras based on the OV519 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_ov519. + To compile this driver as a module, choose M here: the + module will be called gspca_ov519. config USB_GSPCA_PAC207 tristate "Pixart PAC207 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the PAC207 chip. + Say Y here if you want support for cameras based on the PAC207 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_pac207. + To compile this driver as a module, choose M here: the + module will be called gspca_pac207. config USB_GSPCA_PAC7311 tristate "Pixart PAC7311 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the PAC7311 chip. + Say Y here if you want support for cameras based on the PAC7311 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_pac7311. + To compile this driver as a module, choose M here: the + module will be called gspca_pac7311. config USB_GSPCA_SONIXB tristate "SN9C102 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SONIXB chip. + Say Y here if you want support for cameras based on the SONIXB chip. - To compile this driver as a module, choose M here: the - module will be called gspca_sonixb. + To compile this driver as a module, choose M here: the + module will be called gspca_sonixb. config USB_GSPCA_SONIXJ tristate "SONIX JPEG USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SONIXJ chip. + Say Y here if you want support for cameras based on the SONIXJ chip. - To compile this driver as a module, choose M here: the - module will be called gspca_sonixj + To compile this driver as a module, choose M here: the + module will be called gspca_sonixj config USB_GSPCA_SPCA500 tristate "SPCA500 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SPCA500 chip. + Say Y here if you want support for cameras based on the SPCA500 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_spca500. + To compile this driver as a module, choose M here: the + module will be called gspca_spca500. config USB_GSPCA_SPCA501 tristate "SPCA501 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SPCA501 chip. + Say Y here if you want support for cameras based on the SPCA501 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_spca501. + To compile this driver as a module, choose M here: the + module will be called gspca_spca501. config USB_GSPCA_SPCA505 tristate "SPCA505 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SPCA505 chip. + Say Y here if you want support for cameras based on the SPCA505 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_spca505. + To compile this driver as a module, choose M here: the + module will be called gspca_spca505. config USB_GSPCA_SPCA506 tristate "SPCA506 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SPCA506 chip. + Say Y here if you want support for cameras based on the SPCA506 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_spca506. + To compile this driver as a module, choose M here: the + module will be called gspca_spca506. config USB_GSPCA_SPCA508 tristate "SPCA508 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SPCA508 chip. + Say Y here if you want support for cameras based on the SPCA508 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_spca508. + To compile this driver as a module, choose M here: the + module will be called gspca_spca508. config USB_GSPCA_SPCA561 tristate "SPCA561 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the SPCA561 chip. + Say Y here if you want support for cameras based on the SPCA561 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_spca561. + To compile this driver as a module, choose M here: the + module will be called gspca_spca561. config USB_GSPCA_STK014 tristate "Syntek DV4000 (STK014) USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the STK014 chip. + Say Y here if you want support for cameras based on the STK014 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_stk014. + To compile this driver as a module, choose M here: the + module will be called gspca_stk014. config USB_GSPCA_SUNPLUS tristate "SUNPLUS USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the Sunplus - SPCA504(abc) SPCA533 SPCA536 chips. + Say Y here if you want support for cameras based on the Sunplus + SPCA504(abc) SPCA533 SPCA536 chips. - To compile this driver as a module, choose M here: the - module will be called gspca_spca5xx. + To compile this driver as a module, choose M here: the + module will be called gspca_spca5xx. config USB_GSPCA_T613 tristate "T613 (JPEG Compliance) USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the T613 chip. + Say Y here if you want support for cameras based on the T613 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_t613. + To compile this driver as a module, choose M here: the + module will be called gspca_t613. config USB_GSPCA_TV8532 tristate "TV8532 USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the TV8531 chip. + Say Y here if you want support for cameras based on the TV8531 chip. - To compile this driver as a module, choose M here: the - module will be called gspca_tv8532. + To compile this driver as a module, choose M here: the + module will be called gspca_tv8532. config USB_GSPCA_VC032X tristate "VC032X USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the VC032X chip. + Say Y here if you want support for cameras based on the VC032X chip. - To compile this driver as a module, choose M here: the - module will be called gspca_vc032x. + To compile this driver as a module, choose M here: the + module will be called gspca_vc032x. config USB_GSPCA_ZC3XX tristate "VC3xx USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help - Say Y here if you want support for cameras based on the ZC3XX chip. + Say Y here if you want support for cameras based on the ZC3XX chip. - To compile this driver as a module, choose M here: the - module will be called gspca_zc3xx. + To compile this driver as a module, choose M here: the + module will be called gspca_zc3xx. endif -- cgit v1.2.3 From 465f8a805d3796fac2b2fb0c630217f6f76e667c Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Tue, 4 Nov 2008 22:02:23 -0300 Subject: V4L/DVB (9515): cx18: Use correct Mailbox IRQ Ack values and misc IRQ handling cleanup cx18: Use correct Mailbox IRQ Ack values and misc IRQ handling cleanup. The SCB field definitions for Ack IRQ's for mailboxes were inconsistent with the bitmasks being loaded into those SCB fields and the SW2 Ack IRQ handling logic. Renamed fields in SCB to make things consistent and did misc IRQ handling cleanups: removing legacy ivtv dma_reg_lock, HPU IRQ flags, etc. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 1 - drivers/media/video/cx18/cx18-driver.h | 2 -- drivers/media/video/cx18/cx18-irq.c | 54 ++++++++++++++++++---------------- drivers/media/video/cx18/cx18-scb.h | 40 ++++++++++++------------- 4 files changed, 49 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 6a840f2d81a..2befa3819cd 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -448,7 +448,6 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) mutex_init(&cx->gpio_lock); spin_lock_init(&cx->lock); - spin_lock_init(&cx->dma_reg_lock); /* start counting open_id at 1 */ cx->open_id = 1; diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index a4b1708fafe..e721c01d217 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -402,8 +402,6 @@ struct cx18 { spinlock_t lock; /* lock access to this struct */ int search_pack_header; - spinlock_t dma_reg_lock; /* lock access to DMA engine registers */ - int open_id; /* incremented each time an open occurs, used as unique ID. Starts at 1, so 0 can be used as uninitialized value in the stream->id. */ diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index a366259bbb7..c306e142c1c 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c @@ -30,8 +30,6 @@ #include "cx18-vbi.h" #include "cx18-scb.h" -#define DMA_MAGIC_COOKIE 0x000001fe - static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) { u32 handle = mb->args[0]; @@ -109,7 +107,7 @@ static void epu_debug(struct cx18 *cx, struct cx18_mailbox *mb) CX18_INFO("FW version: %s\n", p - 1); } -static void hpu_cmd(struct cx18 *cx, u32 sw1) +static void epu_cmd(struct cx18 *cx, u32 sw1) { struct cx18_mailbox mb; @@ -125,12 +123,31 @@ static void hpu_cmd(struct cx18 *cx, u32 sw1) epu_debug(cx, &mb); break; default: - CX18_WARN("Unexpected mailbox command %08x\n", mb.cmd); + CX18_WARN("Unknown CPU_TO_EPU mailbox command %#08x\n", + mb.cmd); break; } } - if (sw1 & (IRQ_APU_TO_EPU | IRQ_HPU_TO_EPU)) - CX18_WARN("Unexpected interrupt %08x\n", sw1); + + if (sw1 & IRQ_APU_TO_EPU) { + cx18_memcpy_fromio(cx, &mb, &cx->scb->apu2epu_mb, sizeof(mb)); + CX18_WARN("Unknown APU_TO_EPU mailbox command %#08x\n", mb.cmd); + } + + if (sw1 & IRQ_HPU_TO_EPU) { + cx18_memcpy_fromio(cx, &mb, &cx->scb->hpu2epu_mb, sizeof(mb)); + CX18_WARN("Unknown HPU_TO_EPU mailbox command %#08x\n", mb.cmd); + } +} + +static void xpu_ack(struct cx18 *cx, u32 sw2) +{ + if (sw2 & IRQ_CPU_TO_EPU_ACK) + wake_up(&cx->mb_cpu_waitq); + if (sw2 & IRQ_APU_TO_EPU_ACK) + wake_up(&cx->mb_apu_waitq); + if (sw2 & IRQ_HPU_TO_EPU_ACK) + wake_up(&cx->mb_hpu_waitq); } irqreturn_t cx18_irq_handler(int irq, void *dev_id) @@ -140,11 +157,9 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) u32 sw2, sw2_mask; u32 hw2, hw2_mask; - spin_lock(&cx->dma_reg_lock); - - sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU; + sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI); sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask; - sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | IRQ_EPU_TO_HPU_ACK; + sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI); sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask; hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI); hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask; @@ -160,26 +175,15 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) CX18_DEBUG_HI_IRQ("SW1: %x SW2: %x HW2: %x\n", sw1, sw2, hw2); /* To do: interrupt-based I2C handling - if (hw2 & 0x00c00000) { + if (hw2 & (HW2_I2C1_INT|HW2_I2C2_INT)) { } */ - if (sw2) { - if (sw2 & (cx18_readl(cx, &cx->scb->cpu2hpu_irq_ack) | - cx18_readl(cx, &cx->scb->cpu2epu_irq_ack))) - wake_up(&cx->mb_cpu_waitq); - if (sw2 & (cx18_readl(cx, &cx->scb->apu2hpu_irq_ack) | - cx18_readl(cx, &cx->scb->apu2epu_irq_ack))) - wake_up(&cx->mb_apu_waitq); - if (sw2 & cx18_readl(cx, &cx->scb->epu2hpu_irq_ack)) - wake_up(&cx->mb_epu_waitq); - if (sw2 & cx18_readl(cx, &cx->scb->hpu2epu_irq_ack)) - wake_up(&cx->mb_hpu_waitq); - } + if (sw2) + xpu_ack(cx, sw2); if (sw1) - hpu_cmd(cx, sw1); - spin_unlock(&cx->dma_reg_lock); + epu_cmd(cx, sw1); return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE; } diff --git a/drivers/media/video/cx18/cx18-scb.h b/drivers/media/video/cx18/cx18-scb.h index 86b4cb15d16..594713bbed6 100644 --- a/drivers/media/video/cx18/cx18-scb.h +++ b/drivers/media/video/cx18/cx18-scb.h @@ -128,22 +128,22 @@ struct cx18_scb { u32 apu2cpu_irq; /* Value to write to register SW2 register set (0xC7003140) after the command is cleared */ - u32 apu2cpu_irq_ack; + u32 cpu2apu_irq_ack; u32 reserved2[13]; u32 hpu2cpu_mb_offset; u32 hpu2cpu_irq; - u32 hpu2cpu_irq_ack; + u32 cpu2hpu_irq_ack; u32 reserved3[13]; u32 ppu2cpu_mb_offset; u32 ppu2cpu_irq; - u32 ppu2cpu_irq_ack; + u32 cpu2ppu_irq_ack; u32 reserved4[13]; u32 epu2cpu_mb_offset; u32 epu2cpu_irq; - u32 epu2cpu_irq_ack; + u32 cpu2epu_irq_ack; u32 reserved5[13]; u32 reserved6[8]; @@ -153,22 +153,22 @@ struct cx18_scb { u32 reserved11[7]; u32 cpu2apu_mb_offset; u32 cpu2apu_irq; - u32 cpu2apu_irq_ack; + u32 apu2cpu_irq_ack; u32 reserved12[13]; u32 hpu2apu_mb_offset; u32 hpu2apu_irq; - u32 hpu2apu_irq_ack; + u32 apu2hpu_irq_ack; u32 reserved13[13]; u32 ppu2apu_mb_offset; u32 ppu2apu_irq; - u32 ppu2apu_irq_ack; + u32 apu2ppu_irq_ack; u32 reserved14[13]; u32 epu2apu_mb_offset; u32 epu2apu_irq; - u32 epu2apu_irq_ack; + u32 apu2epu_irq_ack; u32 reserved15[13]; u32 reserved16[8]; @@ -178,22 +178,22 @@ struct cx18_scb { u32 reserved21[7]; u32 cpu2hpu_mb_offset; u32 cpu2hpu_irq; - u32 cpu2hpu_irq_ack; + u32 hpu2cpu_irq_ack; u32 reserved22[13]; u32 apu2hpu_mb_offset; u32 apu2hpu_irq; - u32 apu2hpu_irq_ack; + u32 hpu2apu_irq_ack; u32 reserved23[13]; u32 ppu2hpu_mb_offset; u32 ppu2hpu_irq; - u32 ppu2hpu_irq_ack; + u32 hpu2ppu_irq_ack; u32 reserved24[13]; u32 epu2hpu_mb_offset; u32 epu2hpu_irq; - u32 epu2hpu_irq_ack; + u32 hpu2epu_irq_ack; u32 reserved25[13]; u32 reserved26[8]; @@ -203,22 +203,22 @@ struct cx18_scb { u32 reserved31[7]; u32 cpu2ppu_mb_offset; u32 cpu2ppu_irq; - u32 cpu2ppu_irq_ack; + u32 ppu2cpu_irq_ack; u32 reserved32[13]; u32 apu2ppu_mb_offset; u32 apu2ppu_irq; - u32 apu2ppu_irq_ack; + u32 ppu2apu_irq_ack; u32 reserved33[13]; u32 hpu2ppu_mb_offset; u32 hpu2ppu_irq; - u32 hpu2ppu_irq_ack; + u32 ppu2hpu_irq_ack; u32 reserved34[13]; u32 epu2ppu_mb_offset; u32 epu2ppu_irq; - u32 epu2ppu_irq_ack; + u32 ppu2epu_irq_ack; u32 reserved35[13]; u32 reserved36[8]; @@ -228,22 +228,22 @@ struct cx18_scb { u32 reserved41[7]; u32 cpu2epu_mb_offset; u32 cpu2epu_irq; - u32 cpu2epu_irq_ack; + u32 epu2cpu_irq_ack; u32 reserved42[13]; u32 apu2epu_mb_offset; u32 apu2epu_irq; - u32 apu2epu_irq_ack; + u32 epu2apu_irq_ack; u32 reserved43[13]; u32 hpu2epu_mb_offset; u32 hpu2epu_irq; - u32 hpu2epu_irq_ack; + u32 epu2hpu_irq_ack; u32 reserved44[13]; u32 ppu2epu_mb_offset; u32 ppu2epu_irq; - u32 ppu2epu_irq_ack; + u32 epu2ppu_irq_ack; u32 reserved45[13]; u32 reserved46[8]; -- cgit v1.2.3 From 93d0f0385adafc331d070a4e874c8ae686e6179a Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Sat, 25 Oct 2008 05:06:58 -0300 Subject: V4L/DVB (9549): gspca: Fix a typo in one of gspca chips name. Signed-off-by: Krzysztof Helt Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 96a16db3d7a..6b557c057fa 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig @@ -201,7 +201,7 @@ config USB_GSPCA_VC032X module will be called gspca_vc032x. config USB_GSPCA_ZC3XX - tristate "VC3xx USB Camera Driver" + tristate "ZC3XX USB Camera Driver" depends on VIDEO_V4L2 && USB_GSPCA help Say Y here if you want support for cameras based on the ZC3XX chip. -- cgit v1.2.3 From 03bf75654cd31610ddd1ea66fab311b5b24700f0 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 6 Nov 2008 14:47:13 -0300 Subject: V4L/DVB (9556): gspca: Bad init sequence for sensor HV7131B in zc3xx. This patch fixes the H flip and the R & B color inversion of mode 320x240. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index d0a4451dc46..3e594462b16 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -2266,7 +2266,7 @@ static const struct usb_action hdcs2020b_NoFliker[] = { {} }; -static const struct usb_action hv7131bxx_Initial[] = { +static const struct usb_action hv7131bxx_Initial[] = { /* 320x240 */ {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, @@ -2309,7 +2309,7 @@ static const struct usb_action hv7131bxx_Initial[] = { {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xaa, 0x02, 0x0080}, /* {0xaa, 0x02, 0x0090}; */ + {0xaa, 0x02, 0x0090}, /* {0xaa, 0x02, 0x0080}; */ {0xa1, 0x01, 0x0002}, {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT}, {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND}, @@ -2374,7 +2374,7 @@ static const struct usb_action hv7131bxx_Initial[] = { {} }; -static const struct usb_action hv7131bxx_InitialScale[] = { +static const struct usb_action hv7131bxx_InitialScale[] = { /* 640x480*/ {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT}, -- cgit v1.2.3 From c9ff1b689a5d605640f098afc37d6102ecef9876 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Thu, 6 Nov 2008 15:29:47 -0300 Subject: V4L/DVB (9557): gspca: Small changes for the sensor HV7131B in zc3xx. - touch only one register for brightness change - no quality control - don't probe again at streamon time. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/zc3xx.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 3e594462b16..8b3101d347c 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -2290,7 +2290,7 @@ static const struct usb_action hv7131bxx_Initial[] = { /* 320x240 */ {0xaa, 0x14, 0x0001}, {0xaa, 0x15, 0x00e8}, {0xaa, 0x16, 0x0002}, - {0xaa, 0x17, 0x0086}, + {0xaa, 0x17, 0x0086}, /* 00,17,88,aa */ {0xaa, 0x31, 0x0038}, {0xaa, 0x32, 0x0038}, {0xaa, 0x33, 0x0038}, @@ -2309,7 +2309,7 @@ static const struct usb_action hv7131bxx_Initial[] = { /* 320x240 */ {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, - {0xaa, 0x02, 0x0090}, /* {0xaa, 0x02, 0x0080}; */ + {0xaa, 0x02, 0x0090}, /* 00,02,80,aa */ {0xa1, 0x01, 0x0002}, {0xa0, 0x00, ZC3XX_R092_I2CADDRESSSELECT}, {0xa0, 0x02, ZC3XX_R090_I2CCOMMAND}, @@ -6388,6 +6388,8 @@ static void setbrightness(struct gspca_dev *gspca_dev) /*fixme: is it really write to 011d and 018d for all other sensors? */ brightness = sd->brightness; reg_w(gspca_dev->dev, brightness, 0x011d); + if (sd->sensor == SENSOR_HV7131B) + return; if (brightness < 0x70) brightness += 0x10; else @@ -6529,6 +6531,7 @@ static void setquality(struct gspca_dev *gspca_dev) switch (sd->sensor) { case SENSOR_GC0305: + case SENSOR_HV7131B: case SENSOR_OV7620: case SENSOR_PO2030: return; @@ -7209,7 +7212,6 @@ static int sd_start(struct gspca_dev *gspca_dev) mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv; zc3_init = init_tb[(int) sd->sensor][mode]; switch (sd->sensor) { - case SENSOR_HV7131B: case SENSOR_HV7131C: zcxx_probeSensor(gspca_dev); break; -- cgit v1.2.3 From 1d6782bda5c1fb2bca44af50647b45427d8ef4ec Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Wed, 5 Nov 2008 00:49:14 -0300 Subject: V4L/DVB (9516): cx18: Move DVB buffer transfer handling from irq handler to work_queue cx18: Move DVB buffer transfer handling from irq handler to work_queue thread. In order to properly lock the epu2cpu mailbox for driver to CX23418 commands, the DVB/TS buffer handling needs to be moved from the IRQ handler and IRQ context to a work queue. This work_queue implmentation is strikingly similar to the ivtv implementation - for better or worse. Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 12 ++++++++++++ drivers/media/video/cx18/cx18-driver.h | 18 ++++++++++++------ drivers/media/video/cx18/cx18-dvb.c | 23 +++++++++++++++++++++++ drivers/media/video/cx18/cx18-dvb.h | 1 + drivers/media/video/cx18/cx18-irq.c | 29 ++++++++++++++++++++--------- drivers/media/video/cx18/cx18-irq.h | 4 +--- drivers/media/video/cx18/cx18-queue.c | 14 ++++++-------- 7 files changed, 75 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 2befa3819cd..7874d9790a5 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -449,6 +449,14 @@ static int __devinit cx18_init_struct1(struct cx18 *cx) spin_lock_init(&cx->lock); + cx->work_queue = create_singlethread_workqueue(cx->name); + if (cx->work_queue == NULL) { + CX18_ERR("Could not create work queue\n"); + return -1; + } + + INIT_WORK(&cx->work, cx18_work_handler); + /* start counting open_id at 1 */ cx->open_id = 1; @@ -831,6 +839,7 @@ free_map: free_mem: release_mem_region(cx->base_addr, CX18_MEM_SIZE); free_workqueue: + destroy_workqueue(cx->work_queue); err: if (retval == 0) retval = -ENODEV; @@ -931,6 +940,9 @@ static void cx18_remove(struct pci_dev *pci_dev) cx18_halt_firmware(cx); + flush_workqueue(cx->work_queue); + destroy_workqueue(cx->work_queue); + cx18_streams_cleanup(cx, 1); exit_cx18_i2c(cx); diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index e721c01d217..bbdd5f25041 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -199,12 +199,15 @@ struct cx18_options { #define CX18_F_S_APPL_IO 8 /* this stream is used read/written by an application */ /* per-cx18, i_flags */ -#define CX18_F_I_LOADED_FW 0 /* Loaded the firmware the first time */ -#define CX18_F_I_EOS 4 /* End of encoder stream reached */ -#define CX18_F_I_RADIO_USER 5 /* The radio tuner is selected */ -#define CX18_F_I_ENC_PAUSED 13 /* the encoder is paused */ -#define CX18_F_I_INITED 21 /* set after first open */ -#define CX18_F_I_FAILED 22 /* set if first open failed */ +#define CX18_F_I_LOADED_FW 0 /* Loaded firmware 1st time */ +#define CX18_F_I_EOS 4 /* End of encoder stream */ +#define CX18_F_I_RADIO_USER 5 /* radio tuner is selected */ +#define CX18_F_I_ENC_PAUSED 13 /* the encoder is paused */ +#define CX18_F_I_HAVE_WORK 15 /* there is work to be done */ +#define CX18_F_I_WORK_HANDLER_DVB 18 /* work to be done for DVB */ +#define CX18_F_I_INITED 21 /* set after first open */ +#define CX18_F_I_FAILED 22 /* set if first open failed */ +#define CX18_F_I_WORK_INITED 23 /* worker thread initialized */ /* These are the VBI types as they appear in the embedded VBI private packets. */ #define CX18_SLICED_TYPE_TELETEXT_B (1) @@ -431,6 +434,9 @@ struct cx18 { /* when the current DMA is finished this queue is woken up */ wait_queue_head_t dma_waitq; + struct workqueue_struct *work_queue; + struct work_struct work; + /* i2c */ struct i2c_adapter i2c_adap[2]; struct i2c_algo_bit_data i2c_algo[2]; diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index afc694e7bdb..4542e2e5e3d 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -23,6 +23,8 @@ #include "cx18-dvb.h" #include "cx18-io.h" #include "cx18-streams.h" +#include "cx18-queue.h" +#include "cx18-scb.h" #include "cx18-cards.h" #include "s5h1409.h" #include "mxl5005s.h" @@ -300,3 +302,24 @@ static int dvb_register(struct cx18_stream *stream) return ret; } + +void cx18_dvb_work_handler(struct cx18 *cx) +{ + struct cx18_buffer *buf; + struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_TS]; + + while ((buf = cx18_dequeue(s, &s->q_full)) != NULL) { + if (s->dvb.enabled) + dvb_dmx_swfilter(&s->dvb.demux, buf->buf, + buf->bytesused); + + cx18_enqueue(s, buf, &s->q_free); + cx18_buf_sync_for_device(s, buf); + if (s->handle == CX18_INVALID_TASK_HANDLE) /* FIXME: improve */ + continue; + + cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, + (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, + 1, buf->id, s->buf_size); + } +} diff --git a/drivers/media/video/cx18/cx18-dvb.h b/drivers/media/video/cx18/cx18-dvb.h index bf8d8f6f545..bbdcefc87f2 100644 --- a/drivers/media/video/cx18/cx18-dvb.h +++ b/drivers/media/video/cx18/cx18-dvb.h @@ -23,3 +23,4 @@ int cx18_dvb_register(struct cx18_stream *stream); void cx18_dvb_unregister(struct cx18_stream *stream); +void cx18_dvb_work_handler(struct cx18 *cx); diff --git a/drivers/media/video/cx18/cx18-irq.c b/drivers/media/video/cx18/cx18-irq.c index c306e142c1c..5fbfbd0f149 100644 --- a/drivers/media/video/cx18/cx18-irq.c +++ b/drivers/media/video/cx18/cx18-irq.c @@ -29,6 +29,20 @@ #include "cx18-mailbox.h" #include "cx18-vbi.h" #include "cx18-scb.h" +#include "cx18-dvb.h" + +void cx18_work_handler(struct work_struct *work) +{ + struct cx18 *cx = container_of(work, struct cx18, work); + if (test_and_clear_bit(CX18_F_I_WORK_INITED, &cx->i_flags)) { + struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; + /* This thread must use the FIFO scheduler as it + * is realtime sensitive. */ + sched_setscheduler(current, SCHED_FIFO, ¶m); + } + if (test_and_clear_bit(CX18_F_I_WORK_HANDLER_DVB, &cx->i_flags)) + cx18_dvb_work_handler(cx); +} static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) { @@ -65,17 +79,11 @@ static void epu_dma_done(struct cx18 *cx, struct cx18_mailbox *mb) if (buf) { cx18_buf_sync_for_cpu(s, buf); if (s->type == CX18_ENC_STREAM_TYPE_TS && s->dvb.enabled) { - /* process the buffer here */ - CX18_DEBUG_HI_DMA("TS recv and sent bytesused=%d\n", + CX18_DEBUG_HI_DMA("TS recv bytesused = %d\n", buf->bytesused); - dvb_dmx_swfilter(&s->dvb.demux, buf->buf, - buf->bytesused); - - cx18_buf_sync_for_device(s, buf); - cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle, - (void __iomem *)&cx->scb->cpu_mdl[buf->id] - cx->enc_mem, - 1, buf->id, s->buf_size); + set_bit(CX18_F_I_WORK_HANDLER_DVB, &cx->i_flags); + set_bit(CX18_F_I_HAVE_WORK, &cx->i_flags); } else set_bit(CX18_F_B_NEED_BUF_SWAP, &buf->b_flags); } else { @@ -185,5 +193,8 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id) if (sw1) epu_cmd(cx, sw1); + if (test_and_clear_bit(CX18_F_I_HAVE_WORK, &cx->i_flags)) + queue_work(cx->work_queue, &cx->work); + return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE; } diff --git a/drivers/media/video/cx18/cx18-irq.h b/drivers/media/video/cx18/cx18-irq.h index 379f704f5cb..6173ca3bc9e 100644 --- a/drivers/media/video/cx18/cx18-irq.h +++ b/drivers/media/video/cx18/cx18-irq.h @@ -32,6 +32,4 @@ irqreturn_t cx18_irq_handler(int irq, void *dev_id); -void cx18_irq_work_handler(struct work_struct *work); -void cx18_dma_stream_dec_prepare(struct cx18_stream *s, u32 offset, int lock); -void cx18_unfinished_dma(unsigned long arg); +void cx18_work_handler(struct work_struct *work); diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index a33ba04a268..174682c2582 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -88,15 +88,13 @@ struct cx18_buffer *cx18_queue_get_buf_irq(struct cx18_stream *s, u32 id, if (buf->id != id) continue; + buf->bytesused = bytesused; - /* the transport buffers are handled differently, - they are not moved to the full queue */ - if (s->type != CX18_ENC_STREAM_TYPE_TS) { - atomic_dec(&s->q_free.buffers); - atomic_inc(&s->q_full.buffers); - s->q_full.bytesused += buf->bytesused; - list_move_tail(&buf->list, &s->q_full.list); - } + atomic_dec(&s->q_free.buffers); + atomic_inc(&s->q_full.buffers); + s->q_full.bytesused += buf->bytesused; + list_move_tail(&buf->list, &s->q_full.list); + spin_unlock(&s->qlock); return buf; } -- cgit v1.2.3 From 1ec26db1f8cae0aca64708e0fe1f687eab7c82e5 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 11 Nov 2008 21:45:57 +0800 Subject: pxafb: introduce LCD_TYPE_MASK and use it. Signed-off-by: Daniel Mack Signed-off-by: Eric Miao --- drivers/video/pxafb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 97204497d9f..64990592dc5 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -1372,7 +1372,7 @@ static void pxafb_decode_mach_info(struct pxafb_info *fbi, fbi->cmap_inverse = inf->cmap_inverse; fbi->cmap_static = inf->cmap_static; - switch (lcd_conn & 0xf) { + switch (lcd_conn & LCD_TYPE_MASK) { case LCD_TYPE_MONO_STN: fbi->lccr0 = LCCR0_CMS; break; -- cgit v1.2.3 From 6cc4abe43e9362034881ad8c005f4ab8a684ae3e Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 11 Nov 2008 21:47:07 +0800 Subject: pxafb: only initialize the smart panel thread when dealing with a smartpanel Signed-off-by: Daniel Mack Signed-off-by: Eric Miao --- drivers/video/pxafb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 64990592dc5..cc59c52e110 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -804,6 +804,9 @@ static int pxafb_smart_thread(void *arg) static int pxafb_smart_init(struct pxafb_info *fbi) { + if (!(fbi->lccr0 | LCCR0_LCDT)) + return 0; + fbi->smart_thread = kthread_run(pxafb_smart_thread, fbi, "lcd_refresh"); if (IS_ERR(fbi->smart_thread)) { -- cgit v1.2.3 From 786b11cc0f505e44c29f778fd329dafafafed76c Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Tue, 11 Nov 2008 09:37:14 -0500 Subject: Input: i8042 - add Dell XPS M1530 to nomux list Dell XPS M1530 needs i8042.nomux=1 for ALPS touchpad to work as reported on https://qa.mandriva.com/show_bug.cgi?id=43532 It is said that before A08 bios version this isn't needed (I don't have the hardware so can't check), and suppose this will not break with bios versions before A08. Signed-off-by: Herton Ronaldo Krzesinski Tested-by: Andreas Ericsson Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index eec375cd10e..5db1d0b7456 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -337,6 +337,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "2656"), }, }, + { + .ident = "Dell XPS M1530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"), + }, + }, { } }; -- cgit v1.2.3 From a8215b81cc31cf267506bc6a4a4bfe93f4ca1652 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 11 Nov 2008 09:40:42 -0500 Subject: Input: atkbd - add keymap quirk for Inventec Symphony systems The Zepto 6615WD laptop (rebranded Inventec Symphony system) needs a key release quirk for its volume keys to work. The attached patch adds the quirk to the atkbd driver. Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=460237 Signed-off-by: Matthew Garrett Signed-off-by: Adel Gadllah Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 22016ca1535..c93b9b4ff03 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -867,6 +867,22 @@ static void atkbd_hp_keymap_fixup(struct atkbd *atkbd) atkbd->force_release_mask); } +/* + * Inventec system with broken key release on volume keys + */ +static void atkbd_inventec_keymap_fixup(struct atkbd *atkbd) +{ + const unsigned int forced_release_keys[] = { + 0xae, 0xb0, + }; + int i; + + if (atkbd->set == 2) + for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) + __set_bit(forced_release_keys[i], + atkbd->force_release_mask); +} + /* * atkbd_set_keycode_table() initializes keyboard's keycode table * according to the selected scancode set @@ -1468,6 +1484,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { .callback = atkbd_setup_fixup, .driver_data = atkbd_hp_keymap_fixup, }, + { + .ident = "Inventec Symphony", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"), + DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"), + }, + .callback = atkbd_setup_fixup, + .driver_data = atkbd_inventec_keymap_fixup, + }, { } }; -- cgit v1.2.3 From d6d79a785d430c0e17f7e2d662f10de022cbca93 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 11 Nov 2008 09:43:21 -0500 Subject: Input: atkbd - cancel delayed work before freeing its structure Pointed out by Oleg Nesterov. Since delayed work is used here, use of flush_scheduled_work() is not sufficient in atkbd_disconnect(). It does not wait for scheduled delayed work to finish. This patch prevents delayed work to be processed after freeing atkbd structure (used struct delayed_work is part of atkbd) by cancelling this delayed work. Signed-off-by: Jiri Pirko Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index c93b9b4ff03..379b7ff354e 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -824,7 +824,7 @@ static void atkbd_disconnect(struct serio *serio) atkbd_disable(atkbd); /* make sure we don't have a command in flight */ - flush_scheduled_work(); + cancel_delayed_work_sync(&atkbd->event_work); sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group); input_unregister_device(atkbd->dev); -- cgit v1.2.3 From 5fb17fd9a2d05be77be91369aa2f7b0db42fc8b4 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Tue, 11 Nov 2008 09:52:21 -0500 Subject: Input: psmouse - fix incorrect validate_byte check in OLPC protocol The validate_byte check logic was backwards; it should return true for an *invalid* packet. Thanks to Jeremy Katz for spotting this one. Signed-off-by: Andres Salomon Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/hgpk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index e82d34201e9..88f04bf2ad6 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c @@ -125,7 +125,7 @@ static void hgpk_spewing_hack(struct psmouse *psmouse, */ static int hgpk_validate_byte(unsigned char *packet) { - return (packet[0] & 0x0C) == 0x08; + return (packet[0] & 0x0C) != 0x08; } static void hgpk_process_packet(struct psmouse *psmouse) -- cgit v1.2.3 From 8eb04cf3402c59e84af9d2e86149edb4044f9a9e Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 11 Nov 2008 14:48:44 +0000 Subject: tty: trivial - fix up email addresses in tty related stuff Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/isicom.c | 6 ++++-- drivers/char/mxser.c | 3 ++- drivers/usb/serial/ir-usb.c | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 7d30ee1d3fc..04e4549299b 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -7,12 +7,14 @@ * Original driver code supplied by Multi-Tech * * Changes - * 1/9/98 alan@redhat.com Merge to 2.0.x kernel tree + * 1/9/98 alan@lxorguk.ukuu.org.uk + * Merge to 2.0.x kernel tree * Obtain and use official major/minors * Loader switched to a misc device * (fixed range check bug as a side effect) * Printk clean up - * 9/12/98 alan@redhat.com Rough port to 2.1.x + * 9/12/98 alan@lxorguk.ukuu.org.uk + * Rough port to 2.1.x * * 10/6/99 sameer Merged the ISA and PCI drivers to * a new unified driver. diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 8beef50f95a..04776691541 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -14,7 +14,8 @@ * (at your option) any later version. * * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox - * . The original 1.8 code is available on www.moxa.com. + * . The original 1.8 code is available on + * www.moxa.com. * - Fixed x86_64 cleanness */ diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index b679a556b98..4e2cda93da5 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -26,7 +26,7 @@ * Introduced common header to be used also in USB Gadget Framework. * Still needs some other style fixes. * - * 2007_Jun_21 Alan Cox + * 2007_Jun_21 Alan Cox * Minimal cleanups for some of the driver problens and tty layer abuse. * Still needs fixing to allow multiple dongles. * -- cgit v1.2.3 From 0906dd9df2f79042cfa82d8388895be7cbe7a51b Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 11 Nov 2008 14:51:23 +0000 Subject: telephony: trivial: fix up email address Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/telephony/phonedev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c index 37caf4d6903..b52cc830c0b 100644 --- a/drivers/telephony/phonedev.c +++ b/drivers/telephony/phonedev.c @@ -8,7 +8,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Author: Alan Cox, + * Author: Alan Cox, * * Fixes: Mar 01 2000 Thomas Sparr, * phone_register_device now works with unit!=PHONE_UNIT_ANY -- cgit v1.2.3 From 734f0bae9504216bd760493ed4744a34cfe0e7ce Mon Sep 17 00:00:00 2001 From: Daniel Gimpelevich Date: Tue, 11 Nov 2008 13:57:30 -0500 Subject: Input: cm109 - add keymap for ATCom AU-100 phone Signed-off-by: Daniel Gimpelevich Signed-off-by: Dmitry Torokhov --- drivers/input/misc/cm109.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c index bce160f4349..86457feccfc 100644 --- a/drivers/input/misc/cm109.c +++ b/drivers/input/misc/cm109.c @@ -42,7 +42,7 @@ static char *phone = "kip1000"; module_param(phone, charp, S_IRUSR); -MODULE_PARM_DESC(phone, "Phone name {kip1000, gtalk, usbph01}"); +MODULE_PARM_DESC(phone, "Phone name {kip1000, gtalk, usbph01, atcom}"); enum { /* HID Registers */ @@ -258,6 +258,37 @@ static unsigned short keymap_usbph01(int scancode) } } +/* + * Keymap for ATCom AU-100 + * http://www.atcom.cn/En_products_AU100.html + * http://www.packetizer.com/products/au100/ + * http://www.voip-info.org/wiki/view/AU-100 + * + * Contributed by daniel@gimpelevich.san-francisco.ca.us + */ +static unsigned short keymap_atcom(int scancode) +{ + switch (scancode) { /* phone key: */ + case 0x82: return KEY_NUMERIC_0; /* 0 */ + case 0x11: return KEY_NUMERIC_1; /* 1 */ + case 0x12: return KEY_NUMERIC_2; /* 2 */ + case 0x14: return KEY_NUMERIC_3; /* 3 */ + case 0x21: return KEY_NUMERIC_4; /* 4 */ + case 0x22: return KEY_NUMERIC_5; /* 5 */ + case 0x24: return KEY_NUMERIC_6; /* 6 */ + case 0x41: return KEY_NUMERIC_7; /* 7 */ + case 0x42: return KEY_NUMERIC_8; /* 8 */ + case 0x44: return KEY_NUMERIC_9; /* 9 */ + case 0x84: return KEY_NUMERIC_POUND; /* # */ + case 0x81: return KEY_NUMERIC_STAR; /* * */ + case 0x18: return KEY_ENTER; /* pickup */ + case 0x28: return KEY_ESC; /* hangup */ + case 0x48: return KEY_LEFT; /* left arrow */ + case 0x88: return KEY_RIGHT; /* right arrow */ + default: return special_keymap(scancode); + } +} + static unsigned short (*keymap)(int) = keymap_kip1000; /* @@ -840,6 +871,10 @@ static int __init cm109_select_keymap(void) keymap = keymap_usbph01; printk(KERN_INFO KBUILD_MODNAME ": " "Keymap for Allied-Telesis Corega USBPH01 phone loaded\n"); + } else if (!strcasecmp(phone, "atcom")) { + keymap = keymap_atcom; + printk(KERN_INFO KBUILD_MODNAME ": " + "Keymap for ATCom AU-100 phone loaded\n"); } else { printk(KERN_ERR KBUILD_MODNAME ": " "Unsupported phone: %s\n", phone); -- cgit v1.2.3 From 137cb55c6dcd56cb367285adaf15f808a2a9fec7 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 11 Nov 2008 13:12:33 -0700 Subject: iop-adma: add a dummy read to flush next descriptor update The current dummy read references the wrong address allowing the next descriptor address update to linger in the store buffer and get passed by an 'append' event. This issue was uncovered by the change from strongly-ordered to device memory for the adma registers. Signed-off-by: Dan Williams --- drivers/dma/iop-adma.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index 71fba82462c..95f5a946681 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c @@ -411,6 +411,7 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx) int slot_cnt; int slots_per_op; dma_cookie_t cookie; + dma_addr_t next_dma; grp_start = sw_desc->group_head; slot_cnt = grp_start->slot_cnt; @@ -425,11 +426,11 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx) &old_chain_tail->chain_node); /* fix up the hardware chain */ - iop_desc_set_next_desc(old_chain_tail, grp_start->async_tx.phys); + next_dma = grp_start->async_tx.phys; + iop_desc_set_next_desc(old_chain_tail, next_dma); + BUG_ON(iop_desc_get_next_desc(old_chain_tail) != next_dma); /* flush */ - /* 1/ don't add pre-chained descriptors - * 2/ dummy read to flush next_desc write - */ + /* check for pre-chained descriptors */ BUG_ON(iop_desc_get_next_desc(sw_desc)); /* increment the pending count by the number of slots -- cgit v1.2.3 From 65e503814dec83c7b2ac955e75919d009109c919 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 11 Nov 2008 13:12:33 -0700 Subject: iop-adma: use iop_paranoia() for debug BUG_ONs Now that the critical read back to flush the next descriptor address is fixed we can downgrade some BUG_ONs that need only be enabled when testing changes to the driver. Signed-off-by: Dan Williams --- drivers/dma/iop-adma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index 95f5a946681..c7a9306d951 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c @@ -431,7 +431,7 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx) BUG_ON(iop_desc_get_next_desc(old_chain_tail) != next_dma); /* flush */ /* check for pre-chained descriptors */ - BUG_ON(iop_desc_get_next_desc(sw_desc)); + iop_paranoia(iop_desc_get_next_desc(sw_desc)); /* increment the pending count by the number of slots * memcpy operations have a 1:1 (slot:operation) relation -- cgit v1.2.3 From 06190d8415219d9eef7d8f04b52a109e34575a76 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 11 Nov 2008 13:12:33 -0700 Subject: dmaengine: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Acked-by: Maciej Sosnowski Signed-off-by: Kay Sievers Signed-off-by: Dan Williams --- drivers/dma/dmaengine.c | 4 ++-- drivers/dma/dmatest.c | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index dc003a3a787..5317e08221e 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -399,8 +399,8 @@ int dma_async_device_register(struct dma_device *device) chan->chan_id = chancnt++; chan->dev.class = &dma_devclass; chan->dev.parent = device->dev; - snprintf(chan->dev.bus_id, BUS_ID_SIZE, "dma%dchan%d", - device->dev_id, chan->chan_id); + dev_set_name(&chan->dev, "dma%dchan%d", + device->dev_id, chan->chan_id); rc = device_register(&chan->dev); if (rc) { diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index d1e381e35a9..ed9636bfb54 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -20,11 +20,11 @@ static unsigned int test_buf_size = 16384; module_param(test_buf_size, uint, S_IRUGO); MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer"); -static char test_channel[BUS_ID_SIZE]; +static char test_channel[20]; module_param_string(channel, test_channel, sizeof(test_channel), S_IRUGO); MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)"); -static char test_device[BUS_ID_SIZE]; +static char test_device[20]; module_param_string(device, test_device, sizeof(test_device), S_IRUGO); MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)"); @@ -80,14 +80,14 @@ static bool dmatest_match_channel(struct dma_chan *chan) { if (test_channel[0] == '\0') return true; - return strcmp(chan->dev.bus_id, test_channel) == 0; + return strcmp(dev_name(&chan->dev), test_channel) == 0; } static bool dmatest_match_device(struct dma_device *device) { if (test_device[0] == '\0') return true; - return strcmp(device->dev->bus_id, test_device) == 0; + return strcmp(dev_name(device->dev), test_device) == 0; } static unsigned long dmatest_random(void) @@ -332,7 +332,7 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan) dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); if (!dtc) { - pr_warning("dmatest: No memory for %s\n", chan->dev.bus_id); + pr_warning("dmatest: No memory for %s\n", dev_name(&chan->dev)); return DMA_NAK; } @@ -343,16 +343,16 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan) thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL); if (!thread) { pr_warning("dmatest: No memory for %s-test%u\n", - chan->dev.bus_id, i); + dev_name(&chan->dev), i); break; } thread->chan = dtc->chan; smp_wmb(); thread->task = kthread_run(dmatest_func, thread, "%s-test%u", - chan->dev.bus_id, i); + dev_name(&chan->dev), i); if (IS_ERR(thread->task)) { pr_warning("dmatest: Failed to run thread %s-test%u\n", - chan->dev.bus_id, i); + dev_name(&chan->dev), i); kfree(thread); break; } @@ -362,7 +362,7 @@ static enum dma_state_client dmatest_add_channel(struct dma_chan *chan) list_add_tail(&thread->node, &dtc->threads); } - pr_info("dmatest: Started %u threads using %s\n", i, chan->dev.bus_id); + pr_info("dmatest: Started %u threads using %s\n", i, dev_name(&chan->dev)); list_add_tail(&dtc->node, &dmatest_channels); nr_channels++; @@ -379,7 +379,7 @@ static enum dma_state_client dmatest_remove_channel(struct dma_chan *chan) list_del(&dtc->node); dmatest_cleanup_channel(dtc); pr_debug("dmatest: lost channel %s\n", - chan->dev.bus_id); + dev_name(&chan->dev)); return DMA_ACK; } } @@ -418,7 +418,7 @@ dmatest_event(struct dma_client *client, struct dma_chan *chan, default: pr_info("dmatest: Unhandled event %u (%s)\n", - state, chan->dev.bus_id); + state, dev_name(&chan->dev)); break; } -- cgit v1.2.3 From 2485b8674bf5762822e14e1554938e36511c0ae4 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Mon, 10 Nov 2008 13:54:43 +0900 Subject: PCI: ignore bit0 of _OSC return code Currently acpi_run_osc() checks all the bits in _OSC result code (the first DWORD in the capabilities buffer) to see error condition. But the bit 0, which doesn't indicate any error, must be ignored. The bit 0 is used as the query flag at _OSC invocation time. Some platforms clear it during _OSC evaluation, but the others don't. On latter platforms, current acpi_run_osc() mis-detects error when _OSC is evaluated with query flag set because it doesn't ignore the bit 0. Because of this, the __acpi_query_osc() always fails on such platforms. And this is the cause of the problem that pci_osc_control_set() doesn't work since the commit 4e39432f4df544d3dfe4fc90a22d87de64d15815 which changed pci_osc_control_set() to use __acpi_query_osc(). Tested-by:"Tomasz Czernecki Signed-off-by: Kenji Kaneshige Signed-off-by: Jesse Barnes --- drivers/pci/pci-acpi.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index b3a63edb690..ae5ec76dca7 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -63,7 +63,7 @@ static acpi_status acpi_run_osc(acpi_handle handle, union acpi_object in_params[4]; struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; union acpi_object *out_obj; - u32 osc_dw0, flags = osc_args->capbuf[OSC_QUERY_TYPE]; + u32 errors, flags = osc_args->capbuf[OSC_QUERY_TYPE]; /* Setting up input parameters */ input.count = 4; @@ -92,15 +92,16 @@ static acpi_status acpi_run_osc(acpi_handle handle, status = AE_TYPE; goto out_kfree; } - osc_dw0 = *((u32 *)out_obj->buffer.pointer); - if (osc_dw0) { - if (osc_dw0 & OSC_REQUEST_ERROR) + /* Need to ignore the bit0 in result code */ + errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); + if (errors) { + if (errors & OSC_REQUEST_ERROR) printk(KERN_DEBUG "_OSC request fails\n"); - if (osc_dw0 & OSC_INVALID_UUID_ERROR) + if (errors & OSC_INVALID_UUID_ERROR) printk(KERN_DEBUG "_OSC invalid UUID\n"); - if (osc_dw0 & OSC_INVALID_REVISION_ERROR) + if (errors & OSC_INVALID_REVISION_ERROR) printk(KERN_DEBUG "_OSC invalid revision\n"); - if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { + if (errors & OSC_CAPABILITIES_MASK_ERROR) { if (flags & OSC_QUERY_ENABLE) goto out_success; printk(KERN_DEBUG "_OSC FW not grant req. control\n"); -- cgit v1.2.3 From 1cfe62c8010ac56e1bd3827e30386a87cc2f3594 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Tue, 28 Oct 2008 00:35:30 +0300 Subject: ACPI: EC: revert msleep patch With the better solution for EC interrupt storm issue, there is no need to use msleep over udelay. References: http://bugzilla.kernel.org/show_bug.cgi?id=11810 http://bugzilla.kernel.org/show_bug.cgi?id=10724 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ef42316f89f..3ef5b796a68 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -239,10 +239,10 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state) static int ec_poll(struct acpi_ec *ec) { unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); - msleep(1); + udelay(ACPI_EC_UDELAY); while (time_before(jiffies, delay)) { gpe_transaction(ec, acpi_ec_read_status(ec)); - msleep(1); + udelay(ACPI_EC_UDELAY); if (ec_transaction_done(ec)) return 0; } -- cgit v1.2.3 From f8248434e6a11d7cd314281be3b39bbcf82fc243 Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Sat, 1 Nov 2008 11:05:26 +0000 Subject: ACPI: EC: make kernel messages more useful when GPE storm is detected Make sure we can tell if the GPE storm workaround gets activated, and avoid flooding the logs afterwards. http://bugzilla.kernel.org/show_bug.cgi?id=11841 "plenty of line "ACPI: EC: non-query interrupt received, switching to interrupt mode" in dmesg" Signed-off-by: Alan Jenkins Acked-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 3ef5b796a68..b340e08cf1d 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -286,7 +286,8 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && t->irq_count > ACPI_EC_STORM_THRESHOLD) { - pr_debug(PREFIX "GPE storm detected\n"); + pr_info(PREFIX "GPE storm detected, " + "transactions will use polling mode\n"); set_bit(EC_FLAGS_GPE_STORM, &ec->flags); } return ret; @@ -566,9 +567,15 @@ static u32 acpi_ec_gpe_handler(void *data) if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && !test_bit(EC_FLAGS_NO_GPE, &ec->flags)) { /* this is non-query, must be confirmation */ - if (printk_ratelimit()) - pr_info(PREFIX "non-query interrupt received," + if (!test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + if (printk_ratelimit()) + pr_info(PREFIX "non-query interrupt received," + " switching to interrupt mode\n"); + } else { + /* hush, STORM switches the mode every transaction */ + pr_debug(PREFIX "non-query interrupt received," " switching to interrupt mode\n"); + } set_bit(EC_FLAGS_GPE_MODE, &ec->flags); } return ACPI_INTERRUPT_HANDLED; -- cgit v1.2.3 From dd15f8c42af09031e27da5b4d697ce925511f2e1 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Sat, 8 Nov 2008 21:42:30 +0300 Subject: ACPI: EC: wait for last write gpe There is a possibility that EC might break if next command is issued within 1 us after write or burst-disable command. Suggestd-by: Zhao Yakui Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index b340e08cf1d..cebd65d2e2a 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -102,6 +102,7 @@ struct transaction { u8 command; u8 wlen; u8 rlen; + bool done; }; static struct acpi_ec { @@ -178,7 +179,7 @@ static int ec_transaction_done(struct acpi_ec *ec) unsigned long flags; int ret = 0; spin_lock_irqsave(&ec->curr_lock, flags); - if (!ec->curr || (!ec->curr->wlen && !ec->curr->rlen)) + if (!ec->curr || ec->curr->done) ret = 1; spin_unlock_irqrestore(&ec->curr_lock, flags); return ret; @@ -195,17 +196,20 @@ static void gpe_transaction(struct acpi_ec *ec, u8 status) acpi_ec_write_data(ec, *(ec->curr->wdata++)); --ec->curr->wlen; } else - /* false interrupt, state didn't change */ - ++ec->curr->irq_count; - + goto err; } else if (ec->curr->rlen > 0) { if ((status & ACPI_EC_FLAG_OBF) == 1) { *(ec->curr->rdata++) = acpi_ec_read_data(ec); - --ec->curr->rlen; + if (--ec->curr->rlen == 0) + ec->curr->done = true; } else - /* false interrupt, state didn't change */ - ++ec->curr->irq_count; - } + goto err; + } else if (ec->curr->wlen == 0 && (status & ACPI_EC_FLAG_IBF) == 0) + ec->curr->done = true; + goto unlock; +err: + /* false interrupt, state didn't change */ + ++ec->curr->irq_count; unlock: spin_unlock_irqrestore(&ec->curr_lock, flags); } @@ -265,6 +269,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, spin_lock_irqsave(&ec->curr_lock, tmp); /* following two actions should be kept atomic */ t->irq_count = 0; + t->done = false; ec->curr = t; acpi_ec_write_cmd(ec, ec->curr->command); if (ec->curr->command == ACPI_EC_COMMAND_QUERY) -- cgit v1.2.3 From a2f93aeadf97e870ff385030633a73e21146815d Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 12 Nov 2008 01:40:19 +0300 Subject: ACPI: EC: restart failed command Restart current transaction if we recieved unexpected GPEs instead of needed ones. http://bugzilla.kernel.org/show_bug.cgi?id=11896 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index cebd65d2e2a..34c67ca3beb 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -100,6 +100,8 @@ struct transaction { u8 *rdata; unsigned short irq_count; u8 command; + u8 wi; + u8 ri; u8 wlen; u8 rlen; bool done; @@ -185,26 +187,34 @@ static int ec_transaction_done(struct acpi_ec *ec) return ret; } +static void start_transaction(struct acpi_ec *ec) +{ + ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0; + ec->curr->done = false; + acpi_ec_write_cmd(ec, ec->curr->command); +} + static void gpe_transaction(struct acpi_ec *ec, u8 status) { unsigned long flags; spin_lock_irqsave(&ec->curr_lock, flags); if (!ec->curr) goto unlock; - if (ec->curr->wlen > 0) { - if ((status & ACPI_EC_FLAG_IBF) == 0) { - acpi_ec_write_data(ec, *(ec->curr->wdata++)); - --ec->curr->wlen; - } else + if (ec->curr->wlen > ec->curr->wi) { + if ((status & ACPI_EC_FLAG_IBF) == 0) + acpi_ec_write_data(ec, + ec->curr->wdata[ec->curr->wi++]); + else goto err; - } else if (ec->curr->rlen > 0) { + } else if (ec->curr->rlen > ec->curr->ri) { if ((status & ACPI_EC_FLAG_OBF) == 1) { - *(ec->curr->rdata++) = acpi_ec_read_data(ec); - if (--ec->curr->rlen == 0) + ec->curr->rdata[ec->curr->ri++] = acpi_ec_read_data(ec); + if (ec->curr->rlen == ec->curr->ri) ec->curr->done = true; } else goto err; - } else if (ec->curr->wlen == 0 && (status & ACPI_EC_FLAG_IBF) == 0) + } else if (ec->curr->wlen == ec->curr->wi && + (status & ACPI_EC_FLAG_IBF) == 0) ec->curr->done = true; goto unlock; err: @@ -219,6 +229,15 @@ static int acpi_ec_wait(struct acpi_ec *ec) if (wait_event_timeout(ec->wait, ec_transaction_done(ec), msecs_to_jiffies(ACPI_EC_DELAY))) return 0; + /* try restart command if we get any false interrupts */ + if (ec->curr->irq_count && + (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { + pr_debug(PREFIX "controller reset, restart transaction\n"); + start_transaction(ec); + if (wait_event_timeout(ec->wait, ec_transaction_done(ec), + msecs_to_jiffies(ACPI_EC_DELAY))) + return 0; + } /* missing GPEs, switch back to poll mode */ if (printk_ratelimit()) pr_info(PREFIX "missing confirmations, " @@ -268,10 +287,8 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, /* start transaction */ spin_lock_irqsave(&ec->curr_lock, tmp); /* following two actions should be kept atomic */ - t->irq_count = 0; - t->done = false; ec->curr = t; - acpi_ec_write_cmd(ec, ec->curr->command); + start_transaction(ec); if (ec->curr->command == ACPI_EC_COMMAND_QUERY) clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); spin_unlock_irqrestore(&ec->curr_lock, tmp); -- cgit v1.2.3 From 0b7084ac67fb84f0cf2f8bc02d7e0dea8521dd2d Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Sat, 25 Oct 2008 21:48:46 +0400 Subject: ACPICA: Use spinlock for acpi_{en|dis}able_gpe Disabling gpe might interfere with gpe detection/handling, thus producing "interrupt not handled" errors. Ironically, disabling of GPE from interrupt context is already under spinlock, so only userspace needs to start using it. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/button.c | 2 +- drivers/acpi/ec.c | 10 +++++----- drivers/acpi/events/evxfevnt.c | 35 +++++++++-------------------------- drivers/acpi/sleep/wakeup.c | 8 ++++---- drivers/acpi/system.c | 4 ++-- 5 files changed, 21 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index cb046c3fc3f..eb6bf3025f9 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -479,7 +479,7 @@ static int acpi_button_add(struct acpi_device *device) device->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN); acpi_enable_gpe(device->wakeup.gpe_device, - device->wakeup.gpe_number, ACPI_NOT_ISR); + device->wakeup.gpe_number); device->wakeup.state.enabled = 1; } diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 34c67ca3beb..89d6d2868e8 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -282,7 +282,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, /* disable GPE during transaction if storm is detected */ if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); - acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + acpi_disable_gpe(NULL, ec->gpe); } /* start transaction */ spin_lock_irqsave(&ec->curr_lock, tmp); @@ -305,7 +305,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, /* check if we received SCI during transaction */ ec_check_sci(ec, acpi_ec_read_status(ec)); /* it is safe to enable GPE outside of transaction */ - acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->gpe); } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && t->irq_count > ACPI_EC_STORM_THRESHOLD) { pr_info(PREFIX "GPE storm detected, " @@ -897,7 +897,7 @@ static int ec_install_handlers(struct acpi_ec *ec) if (ACPI_FAILURE(status)) return -ENODEV; acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); - acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->gpe); status = acpi_install_address_space_handler(ec->handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, @@ -1036,7 +1036,7 @@ static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state) /* Stop using GPE */ set_bit(EC_FLAGS_NO_GPE, &ec->flags); clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); - acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + acpi_disable_gpe(NULL, ec->gpe); return 0; } @@ -1045,7 +1045,7 @@ static int acpi_ec_resume(struct acpi_device *device) struct acpi_ec *ec = acpi_driver_data(device); /* Enable use of GPE back */ clear_bit(EC_FLAGS_NO_GPE, &ec->flags); - acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + acpi_enable_gpe(NULL, ec->gpe); return 0; } diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index 73bfd6bf962..39db00874a2 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c @@ -248,21 +248,15 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe_type) * DESCRIPTION: Enable an ACPI event (general purpose) * ******************************************************************************/ -acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) +acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) { acpi_status status = AE_OK; + acpi_cpu_flags flags; struct acpi_gpe_event_info *gpe_event_info; ACPI_FUNCTION_TRACE(acpi_enable_gpe); - /* Use semaphore lock if not executing at interrupt level */ - - if (flags & ACPI_NOT_ISR) { - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); /* Ensure that we have a valid GPE number */ @@ -277,9 +271,7 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) status = acpi_ev_enable_gpe(gpe_event_info, TRUE); unlock_and_exit: - if (flags & ACPI_NOT_ISR) { - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - } + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } @@ -299,22 +291,15 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe) * DESCRIPTION: Disable an ACPI event (general purpose) * ******************************************************************************/ -acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) +acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) { acpi_status status = AE_OK; + acpi_cpu_flags flags; struct acpi_gpe_event_info *gpe_event_info; ACPI_FUNCTION_TRACE(acpi_disable_gpe); - /* Use semaphore lock if not executing at interrupt level */ - - if (flags & ACPI_NOT_ISR) { - status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - } - + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); /* Ensure that we have a valid GPE number */ gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); @@ -325,10 +310,8 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) status = acpi_ev_disable_gpe(gpe_event_info); - unlock_and_exit: - if (flags & ACPI_NOT_ISR) { - (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); - } +unlock_and_exit: + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c index 38655eb132d..dea4c23df76 100644 --- a/drivers/acpi/sleep/wakeup.c +++ b/drivers/acpi/sleep/wakeup.c @@ -88,7 +88,7 @@ void acpi_enable_wakeup_device(u8 sleep_state) spin_unlock(&acpi_device_lock); if (!dev->wakeup.flags.run_wake) acpi_enable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, ACPI_ISR); + dev->wakeup.gpe_number); spin_lock(&acpi_device_lock); } spin_unlock(&acpi_device_lock); @@ -122,7 +122,7 @@ void acpi_disable_wakeup_device(u8 sleep_state) ACPI_GPE_TYPE_WAKE_RUN); /* Re-enable it, since set_gpe_type will disable it */ acpi_enable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, ACPI_NOT_ISR); + dev->wakeup.gpe_number); spin_lock(&acpi_device_lock); } continue; @@ -133,7 +133,7 @@ void acpi_disable_wakeup_device(u8 sleep_state) /* Never disable run-wake GPE */ if (!dev->wakeup.flags.run_wake) { acpi_disable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, ACPI_NOT_ISR); + dev->wakeup.gpe_number); acpi_clear_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number, ACPI_NOT_ISR); } @@ -162,7 +162,7 @@ static int __init acpi_wakeup_device_init(void) dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN); acpi_enable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number, ACPI_NOT_ISR); + dev->wakeup.gpe_number); dev->wakeup.state.enabled = 1; spin_lock(&acpi_device_lock); } diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 1d74171b794..11995b612ad 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -394,10 +394,10 @@ static ssize_t counter_set(struct kobject *kobj, if (index < num_gpes) { if (!strcmp(buf, "disable\n") && (status & ACPI_EVENT_FLAG_ENABLED)) - result = acpi_disable_gpe(handle, index, ACPI_NOT_ISR); + result = acpi_disable_gpe(handle, index); else if (!strcmp(buf, "enable\n") && !(status & ACPI_EVENT_FLAG_ENABLED)) - result = acpi_enable_gpe(handle, index, ACPI_NOT_ISR); + result = acpi_enable_gpe(handle, index); else if (!strcmp(buf, "clear\n") && (status & ACPI_EVENT_FLAG_SET)) result = acpi_clear_gpe(handle, index, ACPI_NOT_ISR); -- cgit v1.2.3 From 06cf7d3c7af902939cd1754abcafb2464060cba8 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Sun, 9 Nov 2008 19:01:06 +0300 Subject: ACPI: EC: lower interrupt storm treshold http://bugzilla.kernel.org/show_bug.cgi?id=11892 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 89d6d2868e8..ab84f99f136 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -70,7 +70,7 @@ enum ec_command { #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ #define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ -#define ACPI_EC_STORM_THRESHOLD 20 /* number of false interrupts +#define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts per one transaction */ enum { -- cgit v1.2.3 From 8517934ef6aaa28d6e055b98df65b31cedbd1372 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Tue, 11 Nov 2008 12:54:11 +0300 Subject: ACPI: EC: Don't do transaction from GPE handler in poll mode. Referencies: http://bugzilla.kernel.org/show_bug.cgi?id=12004 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ab84f99f136..bd1af3e9e4c 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -581,9 +581,12 @@ static u32 acpi_ec_gpe_handler(void *data) pr_debug(PREFIX "~~~> interrupt\n"); status = acpi_ec_read_status(ec); - gpe_transaction(ec, status); - if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) - wake_up(&ec->wait); + if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) { + gpe_transaction(ec, status); + if (ec_transaction_done(ec) && + (status & ACPI_EC_FLAG_IBF) == 0) + wake_up(&ec->wait); + } ec_check_sci(ec, status); if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && -- cgit v1.2.3 From fad96ab62d38b94efbdb4c3c5fc55cb90d57937d Mon Sep 17 00:00:00 2001 From: Stefan Roscher Date: Tue, 11 Nov 2008 15:44:22 -0800 Subject: IB/ehca: Remove reference to special QP in case of port activation failure If the initialization of a special QP (e.g. AQP1) fails due to a software timeout, we have to remove the reference to that special QP struct from the port struct to stop the driver from accessing the QP, since it will be/has been destroyed by the caller, eg in this case ib_mad. Signed-off-by: Stefan Roscher Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ehca/ehca_irq.c | 44 ++++++++++++++++++++++------------- drivers/infiniband/hw/ehca/ehca_qp.c | 5 ++++ 2 files changed, 33 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index cb55be04442..757035ea246 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/drivers/infiniband/hw/ehca/ehca_irq.c @@ -359,36 +359,48 @@ static void notify_port_conf_change(struct ehca_shca *shca, int port_num) *old_attr = new_attr; } +/* replay modify_qp for sqps -- return 0 if all is well, 1 if AQP1 destroyed */ +static int replay_modify_qp(struct ehca_sport *sport) +{ + int aqp1_destroyed; + unsigned long flags; + + spin_lock_irqsave(&sport->mod_sqp_lock, flags); + + aqp1_destroyed = !sport->ibqp_sqp[IB_QPT_GSI]; + + if (sport->ibqp_sqp[IB_QPT_SMI]) + ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]); + if (!aqp1_destroyed) + ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]); + + spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); + + return aqp1_destroyed; +} + static void parse_ec(struct ehca_shca *shca, u64 eqe) { u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); u8 spec_event; struct ehca_sport *sport = &shca->sport[port - 1]; - unsigned long flags; switch (ec) { case 0x30: /* port availability change */ if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { - int suppress_event; - /* replay modify_qp for sqps */ - spin_lock_irqsave(&sport->mod_sqp_lock, flags); - suppress_event = !sport->ibqp_sqp[IB_QPT_GSI]; - if (sport->ibqp_sqp[IB_QPT_SMI]) - ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]); - if (!suppress_event) - ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]); - spin_unlock_irqrestore(&sport->mod_sqp_lock, flags); - - /* AQP1 was destroyed, ignore this event */ - if (suppress_event) - break; + /* only replay modify_qp calls in autodetect mode; + * if AQP1 was destroyed, the port is already down + * again and we can drop the event. + */ + if (ehca_nr_ports < 0) + if (replay_modify_qp(sport)) + break; sport->port_state = IB_PORT_ACTIVE; dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE, "is active"); - ehca_query_sma_attr(shca, port, - &sport->saved_attr); + ehca_query_sma_attr(shca, port, &sport->saved_attr); } else { sport->port_state = IB_PORT_DOWN; dispatch_port_event(shca, port, IB_EVENT_PORT_ERR, diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index 4d54b9f6456..9e05ee2db39 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c @@ -860,6 +860,11 @@ static struct ehca_qp *internal_create_qp( if (qp_type == IB_QPT_GSI) { h_ret = ehca_define_sqp(shca, my_qp, init_attr); if (h_ret != H_SUCCESS) { + kfree(my_qp->mod_qp_parm); + my_qp->mod_qp_parm = NULL; + /* the QP pointer is no longer valid */ + shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] = + NULL; ret = ehca2ib_return_code(h_ret); goto create_qp_exit6; } -- cgit v1.2.3 From 56960b546a88844a6f5295a9f81aab9e6b81edc9 Mon Sep 17 00:00:00 2001 From: Tony Vroon Date: Sun, 9 Nov 2008 04:20:05 +0000 Subject: fujitsu-laptop: Add DMI callback for Lifebook S6420 The Lifebook S6420 is the ICH9M-based follow-up to the S6410. The application panel contains the following keys: lock, mobility center, eco, info. Whilst key 4 might be more appropriate for help then key 2, I've done things the S6410 way. I can confirm that backlight control is functional, and that the lock key activates the Gnome screensaver as expected. Signed-off-by: Tony Vroon Acked-by: Jonathan Woithe Signed-off-by: Len Brown --- drivers/misc/fujitsu-laptop.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c index 9124fcdc4d0..5ec77ae08d9 100644 --- a/drivers/misc/fujitsu-laptop.c +++ b/drivers/misc/fujitsu-laptop.c @@ -464,6 +464,14 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id) return 0; } +static int dmi_check_cb_s6420(const struct dmi_system_id *id) +{ + dmi_check_cb_common(id); + fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ + fujitsu->keycode2 = KEY_HELP; /* "Mobility Center" */ + return 0; +} + static int dmi_check_cb_p8010(const struct dmi_system_id *id) { dmi_check_cb_common(id); @@ -481,6 +489,13 @@ static struct dmi_system_id fujitsu_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6410"), }, .callback = dmi_check_cb_s6410}, + { + .ident = "Fujitsu Siemens S6420", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK S6420"), + }, + .callback = dmi_check_cb_s6420}, { .ident = "Fujitsu LifeBook P8010", .matches = { -- cgit v1.2.3 From 32836259ff25ce97010569706cd33ba94de81d62 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 5 Nov 2008 16:17:52 -0700 Subject: ACPI: pci_link: remove acpi_irq_balance_set() interface This removes the acpi_irq_balance_set() interface from the PCI interrupt link driver. x86 used acpi_irq_balance_set() to tell the PCI interrupt link driver to configure links to minimize IRQ sharing. But the link driver can easily figure out whether to turn on IRQ balancing based on the IRQ model (PIC/IOAPIC/etc), so we can get rid of that external interface. It's better for the driver to figure this out at init-time. If we set it externally via the x86 code, the interface reduces modularity, and we depend on the fact that acpi_process_madt() happens before we process the kernel command line. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_link.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index fcfdef7b4fd..e52ad91ce2d 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -531,7 +531,7 @@ int __init acpi_irq_penalty_init(void) return 0; } -static int acpi_irq_balance; /* 0: static, 1: balance */ +static int acpi_irq_balance = -1; /* 0: static, 1: balance */ static int acpi_pci_link_allocate(struct acpi_pci_link *link) { @@ -950,10 +950,17 @@ device_initcall(irqrouter_init_sysfs); static int __init acpi_pci_link_init(void) { - if (acpi_noirq) return 0; + if (acpi_irq_balance == -1) { + /* no command line switch: enable balancing in IOAPIC mode */ + if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) + acpi_irq_balance = 1; + else + acpi_irq_balance = 0; + } + acpi_link.count = 0; INIT_LIST_HEAD(&acpi_link.entries); -- cgit v1.2.3 From 1a22f08dbd0e77c7cf45b5f527f93131d0b591b6 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 11 Nov 2008 12:19:05 +0900 Subject: serial: sh-sci: fix cannot work SH7723 SCIFA SH7723 has SCIFA. This module is similer SCI register map, but it has FIFO. So this patch adds new type(PORT_SCIFA) and change some type checking. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 20 +++++++++++--------- drivers/serial/sh-sci.h | 16 ++++++++-------- 2 files changed, 19 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 5c0f32c7fbf..518c0321e4d 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -478,10 +478,10 @@ static void sci_transmit_chars(struct uart_port *port) return; } - if (port->type == PORT_SCIF) - count = scif_txroom(port); - else + if (port->type == PORT_SCI) count = sci_txroom(port); + else + count = scif_txroom(port); do { unsigned char c; @@ -510,7 +510,7 @@ static void sci_transmit_chars(struct uart_port *port) } else { ctrl = sci_in(port, SCSCR); - if (port->type == PORT_SCIF) { + if (port->type != PORT_SCI) { sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); } @@ -536,10 +536,10 @@ static inline void sci_receive_chars(struct uart_port *port) return; while (1) { - if (port->type == PORT_SCIF) - count = scif_rxroom(port); - else + if (port->type == PORT_SCI) count = sci_rxroom(port); + else + count = scif_rxroom(port); /* Don't copy more bytes than there is room for in the buffer */ count = tty_buffer_request_room(tty, count); @@ -714,7 +714,7 @@ static inline int sci_handle_breaks(struct uart_port *port) #if defined(SCIF_ORER) /* XXX: Handle SCIF overrun error */ - if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) { + if (port->type != PORT_SCI && (sci_in(port, SCLSR) & SCIF_ORER) != 0) { sci_out(port, SCLSR, 0); if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) { copied++; @@ -1042,7 +1042,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ - if (port->type == PORT_SCIF) + if (port->type != PORT_SCI) sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); smr_val = sci_in(port, SCSMR) & 3; @@ -1085,6 +1085,7 @@ static const char *sci_type(struct uart_port *port) case PORT_SCI: return "sci"; case PORT_SCIF: return "scif"; case PORT_IRDA: return "irda"; + case PORT_SCIFA: return "scifa"; } return NULL; @@ -1112,6 +1113,7 @@ static void sci_config_port(struct uart_port *port, int flags) s->init_pins = sci_init_pins_sci; break; case PORT_SCIF: + case PORT_SCIFA: s->init_pins = sci_init_pins_scif; break; case PORT_IRDA: diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 6163a45f968..9f33b064172 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -289,18 +289,18 @@ #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\ static inline unsigned int sci_##name##_in(struct uart_port *port) \ { \ - if (port->type == PORT_SCI) { \ - SCI_IN(sci_size, sci_offset) \ - } else { \ - SCI_IN(scif_size, scif_offset); \ + if (port->type == PORT_SCIF) { \ + SCI_IN(scif_size, scif_offset) \ + } else { /* PORT_SCI or PORT_SCIFA */ \ + SCI_IN(sci_size, sci_offset); \ } \ } \ static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ { \ - if (port->type == PORT_SCI) { \ - SCI_OUT(sci_size, sci_offset, value) \ - } else { \ - SCI_OUT(scif_size, scif_offset, value); \ + if (port->type == PORT_SCIF) { \ + SCI_OUT(scif_size, scif_offset, value) \ + } else { /* PORT_SCI or PORT_SCIFA */ \ + SCI_OUT(sci_size, sci_offset, value); \ } \ } -- cgit v1.2.3 From ade7a9b4ccd20ab8159c77a0abd20552f2d6b06c Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 11 Nov 2008 16:47:21 +0900 Subject: usb: r8a66597-hcd: fix wrong data access in SuperH on-chip USB When I used SuperH on-chip USB, there was the problem that accessed r8a66597_root_hub which was not allocated. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- drivers/usb/host/r8a66597-hcd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index c18d8790c41..2376f24f3c8 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1763,11 +1763,12 @@ static void r8a66597_timer(unsigned long _r8a66597) { struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597; unsigned long flags; + int port; spin_lock_irqsave(&r8a66597->lock, flags); - r8a66597_root_hub_control(r8a66597, 0); - r8a66597_root_hub_control(r8a66597, 1); + for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) + r8a66597_root_hub_control(r8a66597, port); spin_unlock_irqrestore(&r8a66597->lock, flags); } -- cgit v1.2.3 From b3e123cf65baadc0cc30a843fd48cfd6a4b2e1ca Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Wed, 12 Nov 2008 10:16:47 -0800 Subject: RDMA/cxgb3: Fix deadlock in iw_cxgb3 (hang when configuring interface) When the iw_cxgb3 module's cxgb3_client "add" func gets called by the cxgb3 module, the iwarp driver ends up calling the ethtool ops get_drvinfo function in cxgb3 to get the fw version and other info. Currently the iwarp driver grabs the rtnl lock around this down call to serialize. As of 2.6.27 or so, things changed such that the rtnl lock is held around the call to the netdev driver open function. Also the cxgb3_client "add" function doesn't get called if the device is down. So, if you load cxgb3, then load iw_cxgb3, then ifconfig up the device, the iw_cxgb3 add func gets called with the rtnl_lock held. If you load cxgb3, ifconfig up the device, then load iw_cxgb3, the add func gets called without the rtnl_lock held. The former causes the deadlock, the latter does not. In addition, there are iw_cxgb3 sysfs handlers that also can call down into cxgb3 to gather the fw and hw versions. These can be called concurrently on different processors and at any time. Thus we need to push this serialization down in the cxgb3 driver get_drvinfo func. The fix is to remove rtnl lock usage, and use a per-device lock in cxgb3. Signed-off-by: Steve Wise Acked-by: Divy Le Ray Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb3/iwch_provider.c | 6 ------ drivers/net/cxgb3/cxgb3_main.c | 2 ++ 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c index ecff9804358..160ef482712 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c @@ -1102,9 +1102,7 @@ static u64 fw_vers_string_to_u64(struct iwch_dev *iwch_dev) char *cp, *next; unsigned fw_maj, fw_min, fw_mic; - rtnl_lock(); lldev->ethtool_ops->get_drvinfo(lldev, &info); - rtnl_unlock(); next = info.fw_version + 1; cp = strsep(&next, "."); @@ -1192,9 +1190,7 @@ static ssize_t show_fw_ver(struct device *dev, struct device_attribute *attr, ch struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev; PDBG("%s dev 0x%p\n", __func__, dev); - rtnl_lock(); lldev->ethtool_ops->get_drvinfo(lldev, &info); - rtnl_unlock(); return sprintf(buf, "%s\n", info.fw_version); } @@ -1207,9 +1203,7 @@ static ssize_t show_hca(struct device *dev, struct device_attribute *attr, struct net_device *lldev = iwch_dev->rdev.t3cdev_p->lldev; PDBG("%s dev 0x%p\n", __func__, dev); - rtnl_lock(); lldev->ethtool_ops->get_drvinfo(lldev, &info); - rtnl_unlock(); return sprintf(buf, "%s\n", info.driver); } diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 1ace41a13ac..5e663ccda4d 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1307,8 +1307,10 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) u32 fw_vers = 0; u32 tp_vers = 0; + spin_lock(&adapter->stats_lock); t3_get_fw_version(adapter, &fw_vers); t3_get_tp_version(adapter, &tp_vers); + spin_unlock(&adapter->stats_lock); strcpy(info->driver, DRV_NAME); strcpy(info->version, DRV_VERSION); -- cgit v1.2.3 From fe25c56190bbc0951d7c53b4ccd148e669d69938 Mon Sep 17 00:00:00 2001 From: Yossi Etigin Date: Wed, 12 Nov 2008 10:24:36 -0800 Subject: IPoIB: Don't enable NAPI when it's already enabled If a P_Key is not present when an interface is created, ipoib_open() will return after doing napi_enable(). ipoib_open() will be called again from ipoib_pkey_poll() when the P_Key appears, after NAPI has already been enabled, and try to enable it again. This triggers a BUG_ON() in napi_enable(). Fix this by moving the call to napi_enable() to after the test for P_Key presence. Signed-off-by: Yossi Etigin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index fddded7900d..b1eeb5a427c 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -106,12 +106,13 @@ int ipoib_open(struct net_device *dev) ipoib_dbg(priv, "bringing up interface\n"); - napi_enable(&priv->napi); set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); if (ipoib_pkey_dev_delay_open(dev)) return 0; + napi_enable(&priv->napi); + if (ipoib_ib_dev_open(dev)) { napi_disable(&priv->napi); return -EINVAL; -- cgit v1.2.3 From 93a3ab939ba90e00e193f0bad98f43fbdfbd925d Mon Sep 17 00:00:00 2001 From: Yossi Etigin Date: Wed, 12 Nov 2008 10:24:38 -0800 Subject: IPoIB: Fix hang in ipoib_flush_paths() ipoib_flush_paths() can hang during an SM up/down loop: if path_rec_start() fails (for instance, because there is no sm_ah), the path is still added to the path list by neigh_add_path(). Then, ipoib_flush_paths() will wait for path->done, but it will never complete because the request was not issued at all. Fix this by completing path->done if issuing the query fails. This fixes . Signed-off-by: Yossi Etigin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index b1eeb5a427c..0b2f601e8ca 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -547,6 +547,7 @@ static int path_rec_start(struct net_device *dev, if (path->query_id < 0) { ipoib_warn(priv, "ib_sa_path_rec_get failed: %d\n", path->query_id); path->query = NULL; + complete(&path->done); return path->query_id; } -- cgit v1.2.3 From ff79ae80837cf45cb703b34824dd3862d2ddcb24 Mon Sep 17 00:00:00 2001 From: Yossi Etigin Date: Wed, 12 Nov 2008 10:24:39 -0800 Subject: IPoIB: Fix crash in path_rec_completion() Fix a crash in path_rec_completion() during an SM up/down loop. If more than one path record request is issued, the first completion releases path->done, allowing ipoib_flush_paths() to free the path, and thus corrupting it for the second completion. Commit ee1e2c82 ("IPoIB: Refresh paths instead of flushing them on SM change events") added the field path->valid and changed the test "if (!path)" to "if (!path || !path->valid)". This change made it possible for a path with an outstanding query to pass the test and issue another query on the same path. Having two queries on the same path leads to a crash. This fixes . Signed-off-by: Yossi Etigin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 0b2f601e8ca..85257f6b957 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -664,7 +664,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, skb_push(skb, sizeof *phdr); __skb_queue_tail(&path->queue, skb); - if (path_rec_start(dev, path)) { + if (!path->query && path_rec_start(dev, path)) { spin_unlock_irqrestore(&priv->lock, flags); path_free(dev, path); return; -- cgit v1.2.3 From 8f7c41d4cec91cdbfa89b4a77d5a628938875366 Mon Sep 17 00:00:00 2001 From: Ivan Kuten Date: Mon, 10 Nov 2008 19:39:25 -0600 Subject: rtl8187: Add Abocom USB ID Signed-off-by: Ivan Kuten Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtl8187_dev.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 431e3c78bf2..0ce9fb03795 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -48,6 +48,8 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { {USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187}, /* Sitecom */ {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, + /* Abocom */ + {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187}, {} }; -- cgit v1.2.3 From f3c769185a28b7947d97b3552a977102c1fac3f2 Mon Sep 17 00:00:00 2001 From: Bob Jolliffe Date: Wed, 12 Nov 2008 20:16:59 +0000 Subject: rtl8187 : support for Sitecom WL-168 0001 v4 the Sitecom 0001 v4 with product id 0x0df6:0028, uses Realtek's RTL8187B and work fine with new 2.6.27 driver. Signed-off-by: John W. Linville --- drivers/net/wireless/rtl8187_dev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 0ce9fb03795..69eb0132593 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -48,6 +48,7 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { {USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187}, /* Sitecom */ {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, + {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, /* Abocom */ {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187}, {} -- cgit v1.2.3 From f7cd168645dda3e9067f24fabbfa787f9a237488 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 12 Nov 2008 16:54:22 -0500 Subject: hostap: pad the skb->cb usage in lieu of a proper fix Like mac80211 did, this driver makes 'clever' use of skb->cb to pass information along with an skb as it is requeued from the virtual device to the physical wireless device. Unfortunately, that trick no longer works... Unlike mac80211, code complexity and driver apathy makes this hack the best option we have in the short run. Hopefully someone will eventually be motivated to code a proper fix before all the effected hardware dies. (Above text by me. Johannes officially disavows all knowledge of this hack. -- JWL) Signed-off-by: Johannes Berg Cc: stable@kernel.org Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_wlan.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h index ffdf4876121..a68f97c3935 100644 --- a/drivers/net/wireless/hostap/hostap_wlan.h +++ b/drivers/net/wireless/hostap/hostap_wlan.h @@ -918,9 +918,12 @@ struct hostap_interface { /* * TX meta data - stored in skb->cb buffer, so this must not be increased over - * the 40-byte limit + * the 48-byte limit. + * THE PADDING THIS STARTS WITH IS A HORRIBLE HACK THAT SHOULD NOT LIVE + * TO SEE THE DAY. */ struct hostap_skb_tx_data { + unsigned int __padding_for_default_qdiscs; u32 magic; /* HOSTAP_SKB_TX_DATA_MAGIC */ u8 rate; /* transmit rate */ #define HOSTAP_TX_FLAGS_WDS BIT(0) -- cgit v1.2.3 From e23a59e1ca6d177a57a7791b3629db93ff1d9813 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 12 Nov 2008 14:32:54 -0800 Subject: niu: Fix readq implementation when architecture does not provide one. This fixes a TX hang reported by Jesper Dangaard Brouer. When an architecutre cannot provide a fully functional 64-bit atomic readq/writeq, the driver must implement it's own. This is because only the driver can say whether doing something like using two 32-bit reads to implement the full 64-bit read will actually work properly. In particular one of the issues is whether the top 32-bits or the bottom 32-bits of the 64-bit register should be read first. There could be side effects, and in fact that is exactly the problem here. The TX_CS register has counters in the upper 32-bits and state bits in the lower 32-bits. A read clears the state bits. We would read the counter half before the state bit half. That first read would clear the state bits, and then the driver thinks that no interrupts are pending because the interrupt indication state bits are seen clear every time. Fix this by reading the bottom half before the upper half. Tested-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- drivers/net/niu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 9acb5d70a3a..d8463b1c3df 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -51,8 +51,7 @@ MODULE_VERSION(DRV_MODULE_VERSION); #ifndef readq static u64 readq(void __iomem *reg) { - return (((u64)readl(reg + 0x4UL) << 32) | - (u64)readl(reg)); + return ((u64) readl(reg)) | (((u64) readl(reg + 4UL)) << 32); } static void writeq(u64 val, void __iomem *reg) -- cgit v1.2.3 From b2af2c1d3e4ddeea9d02c46d0df0c322cc7b7061 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Wed, 12 Nov 2008 16:23:44 -0800 Subject: bnx2: fix poll_controller to pass proper structures and check all rx queues Fix bnx2 so that netpoll works properly. Specifically: 1) Fix parameters to bnx2_interrupt to be a struct bnx2_napi rather than a struct net_device 2) Fix poll_controller method to check every queue in the rx case so frames aren't missed Signed-off-by: Neil Horman Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 430d430bce2..d07e3f14895 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -7204,10 +7204,13 @@ static void poll_bnx2(struct net_device *dev) { struct bnx2 *bp = netdev_priv(dev); + int i; - disable_irq(bp->pdev->irq); - bnx2_interrupt(bp->pdev->irq, dev); - enable_irq(bp->pdev->irq); + for (i = 0; i < bp->irq_nvecs; i++) { + disable_irq(bp->irq_tbl[i].vector); + bnx2_interrupt(bp->irq_tbl[i].vector, &bp->bnx2_napi[i]); + enable_irq(bp->irq_tbl[i].vector); + } } #endif -- cgit v1.2.3 From 468cc0320ed083e26364d9febde2679d981ed6a6 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Wed, 12 Nov 2008 13:24:58 -0800 Subject: hwmon: applesmc: add support for Macbook 4 This patch adds accelerometer and temperature sensor support for Macbook 4. Signed-off-by: Henrik Rydberg Cc: Nicolas Boichat Signed-off-by: Linus Torvalds --- drivers/hwmon/applesmc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index be3285912cb..488e45cd43d 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -1280,7 +1280,7 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { { .accelerometer = 0, .light = 0, .temperature_set = 4 }, /* iMac: temperature set 5 */ { .accelerometer = 0, .light = 0, .temperature_set = 5 }, -/* MacBook3: accelerometer and temperature set 6 */ +/* MacBook3, MacBook4: accelerometer and temperature set 6 */ { .accelerometer = 1, .light = 0, .temperature_set = 6 }, /* MacBook Air: accelerometer, backlight and temperature set 7 */ { .accelerometer = 1, .light = 1, .temperature_set = 7 }, @@ -1329,6 +1329,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") }, &applesmc_dmi_data[6]}, + { applesmc_dmi_match, "Apple MacBook 4", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4") }, + &applesmc_dmi_data[6]}, { applesmc_dmi_match, "Apple MacBook 5", { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5") }, -- cgit v1.2.3 From fe2d5ffc74a1de6a31e9fd65b65cce72d881edf7 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Wed, 12 Nov 2008 13:25:00 -0800 Subject: Fix platform drivers that crash on suspend/resume It turns out that if one registers a struct platform_device, the platform device code expects that platform_device.device->driver points to a struct driver inside a struct platform_driver. This is not the case with the ipmi-si, ipmi-msghandler and ibmaem drivers, which causes the suspend/resume hook functions to jump off into nowhere, causing a crash. Make this assumption hold true for these three drivers. Signed-off-by: Darrick J. Wong Acked-by: Corey Minyard Cc: Jean Delvare Cc: Kay Sievers Cc: Greg KH Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 20 +++++++++++--------- drivers/char/ipmi/ipmi_si_intf.c | 16 +++++++++------- drivers/hwmon/ibmaem.c | 18 ++++++++++-------- 3 files changed, 30 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 8a59aaa21be..7a88dfd4427 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -422,9 +422,11 @@ struct ipmi_smi { /** * The driver model view of the IPMI messaging driver. */ -static struct device_driver ipmidriver = { - .name = "ipmi", - .bus = &platform_bus_type +static struct platform_driver ipmidriver = { + .driver = { + .name = "ipmi", + .bus = &platform_bus_type + } }; static DEFINE_MUTEX(ipmidriver_mutex); @@ -2384,9 +2386,9 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, * representing the interfaced BMC already */ if (bmc->guid_set) - old_bmc = ipmi_find_bmc_guid(&ipmidriver, bmc->guid); + old_bmc = ipmi_find_bmc_guid(&ipmidriver.driver, bmc->guid); else - old_bmc = ipmi_find_bmc_prod_dev_id(&ipmidriver, + old_bmc = ipmi_find_bmc_prod_dev_id(&ipmidriver.driver, bmc->id.product_id, bmc->id.device_id); @@ -2416,7 +2418,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, snprintf(name, sizeof(name), "ipmi_bmc.%4.4x", bmc->id.product_id); - while (ipmi_find_bmc_prod_dev_id(&ipmidriver, + while (ipmi_find_bmc_prod_dev_id(&ipmidriver.driver, bmc->id.product_id, bmc->id.device_id)) { if (!warn_printed) { @@ -2446,7 +2448,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, " Unable to allocate platform device\n"); return -ENOMEM; } - bmc->dev->dev.driver = &ipmidriver; + bmc->dev->dev.driver = &ipmidriver.driver; dev_set_drvdata(&bmc->dev->dev, bmc); kref_init(&bmc->refcount); @@ -4247,7 +4249,7 @@ static int ipmi_init_msghandler(void) if (initialized) return 0; - rv = driver_register(&ipmidriver); + rv = driver_register(&ipmidriver.driver); if (rv) { printk(KERN_ERR PFX "Could not register IPMI driver\n"); return rv; @@ -4308,7 +4310,7 @@ static __exit void cleanup_ipmi(void) remove_proc_entry(proc_ipmi_root->name, NULL); #endif /* CONFIG_PROC_FS */ - driver_unregister(&ipmidriver); + driver_unregister(&ipmidriver.driver); initialized = 0; diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 3123bf57ad9..3000135f2ea 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -114,9 +114,11 @@ static char *si_to_str[] = { "kcs", "smic", "bt" }; #define DEVICE_NAME "ipmi_si" -static struct device_driver ipmi_driver = { - .name = DEVICE_NAME, - .bus = &platform_bus_type +static struct platform_driver ipmi_driver = { + .driver = { + .name = DEVICE_NAME, + .bus = &platform_bus_type + } }; @@ -2868,7 +2870,7 @@ static int try_smi_init(struct smi_info *new_smi) goto out_err; } new_smi->dev = &new_smi->pdev->dev; - new_smi->dev->driver = &ipmi_driver; + new_smi->dev->driver = &ipmi_driver.driver; rv = platform_device_add(new_smi->pdev); if (rv) { @@ -2983,7 +2985,7 @@ static __devinit int init_ipmi_si(void) initialized = 1; /* Register the device drivers. */ - rv = driver_register(&ipmi_driver); + rv = driver_register(&ipmi_driver.driver); if (rv) { printk(KERN_ERR "init_ipmi_si: Unable to register driver: %d\n", @@ -3052,7 +3054,7 @@ static __devinit int init_ipmi_si(void) #ifdef CONFIG_PPC_OF of_unregister_platform_driver(&ipmi_of_platform_driver); #endif - driver_unregister(&ipmi_driver); + driver_unregister(&ipmi_driver.driver); printk(KERN_WARNING "ipmi_si: Unable to find any System Interface(s)\n"); return -ENODEV; @@ -3151,7 +3153,7 @@ static __exit void cleanup_ipmi_si(void) cleanup_one_si(e); mutex_unlock(&smi_infos_lock); - driver_unregister(&ipmi_driver); + driver_unregister(&ipmi_driver.driver); } module_exit(cleanup_ipmi_si); diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c index 7b0ed5dea39..fe74609a7fe 100644 --- a/drivers/hwmon/ibmaem.c +++ b/drivers/hwmon/ibmaem.c @@ -88,9 +88,11 @@ static DEFINE_IDR(aem_idr); static DEFINE_SPINLOCK(aem_idr_lock); -static struct device_driver aem_driver = { - .name = DRVNAME, - .bus = &platform_bus_type, +static struct platform_driver aem_driver = { + .driver = { + .name = DRVNAME, + .bus = &platform_bus_type, + } }; struct aem_ipmi_data { @@ -583,7 +585,7 @@ static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle) data->pdev = platform_device_alloc(DRVNAME, data->id); if (!data->pdev) goto dev_err; - data->pdev->dev.driver = &aem_driver; + data->pdev->dev.driver = &aem_driver.driver; res = platform_device_add(data->pdev); if (res) @@ -716,7 +718,7 @@ static int aem_init_aem2_inst(struct aem_ipmi_data *probe, data->pdev = platform_device_alloc(DRVNAME, data->id); if (!data->pdev) goto dev_err; - data->pdev->dev.driver = &aem_driver; + data->pdev->dev.driver = &aem_driver.driver; res = platform_device_add(data->pdev); if (res) @@ -1085,7 +1087,7 @@ static int __init aem_init(void) { int res; - res = driver_register(&aem_driver); + res = driver_register(&aem_driver.driver); if (res) { printk(KERN_ERR "Can't register aem driver\n"); return res; @@ -1097,7 +1099,7 @@ static int __init aem_init(void) return 0; ipmi_reg_err: - driver_unregister(&aem_driver); + driver_unregister(&aem_driver.driver); return res; } @@ -1107,7 +1109,7 @@ static void __exit aem_exit(void) struct aem_data *p1, *next1; ipmi_smi_watcher_unregister(&driver_data.bmc_events); - driver_unregister(&aem_driver); + driver_unregister(&aem_driver.driver); list_for_each_entry_safe(p1, next1, &driver_data.aem_devices, list) aem_delete(p1); } -- cgit v1.2.3 From f0f7e0dc7393268947dc3ed285defc3d375487b9 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Wed, 12 Nov 2008 13:25:36 -0800 Subject: i5000-edac: hold reference to mci kobject It turns out that edac_mc_del_mc will kobject_put the last kref on the mci object. If the timing is just right, that means that the mci object is freed before before i5000_remove_one has a chance to free the resources associated with it, causing a null pointer exceptions when unloading the driver. Insert a kobject_{get,put} pair so that this doesn't happen. Signed-off-by: Darrick J. Wong Cc: Doug Thompson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/i5000_edac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index f0d9b415db5..d335086f4a2 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c @@ -1381,6 +1381,7 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) if (mci == NULL) return -ENOMEM; + kobject_get(&mci->edac_mci_kobj); debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); mci->dev = &pdev->dev; /* record ptr to the generic device */ @@ -1453,6 +1454,7 @@ fail1: i5000_put_devices(mci); fail0: + kobject_put(&mci->edac_mci_kobj); edac_mc_free(mci); return -ENODEV; } @@ -1498,7 +1500,7 @@ static void __devexit i5000_remove_one(struct pci_dev *pdev) /* retrieve references to resources, and free those resources */ i5000_put_devices(mci); - + kobject_put(&mci->edac_mci_kobj); edac_mc_free(mci); } -- cgit v1.2.3 From 0bcb6069a6e1af5c114a2a8873ec43ada8933596 Mon Sep 17 00:00:00 2001 From: John Linn Date: Wed, 12 Nov 2008 13:25:38 -0800 Subject: GPIO: add new Xilinx driver for powerpc This driver supports the Xilinx XPS GPIO IP core which has the typical GPIO features. Signed-off-by: Kiran Sutariya Signed-off-by: John Linn Cc: David Brownell Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Cc: Kumar Gala Cc: "Grant Likely" Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/gpio/Kconfig | 8 ++ drivers/gpio/Makefile | 1 + drivers/gpio/xilinx_gpio.c | 235 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+) create mode 100644 drivers/gpio/xilinx_gpio.c (limited to 'drivers') diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 7f2ee27fe76..48f49d93d24 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -65,6 +65,14 @@ config GPIO_SYSFS # put expanders in the right section, in alphabetical order +comment "Memory mapped GPIO expanders:" + +config GPIO_XILINX + bool "Xilinx GPIO support" + depends on PPC_OF + help + Say yes here to support the Xilinx FPGA GPIO device + comment "I2C GPIO expanders:" config GPIO_MAX732X diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 6aafdeb9ad0..49ac64e515e 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -10,4 +10,5 @@ obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o obj-$(CONFIG_GPIO_PCA953X) += pca953x.o obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o +obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o diff --git a/drivers/gpio/xilinx_gpio.c b/drivers/gpio/xilinx_gpio.c new file mode 100644 index 00000000000..3c1177abebd --- /dev/null +++ b/drivers/gpio/xilinx_gpio.c @@ -0,0 +1,235 @@ +/* + * Xilinx gpio driver + * + * Copyright 2008 Xilinx, Inc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Register Offset Definitions */ +#define XGPIO_DATA_OFFSET (0x0) /* Data register */ +#define XGPIO_TRI_OFFSET (0x4) /* I/O direction register */ + +struct xgpio_instance { + struct of_mm_gpio_chip mmchip; + u32 gpio_state; /* GPIO state shadow register */ + u32 gpio_dir; /* GPIO direction shadow register */ + spinlock_t gpio_lock; /* Lock used for synchronization */ +}; + +/** + * xgpio_get - Read the specified signal of the GPIO device. + * @gc: Pointer to gpio_chip device structure. + * @gpio: GPIO signal number. + * + * This function reads the specified signal of the GPIO device. It returns 0 if + * the signal clear, 1 if signal is set or negative value on error. + */ +static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) +{ + struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + + return (in_be32(mm_gc->regs + XGPIO_DATA_OFFSET) >> gpio) & 1; +} + +/** + * xgpio_set - Write the specified signal of the GPIO device. + * @gc: Pointer to gpio_chip device structure. + * @gpio: GPIO signal number. + * @val: Value to be written to specified signal. + * + * This function writes the specified value in to the specified signal of the + * GPIO device. + */ +static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +{ + unsigned long flags; + struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + struct xgpio_instance *chip = + container_of(mm_gc, struct xgpio_instance, mmchip); + + spin_lock_irqsave(&chip->gpio_lock, flags); + + /* Write to GPIO signal and set its direction to output */ + if (val) + chip->gpio_state |= 1 << gpio; + else + chip->gpio_state &= ~(1 << gpio); + out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); + + spin_unlock_irqrestore(&chip->gpio_lock, flags); +} + +/** + * xgpio_dir_in - Set the direction of the specified GPIO signal as input. + * @gc: Pointer to gpio_chip device structure. + * @gpio: GPIO signal number. + * + * This function sets the direction of specified GPIO signal as input. + * It returns 0 if direction of GPIO signals is set as input otherwise it + * returns negative error value. + */ +static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) +{ + unsigned long flags; + struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + struct xgpio_instance *chip = + container_of(mm_gc, struct xgpio_instance, mmchip); + + spin_lock_irqsave(&chip->gpio_lock, flags); + + /* Set the GPIO bit in shadow register and set direction as input */ + chip->gpio_dir |= (1 << gpio); + out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); + + spin_unlock_irqrestore(&chip->gpio_lock, flags); + + return 0; +} + +/** + * xgpio_dir_out - Set the direction of the specified GPIO signal as output. + * @gc: Pointer to gpio_chip device structure. + * @gpio: GPIO signal number. + * @val: Value to be written to specified signal. + * + * This function sets the direction of specified GPIO signal as output. If all + * GPIO signals of GPIO chip is configured as input then it returns + * error otherwise it returns 0. + */ +static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) +{ + unsigned long flags; + struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); + struct xgpio_instance *chip = + container_of(mm_gc, struct xgpio_instance, mmchip); + + spin_lock_irqsave(&chip->gpio_lock, flags); + + /* Write state of GPIO signal */ + if (val) + chip->gpio_state |= 1 << gpio; + else + chip->gpio_state &= ~(1 << gpio); + out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); + + /* Clear the GPIO bit in shadow register and set direction as output */ + chip->gpio_dir &= (~(1 << gpio)); + out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); + + spin_unlock_irqrestore(&chip->gpio_lock, flags); + + return 0; +} + +/** + * xgpio_save_regs - Set initial values of GPIO pins + * @mm_gc: pointer to memory mapped GPIO chip structure + */ +static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) +{ + struct xgpio_instance *chip = + container_of(mm_gc, struct xgpio_instance, mmchip); + + out_be32(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); + out_be32(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); +} + +/** + * xgpio_of_probe - Probe method for the GPIO device. + * @np: pointer to device tree node + * + * This function probes the GPIO device in the device tree. It initializes the + * driver data structure. It returns 0, if the driver is bound to the GPIO + * device, or a negative value if there is an error. + */ +static int __devinit xgpio_of_probe(struct device_node *np) +{ + struct xgpio_instance *chip; + struct of_gpio_chip *ofchip; + int status = 0; + const u32 *tree_info; + + chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + ofchip = &chip->mmchip.of_gc; + + /* Update GPIO state shadow register with default value */ + tree_info = of_get_property(np, "xlnx,dout-default", NULL); + if (tree_info) + chip->gpio_state = *tree_info; + + /* Update GPIO direction shadow register with default value */ + chip->gpio_dir = 0xFFFFFFFF; /* By default, all pins are inputs */ + tree_info = of_get_property(np, "xlnx,tri-default", NULL); + if (tree_info) + chip->gpio_dir = *tree_info; + + /* Check device node and parent device node for device width */ + ofchip->gc.ngpio = 32; /* By default assume full GPIO controller */ + tree_info = of_get_property(np, "xlnx,gpio-width", NULL); + if (!tree_info) + tree_info = of_get_property(np->parent, + "xlnx,gpio-width", NULL); + if (tree_info) + ofchip->gc.ngpio = *tree_info; + + spin_lock_init(&chip->gpio_lock); + + ofchip->gpio_cells = 2; + ofchip->gc.direction_input = xgpio_dir_in; + ofchip->gc.direction_output = xgpio_dir_out; + ofchip->gc.get = xgpio_get; + ofchip->gc.set = xgpio_set; + + chip->mmchip.save_regs = xgpio_save_regs; + + /* Call the OF gpio helper to setup and register the GPIO device */ + status = of_mm_gpiochip_add(np, &chip->mmchip); + if (status) { + kfree(chip); + pr_err("%s: error in probe function with status %d\n", + np->full_name, status); + return status; + } + pr_info("XGpio: %s: registered\n", np->full_name); + return 0; +} + +static struct of_device_id xgpio_of_match[] __devinitdata = { + { .compatible = "xlnx,xps-gpio-1.00.a", }, + { /* end of list */ }, +}; + +static int __init xgpio_init(void) +{ + struct device_node *np; + + for_each_matching_node(np, xgpio_of_match) + xgpio_of_probe(np); + + return 0; +} + +/* Make sure we get initialized before anyone else tries to use us */ +subsys_initcall(xgpio_init); +/* No exit call at the moment as we cannot unregister of GPIO chips */ + +MODULE_AUTHOR("Xilinx, Inc."); +MODULE_DESCRIPTION("Xilinx GPIO driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 05a9bd46e49a9cbb09a0c61c901642a9911bf56e Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Wed, 12 Nov 2008 13:26:57 -0800 Subject: adt7470: check input range when sysfs files are written Implement correct range checking for adt7470 to prevent userland from writing impossible values into the chip, and cap out-of-range values per standard hwmon conventions. Implement correct rounding of input values per standard hwmon conventions. Signed-off-by: Darrick J. Wong Cc: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/adt7470.c | 75 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index d368d8f845e..1311a595147 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c @@ -137,6 +137,8 @@ I2C_CLIENT_INSMOD_1(adt7470); #define FAN_PERIOD_INVALID 65535 #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) +#define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor)) + struct adt7470_data { struct device *hwmon_dev; struct attribute_group attrs; @@ -353,7 +355,13 @@ static ssize_t set_temp_min(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7470_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10) / 1000; + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = ROUND_DIV(temp, 1000); + temp = SENSORS_LIMIT(temp, 0, 255); mutex_lock(&data->lock); data->temp_min[attr->index] = temp; @@ -381,7 +389,13 @@ static ssize_t set_temp_max(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7470_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10) / 1000; + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = ROUND_DIV(temp, 1000); + temp = SENSORS_LIMIT(temp, 0, 255); mutex_lock(&data->lock); data->temp_max[attr->index] = temp; @@ -430,11 +444,13 @@ static ssize_t set_fan_max(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7470_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10); + long temp; - if (!temp) + if (strict_strtol(buf, 10, &temp) || !temp) return -EINVAL; + temp = FAN_RPM_TO_PERIOD(temp); + temp = SENSORS_LIMIT(temp, 1, 65534); mutex_lock(&data->lock); data->fan_max[attr->index] = temp; @@ -465,11 +481,13 @@ static ssize_t set_fan_min(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7470_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10); + long temp; - if (!temp) + if (strict_strtol(buf, 10, &temp) || !temp) return -EINVAL; + temp = FAN_RPM_TO_PERIOD(temp); + temp = SENSORS_LIMIT(temp, 1, 65534); mutex_lock(&data->lock); data->fan_min[attr->index] = temp; @@ -507,9 +525,12 @@ static ssize_t set_force_pwm_max(struct device *dev, { struct i2c_client *client = to_i2c_client(dev); struct adt7470_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10); + long temp; u8 reg; + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + mutex_lock(&data->lock); data->force_pwm_max = temp; reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); @@ -537,7 +558,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7470_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = SENSORS_LIMIT(temp, 0, 255); mutex_lock(&data->lock); data->pwm[attr->index] = temp; @@ -564,7 +590,12 @@ static ssize_t set_pwm_max(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7470_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = SENSORS_LIMIT(temp, 0, 255); mutex_lock(&data->lock); data->pwm_max[attr->index] = temp; @@ -592,7 +623,12 @@ static ssize_t set_pwm_min(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7470_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = SENSORS_LIMIT(temp, 0, 255); mutex_lock(&data->lock); data->pwm_min[attr->index] = temp; @@ -630,7 +666,13 @@ static ssize_t set_pwm_tmin(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7470_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10) / 1000; + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = ROUND_DIV(temp, 1000); + temp = SENSORS_LIMIT(temp, 0, 255); mutex_lock(&data->lock); data->pwm_tmin[attr->index] = temp; @@ -658,11 +700,14 @@ static ssize_t set_pwm_auto(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7470_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10); int pwm_auto_reg = ADT7470_REG_PWM_CFG(attr->index); int pwm_auto_reg_mask; + long temp; u8 reg; + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + if (attr->index % 2) pwm_auto_reg_mask = ADT7470_PWM2_AUTO_MASK; else @@ -716,10 +761,14 @@ static ssize_t set_pwm_auto_temp(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7470_data *data = i2c_get_clientdata(client); - int temp = cvt_auto_temp(simple_strtol(buf, NULL, 10)); int pwm_auto_reg = ADT7470_REG_PWM_AUTO_TEMP(attr->index); + long temp; u8 reg; + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = cvt_auto_temp(temp); if (temp < 0) return temp; -- cgit v1.2.3 From 862343c4ea2ece307f25db1812637cff142d3263 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Wed, 12 Nov 2008 13:26:58 -0800 Subject: adt7473: check inputs from sysfs writes Implement correct range checking for adt7470 to prevent userland from writing impossible values into the chip, and cap out-of-range values per standard hwmon conventions. Implement correct rounding of input values per standard hwmon conventions. Signed-off-by: Darrick J. Wong Cc: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/adt7473.c | 89 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/adt7473.c b/drivers/hwmon/adt7473.c index b9a8ea30c99..18aa30866a6 100644 --- a/drivers/hwmon/adt7473.c +++ b/drivers/hwmon/adt7473.c @@ -129,6 +129,8 @@ I2C_CLIENT_INSMOD_1(adt7473); #define FAN_PERIOD_INVALID 65535 #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) +#define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor)) + struct adt7473_data { struct device *hwmon_dev; struct attribute_group attrs; @@ -357,7 +359,12 @@ static ssize_t set_volt_min(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); - int volt = encode_volt(attr->index, simple_strtol(buf, NULL, 10)); + long volt; + + if (strict_strtol(buf, 10, &volt)) + return -EINVAL; + + volt = encode_volt(attr->index, volt); mutex_lock(&data->lock); data->volt_min[attr->index] = volt; @@ -386,7 +393,12 @@ static ssize_t set_volt_max(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); - int volt = encode_volt(attr->index, simple_strtol(buf, NULL, 10)); + long volt; + + if (strict_strtol(buf, 10, &volt)) + return -EINVAL; + + volt = encode_volt(attr->index, volt); mutex_lock(&data->lock); data->volt_max[attr->index] = volt; @@ -419,7 +431,8 @@ static int decode_temp(u8 twos_complement, u8 raw) static u8 encode_temp(u8 twos_complement, int cooked) { - return twos_complement ? cooked & 0xFF : cooked + 64; + u8 ret = twos_complement ? cooked & 0xFF : cooked + 64; + return SENSORS_LIMIT(ret, 0, 255); } static ssize_t show_temp_min(struct device *dev, @@ -441,7 +454,12 @@ static ssize_t set_temp_min(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10) / 1000; + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = ROUND_DIV(temp, 1000); temp = encode_temp(data->temp_twos_complement, temp); mutex_lock(&data->lock); @@ -472,7 +490,12 @@ static ssize_t set_temp_max(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10) / 1000; + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = ROUND_DIV(temp, 1000); temp = encode_temp(data->temp_twos_complement, temp); mutex_lock(&data->lock); @@ -515,11 +538,13 @@ static ssize_t set_fan_min(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10); + long temp; - if (!temp) + if (strict_strtol(buf, 10, &temp) || !temp) return -EINVAL; + temp = FAN_RPM_TO_PERIOD(temp); + temp = SENSORS_LIMIT(temp, 1, 65534); mutex_lock(&data->lock); data->fan_min[attr->index] = temp; @@ -558,7 +583,10 @@ static ssize_t set_max_duty_at_crit(struct device *dev, u8 reg; struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; mutex_lock(&data->lock); data->max_duty_at_overheat = !!temp; @@ -587,7 +615,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = SENSORS_LIMIT(temp, 0, 255); mutex_lock(&data->lock); data->pwm[attr->index] = temp; @@ -614,7 +647,12 @@ static ssize_t set_pwm_max(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = SENSORS_LIMIT(temp, 0, 255); mutex_lock(&data->lock); data->pwm_max[attr->index] = temp; @@ -642,7 +680,12 @@ static ssize_t set_pwm_min(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = SENSORS_LIMIT(temp, 0, 255); mutex_lock(&data->lock); data->pwm_min[attr->index] = temp; @@ -672,7 +715,12 @@ static ssize_t set_temp_tmax(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10) / 1000; + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = ROUND_DIV(temp, 1000); temp = encode_temp(data->temp_twos_complement, temp); mutex_lock(&data->lock); @@ -703,7 +751,12 @@ static ssize_t set_temp_tmin(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10) / 1000; + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = ROUND_DIV(temp, 1000); temp = encode_temp(data->temp_twos_complement, temp); mutex_lock(&data->lock); @@ -741,7 +794,10 @@ static ssize_t set_pwm_enable(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; switch (temp) { case 0: @@ -805,7 +861,10 @@ static ssize_t set_pwm_auto_temp(struct device *dev, struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i2c_client *client = to_i2c_client(dev); struct adt7473_data *data = i2c_get_clientdata(client); - int temp = simple_strtol(buf, NULL, 10); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; switch (temp) { case 1: -- cgit v1.2.3 From 79b92f2bab0dc5ac70e8391548f75ac3268426e4 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Wed, 12 Nov 2008 13:26:59 -0800 Subject: lm85: support adt7468 chips The adt7468 is a follow-on to the adt7463, so plumb in adt7468 support along the same code paths. Signed-off-by: Darrick J. Wong Cc: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/lm85.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 3ff0285396f..cfc1ee90f5a 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -39,7 +39,8 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; /* Insmod parameters */ -I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102); +I2C_CLIENT_INSMOD_7(lm85b, lm85c, adm1027, adt7463, adt7468, emc6d100, + emc6d102); /* The LM85 registers */ @@ -59,6 +60,12 @@ I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102); #define LM85_REG_COMPANY 0x3e #define LM85_REG_VERSTEP 0x3f + +#define ADT7468_REG_CFG5 0x7c +#define ADT7468_OFF64 0x01 +#define IS_ADT7468_OFF64(data) \ + ((data)->type == adt7468 && !((data)->cfg5 & ADT7468_OFF64)) + /* These are the recognized values for the above regs */ #define LM85_COMPANY_NATIONAL 0x01 #define LM85_COMPANY_ANALOG_DEV 0x41 @@ -70,6 +77,8 @@ I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102); #define LM85_VERSTEP_ADM1027 0x60 #define LM85_VERSTEP_ADT7463 0x62 #define LM85_VERSTEP_ADT7463C 0x6A +#define LM85_VERSTEP_ADT7468_1 0x71 +#define LM85_VERSTEP_ADT7468_2 0x72 #define LM85_VERSTEP_EMC6D100_A0 0x60 #define LM85_VERSTEP_EMC6D100_A1 0x61 #define LM85_VERSTEP_EMC6D102 0x65 @@ -306,6 +315,7 @@ struct lm85_data { u8 vid; /* Register value */ u8 vrm; /* VRM version */ u32 alarms; /* Register encoding, combined */ + u8 cfg5; /* Config Register 5 on ADT7468 */ struct lm85_autofan autofan[3]; struct lm85_zone zone[3]; }; @@ -685,6 +695,9 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); + if (IS_ADT7468_OFF64(data)) + val += 64; + mutex_lock(&data->update_lock); data->temp_min[nr] = TEMP_TO_REG(val); lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]); @@ -708,6 +721,9 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, struct lm85_data *data = i2c_get_clientdata(client); long val = simple_strtol(buf, NULL, 10); + if (IS_ADT7468_OFF64(data)) + val += 64; + mutex_lock(&data->update_lock); data->temp_max[nr] = TEMP_TO_REG(val); lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]); @@ -1163,6 +1179,10 @@ static int lm85_detect(struct i2c_client *client, int kind, case LM85_VERSTEP_ADT7463C: kind = adt7463; break; + case LM85_VERSTEP_ADT7468_1: + case LM85_VERSTEP_ADT7468_2: + kind = adt7468; + break; } } else if (company == LM85_COMPANY_SMSC) { switch (verstep) { @@ -1195,6 +1215,9 @@ static int lm85_detect(struct i2c_client *client, int kind, case adt7463: type_name = "adt7463"; break; + case adt7468: + type_name = "adt7468"; + break; case emc6d100: type_name = "emc6d100"; break; @@ -1246,10 +1269,11 @@ static int lm85_probe(struct i2c_client *client, if (err) goto err_kfree; - /* The ADT7463 has an optional VRM 10 mode where pin 21 is used + /* The ADT7463/68 have an optional VRM 10 mode where pin 21 is used as a sixth digital VID input rather than an analog input. */ data->vid = lm85_read_value(client, LM85_REG_VID); - if (!(data->type == adt7463 && (data->vid & 0x80))) + if (!((data->type == adt7463 || data->type == adt7468) && + (data->vid & 0x80))) if ((err = sysfs_create_group(&client->dev.kobj, &lm85_group_in4))) goto err_remove_files; @@ -1357,7 +1381,8 @@ static struct lm85_data *lm85_update_device(struct device *dev) * There are 2 additional resolution bits per channel and we * have room for 4, so we shift them to the left. */ - if (data->type == adm1027 || data->type == adt7463) { + if (data->type == adm1027 || data->type == adt7463 || + data->type == adt7468) { int ext1 = lm85_read_value(client, ADM1027_REG_EXTEND_ADC1); int ext2 = lm85_read_value(client, @@ -1382,16 +1407,23 @@ static struct lm85_data *lm85_update_device(struct device *dev) lm85_read_value(client, LM85_REG_FAN(i)); } - if (!(data->type == adt7463 && (data->vid & 0x80))) { + if (!((data->type == adt7463 || data->type == adt7468) && + (data->vid & 0x80))) { data->in[4] = lm85_read_value(client, LM85_REG_IN(4)); } + if (data->type == adt7468) + data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5); + for (i = 0; i <= 2; ++i) { data->temp[i] = lm85_read_value(client, LM85_REG_TEMP(i)); data->pwm[i] = lm85_read_value(client, LM85_REG_PWM(i)); + + if (IS_ADT7468_OFF64(data)) + data->temp[i] -= 64; } data->alarms = lm85_read_value(client, LM85_REG_ALARM1); @@ -1446,7 +1478,8 @@ static struct lm85_data *lm85_update_device(struct device *dev) lm85_read_value(client, LM85_REG_FAN_MIN(i)); } - if (!(data->type == adt7463 && (data->vid & 0x80))) { + if (!((data->type == adt7463 || data->type == adt7468) && + (data->vid & 0x80))) { data->in_min[4] = lm85_read_value(client, LM85_REG_IN_MIN(4)); data->in_max[4] = lm85_read_value(client, @@ -1481,6 +1514,13 @@ static struct lm85_data *lm85_update_device(struct device *dev) lm85_read_value(client, LM85_REG_AFAN_LIMIT(i)); data->zone[i].critical = lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i)); + + if (IS_ADT7468_OFF64(data)) { + data->temp_min[i] -= 64; + data->temp_max[i] -= 64; + data->zone[i].limit -= 64; + data->zone[i].critical -= 64; + } } i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1); -- cgit v1.2.3 From 50d7d5bf3168db5d04566dd7ffb9a820e9fdf484 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Lallemand Date: Wed, 12 Nov 2008 13:27:00 -0800 Subject: atmel_spi: work-around required for new HW bug in AT91SAM9263 Rev.B SPI controller We're working with an AT91SAM9263 Rev B in our design and I experienced some inconsistency in spi-based touchscreen usage between our board and the Atmel evaluation kit we have that runs on a Rev A chip. The data was apparently delayed by 1 byte and got ridiculous data out of the touchscreen driver, very strange. As everything looked normal in the spi, touchscreen and dma logs, I contacted the Atmel support and they triggered me on a new HW bug that appeared in the Rev B SPI controller. The problem is that the SPI controller on the Rev B needs that the software reset is performed two times so that it's performed correctly. Applying the patch below solves the issue on my Rev B board. I've tested it as well on my Rev A evaluation kit and it has apparently no unwanted side effect, things continue to work as expected. Signed-off-by: Haavard Skinnemoen Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/atmel_spi.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 02f9320f3ef..8abae4ad0fa 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -766,6 +766,7 @@ static int __init atmel_spi_probe(struct platform_device *pdev) /* Initialize the hardware */ clk_enable(clk); spi_writel(as, CR, SPI_BIT(SWRST)); + spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS)); spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); spi_writel(as, CR, SPI_BIT(SPIEN)); @@ -782,6 +783,7 @@ static int __init atmel_spi_probe(struct platform_device *pdev) out_reset_hw: spi_writel(as, CR, SPI_BIT(SWRST)); + spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ clk_disable(clk); free_irq(irq, master); out_unmap_regs: @@ -805,6 +807,7 @@ static int __exit atmel_spi_remove(struct platform_device *pdev) spin_lock_irq(&as->lock); as->stopping = 1; spi_writel(as, CR, SPI_BIT(SWRST)); + spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ spi_readl(as, SR); spin_unlock_irq(&as->lock); -- cgit v1.2.3 From 455fbdd376c3ed3a5be8c039348896fdd87e9930 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Wed, 12 Nov 2008 13:27:02 -0800 Subject: LIS3LV02Dx Accelerometer driver This adds a driver to the accelerometer sensor found in several HP laptops (under the commercial names of "HP Mobile Data Protection System 3D" and "HP 3D driveguard"). It tries to have more or less the same interfaces as the hdaps and other accelerometer drivers: in sysfs and as a joystick. This driver was first written by Yan Burman. Eric Piel has updated it and slimed it up (including the removal of an interface to access to the free-fall feature of the sensor because it is not reliable enough for now). Pavel Machek removed few more features and switched locking from semaphore to mutex. Several people have contributed to the database of the axes. [eric.piel@tremplin-utc.net: LIS3LV02D: Conform to the new ACPI API] Signed-off-by: Eric Piel Signed-off-by: Yan Burman Signed-off-by: Pavel Machek Cc: "Mark M. Hoffman" Signed-off-by: Eric Piel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/Kconfig | 19 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/lis3lv02d.c | 582 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/hwmon/lis3lv02d.h | 149 ++++++++++++ 4 files changed, 751 insertions(+) create mode 100644 drivers/hwmon/lis3lv02d.c create mode 100644 drivers/hwmon/lis3lv02d.h (limited to 'drivers') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 6de1e0ffd39..1c44f5c47aa 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -825,6 +825,25 @@ config SENSORS_HDAPS Say Y here if you have an applicable laptop and want to experience the awesome power of hdaps. +config SENSORS_LIS3LV02D + tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer" + depends on ACPI && INPUT + default n + help + This driver provides support for the LIS3LV02Dx accelerometer. In + particular, it can be found in a number of HP laptops, which have the + "Mobile Data Protection System 3D" or "3D DriveGuard" feature. On such + systems the driver should load automatically (via ACPI). The + accelerometer might also be found in other systems, connected via SPI + or I2C. The accelerometer data is readable via + /sys/devices/platform/lis3lv02d. + + This driver also provides an absolute input class device, allowing + the laptop to act as a pinball machine-esque joystick. + + This driver can also be built as a module. If so, the module + will be called lis3lv02d. + config SENSORS_APPLESMC tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)" depends on INPUT && X86 diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 042d5a78622..e0d90a68bea 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o obj-$(CONFIG_SENSORS_IT87) += it87.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o +obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o obj-$(CONFIG_SENSORS_LM63) += lm63.o obj-$(CONFIG_SENSORS_LM70) += lm70.o obj-$(CONFIG_SENSORS_LM75) += lm75.o diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c new file mode 100644 index 00000000000..752b5c44df9 --- /dev/null +++ b/drivers/hwmon/lis3lv02d.c @@ -0,0 +1,582 @@ +/* + * lis3lv02d.c - ST LIS3LV02DL accelerometer driver + * + * Copyright (C) 2007-2008 Yan Burman + * Copyright (C) 2008 Eric Piel + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lis3lv02d.h" + +#define DRIVER_NAME "lis3lv02d" +#define ACPI_MDPS_CLASS "accelerometer" + +/* joystick device poll interval in milliseconds */ +#define MDPS_POLL_INTERVAL 50 +/* + * The sensor can also generate interrupts (DRDY) but it's pretty pointless + * because their are generated even if the data do not change. So it's better + * to keep the interrupt for the free-fall event. The values are updated at + * 40Hz (at the lowest frequency), but as it can be pretty time consuming on + * some low processor, we poll the sensor only at 20Hz... enough for the + * joystick. + */ + +/* Maximum value our axis may get for the input device (signed 12 bits) */ +#define MDPS_MAX_VAL 2048 + +struct axis_conversion { + s8 x; + s8 y; + s8 z; +}; + +struct acpi_lis3lv02d { + struct acpi_device *device; /* The ACPI device */ + struct input_dev *idev; /* input device */ + struct task_struct *kthread; /* kthread for input */ + struct mutex lock; + struct platform_device *pdev; /* platform device */ + atomic_t count; /* interrupt count after last read */ + int xcalib; /* calibrated null value for x */ + int ycalib; /* calibrated null value for y */ + int zcalib; /* calibrated null value for z */ + unsigned char is_on; /* whether the device is on or off */ + unsigned char usage; /* usage counter */ + struct axis_conversion ac; /* hw -> logical axis */ +}; + +static struct acpi_lis3lv02d adev; + +static int lis3lv02d_remove_fs(void); +static int lis3lv02d_add_fs(struct acpi_device *device); + +/* For automatic insertion of the module */ +static struct acpi_device_id lis3lv02d_device_ids[] = { + {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids); + +/** + * lis3lv02d_acpi_init - ACPI _INI method: initialize the device. + * @handle: the handle of the device + * + * Returns AE_OK on success. + */ +static inline acpi_status lis3lv02d_acpi_init(acpi_handle handle) +{ + return acpi_evaluate_object(handle, METHOD_NAME__INI, NULL, NULL); +} + +/** + * lis3lv02d_acpi_read - ACPI ALRD method: read a register + * @handle: the handle of the device + * @reg: the register to read + * @ret: result of the operation + * + * Returns AE_OK on success. + */ +static acpi_status lis3lv02d_acpi_read(acpi_handle handle, int reg, u8 *ret) +{ + union acpi_object arg0 = { ACPI_TYPE_INTEGER }; + struct acpi_object_list args = { 1, &arg0 }; + unsigned long long lret; + acpi_status status; + + arg0.integer.value = reg; + + status = acpi_evaluate_integer(handle, "ALRD", &args, &lret); + *ret = lret; + return status; +} + +/** + * lis3lv02d_acpi_write - ACPI ALWR method: write to a register + * @handle: the handle of the device + * @reg: the register to write to + * @val: the value to write + * + * Returns AE_OK on success. + */ +static acpi_status lis3lv02d_acpi_write(acpi_handle handle, int reg, u8 val) +{ + unsigned long long ret; /* Not used when writting */ + union acpi_object in_obj[2]; + struct acpi_object_list args = { 2, in_obj }; + + in_obj[0].type = ACPI_TYPE_INTEGER; + in_obj[0].integer.value = reg; + in_obj[1].type = ACPI_TYPE_INTEGER; + in_obj[1].integer.value = val; + + return acpi_evaluate_integer(handle, "ALWR", &args, &ret); +} + +static s16 lis3lv02d_read_16(acpi_handle handle, int reg) +{ + u8 lo, hi; + + lis3lv02d_acpi_read(handle, reg, &lo); + lis3lv02d_acpi_read(handle, reg + 1, &hi); + /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */ + return (s16)((hi << 8) | lo); +} + +/** + * lis3lv02d_get_axis - For the given axis, give the value converted + * @axis: 1,2,3 - can also be negative + * @hw_values: raw values returned by the hardware + * + * Returns the converted value. + */ +static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3]) +{ + if (axis > 0) + return hw_values[axis - 1]; + else + return -hw_values[-axis - 1]; +} + +/** + * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer + * @handle: the handle to the device + * @x: where to store the X axis value + * @y: where to store the Y axis value + * @z: where to store the Z axis value + * + * Note that 40Hz input device can eat up about 10% CPU at 800MHZ + */ +static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z) +{ + int position[3]; + + position[0] = lis3lv02d_read_16(handle, OUTX_L); + position[1] = lis3lv02d_read_16(handle, OUTY_L); + position[2] = lis3lv02d_read_16(handle, OUTZ_L); + + *x = lis3lv02d_get_axis(adev.ac.x, position); + *y = lis3lv02d_get_axis(adev.ac.y, position); + *z = lis3lv02d_get_axis(adev.ac.z, position); +} + +static inline void lis3lv02d_poweroff(acpi_handle handle) +{ + adev.is_on = 0; + /* disable X,Y,Z axis and power down */ + lis3lv02d_acpi_write(handle, CTRL_REG1, 0x00); +} + +static void lis3lv02d_poweron(acpi_handle handle) +{ + u8 val; + + adev.is_on = 1; + lis3lv02d_acpi_init(handle); + lis3lv02d_acpi_write(handle, FF_WU_CFG, 0); + /* + * BDU: LSB and MSB values are not updated until both have been read. + * So the value read will always be correct. + * IEN: Interrupt for free-fall and DD, not for data-ready. + */ + lis3lv02d_acpi_read(handle, CTRL_REG2, &val); + val |= CTRL2_BDU | CTRL2_IEN; + lis3lv02d_acpi_write(handle, CTRL_REG2, val); +} + +#ifdef CONFIG_PM +static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state) +{ + /* make sure the device is off when we suspend */ + lis3lv02d_poweroff(device->handle); + return 0; +} + +static int lis3lv02d_resume(struct acpi_device *device) +{ + /* put back the device in the right state (ACPI might turn it on) */ + mutex_lock(&adev.lock); + if (adev.usage > 0) + lis3lv02d_poweron(device->handle); + else + lis3lv02d_poweroff(device->handle); + mutex_unlock(&adev.lock); + return 0; +} +#else +#define lis3lv02d_suspend NULL +#define lis3lv02d_resume NULL +#endif + + +/* + * To be called before starting to use the device. It makes sure that the + * device will always be on until a call to lis3lv02d_decrease_use(). Not to be + * used from interrupt context. + */ +static void lis3lv02d_increase_use(struct acpi_lis3lv02d *dev) +{ + mutex_lock(&dev->lock); + dev->usage++; + if (dev->usage == 1) { + if (!dev->is_on) + lis3lv02d_poweron(dev->device->handle); + } + mutex_unlock(&dev->lock); +} + +/* + * To be called whenever a usage of the device is stopped. + * It will make sure to turn off the device when there is not usage. + */ +static void lis3lv02d_decrease_use(struct acpi_lis3lv02d *dev) +{ + mutex_lock(&dev->lock); + dev->usage--; + if (dev->usage == 0) + lis3lv02d_poweroff(dev->device->handle); + mutex_unlock(&dev->lock); +} + +/** + * lis3lv02d_joystick_kthread - Kthread polling function + * @data: unused - here to conform to threadfn prototype + */ +static int lis3lv02d_joystick_kthread(void *data) +{ + int x, y, z; + + while (!kthread_should_stop()) { + lis3lv02d_get_xyz(adev.device->handle, &x, &y, &z); + input_report_abs(adev.idev, ABS_X, x - adev.xcalib); + input_report_abs(adev.idev, ABS_Y, y - adev.ycalib); + input_report_abs(adev.idev, ABS_Z, z - adev.zcalib); + + input_sync(adev.idev); + + try_to_freeze(); + msleep_interruptible(MDPS_POLL_INTERVAL); + } + + return 0; +} + +static int lis3lv02d_joystick_open(struct input_dev *input) +{ + lis3lv02d_increase_use(&adev); + adev.kthread = kthread_run(lis3lv02d_joystick_kthread, NULL, "klis3lv02d"); + if (IS_ERR(adev.kthread)) { + lis3lv02d_decrease_use(&adev); + return PTR_ERR(adev.kthread); + } + + return 0; +} + +static void lis3lv02d_joystick_close(struct input_dev *input) +{ + kthread_stop(adev.kthread); + lis3lv02d_decrease_use(&adev); +} + + +static inline void lis3lv02d_calibrate_joystick(void) +{ + lis3lv02d_get_xyz(adev.device->handle, &adev.xcalib, &adev.ycalib, &adev.zcalib); +} + +static int lis3lv02d_joystick_enable(void) +{ + int err; + + if (adev.idev) + return -EINVAL; + + adev.idev = input_allocate_device(); + if (!adev.idev) + return -ENOMEM; + + lis3lv02d_calibrate_joystick(); + + adev.idev->name = "ST LIS3LV02DL Accelerometer"; + adev.idev->phys = DRIVER_NAME "/input0"; + adev.idev->id.bustype = BUS_HOST; + adev.idev->id.vendor = 0; + adev.idev->dev.parent = &adev.pdev->dev; + adev.idev->open = lis3lv02d_joystick_open; + adev.idev->close = lis3lv02d_joystick_close; + + set_bit(EV_ABS, adev.idev->evbit); + input_set_abs_params(adev.idev, ABS_X, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3); + input_set_abs_params(adev.idev, ABS_Y, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3); + input_set_abs_params(adev.idev, ABS_Z, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3); + + err = input_register_device(adev.idev); + if (err) { + input_free_device(adev.idev); + adev.idev = NULL; + } + + return err; +} + +static void lis3lv02d_joystick_disable(void) +{ + if (!adev.idev) + return; + + input_unregister_device(adev.idev); + adev.idev = NULL; +} + + +/* + * Initialise the accelerometer and the various subsystems. + * Should be rather independant of the bus system. + */ +static int lis3lv02d_init_device(struct acpi_lis3lv02d *dev) +{ + mutex_init(&dev->lock); + lis3lv02d_add_fs(dev->device); + lis3lv02d_increase_use(dev); + + if (lis3lv02d_joystick_enable()) + printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n"); + + lis3lv02d_decrease_use(dev); + return 0; +} + +static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi) +{ + adev.ac = *((struct axis_conversion *)dmi->driver_data); + printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident); + + return 1; +} + +/* Represents, for each axis seen by userspace, the corresponding hw axis (+1). + * If the value is negative, the opposite of the hw value is used. */ +static struct axis_conversion lis3lv02d_axis_normal = {1, 2, 3}; +static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3}; +static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3}; +static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3}; +static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3}; +static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3}; + +#define AXIS_DMI_MATCH(_ident, _name, _axis) { \ + .ident = _ident, \ + .callback = lis3lv02d_dmi_matched, \ + .matches = { \ + DMI_MATCH(DMI_PRODUCT_NAME, _name) \ + }, \ + .driver_data = &lis3lv02d_axis_##_axis \ +} +static struct dmi_system_id lis3lv02d_dmi_ids[] = { + /* product names are truncated to match all kinds of a same model */ + AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted), + AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted), + AXIS_DMI_MATCH("NX9420", "HP Compaq nx9420", x_inverted), + AXIS_DMI_MATCH("NW9440", "HP Compaq nw9440", x_inverted), + AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted), + AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted), + AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left), + { NULL, } +/* Laptop models without axis info (yet): + * "NC651xx" "HP Compaq 651" + * "NC671xx" "HP Compaq 671" + * "NC6910" "HP Compaq 6910" + * HP Compaq 8710x Notebook PC / Mobile Workstation + * "NC2400" "HP Compaq nc2400" + * "NX74x0" "HP Compaq nx74" + * "NX6325" "HP Compaq nx6325" + * "NC4400" "HP Compaq nc4400" + */ +}; + +static int lis3lv02d_add(struct acpi_device *device) +{ + u8 val; + + if (!device) + return -EINVAL; + + adev.device = device; + strcpy(acpi_device_name(device), DRIVER_NAME); + strcpy(acpi_device_class(device), ACPI_MDPS_CLASS); + device->driver_data = &adev; + + lis3lv02d_acpi_read(device->handle, WHO_AM_I, &val); + if ((val != LIS3LV02DL_ID) && (val != LIS302DL_ID)) { + printk(KERN_ERR DRIVER_NAME + ": Accelerometer chip not LIS3LV02D{L,Q}\n"); + } + + /* If possible use a "standard" axes order */ + if (dmi_check_system(lis3lv02d_dmi_ids) == 0) { + printk(KERN_INFO DRIVER_NAME ": laptop model unknown, " + "using default axes configuration\n"); + adev.ac = lis3lv02d_axis_normal; + } + + return lis3lv02d_init_device(&adev); +} + +static int lis3lv02d_remove(struct acpi_device *device, int type) +{ + if (!device) + return -EINVAL; + + lis3lv02d_joystick_disable(); + lis3lv02d_poweroff(device->handle); + + return lis3lv02d_remove_fs(); +} + + +/* Sysfs stuff */ +static ssize_t lis3lv02d_position_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int x, y, z; + + lis3lv02d_increase_use(&adev); + lis3lv02d_get_xyz(adev.device->handle, &x, &y, &z); + lis3lv02d_decrease_use(&adev); + return sprintf(buf, "(%d,%d,%d)\n", x, y, z); +} + +static ssize_t lis3lv02d_calibrate_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "(%d,%d,%d)\n", adev.xcalib, adev.ycalib, adev.zcalib); +} + +static ssize_t lis3lv02d_calibrate_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + lis3lv02d_increase_use(&adev); + lis3lv02d_calibrate_joystick(); + lis3lv02d_decrease_use(&adev); + return count; +} + +/* conversion btw sampling rate and the register values */ +static int lis3lv02dl_df_val[4] = {40, 160, 640, 2560}; +static ssize_t lis3lv02d_rate_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 ctrl; + int val; + + lis3lv02d_increase_use(&adev); + lis3lv02d_acpi_read(adev.device->handle, CTRL_REG1, &ctrl); + lis3lv02d_decrease_use(&adev); + val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4; + return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]); +} + +static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL); +static DEVICE_ATTR(calibrate, S_IRUGO|S_IWUSR, lis3lv02d_calibrate_show, + lis3lv02d_calibrate_store); +static DEVICE_ATTR(rate, S_IRUGO, lis3lv02d_rate_show, NULL); + +static struct attribute *lis3lv02d_attributes[] = { + &dev_attr_position.attr, + &dev_attr_calibrate.attr, + &dev_attr_rate.attr, + NULL +}; + +static struct attribute_group lis3lv02d_attribute_group = { + .attrs = lis3lv02d_attributes +}; + +static int lis3lv02d_add_fs(struct acpi_device *device) +{ + adev.pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); + if (IS_ERR(adev.pdev)) + return PTR_ERR(adev.pdev); + + return sysfs_create_group(&adev.pdev->dev.kobj, &lis3lv02d_attribute_group); +} + +static int lis3lv02d_remove_fs(void) +{ + sysfs_remove_group(&adev.pdev->dev.kobj, &lis3lv02d_attribute_group); + platform_device_unregister(adev.pdev); + return 0; +} + +/* For the HP MDPS aka 3D Driveguard */ +static struct acpi_driver lis3lv02d_driver = { + .name = DRIVER_NAME, + .class = ACPI_MDPS_CLASS, + .ids = lis3lv02d_device_ids, + .ops = { + .add = lis3lv02d_add, + .remove = lis3lv02d_remove, + .suspend = lis3lv02d_suspend, + .resume = lis3lv02d_resume, + } +}; + +static int __init lis3lv02d_init_module(void) +{ + int ret; + + if (acpi_disabled) + return -ENODEV; + + ret = acpi_bus_register_driver(&lis3lv02d_driver); + if (ret < 0) + return ret; + + printk(KERN_INFO DRIVER_NAME " driver loaded.\n"); + + return 0; +} + +static void __exit lis3lv02d_exit_module(void) +{ + acpi_bus_unregister_driver(&lis3lv02d_driver); +} + +MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver"); +MODULE_AUTHOR("Yan Burman and Eric Piel"); +MODULE_LICENSE("GPL"); + +module_init(lis3lv02d_init_module); +module_exit(lis3lv02d_exit_module); diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h new file mode 100644 index 00000000000..330cfc60e94 --- /dev/null +++ b/drivers/hwmon/lis3lv02d.h @@ -0,0 +1,149 @@ +/* + * lis3lv02d.h - ST LIS3LV02DL accelerometer driver + * + * Copyright (C) 2007-2008 Yan Burman + * Copyright (C) 2008 Eric Piel + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * The actual chip is STMicroelectronics LIS3LV02DL or LIS3LV02DQ that seems to + * be connected via SPI. There exists also several similar chips (such as LIS302DL or + * LIS3L02DQ) but not in the HP laptops and they have slightly different registers. + * They can also be connected via I²C. + */ + +#define LIS3LV02DL_ID 0x3A /* Also the LIS3LV02DQ */ +#define LIS302DL_ID 0x3B /* Also the LIS202DL! */ + +enum lis3lv02d_reg { + WHO_AM_I = 0x0F, + OFFSET_X = 0x16, + OFFSET_Y = 0x17, + OFFSET_Z = 0x18, + GAIN_X = 0x19, + GAIN_Y = 0x1A, + GAIN_Z = 0x1B, + CTRL_REG1 = 0x20, + CTRL_REG2 = 0x21, + CTRL_REG3 = 0x22, + HP_FILTER_RESET = 0x23, + STATUS_REG = 0x27, + OUTX_L = 0x28, + OUTX_H = 0x29, + OUTY_L = 0x2A, + OUTY_H = 0x2B, + OUTZ_L = 0x2C, + OUTZ_H = 0x2D, + FF_WU_CFG = 0x30, + FF_WU_SRC = 0x31, + FF_WU_ACK = 0x32, + FF_WU_THS_L = 0x34, + FF_WU_THS_H = 0x35, + FF_WU_DURATION = 0x36, + DD_CFG = 0x38, + DD_SRC = 0x39, + DD_ACK = 0x3A, + DD_THSI_L = 0x3C, + DD_THSI_H = 0x3D, + DD_THSE_L = 0x3E, + DD_THSE_H = 0x3F, +}; + +enum lis3lv02d_ctrl1 { + CTRL1_Xen = 0x01, + CTRL1_Yen = 0x02, + CTRL1_Zen = 0x04, + CTRL1_ST = 0x08, + CTRL1_DF0 = 0x10, + CTRL1_DF1 = 0x20, + CTRL1_PD0 = 0x40, + CTRL1_PD1 = 0x80, +}; +enum lis3lv02d_ctrl2 { + CTRL2_DAS = 0x01, + CTRL2_SIM = 0x02, + CTRL2_DRDY = 0x04, + CTRL2_IEN = 0x08, + CTRL2_BOOT = 0x10, + CTRL2_BLE = 0x20, + CTRL2_BDU = 0x40, /* Block Data Update */ + CTRL2_FS = 0x80, /* Full Scale selection */ +}; + + +enum lis3lv02d_ctrl3 { + CTRL3_CFS0 = 0x01, + CTRL3_CFS1 = 0x02, + CTRL3_FDS = 0x10, + CTRL3_HPFF = 0x20, + CTRL3_HPDD = 0x40, + CTRL3_ECK = 0x80, +}; + +enum lis3lv02d_status_reg { + STATUS_XDA = 0x01, + STATUS_YDA = 0x02, + STATUS_ZDA = 0x04, + STATUS_XYZDA = 0x08, + STATUS_XOR = 0x10, + STATUS_YOR = 0x20, + STATUS_ZOR = 0x40, + STATUS_XYZOR = 0x80, +}; + +enum lis3lv02d_ff_wu_cfg { + FF_WU_CFG_XLIE = 0x01, + FF_WU_CFG_XHIE = 0x02, + FF_WU_CFG_YLIE = 0x04, + FF_WU_CFG_YHIE = 0x08, + FF_WU_CFG_ZLIE = 0x10, + FF_WU_CFG_ZHIE = 0x20, + FF_WU_CFG_LIR = 0x40, + FF_WU_CFG_AOI = 0x80, +}; + +enum lis3lv02d_ff_wu_src { + FF_WU_SRC_XL = 0x01, + FF_WU_SRC_XH = 0x02, + FF_WU_SRC_YL = 0x04, + FF_WU_SRC_YH = 0x08, + FF_WU_SRC_ZL = 0x10, + FF_WU_SRC_ZH = 0x20, + FF_WU_SRC_IA = 0x40, +}; + +enum lis3lv02d_dd_cfg { + DD_CFG_XLIE = 0x01, + DD_CFG_XHIE = 0x02, + DD_CFG_YLIE = 0x04, + DD_CFG_YHIE = 0x08, + DD_CFG_ZLIE = 0x10, + DD_CFG_ZHIE = 0x20, + DD_CFG_LIR = 0x40, + DD_CFG_IEND = 0x80, +}; + +enum lis3lv02d_dd_src { + DD_SRC_XL = 0x01, + DD_SRC_XH = 0x02, + DD_SRC_YL = 0x04, + DD_SRC_YH = 0x08, + DD_SRC_ZL = 0x10, + DD_SRC_ZH = 0x20, + DD_SRC_IA = 0x40, +}; + -- cgit v1.2.3 From c0b4e3ab0c769913438aeb078535ff117eeba5fb Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Wed, 12 Nov 2008 13:27:03 -0800 Subject: adt7462: new hwmon driver New driver to play with. As Jean mentioned a couple of years ago, this chip is a beast with odd combinations of 8 fans, 4 temperatures, and 13 voltage sensors. This driver has been tested on an IntelliStation Z30. Signed-off-by: Darrick J. Wong Cc: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/Kconfig | 10 + drivers/hwmon/Makefile | 1 + drivers/hwmon/adt7462.c | 2002 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 2013 insertions(+) create mode 100644 drivers/hwmon/adt7462.c (limited to 'drivers') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 1c44f5c47aa..c709e821f04 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -159,6 +159,16 @@ config SENSORS_ADM9240 This driver can also be built as a module. If so, the module will be called adm9240. +config SENSORS_ADT7462 + tristate "Analog Devices ADT7462" + depends on I2C && EXPERIMENTAL + help + If you say yes here you get support for the Analog Devices + ADT7462 temperature monitoring chips. + + This driver can also be built as a module. If so, the module + will be called adt7462. + config SENSORS_ADT7470 tristate "Analog Devices ADT7470" depends on I2C && EXPERIMENTAL diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index e0d90a68bea..58fc5be5355 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o +obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o obj-$(CONFIG_SENSORS_ADT7473) += adt7473.o obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c new file mode 100644 index 00000000000..66107b4dc12 --- /dev/null +++ b/drivers/hwmon/adt7462.c @@ -0,0 +1,2002 @@ +/* + * A hwmon driver for the Analog Devices ADT7462 + * Copyright (C) 2008 IBM + * + * Author: Darrick J. Wong + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_1(adt7462); + +/* ADT7462 registers */ +#define ADT7462_REG_DEVICE 0x3D +#define ADT7462_REG_VENDOR 0x3E +#define ADT7462_REG_REVISION 0x3F + +#define ADT7462_REG_MIN_TEMP_BASE_ADDR 0x44 +#define ADT7462_REG_MIN_TEMP_MAX_ADDR 0x47 +#define ADT7462_REG_MAX_TEMP_BASE_ADDR 0x48 +#define ADT7462_REG_MAX_TEMP_MAX_ADDR 0x4B +#define ADT7462_REG_TEMP_BASE_ADDR 0x88 +#define ADT7462_REG_TEMP_MAX_ADDR 0x8F + +#define ADT7462_REG_FAN_BASE_ADDR 0x98 +#define ADT7462_REG_FAN_MAX_ADDR 0x9F +#define ADT7462_REG_FAN2_BASE_ADDR 0xA2 +#define ADT7462_REG_FAN2_MAX_ADDR 0xA9 +#define ADT7462_REG_FAN_ENABLE 0x07 +#define ADT7462_REG_FAN_MIN_BASE_ADDR 0x78 +#define ADT7462_REG_FAN_MIN_MAX_ADDR 0x7F + +#define ADT7462_REG_CFG2 0x02 +#define ADT7462_FSPD_MASK 0x20 + +#define ADT7462_REG_PWM_BASE_ADDR 0xAA +#define ADT7462_REG_PWM_MAX_ADDR 0xAD +#define ADT7462_REG_PWM_MIN_BASE_ADDR 0x28 +#define ADT7462_REG_PWM_MIN_MAX_ADDR 0x2B +#define ADT7462_REG_PWM_MAX 0x2C +#define ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR 0x5C +#define ADT7462_REG_PWM_TEMP_MIN_MAX_ADDR 0x5F +#define ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR 0x60 +#define ADT7462_REG_PWM_TEMP_RANGE_MAX_ADDR 0x63 +#define ADT7462_PWM_HYST_MASK 0x0F +#define ADT7462_PWM_RANGE_MASK 0xF0 +#define ADT7462_PWM_RANGE_SHIFT 4 +#define ADT7462_REG_PWM_CFG_BASE_ADDR 0x21 +#define ADT7462_REG_PWM_CFG_MAX_ADDR 0x24 +#define ADT7462_PWM_CHANNEL_MASK 0xE0 +#define ADT7462_PWM_CHANNEL_SHIFT 5 + +#define ADT7462_REG_PIN_CFG_BASE_ADDR 0x10 +#define ADT7462_REG_PIN_CFG_MAX_ADDR 0x13 +#define ADT7462_PIN7_INPUT 0x01 /* cfg0 */ +#define ADT7462_DIODE3_INPUT 0x20 +#define ADT7462_DIODE1_INPUT 0x40 +#define ADT7462_VID_INPUT 0x80 +#define ADT7462_PIN22_INPUT 0x04 /* cfg1 */ +#define ADT7462_PIN21_INPUT 0x08 +#define ADT7462_PIN19_INPUT 0x10 +#define ADT7462_PIN15_INPUT 0x20 +#define ADT7462_PIN13_INPUT 0x40 +#define ADT7462_PIN8_INPUT 0x80 +#define ADT7462_PIN23_MASK 0x03 +#define ADT7462_PIN23_SHIFT 0 +#define ADT7462_PIN26_MASK 0x0C /* cfg2 */ +#define ADT7462_PIN26_SHIFT 2 +#define ADT7462_PIN25_MASK 0x30 +#define ADT7462_PIN25_SHIFT 4 +#define ADT7462_PIN24_MASK 0xC0 +#define ADT7462_PIN24_SHIFT 6 +#define ADT7462_PIN26_VOLT_INPUT 0x08 +#define ADT7462_PIN25_VOLT_INPUT 0x20 +#define ADT7462_PIN28_SHIFT 6 /* cfg3 */ +#define ADT7462_PIN28_VOLT 0x5 + +#define ADT7462_REG_ALARM1 0xB8 +#define ADT7462_LT_ALARM 0x02 +#define ADT7462_R1T_ALARM 0x04 +#define ADT7462_R2T_ALARM 0x08 +#define ADT7462_R3T_ALARM 0x10 +#define ADT7462_REG_ALARM2 0xBB +#define ADT7462_V0_ALARM 0x01 +#define ADT7462_V1_ALARM 0x02 +#define ADT7462_V2_ALARM 0x04 +#define ADT7462_V3_ALARM 0x08 +#define ADT7462_V4_ALARM 0x10 +#define ADT7462_V5_ALARM 0x20 +#define ADT7462_V6_ALARM 0x40 +#define ADT7462_V7_ALARM 0x80 +#define ADT7462_REG_ALARM3 0xBC +#define ADT7462_V8_ALARM 0x08 +#define ADT7462_V9_ALARM 0x10 +#define ADT7462_V10_ALARM 0x20 +#define ADT7462_V11_ALARM 0x40 +#define ADT7462_V12_ALARM 0x80 +#define ADT7462_REG_ALARM4 0xBD +#define ADT7462_F0_ALARM 0x01 +#define ADT7462_F1_ALARM 0x02 +#define ADT7462_F2_ALARM 0x04 +#define ADT7462_F3_ALARM 0x08 +#define ADT7462_F4_ALARM 0x10 +#define ADT7462_F5_ALARM 0x20 +#define ADT7462_F6_ALARM 0x40 +#define ADT7462_F7_ALARM 0x80 +#define ADT7462_ALARM1 0x0000 +#define ADT7462_ALARM2 0x0100 +#define ADT7462_ALARM3 0x0200 +#define ADT7462_ALARM4 0x0300 +#define ADT7462_ALARM_REG_SHIFT 8 +#define ADT7462_ALARM_FLAG_MASK 0x0F + +#define ADT7462_TEMP_COUNT 4 +#define ADT7462_TEMP_REG(x) (ADT7462_REG_TEMP_BASE_ADDR + (x * 2)) +#define ADT7462_TEMP_MIN_REG(x) (ADT7462_REG_MIN_TEMP_BASE_ADDR + (x)) +#define ADT7462_TEMP_MAX_REG(x) (ADT7462_REG_MAX_TEMP_BASE_ADDR + (x)) +#define TEMP_FRAC_OFFSET 6 + +#define ADT7462_FAN_COUNT 8 +#define ADT7462_REG_FAN_MIN(x) (ADT7462_REG_FAN_MIN_BASE_ADDR + (x)) + +#define ADT7462_PWM_COUNT 4 +#define ADT7462_REG_PWM(x) (ADT7462_REG_PWM_BASE_ADDR + (x)) +#define ADT7462_REG_PWM_MIN(x) (ADT7462_REG_PWM_MIN_BASE_ADDR + (x)) +#define ADT7462_REG_PWM_TMIN(x) \ + (ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR + (x)) +#define ADT7462_REG_PWM_TRANGE(x) \ + (ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR + (x)) + +#define ADT7462_PIN_CFG_REG_COUNT 4 +#define ADT7462_REG_PIN_CFG(x) (ADT7462_REG_PIN_CFG_BASE_ADDR + (x)) +#define ADT7462_REG_PWM_CFG(x) (ADT7462_REG_PWM_CFG_BASE_ADDR + (x)) + +#define ADT7462_ALARM_REG_COUNT 4 + +/* + * The chip can measure 13 different voltage sources: + * + * 1. +12V1 (pin 7) + * 2. Vccp1/+2.5V/+1.8V/+1.5V (pin 23) + * 3. +12V3 (pin 22) + * 4. +5V (pin 21) + * 5. +1.25V/+0.9V (pin 19) + * 6. +2.5V/+1.8V (pin 15) + * 7. +3.3v (pin 13) + * 8. +12V2 (pin 8) + * 9. Vbatt/FSB_Vtt (pin 26) + * A. +3.3V/+1.2V1 (pin 25) + * B. Vccp2/+2.5V/+1.8V/+1.5V (pin 24) + * C. +1.5V ICH (only if BOTH pin 28/29 are set to +1.5V) + * D. +1.5V 3GPIO (only if BOTH pin 28/29 are set to +1.5V) + * + * Each of these 13 has a factor to convert raw to voltage. Even better, + * the pins can be connected to other sensors (tach/gpio/hot/etc), which + * makes the bookkeeping tricky. + * + * Some, but not all, of these voltages have low/high limits. + */ +#define ADT7462_VOLT_COUNT 12 + +#define ADT7462_VENDOR 0x41 +#define ADT7462_DEVICE 0x62 +/* datasheet only mentions a revision 4 */ +#define ADT7462_REVISION 0x04 + +/* How often do we reread sensors values? (In jiffies) */ +#define SENSOR_REFRESH_INTERVAL (2 * HZ) + +/* How often do we reread sensor limit values? (In jiffies) */ +#define LIMIT_REFRESH_INTERVAL (60 * HZ) + +/* datasheet says to divide this number by the fan reading to get fan rpm */ +#define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x)) +#define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM +#define FAN_PERIOD_INVALID 65535 +#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) + +#define MASK_AND_SHIFT(value, prefix) \ + (((value) & prefix##_MASK) >> prefix##_SHIFT) + +#define ROUND_DIV(x, divisor) (((x) + ((divisor) / 2)) / (divisor)) + +struct adt7462_data { + struct device *hwmon_dev; + struct attribute_group attrs; + struct mutex lock; + char sensors_valid; + char limits_valid; + unsigned long sensors_last_updated; /* In jiffies */ + unsigned long limits_last_updated; /* In jiffies */ + + u8 temp[ADT7462_TEMP_COUNT]; + /* bits 6-7 are quarter pieces of temp */ + u8 temp_frac[ADT7462_TEMP_COUNT]; + u8 temp_min[ADT7462_TEMP_COUNT]; + u8 temp_max[ADT7462_TEMP_COUNT]; + u16 fan[ADT7462_FAN_COUNT]; + u8 fan_enabled; + u8 fan_min[ADT7462_FAN_COUNT]; + u8 cfg2; + u8 pwm[ADT7462_PWM_COUNT]; + u8 pin_cfg[ADT7462_PIN_CFG_REG_COUNT]; + u8 voltages[ADT7462_VOLT_COUNT]; + u8 volt_max[ADT7462_VOLT_COUNT]; + u8 volt_min[ADT7462_VOLT_COUNT]; + u8 pwm_min[ADT7462_PWM_COUNT]; + u8 pwm_tmin[ADT7462_PWM_COUNT]; + u8 pwm_trange[ADT7462_PWM_COUNT]; + u8 pwm_max; /* only one per chip */ + u8 pwm_cfg[ADT7462_PWM_COUNT]; + u8 alarms[ADT7462_ALARM_REG_COUNT]; +}; + +static int adt7462_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int adt7462_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int adt7462_remove(struct i2c_client *client); + +static const struct i2c_device_id adt7462_id[] = { + { "adt7462", adt7462 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adt7462_id); + +static struct i2c_driver adt7462_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "adt7462", + }, + .probe = adt7462_probe, + .remove = adt7462_remove, + .id_table = adt7462_id, + .detect = adt7462_detect, + .address_data = &addr_data, +}; + +/* + * 16-bit registers on the ADT7462 are low-byte first. The data sheet says + * that the low byte must be read before the high byte. + */ +static inline int adt7462_read_word_data(struct i2c_client *client, u8 reg) +{ + u16 foo; + foo = i2c_smbus_read_byte_data(client, reg); + foo |= ((u16)i2c_smbus_read_byte_data(client, reg + 1) << 8); + return foo; +} + +/* For some reason these registers are not contiguous. */ +static int ADT7462_REG_FAN(int fan) +{ + if (fan < 4) + return ADT7462_REG_FAN_BASE_ADDR + (2 * fan); + return ADT7462_REG_FAN2_BASE_ADDR + (2 * (fan - 4)); +} + +/* Voltage registers are scattered everywhere */ +static int ADT7462_REG_VOLT_MAX(struct adt7462_data *data, int which) +{ + switch (which) { + case 0: + if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) + return 0x7C; + break; + case 1: + return 0x69; + case 2: + if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) + return 0x7F; + break; + case 3: + if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) + return 0x7E; + break; + case 4: + if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) + return 0x4B; + break; + case 5: + if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) + return 0x49; + break; + case 6: + if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) + return 0x68; + break; + case 7: + if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) + return 0x7D; + break; + case 8: + if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT)) + return 0x6C; + break; + case 9: + if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT)) + return 0x6B; + break; + case 10: + return 0x6A; + case 11: + if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == + ADT7462_PIN28_VOLT && + !(data->pin_cfg[0] & ADT7462_VID_INPUT)) + return 0x50; + break; + case 12: + if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == + ADT7462_PIN28_VOLT && + !(data->pin_cfg[0] & ADT7462_VID_INPUT)) + return 0x4C; + break; + } + return -ENODEV; +} + +static int ADT7462_REG_VOLT_MIN(struct adt7462_data *data, int which) +{ + switch (which) { + case 0: + if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) + return 0x6D; + break; + case 1: + return 0x72; + case 2: + if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) + return 0x6F; + break; + case 3: + if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) + return 0x71; + break; + case 4: + if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) + return 0x47; + break; + case 5: + if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) + return 0x45; + break; + case 6: + if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) + return 0x70; + break; + case 7: + if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) + return 0x6E; + break; + case 8: + if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT)) + return 0x75; + break; + case 9: + if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT)) + return 0x74; + break; + case 10: + return 0x73; + case 11: + if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == + ADT7462_PIN28_VOLT && + !(data->pin_cfg[0] & ADT7462_VID_INPUT)) + return 0x76; + break; + case 12: + if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == + ADT7462_PIN28_VOLT && + !(data->pin_cfg[0] & ADT7462_VID_INPUT)) + return 0x77; + break; + } + return -ENODEV; +} + +static int ADT7462_REG_VOLT(struct adt7462_data *data, int which) +{ + switch (which) { + case 0: + if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) + return 0xA3; + break; + case 1: + return 0x90; + case 2: + if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) + return 0xA9; + break; + case 3: + if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) + return 0xA7; + break; + case 4: + if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) + return 0x8F; + break; + case 5: + if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) + return 0x8B; + break; + case 6: + if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) + return 0x96; + break; + case 7: + if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) + return 0xA5; + break; + case 8: + if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT)) + return 0x93; + break; + case 9: + if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT)) + return 0x92; + break; + case 10: + return 0x91; + case 11: + if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == + ADT7462_PIN28_VOLT && + !(data->pin_cfg[0] & ADT7462_VID_INPUT)) + return 0x94; + break; + case 12: + if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == + ADT7462_PIN28_VOLT && + !(data->pin_cfg[0] & ADT7462_VID_INPUT)) + return 0x95; + break; + } + return -ENODEV; +} + +/* Provide labels for sysfs */ +static const char *voltage_label(struct adt7462_data *data, int which) +{ + switch (which) { + case 0: + if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) + return "+12V1"; + break; + case 1: + switch (MASK_AND_SHIFT(data->pin_cfg[1], ADT7462_PIN23)) { + case 0: + return "Vccp1"; + case 1: + return "+2.5V"; + case 2: + return "+1.8V"; + case 3: + return "+1.5V"; + } + case 2: + if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) + return "+12V3"; + break; + case 3: + if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) + return "+5V"; + break; + case 4: + if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) { + if (data->pin_cfg[1] & ADT7462_PIN19_INPUT) + return "+0.9V"; + return "+1.25V"; + } + break; + case 5: + if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) { + if (data->pin_cfg[1] & ADT7462_PIN19_INPUT) + return "+1.8V"; + return "+2.5V"; + } + break; + case 6: + if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) + return "+3.3V"; + break; + case 7: + if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) + return "+12V2"; + break; + case 8: + switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN26)) { + case 0: + return "Vbatt"; + case 1: + return "FSB_Vtt"; + } + break; + case 9: + switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN25)) { + case 0: + return "+3.3V"; + case 1: + return "+1.2V1"; + } + break; + case 10: + switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN24)) { + case 0: + return "Vccp2"; + case 1: + return "+2.5V"; + case 2: + return "+1.8V"; + case 3: + return "+1.5"; + } + case 11: + if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == + ADT7462_PIN28_VOLT && + !(data->pin_cfg[0] & ADT7462_VID_INPUT)) + return "+1.5V ICH"; + break; + case 12: + if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == + ADT7462_PIN28_VOLT && + !(data->pin_cfg[0] & ADT7462_VID_INPUT)) + return "+1.5V 3GPIO"; + break; + } + return "N/A"; +} + +/* Multipliers are actually in uV, not mV. */ +static int voltage_multiplier(struct adt7462_data *data, int which) +{ + switch (which) { + case 0: + if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) + return 62500; + break; + case 1: + switch (MASK_AND_SHIFT(data->pin_cfg[1], ADT7462_PIN23)) { + case 0: + if (data->pin_cfg[0] & ADT7462_VID_INPUT) + return 12500; + return 6250; + case 1: + return 13000; + case 2: + return 9400; + case 3: + return 7800; + } + case 2: + if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) + return 62500; + break; + case 3: + if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) + return 26000; + break; + case 4: + if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) { + if (data->pin_cfg[1] & ADT7462_PIN19_INPUT) + return 4690; + return 6500; + } + break; + case 5: + if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) { + if (data->pin_cfg[1] & ADT7462_PIN15_INPUT) + return 9400; + return 13000; + } + break; + case 6: + if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) + return 17200; + break; + case 7: + if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) + return 62500; + break; + case 8: + switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN26)) { + case 0: + return 15600; + case 1: + return 6250; + } + break; + case 9: + switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN25)) { + case 0: + return 17200; + case 1: + return 6250; + } + break; + case 10: + switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN24)) { + case 0: + return 6250; + case 1: + return 13000; + case 2: + return 9400; + case 3: + return 7800; + } + case 11: + case 12: + if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == + ADT7462_PIN28_VOLT && + !(data->pin_cfg[0] & ADT7462_VID_INPUT)) + return 7800; + } + return 0; +} + +static int temp_enabled(struct adt7462_data *data, int which) +{ + switch (which) { + case 0: + case 2: + return 1; + case 1: + if (data->pin_cfg[0] & ADT7462_DIODE1_INPUT) + return 1; + break; + case 3: + if (data->pin_cfg[0] & ADT7462_DIODE3_INPUT) + return 1; + break; + } + return 0; +} + +static const char *temp_label(struct adt7462_data *data, int which) +{ + switch (which) { + case 0: + return "local"; + case 1: + if (data->pin_cfg[0] & ADT7462_DIODE1_INPUT) + return "remote1"; + break; + case 2: + return "remote2"; + case 3: + if (data->pin_cfg[0] & ADT7462_DIODE3_INPUT) + return "remote3"; + break; + } + return "N/A"; +} + +/* Map Trange register values to mC */ +#define NUM_TRANGE_VALUES 16 +static const int trange_values[NUM_TRANGE_VALUES] = { + 2000, + 2500, + 3300, + 4000, + 5000, + 6700, + 8000, + 10000, + 13300, + 16000, + 20000, + 26700, + 32000, + 40000, + 53300, + 80000 +}; + +static int find_trange_value(int trange) +{ + int i; + + for (i = 0; i < NUM_TRANGE_VALUES; i++) + if (trange_values[i] == trange) + return i; + + return -ENODEV; +} + +static struct adt7462_data *adt7462_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adt7462_data *data = i2c_get_clientdata(client); + unsigned long local_jiffies = jiffies; + int i; + + mutex_lock(&data->lock); + if (time_before(local_jiffies, data->sensors_last_updated + + SENSOR_REFRESH_INTERVAL) + && data->sensors_valid) + goto no_sensor_update; + + for (i = 0; i < ADT7462_TEMP_COUNT; i++) { + /* + * Reading the fractional register locks the integral + * register until both have been read. + */ + data->temp_frac[i] = i2c_smbus_read_byte_data(client, + ADT7462_TEMP_REG(i)); + data->temp[i] = i2c_smbus_read_byte_data(client, + ADT7462_TEMP_REG(i) + 1); + } + + for (i = 0; i < ADT7462_FAN_COUNT; i++) + data->fan[i] = adt7462_read_word_data(client, + ADT7462_REG_FAN(i)); + + data->fan_enabled = i2c_smbus_read_byte_data(client, + ADT7462_REG_FAN_ENABLE); + + for (i = 0; i < ADT7462_PWM_COUNT; i++) + data->pwm[i] = i2c_smbus_read_byte_data(client, + ADT7462_REG_PWM(i)); + + for (i = 0; i < ADT7462_PIN_CFG_REG_COUNT; i++) + data->pin_cfg[i] = i2c_smbus_read_byte_data(client, + ADT7462_REG_PIN_CFG(i)); + + for (i = 0; i < ADT7462_VOLT_COUNT; i++) { + int reg = ADT7462_REG_VOLT(data, i); + if (!reg) + data->voltages[i] = 0; + else + data->voltages[i] = i2c_smbus_read_byte_data(client, + reg); + } + + data->alarms[0] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM1); + data->alarms[1] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM2); + data->alarms[2] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM3); + data->alarms[3] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM4); + + data->sensors_last_updated = local_jiffies; + data->sensors_valid = 1; + +no_sensor_update: + if (time_before(local_jiffies, data->limits_last_updated + + LIMIT_REFRESH_INTERVAL) + && data->limits_valid) + goto out; + + for (i = 0; i < ADT7462_TEMP_COUNT; i++) { + data->temp_min[i] = i2c_smbus_read_byte_data(client, + ADT7462_TEMP_MIN_REG(i)); + data->temp_max[i] = i2c_smbus_read_byte_data(client, + ADT7462_TEMP_MAX_REG(i)); + } + + for (i = 0; i < ADT7462_FAN_COUNT; i++) + data->fan_min[i] = i2c_smbus_read_byte_data(client, + ADT7462_REG_FAN_MIN(i)); + + for (i = 0; i < ADT7462_VOLT_COUNT; i++) { + int reg = ADT7462_REG_VOLT_MAX(data, i); + data->volt_max[i] = + (reg ? i2c_smbus_read_byte_data(client, reg) : 0); + + reg = ADT7462_REG_VOLT_MIN(data, i); + data->volt_min[i] = + (reg ? i2c_smbus_read_byte_data(client, reg) : 0); + } + + for (i = 0; i < ADT7462_PWM_COUNT; i++) { + data->pwm_min[i] = i2c_smbus_read_byte_data(client, + ADT7462_REG_PWM_MIN(i)); + data->pwm_tmin[i] = i2c_smbus_read_byte_data(client, + ADT7462_REG_PWM_TMIN(i)); + data->pwm_trange[i] = i2c_smbus_read_byte_data(client, + ADT7462_REG_PWM_TRANGE(i)); + data->pwm_cfg[i] = i2c_smbus_read_byte_data(client, + ADT7462_REG_PWM_CFG(i)); + } + + data->pwm_max = i2c_smbus_read_byte_data(client, ADT7462_REG_PWM_MAX); + + data->cfg2 = i2c_smbus_read_byte_data(client, ADT7462_REG_CFG2); + + data->limits_last_updated = local_jiffies; + data->limits_valid = 1; + +out: + mutex_unlock(&data->lock); + return data; +} + +static ssize_t show_temp_min(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + + if (!temp_enabled(data, attr->index)) + return sprintf(buf, "0\n"); + + return sprintf(buf, "%d\n", 1000 * (data->temp_min[attr->index] - 64)); +} + +static ssize_t set_temp_min(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7462_data *data = i2c_get_clientdata(client); + long temp; + + if (strict_strtol(buf, 10, &temp) || !temp_enabled(data, attr->index)) + return -EINVAL; + + temp = ROUND_DIV(temp, 1000) + 64; + temp = SENSORS_LIMIT(temp, 0, 255); + + mutex_lock(&data->lock); + data->temp_min[attr->index] = temp; + i2c_smbus_write_byte_data(client, ADT7462_TEMP_MIN_REG(attr->index), + temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_temp_max(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + + if (!temp_enabled(data, attr->index)) + return sprintf(buf, "0\n"); + + return sprintf(buf, "%d\n", 1000 * (data->temp_max[attr->index] - 64)); +} + +static ssize_t set_temp_max(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7462_data *data = i2c_get_clientdata(client); + long temp; + + if (strict_strtol(buf, 10, &temp) || !temp_enabled(data, attr->index)) + return -EINVAL; + + temp = ROUND_DIV(temp, 1000) + 64; + temp = SENSORS_LIMIT(temp, 0, 255); + + mutex_lock(&data->lock); + data->temp_max[attr->index] = temp; + i2c_smbus_write_byte_data(client, ADT7462_TEMP_MAX_REG(attr->index), + temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + u8 frac = data->temp_frac[attr->index] >> TEMP_FRAC_OFFSET; + + if (!temp_enabled(data, attr->index)) + return sprintf(buf, "0\n"); + + return sprintf(buf, "%d\n", 1000 * (data->temp[attr->index] - 64) + + 250 * frac); +} + +static ssize_t show_temp_label(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + + return sprintf(buf, "%s\n", temp_label(data, attr->index)); +} + +static ssize_t show_volt_max(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + int x = voltage_multiplier(data, attr->index); + + x *= data->volt_max[attr->index]; + x /= 1000; /* convert from uV to mV */ + + return sprintf(buf, "%d\n", x); +} + +static ssize_t set_volt_max(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7462_data *data = i2c_get_clientdata(client); + int x = voltage_multiplier(data, attr->index); + long temp; + + if (strict_strtol(buf, 10, &temp) || !x) + return -EINVAL; + + temp *= 1000; /* convert mV to uV */ + temp = ROUND_DIV(temp, x); + temp = SENSORS_LIMIT(temp, 0, 255); + + mutex_lock(&data->lock); + data->volt_max[attr->index] = temp; + i2c_smbus_write_byte_data(client, + ADT7462_REG_VOLT_MAX(data, attr->index), + temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_volt_min(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + int x = voltage_multiplier(data, attr->index); + + x *= data->volt_min[attr->index]; + x /= 1000; /* convert from uV to mV */ + + return sprintf(buf, "%d\n", x); +} + +static ssize_t set_volt_min(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7462_data *data = i2c_get_clientdata(client); + int x = voltage_multiplier(data, attr->index); + long temp; + + if (strict_strtol(buf, 10, &temp) || !x) + return -EINVAL; + + temp *= 1000; /* convert mV to uV */ + temp = ROUND_DIV(temp, x); + temp = SENSORS_LIMIT(temp, 0, 255); + + mutex_lock(&data->lock); + data->volt_min[attr->index] = temp; + i2c_smbus_write_byte_data(client, + ADT7462_REG_VOLT_MIN(data, attr->index), + temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_voltage(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + int x = voltage_multiplier(data, attr->index); + + x *= data->voltages[attr->index]; + x /= 1000; /* convert from uV to mV */ + + return sprintf(buf, "%d\n", x); +} + +static ssize_t show_voltage_label(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + + return sprintf(buf, "%s\n", voltage_label(data, attr->index)); +} + +static ssize_t show_alarm(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + int reg = attr->index >> ADT7462_ALARM_REG_SHIFT; + int mask = attr->index & ADT7462_ALARM_FLAG_MASK; + + if (data->alarms[reg] & mask) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static int fan_enabled(struct adt7462_data *data, int fan) +{ + return data->fan_enabled & (1 << fan); +} + +static ssize_t show_fan_min(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + u16 temp; + + /* Only the MSB of the min fan period is stored... */ + temp = data->fan_min[attr->index]; + temp <<= 8; + + if (!fan_enabled(data, attr->index) || + !FAN_DATA_VALID(temp)) + return sprintf(buf, "0\n"); + + return sprintf(buf, "%d\n", FAN_PERIOD_TO_RPM(temp)); +} + +static ssize_t set_fan_min(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7462_data *data = i2c_get_clientdata(client); + long temp; + + if (strict_strtol(buf, 10, &temp) || !temp || + !fan_enabled(data, attr->index)) + return -EINVAL; + + temp = FAN_RPM_TO_PERIOD(temp); + temp >>= 8; + temp = SENSORS_LIMIT(temp, 1, 255); + + mutex_lock(&data->lock); + data->fan_min[attr->index] = temp; + i2c_smbus_write_byte_data(client, ADT7462_REG_FAN_MIN(attr->index), + temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + + if (!fan_enabled(data, attr->index) || + !FAN_DATA_VALID(data->fan[attr->index])) + return sprintf(buf, "0\n"); + + return sprintf(buf, "%d\n", + FAN_PERIOD_TO_RPM(data->fan[attr->index])); +} + +static ssize_t show_force_pwm_max(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct adt7462_data *data = adt7462_update_device(dev); + return sprintf(buf, "%d\n", (data->cfg2 & ADT7462_FSPD_MASK ? 1 : 0)); +} + +static ssize_t set_force_pwm_max(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adt7462_data *data = i2c_get_clientdata(client); + long temp; + u8 reg; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + mutex_lock(&data->lock); + reg = i2c_smbus_read_byte_data(client, ADT7462_REG_CFG2); + if (temp) + reg |= ADT7462_FSPD_MASK; + else + reg &= ~ADT7462_FSPD_MASK; + data->cfg2 = reg; + i2c_smbus_write_byte_data(client, ADT7462_REG_CFG2, reg); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + return sprintf(buf, "%d\n", data->pwm[attr->index]); +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7462_data *data = i2c_get_clientdata(client); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = SENSORS_LIMIT(temp, 0, 255); + + mutex_lock(&data->lock); + data->pwm[attr->index] = temp; + i2c_smbus_write_byte_data(client, ADT7462_REG_PWM(attr->index), temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_pwm_max(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct adt7462_data *data = adt7462_update_device(dev); + return sprintf(buf, "%d\n", data->pwm_max); +} + +static ssize_t set_pwm_max(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adt7462_data *data = i2c_get_clientdata(client); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = SENSORS_LIMIT(temp, 0, 255); + + mutex_lock(&data->lock); + data->pwm_max = temp; + i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_MAX, temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_pwm_min(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + return sprintf(buf, "%d\n", data->pwm_min[attr->index]); +} + +static ssize_t set_pwm_min(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7462_data *data = i2c_get_clientdata(client); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = SENSORS_LIMIT(temp, 0, 255); + + mutex_lock(&data->lock); + data->pwm_min[attr->index] = temp; + i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_MIN(attr->index), + temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_pwm_hyst(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + return sprintf(buf, "%d\n", 1000 * + (data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK)); +} + +static ssize_t set_pwm_hyst(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7462_data *data = i2c_get_clientdata(client); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = ROUND_DIV(temp, 1000); + temp = SENSORS_LIMIT(temp, 0, 15); + + /* package things up */ + temp &= ADT7462_PWM_HYST_MASK; + temp |= data->pwm_trange[attr->index] & ADT7462_PWM_RANGE_MASK; + + mutex_lock(&data->lock); + data->pwm_trange[attr->index] = temp; + i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TRANGE(attr->index), + temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_pwm_tmax(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + + /* tmax = tmin + trange */ + int trange = trange_values[data->pwm_trange[attr->index] >> + ADT7462_PWM_RANGE_SHIFT]; + int tmin = (data->pwm_tmin[attr->index] - 64) * 1000; + + return sprintf(buf, "%d\n", tmin + trange); +} + +static ssize_t set_pwm_tmax(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + int temp; + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7462_data *data = i2c_get_clientdata(client); + int tmin, trange_value; + long trange; + + if (strict_strtol(buf, 10, &trange)) + return -EINVAL; + + /* trange = tmax - tmin */ + tmin = (data->pwm_tmin[attr->index] - 64) * 1000; + trange_value = find_trange_value(trange - tmin); + + if (trange_value < 0) + return -EINVAL; + + temp = trange_value << ADT7462_PWM_RANGE_SHIFT; + temp |= data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK; + + mutex_lock(&data->lock); + data->pwm_trange[attr->index] = temp; + i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TRANGE(attr->index), + temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_pwm_tmin(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + return sprintf(buf, "%d\n", 1000 * (data->pwm_tmin[attr->index] - 64)); +} + +static ssize_t set_pwm_tmin(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7462_data *data = i2c_get_clientdata(client); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = ROUND_DIV(temp, 1000) + 64; + temp = SENSORS_LIMIT(temp, 0, 255); + + mutex_lock(&data->lock); + data->pwm_tmin[attr->index] = temp; + i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TMIN(attr->index), + temp); + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t show_pwm_auto(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + int cfg = data->pwm_cfg[attr->index] >> ADT7462_PWM_CHANNEL_SHIFT; + + switch (cfg) { + case 4: /* off */ + return sprintf(buf, "0\n"); + case 7: /* manual */ + return sprintf(buf, "1\n"); + default: /* automatic */ + return sprintf(buf, "2\n"); + } +} + +static void set_pwm_channel(struct i2c_client *client, + struct adt7462_data *data, + int which, + int value) +{ + int temp = data->pwm_cfg[which] & ~ADT7462_PWM_CHANNEL_MASK; + temp |= value << ADT7462_PWM_CHANNEL_SHIFT; + + mutex_lock(&data->lock); + data->pwm_cfg[which] = temp; + i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_CFG(which), temp); + mutex_unlock(&data->lock); +} + +static ssize_t set_pwm_auto(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7462_data *data = i2c_get_clientdata(client); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + switch (temp) { + case 0: /* off */ + set_pwm_channel(client, data, attr->index, 4); + return count; + case 1: /* manual */ + set_pwm_channel(client, data, attr->index, 7); + return count; + default: + return -EINVAL; + } +} + +static ssize_t show_pwm_auto_temp(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct adt7462_data *data = adt7462_update_device(dev); + int channel = data->pwm_cfg[attr->index] >> ADT7462_PWM_CHANNEL_SHIFT; + + switch (channel) { + case 0: /* temp[1234] only */ + case 1: + case 2: + case 3: + return sprintf(buf, "%d\n", (1 << channel)); + case 5: /* temp1 & temp4 */ + return sprintf(buf, "9\n"); + case 6: + return sprintf(buf, "15\n"); + default: + return sprintf(buf, "0\n"); + } +} + +static int cvt_auto_temp(int input) +{ + if (input == 0xF) + return 6; + if (input == 0x9) + return 5; + if (input < 1 || !is_power_of_2(input)) + return -EINVAL; + return ilog2(input); +} + +static ssize_t set_pwm_auto_temp(struct device *dev, + struct device_attribute *devattr, + const char *buf, + size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct adt7462_data *data = i2c_get_clientdata(client); + long temp; + + if (strict_strtol(buf, 10, &temp)) + return -EINVAL; + + temp = cvt_auto_temp(temp); + if (temp < 0) + return temp; + + set_pwm_channel(client, data, attr->index, temp); + + return count; +} + +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 0); +static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 1); +static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 2); +static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_max, + set_temp_max, 3); + +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 0); +static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 1); +static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 2); +static SENSOR_DEVICE_ATTR(temp4_min, S_IWUSR | S_IRUGO, show_temp_min, + set_temp_min, 3); + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); + +static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1); +static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2); +static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3); + +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM1 | ADT7462_LT_ALARM); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM1 | ADT7462_R1T_ALARM); +static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM1 | ADT7462_R2T_ALARM); +static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM1 | ADT7462_R3T_ALARM); + +static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, show_volt_max, + set_volt_max, 0); +static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, show_volt_max, + set_volt_max, 1); +static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, show_volt_max, + set_volt_max, 2); +static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, show_volt_max, + set_volt_max, 3); +static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, show_volt_max, + set_volt_max, 4); +static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, show_volt_max, + set_volt_max, 5); +static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO, show_volt_max, + set_volt_max, 6); +static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO, show_volt_max, + set_volt_max, 7); +static SENSOR_DEVICE_ATTR(in9_max, S_IWUSR | S_IRUGO, show_volt_max, + set_volt_max, 8); +static SENSOR_DEVICE_ATTR(in10_max, S_IWUSR | S_IRUGO, show_volt_max, + set_volt_max, 9); +static SENSOR_DEVICE_ATTR(in11_max, S_IWUSR | S_IRUGO, show_volt_max, + set_volt_max, 10); +static SENSOR_DEVICE_ATTR(in12_max, S_IWUSR | S_IRUGO, show_volt_max, + set_volt_max, 11); +static SENSOR_DEVICE_ATTR(in13_max, S_IWUSR | S_IRUGO, show_volt_max, + set_volt_max, 12); + +static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, show_volt_min, + set_volt_min, 0); +static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, show_volt_min, + set_volt_min, 1); +static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, show_volt_min, + set_volt_min, 2); +static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, show_volt_min, + set_volt_min, 3); +static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, show_volt_min, + set_volt_min, 4); +static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, show_volt_min, + set_volt_min, 5); +static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO, show_volt_min, + set_volt_min, 6); +static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO, show_volt_min, + set_volt_min, 7); +static SENSOR_DEVICE_ATTR(in9_min, S_IWUSR | S_IRUGO, show_volt_min, + set_volt_min, 8); +static SENSOR_DEVICE_ATTR(in10_min, S_IWUSR | S_IRUGO, show_volt_min, + set_volt_min, 9); +static SENSOR_DEVICE_ATTR(in11_min, S_IWUSR | S_IRUGO, show_volt_min, + set_volt_min, 10); +static SENSOR_DEVICE_ATTR(in12_min, S_IWUSR | S_IRUGO, show_volt_min, + set_volt_min, 11); +static SENSOR_DEVICE_ATTR(in13_min, S_IWUSR | S_IRUGO, show_volt_min, + set_volt_min, 12); + +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 0); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 1); +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_voltage, NULL, 2); +static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_voltage, NULL, 3); +static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 4); +static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 5); +static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 6); +static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_voltage, NULL, 7); +static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_voltage, NULL, 8); +static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_voltage, NULL, 9); +static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_voltage, NULL, 10); +static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_voltage, NULL, 11); +static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_voltage, NULL, 12); + +static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_voltage_label, NULL, 0); +static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_voltage_label, NULL, 1); +static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_voltage_label, NULL, 2); +static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, show_voltage_label, NULL, 3); +static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, show_voltage_label, NULL, 4); +static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, show_voltage_label, NULL, 5); +static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_voltage_label, NULL, 6); +static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_voltage_label, NULL, 7); +static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_voltage_label, NULL, 8); +static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, show_voltage_label, NULL, 9); +static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, show_voltage_label, NULL, 10); +static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, show_voltage_label, NULL, 11); +static SENSOR_DEVICE_ATTR(in13_label, S_IRUGO, show_voltage_label, NULL, 12); + +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM2 | ADT7462_V0_ALARM); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM2 | ADT7462_V7_ALARM); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM2 | ADT7462_V2_ALARM); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM2 | ADT7462_V6_ALARM); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM2 | ADT7462_V5_ALARM); +static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM2 | ADT7462_V4_ALARM); +static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM2 | ADT7462_V3_ALARM); +static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM2 | ADT7462_V1_ALARM); +static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM3 | ADT7462_V10_ALARM); +static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM3 | ADT7462_V9_ALARM); +static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM3 | ADT7462_V8_ALARM); +static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM3 | ADT7462_V11_ALARM); +static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM3 | ADT7462_V12_ALARM); + +static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, + set_fan_min, 0); +static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, + set_fan_min, 1); +static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, + set_fan_min, 2); +static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, + set_fan_min, 3); +static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, + set_fan_min, 4); +static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, + set_fan_min, 5); +static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, + set_fan_min, 6); +static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO, show_fan_min, + set_fan_min, 7); + +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); +static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4); +static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5); +static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6); +static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan, NULL, 7); + +static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM4 | ADT7462_F0_ALARM); +static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM4 | ADT7462_F1_ALARM); +static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM4 | ADT7462_F2_ALARM); +static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM4 | ADT7462_F3_ALARM); +static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM4 | ADT7462_F4_ALARM); +static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM4 | ADT7462_F5_ALARM); +static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM4 | ADT7462_F6_ALARM); +static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_alarm, NULL, + ADT7462_ALARM4 | ADT7462_F7_ALARM); + +static SENSOR_DEVICE_ATTR(force_pwm_max, S_IWUSR | S_IRUGO, + show_force_pwm_max, set_force_pwm_max, 0); + +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); + +static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO, + show_pwm_min, set_pwm_min, 0); +static SENSOR_DEVICE_ATTR(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO, + show_pwm_min, set_pwm_min, 1); +static SENSOR_DEVICE_ATTR(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO, + show_pwm_min, set_pwm_min, 2); +static SENSOR_DEVICE_ATTR(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO, + show_pwm_min, set_pwm_min, 3); + +static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, + show_pwm_max, set_pwm_max, 0); +static SENSOR_DEVICE_ATTR(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO, + show_pwm_max, set_pwm_max, 1); +static SENSOR_DEVICE_ATTR(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO, + show_pwm_max, set_pwm_max, 2); +static SENSOR_DEVICE_ATTR(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO, + show_pwm_max, set_pwm_max, 3); + +static SENSOR_DEVICE_ATTR(temp1_auto_point1_hyst, S_IWUSR | S_IRUGO, + show_pwm_hyst, set_pwm_hyst, 0); +static SENSOR_DEVICE_ATTR(temp2_auto_point1_hyst, S_IWUSR | S_IRUGO, + show_pwm_hyst, set_pwm_hyst, 1); +static SENSOR_DEVICE_ATTR(temp3_auto_point1_hyst, S_IWUSR | S_IRUGO, + show_pwm_hyst, set_pwm_hyst, 2); +static SENSOR_DEVICE_ATTR(temp4_auto_point1_hyst, S_IWUSR | S_IRUGO, + show_pwm_hyst, set_pwm_hyst, 3); + +static SENSOR_DEVICE_ATTR(temp1_auto_point2_hyst, S_IWUSR | S_IRUGO, + show_pwm_hyst, set_pwm_hyst, 0); +static SENSOR_DEVICE_ATTR(temp2_auto_point2_hyst, S_IWUSR | S_IRUGO, + show_pwm_hyst, set_pwm_hyst, 1); +static SENSOR_DEVICE_ATTR(temp3_auto_point2_hyst, S_IWUSR | S_IRUGO, + show_pwm_hyst, set_pwm_hyst, 2); +static SENSOR_DEVICE_ATTR(temp4_auto_point2_hyst, S_IWUSR | S_IRUGO, + show_pwm_hyst, set_pwm_hyst, 3); + +static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, S_IWUSR | S_IRUGO, + show_pwm_tmin, set_pwm_tmin, 0); +static SENSOR_DEVICE_ATTR(temp2_auto_point1_temp, S_IWUSR | S_IRUGO, + show_pwm_tmin, set_pwm_tmin, 1); +static SENSOR_DEVICE_ATTR(temp3_auto_point1_temp, S_IWUSR | S_IRUGO, + show_pwm_tmin, set_pwm_tmin, 2); +static SENSOR_DEVICE_ATTR(temp4_auto_point1_temp, S_IWUSR | S_IRUGO, + show_pwm_tmin, set_pwm_tmin, 3); + +static SENSOR_DEVICE_ATTR(temp1_auto_point2_temp, S_IWUSR | S_IRUGO, + show_pwm_tmax, set_pwm_tmax, 0); +static SENSOR_DEVICE_ATTR(temp2_auto_point2_temp, S_IWUSR | S_IRUGO, + show_pwm_tmax, set_pwm_tmax, 1); +static SENSOR_DEVICE_ATTR(temp3_auto_point2_temp, S_IWUSR | S_IRUGO, + show_pwm_tmax, set_pwm_tmax, 2); +static SENSOR_DEVICE_ATTR(temp4_auto_point2_temp, S_IWUSR | S_IRUGO, + show_pwm_tmax, set_pwm_tmax, 3); + +static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_auto, + set_pwm_auto, 0); +static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_auto, + set_pwm_auto, 1); +static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_auto, + set_pwm_auto, 2); +static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_auto, + set_pwm_auto, 3); + +static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IWUSR | S_IRUGO, + show_pwm_auto_temp, set_pwm_auto_temp, 0); +static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IWUSR | S_IRUGO, + show_pwm_auto_temp, set_pwm_auto_temp, 1); +static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO, + show_pwm_auto_temp, set_pwm_auto_temp, 2); +static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO, + show_pwm_auto_temp, set_pwm_auto_temp, 3); + +static struct attribute *adt7462_attr[] = +{ + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp2_max.dev_attr.attr, + &sensor_dev_attr_temp3_max.dev_attr.attr, + &sensor_dev_attr_temp4_max.dev_attr.attr, + + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp2_min.dev_attr.attr, + &sensor_dev_attr_temp3_min.dev_attr.attr, + &sensor_dev_attr_temp4_min.dev_attr.attr, + + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + + &sensor_dev_attr_temp1_label.dev_attr.attr, + &sensor_dev_attr_temp2_label.dev_attr.attr, + &sensor_dev_attr_temp3_label.dev_attr.attr, + &sensor_dev_attr_temp4_label.dev_attr.attr, + + &sensor_dev_attr_temp1_alarm.dev_attr.attr, + &sensor_dev_attr_temp2_alarm.dev_attr.attr, + &sensor_dev_attr_temp3_alarm.dev_attr.attr, + &sensor_dev_attr_temp4_alarm.dev_attr.attr, + + &sensor_dev_attr_in1_max.dev_attr.attr, + &sensor_dev_attr_in2_max.dev_attr.attr, + &sensor_dev_attr_in3_max.dev_attr.attr, + &sensor_dev_attr_in4_max.dev_attr.attr, + &sensor_dev_attr_in5_max.dev_attr.attr, + &sensor_dev_attr_in6_max.dev_attr.attr, + &sensor_dev_attr_in7_max.dev_attr.attr, + &sensor_dev_attr_in8_max.dev_attr.attr, + &sensor_dev_attr_in9_max.dev_attr.attr, + &sensor_dev_attr_in10_max.dev_attr.attr, + &sensor_dev_attr_in11_max.dev_attr.attr, + &sensor_dev_attr_in12_max.dev_attr.attr, + &sensor_dev_attr_in13_max.dev_attr.attr, + + &sensor_dev_attr_in1_min.dev_attr.attr, + &sensor_dev_attr_in2_min.dev_attr.attr, + &sensor_dev_attr_in3_min.dev_attr.attr, + &sensor_dev_attr_in4_min.dev_attr.attr, + &sensor_dev_attr_in5_min.dev_attr.attr, + &sensor_dev_attr_in6_min.dev_attr.attr, + &sensor_dev_attr_in7_min.dev_attr.attr, + &sensor_dev_attr_in8_min.dev_attr.attr, + &sensor_dev_attr_in9_min.dev_attr.attr, + &sensor_dev_attr_in10_min.dev_attr.attr, + &sensor_dev_attr_in11_min.dev_attr.attr, + &sensor_dev_attr_in12_min.dev_attr.attr, + &sensor_dev_attr_in13_min.dev_attr.attr, + + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in5_input.dev_attr.attr, + &sensor_dev_attr_in6_input.dev_attr.attr, + &sensor_dev_attr_in7_input.dev_attr.attr, + &sensor_dev_attr_in8_input.dev_attr.attr, + &sensor_dev_attr_in9_input.dev_attr.attr, + &sensor_dev_attr_in10_input.dev_attr.attr, + &sensor_dev_attr_in11_input.dev_attr.attr, + &sensor_dev_attr_in12_input.dev_attr.attr, + &sensor_dev_attr_in13_input.dev_attr.attr, + + &sensor_dev_attr_in1_label.dev_attr.attr, + &sensor_dev_attr_in2_label.dev_attr.attr, + &sensor_dev_attr_in3_label.dev_attr.attr, + &sensor_dev_attr_in4_label.dev_attr.attr, + &sensor_dev_attr_in5_label.dev_attr.attr, + &sensor_dev_attr_in6_label.dev_attr.attr, + &sensor_dev_attr_in7_label.dev_attr.attr, + &sensor_dev_attr_in8_label.dev_attr.attr, + &sensor_dev_attr_in9_label.dev_attr.attr, + &sensor_dev_attr_in10_label.dev_attr.attr, + &sensor_dev_attr_in11_label.dev_attr.attr, + &sensor_dev_attr_in12_label.dev_attr.attr, + &sensor_dev_attr_in13_label.dev_attr.attr, + + &sensor_dev_attr_in1_alarm.dev_attr.attr, + &sensor_dev_attr_in2_alarm.dev_attr.attr, + &sensor_dev_attr_in3_alarm.dev_attr.attr, + &sensor_dev_attr_in4_alarm.dev_attr.attr, + &sensor_dev_attr_in5_alarm.dev_attr.attr, + &sensor_dev_attr_in6_alarm.dev_attr.attr, + &sensor_dev_attr_in7_alarm.dev_attr.attr, + &sensor_dev_attr_in8_alarm.dev_attr.attr, + &sensor_dev_attr_in9_alarm.dev_attr.attr, + &sensor_dev_attr_in10_alarm.dev_attr.attr, + &sensor_dev_attr_in11_alarm.dev_attr.attr, + &sensor_dev_attr_in12_alarm.dev_attr.attr, + &sensor_dev_attr_in13_alarm.dev_attr.attr, + + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan2_min.dev_attr.attr, + &sensor_dev_attr_fan3_min.dev_attr.attr, + &sensor_dev_attr_fan4_min.dev_attr.attr, + &sensor_dev_attr_fan5_min.dev_attr.attr, + &sensor_dev_attr_fan6_min.dev_attr.attr, + &sensor_dev_attr_fan7_min.dev_attr.attr, + &sensor_dev_attr_fan8_min.dev_attr.attr, + + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_fan6_input.dev_attr.attr, + &sensor_dev_attr_fan7_input.dev_attr.attr, + &sensor_dev_attr_fan8_input.dev_attr.attr, + + &sensor_dev_attr_fan1_alarm.dev_attr.attr, + &sensor_dev_attr_fan2_alarm.dev_attr.attr, + &sensor_dev_attr_fan3_alarm.dev_attr.attr, + &sensor_dev_attr_fan4_alarm.dev_attr.attr, + &sensor_dev_attr_fan5_alarm.dev_attr.attr, + &sensor_dev_attr_fan6_alarm.dev_attr.attr, + &sensor_dev_attr_fan7_alarm.dev_attr.attr, + &sensor_dev_attr_fan8_alarm.dev_attr.attr, + + &sensor_dev_attr_force_pwm_max.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + + &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, + &sensor_dev_attr_pwm4_auto_point1_pwm.dev_attr.attr, + + &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, + &sensor_dev_attr_pwm4_auto_point2_pwm.dev_attr.attr, + + &sensor_dev_attr_temp1_auto_point1_hyst.dev_attr.attr, + &sensor_dev_attr_temp2_auto_point1_hyst.dev_attr.attr, + &sensor_dev_attr_temp3_auto_point1_hyst.dev_attr.attr, + &sensor_dev_attr_temp4_auto_point1_hyst.dev_attr.attr, + + &sensor_dev_attr_temp1_auto_point2_hyst.dev_attr.attr, + &sensor_dev_attr_temp2_auto_point2_hyst.dev_attr.attr, + &sensor_dev_attr_temp3_auto_point2_hyst.dev_attr.attr, + &sensor_dev_attr_temp4_auto_point2_hyst.dev_attr.attr, + + &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr, + &sensor_dev_attr_temp4_auto_point1_temp.dev_attr.attr, + + &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr, + &sensor_dev_attr_temp4_auto_point2_temp.dev_attr.attr, + + &sensor_dev_attr_pwm1_enable.dev_attr.attr, + &sensor_dev_attr_pwm2_enable.dev_attr.attr, + &sensor_dev_attr_pwm3_enable.dev_attr.attr, + &sensor_dev_attr_pwm4_enable.dev_attr.attr, + + &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, + &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, + &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, + &sensor_dev_attr_pwm4_auto_channels_temp.dev_attr.attr, + NULL +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int adt7462_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + if (kind <= 0) { + int vendor, device, revision; + + vendor = i2c_smbus_read_byte_data(client, ADT7462_REG_VENDOR); + if (vendor != ADT7462_VENDOR) + return -ENODEV; + + device = i2c_smbus_read_byte_data(client, ADT7462_REG_DEVICE); + if (device != ADT7462_DEVICE) + return -ENODEV; + + revision = i2c_smbus_read_byte_data(client, + ADT7462_REG_REVISION); + if (revision != ADT7462_REVISION) + return -ENODEV; + } else + dev_dbg(&adapter->dev, "detection forced\n"); + + strlcpy(info->type, "adt7462", I2C_NAME_SIZE); + + return 0; +} + +static int adt7462_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adt7462_data *data; + int err; + + data = kzalloc(sizeof(struct adt7462_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s chip found\n", client->name); + + /* Register sysfs hooks */ + data->attrs.attrs = adt7462_attr; + err = sysfs_create_group(&client->dev.kobj, &data->attrs); + if (err) + goto exit_free; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + err = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->attrs); +exit_free: + kfree(data); +exit: + return err; +} + +static int adt7462_remove(struct i2c_client *client) +{ + struct adt7462_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->attrs); + kfree(data); + return 0; +} + +static int __init adt7462_init(void) +{ + return i2c_add_driver(&adt7462_driver); +} + +static void __exit adt7462_exit(void) +{ + i2c_del_driver(&adt7462_driver); +} + +MODULE_AUTHOR("Darrick J. Wong "); +MODULE_DESCRIPTION("ADT7462 driver"); +MODULE_LICENSE("GPL"); + +module_init(adt7462_init); +module_exit(adt7462_exit); -- cgit v1.2.3 From a412ae3fb90ab49072b82c8cfa1e3e60d2b27005 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Wed, 12 Nov 2008 13:27:04 -0800 Subject: ics932s401: new clock generator chip driver The ics932s401 is a clock generator chip. This driver allows users to read the current clock outputs. Signed-off-by: Darrick J. Wong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/Kconfig | 10 + drivers/misc/Makefile | 1 + drivers/misc/ics932s401.c | 515 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 526 insertions(+) create mode 100644 drivers/misc/ics932s401.c (limited to 'drivers') diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 4494ad27cbf..dcac7ca7693 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -227,6 +227,16 @@ config HP_WMI To compile this driver as a module, choose M here: the module will be called hp-wmi. +config ICS932S401 + tristate "Integrated Circuits ICS932S401" + depends on I2C && EXPERIMENTAL + help + If you say yes here you get support for the Integrated Circuits + ICS932S401 clock control chips. + + This driver can also be built as a module. If so, the module + will be called ics932s401. + config MSI_LAPTOP tristate "MSI Laptop Extras" depends on X86 diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 909e2468cdc..bb14633d136 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o obj-$(CONFIG_HP_WMI) += hp-wmi.o +obj-$(CONFIG_ICS932S401) += ics932s401.o obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o obj-$(CONFIG_LKDTM) += lkdtm.o obj-$(CONFIG_TIFM_CORE) += tifm_core.o diff --git a/drivers/misc/ics932s401.c b/drivers/misc/ics932s401.c new file mode 100644 index 00000000000..6e43ab4231a --- /dev/null +++ b/drivers/misc/ics932s401.c @@ -0,0 +1,515 @@ +/* + * A driver for the Integrated Circuits ICS932S401 + * Copyright (C) 2008 IBM + * + * Author: Darrick J. Wong + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x69, I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_1(ics932s401); + +/* ICS932S401 registers */ +#define ICS932S401_REG_CFG2 0x01 +#define ICS932S401_CFG1_SPREAD 0x01 +#define ICS932S401_REG_CFG7 0x06 +#define ICS932S401_FS_MASK 0x07 +#define ICS932S401_REG_VENDOR_REV 0x07 +#define ICS932S401_VENDOR 1 +#define ICS932S401_VENDOR_MASK 0x0F +#define ICS932S401_REV 4 +#define ICS932S401_REV_SHIFT 4 +#define ICS932S401_REG_DEVICE 0x09 +#define ICS932S401_DEVICE 11 +#define ICS932S401_REG_CTRL 0x0A +#define ICS932S401_MN_ENABLED 0x80 +#define ICS932S401_CPU_ALT 0x04 +#define ICS932S401_SRC_ALT 0x08 +#define ICS932S401_REG_CPU_M_CTRL 0x0B +#define ICS932S401_M_MASK 0x3F +#define ICS932S401_REG_CPU_N_CTRL 0x0C +#define ICS932S401_REG_CPU_SPREAD1 0x0D +#define ICS932S401_REG_CPU_SPREAD2 0x0E +#define ICS932S401_SPREAD_MASK 0x7FFF +#define ICS932S401_REG_SRC_M_CTRL 0x0F +#define ICS932S401_REG_SRC_N_CTRL 0x10 +#define ICS932S401_REG_SRC_SPREAD1 0x11 +#define ICS932S401_REG_SRC_SPREAD2 0x12 +#define ICS932S401_REG_CPU_DIVISOR 0x13 +#define ICS932S401_CPU_DIVISOR_SHIFT 4 +#define ICS932S401_REG_PCISRC_DIVISOR 0x14 +#define ICS932S401_SRC_DIVISOR_MASK 0x0F +#define ICS932S401_PCI_DIVISOR_SHIFT 4 + +/* Base clock is 14.318MHz */ +#define BASE_CLOCK 14318 + +#define NUM_REGS 21 +#define NUM_MIRRORED_REGS 15 + +static int regs_to_copy[NUM_MIRRORED_REGS] = { + ICS932S401_REG_CFG2, + ICS932S401_REG_CFG7, + ICS932S401_REG_VENDOR_REV, + ICS932S401_REG_DEVICE, + ICS932S401_REG_CTRL, + ICS932S401_REG_CPU_M_CTRL, + ICS932S401_REG_CPU_N_CTRL, + ICS932S401_REG_CPU_SPREAD1, + ICS932S401_REG_CPU_SPREAD2, + ICS932S401_REG_SRC_M_CTRL, + ICS932S401_REG_SRC_N_CTRL, + ICS932S401_REG_SRC_SPREAD1, + ICS932S401_REG_SRC_SPREAD2, + ICS932S401_REG_CPU_DIVISOR, + ICS932S401_REG_PCISRC_DIVISOR, +}; + +/* How often do we reread sensors values? (In jiffies) */ +#define SENSOR_REFRESH_INTERVAL (2 * HZ) + +/* How often do we reread sensor limit values? (In jiffies) */ +#define LIMIT_REFRESH_INTERVAL (60 * HZ) + +struct ics932s401_data { + struct attribute_group attrs; + struct mutex lock; + char sensors_valid; + unsigned long sensors_last_updated; /* In jiffies */ + + u8 regs[NUM_REGS]; +}; + +static int ics932s401_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int ics932s401_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info); +static int ics932s401_remove(struct i2c_client *client); + +static const struct i2c_device_id ics932s401_id[] = { + { "ics932s401", ics932s401 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ics932s401_id); + +static struct i2c_driver ics932s401_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ics932s401", + }, + .probe = ics932s401_probe, + .remove = ics932s401_remove, + .id_table = ics932s401_id, + .detect = ics932s401_detect, + .address_data = &addr_data, +}; + +static struct ics932s401_data *ics932s401_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ics932s401_data *data = i2c_get_clientdata(client); + unsigned long local_jiffies = jiffies; + int i, temp; + + mutex_lock(&data->lock); + if (time_before(local_jiffies, data->sensors_last_updated + + SENSOR_REFRESH_INTERVAL) + && data->sensors_valid) + goto out; + + /* + * Each register must be read as a word and then right shifted 8 bits. + * Not really sure why this is; setting the "byte count programming" + * register to 1 does not fix this problem. + */ + for (i = 0; i < NUM_MIRRORED_REGS; i++) { + temp = i2c_smbus_read_word_data(client, regs_to_copy[i]); + data->regs[regs_to_copy[i]] = temp >> 8; + } + + data->sensors_last_updated = local_jiffies; + data->sensors_valid = 1; + +out: + mutex_unlock(&data->lock); + return data; +} + +static ssize_t show_spread_enabled(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct ics932s401_data *data = ics932s401_update_device(dev); + + if (data->regs[ICS932S401_REG_CFG2] & ICS932S401_CFG1_SPREAD) + return sprintf(buf, "1\n"); + + return sprintf(buf, "0\n"); +} + +/* bit to cpu khz map */ +static const int fs_speeds[] = { + 266666, + 133333, + 200000, + 166666, + 333333, + 100000, + 400000, + 0, +}; + +/* clock divisor map */ +static const int divisors[] = {2, 3, 5, 15, 4, 6, 10, 30, 8, 12, 20, 60, 16, + 24, 40, 120}; + +/* Calculate CPU frequency from the M/N registers. */ +static int calculate_cpu_freq(struct ics932s401_data *data) +{ + int m, n, freq; + + m = data->regs[ICS932S401_REG_CPU_M_CTRL] & ICS932S401_M_MASK; + n = data->regs[ICS932S401_REG_CPU_N_CTRL]; + + /* Pull in bits 8 & 9 from the M register */ + n |= ((int)data->regs[ICS932S401_REG_CPU_M_CTRL] & 0x80) << 1; + n |= ((int)data->regs[ICS932S401_REG_CPU_M_CTRL] & 0x40) << 3; + + freq = BASE_CLOCK * (n + 8) / (m + 2); + freq /= divisors[data->regs[ICS932S401_REG_CPU_DIVISOR] >> + ICS932S401_CPU_DIVISOR_SHIFT]; + + return freq; +} + +static ssize_t show_cpu_clock(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct ics932s401_data *data = ics932s401_update_device(dev); + + return sprintf(buf, "%d\n", calculate_cpu_freq(data)); +} + +static ssize_t show_cpu_clock_sel(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct ics932s401_data *data = ics932s401_update_device(dev); + int freq; + + if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_MN_ENABLED) + freq = calculate_cpu_freq(data); + else { + /* Freq is neatly wrapped up for us */ + int fid = data->regs[ICS932S401_REG_CFG7] & ICS932S401_FS_MASK; + freq = fs_speeds[fid]; + if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_CPU_ALT) { + switch (freq) { + case 166666: + freq = 160000; + break; + case 333333: + freq = 320000; + break; + } + } + } + + return sprintf(buf, "%d\n", freq); +} + +/* Calculate SRC frequency from the M/N registers. */ +static int calculate_src_freq(struct ics932s401_data *data) +{ + int m, n, freq; + + m = data->regs[ICS932S401_REG_SRC_M_CTRL] & ICS932S401_M_MASK; + n = data->regs[ICS932S401_REG_SRC_N_CTRL]; + + /* Pull in bits 8 & 9 from the M register */ + n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x80) << 1; + n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x40) << 3; + + freq = BASE_CLOCK * (n + 8) / (m + 2); + freq /= divisors[data->regs[ICS932S401_REG_PCISRC_DIVISOR] & + ICS932S401_SRC_DIVISOR_MASK]; + + return freq; +} + +static ssize_t show_src_clock(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct ics932s401_data *data = ics932s401_update_device(dev); + + return sprintf(buf, "%d\n", calculate_src_freq(data)); +} + +static ssize_t show_src_clock_sel(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct ics932s401_data *data = ics932s401_update_device(dev); + int freq; + + if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_MN_ENABLED) + freq = calculate_src_freq(data); + else + /* Freq is neatly wrapped up for us */ + if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_CPU_ALT && + data->regs[ICS932S401_REG_CTRL] & ICS932S401_SRC_ALT) + freq = 96000; + else + freq = 100000; + + return sprintf(buf, "%d\n", freq); +} + +/* Calculate PCI frequency from the SRC M/N registers. */ +static int calculate_pci_freq(struct ics932s401_data *data) +{ + int m, n, freq; + + m = data->regs[ICS932S401_REG_SRC_M_CTRL] & ICS932S401_M_MASK; + n = data->regs[ICS932S401_REG_SRC_N_CTRL]; + + /* Pull in bits 8 & 9 from the M register */ + n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x80) << 1; + n |= ((int)data->regs[ICS932S401_REG_SRC_M_CTRL] & 0x40) << 3; + + freq = BASE_CLOCK * (n + 8) / (m + 2); + freq /= divisors[data->regs[ICS932S401_REG_PCISRC_DIVISOR] >> + ICS932S401_PCI_DIVISOR_SHIFT]; + + return freq; +} + +static ssize_t show_pci_clock(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct ics932s401_data *data = ics932s401_update_device(dev); + + return sprintf(buf, "%d\n", calculate_pci_freq(data)); +} + +static ssize_t show_pci_clock_sel(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct ics932s401_data *data = ics932s401_update_device(dev); + int freq; + + if (data->regs[ICS932S401_REG_CTRL] & ICS932S401_MN_ENABLED) + freq = calculate_pci_freq(data); + else + freq = 33333; + + return sprintf(buf, "%d\n", freq); +} + +static ssize_t show_value(struct device *dev, + struct device_attribute *devattr, + char *buf); + +static ssize_t show_spread(struct device *dev, + struct device_attribute *devattr, + char *buf); + +static DEVICE_ATTR(spread_enabled, S_IRUGO, show_spread_enabled, NULL); +static DEVICE_ATTR(cpu_clock_selection, S_IRUGO, show_cpu_clock_sel, NULL); +static DEVICE_ATTR(cpu_clock, S_IRUGO, show_cpu_clock, NULL); +static DEVICE_ATTR(src_clock_selection, S_IRUGO, show_src_clock_sel, NULL); +static DEVICE_ATTR(src_clock, S_IRUGO, show_src_clock, NULL); +static DEVICE_ATTR(pci_clock_selection, S_IRUGO, show_pci_clock_sel, NULL); +static DEVICE_ATTR(pci_clock, S_IRUGO, show_pci_clock, NULL); +static DEVICE_ATTR(usb_clock, S_IRUGO, show_value, NULL); +static DEVICE_ATTR(ref_clock, S_IRUGO, show_value, NULL); +static DEVICE_ATTR(cpu_spread, S_IRUGO, show_spread, NULL); +static DEVICE_ATTR(src_spread, S_IRUGO, show_spread, NULL); + +static struct attribute *ics932s401_attr[] = +{ + &dev_attr_spread_enabled.attr, + &dev_attr_cpu_clock_selection.attr, + &dev_attr_cpu_clock.attr, + &dev_attr_src_clock_selection.attr, + &dev_attr_src_clock.attr, + &dev_attr_pci_clock_selection.attr, + &dev_attr_pci_clock.attr, + &dev_attr_usb_clock.attr, + &dev_attr_ref_clock.attr, + &dev_attr_cpu_spread.attr, + &dev_attr_src_spread.attr, + NULL +}; + +static ssize_t show_value(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + int x; + + if (devattr == &dev_attr_usb_clock) + x = 48000; + else if (devattr == &dev_attr_ref_clock) + x = BASE_CLOCK; + else + BUG(); + + return sprintf(buf, "%d\n", x); +} + +static ssize_t show_spread(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct ics932s401_data *data = ics932s401_update_device(dev); + int reg; + unsigned long val; + + if (!(data->regs[ICS932S401_REG_CFG2] & ICS932S401_CFG1_SPREAD)) + return sprintf(buf, "0%%\n"); + + if (devattr == &dev_attr_src_spread) + reg = ICS932S401_REG_SRC_SPREAD1; + else if (devattr == &dev_attr_cpu_spread) + reg = ICS932S401_REG_CPU_SPREAD1; + else + BUG(); + + val = data->regs[reg] | (data->regs[reg + 1] << 8); + val &= ICS932S401_SPREAD_MASK; + + /* Scale 0..2^14 to -0.5. */ + val = 500000 * val / 16384; + return sprintf(buf, "-0.%lu%%\n", val); +} + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int ics932s401_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + if (kind <= 0) { + int vendor, device, revision; + + vendor = i2c_smbus_read_word_data(client, + ICS932S401_REG_VENDOR_REV); + vendor >>= 8; + revision = vendor >> ICS932S401_REV_SHIFT; + vendor &= ICS932S401_VENDOR_MASK; + if (vendor != ICS932S401_VENDOR) + return -ENODEV; + + device = i2c_smbus_read_word_data(client, + ICS932S401_REG_DEVICE); + device >>= 8; + if (device != ICS932S401_DEVICE) + return -ENODEV; + + if (revision != ICS932S401_REV) + dev_info(&adapter->dev, "Unknown revision %d\n", + revision); + } else + dev_dbg(&adapter->dev, "detection forced\n"); + + strlcpy(info->type, "ics932s401", I2C_NAME_SIZE); + + return 0; +} + +static int ics932s401_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct ics932s401_data *data; + int err; + + data = kzalloc(sizeof(struct ics932s401_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s chip found\n", client->name); + + /* Register sysfs hooks */ + data->attrs.attrs = ics932s401_attr; + err = sysfs_create_group(&client->dev.kobj, &data->attrs); + if (err) + goto exit_free; + + return 0; + +exit_free: + kfree(data); +exit: + return err; +} + +static int ics932s401_remove(struct i2c_client *client) +{ + struct ics932s401_data *data = i2c_get_clientdata(client); + + sysfs_remove_group(&client->dev.kobj, &data->attrs); + kfree(data); + return 0; +} + +static int __init ics932s401_init(void) +{ + return i2c_add_driver(&ics932s401_driver); +} + +static void __exit ics932s401_exit(void) +{ + i2c_del_driver(&ics932s401_driver); +} + +MODULE_AUTHOR("Darrick J. Wong "); +MODULE_DESCRIPTION("ICS932S401 driver"); +MODULE_LICENSE("GPL"); + +module_init(ics932s401_init); +module_exit(ics932s401_exit); + +/* IBM IntelliStation Z30 */ +MODULE_ALIAS("dmi:bvnIBM:*:rn9228:*"); +MODULE_ALIAS("dmi:bvnIBM:*:rn9232:*"); + +/* IBM x3650/x3550 */ +MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3650*"); +MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3550*"); -- cgit v1.2.3 From 077eaf5b40ecb2c345d82f02275c20e965dfa3e5 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Nov 2008 13:27:04 -0800 Subject: rtc: rtc-wm8350: add support for WM8350 RTC This adds support for the RTC provided by the Wolfson Microelectronics WM8350. This driver was originally written by Graeme Gregory and Liam Girdwood, though it has been modified since then to update it to current mainline coding standards and for API completeness. [akpm@linux-foundation.org: s/schedule_timeout_interruptible/schedule_timeout_uninterruptible/ to prevent bogus timeout when signal_pending()] Signed-off-by: Mark Brown Cc: Alessandro Zummo Cc: David Brownell Cc: Liam Girdwood Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 10 + drivers/rtc/Makefile | 1 + drivers/rtc/rtc-wm8350.c | 514 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 525 insertions(+) create mode 100644 drivers/rtc/rtc-wm8350.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 8abbb2020af..7951ad2fd99 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -468,6 +468,16 @@ config RTC_DRV_V3020 This driver can also be built as a module. If so, the module will be called rtc-v3020. +config RTC_DRV_WM8350 + tristate "Wolfson Microelectronics WM8350 RTC" + depends on MFD_WM8350 + help + If you say yes here you will get support for the RTC subsystem + of the Wolfson Microelectronics WM8350. + + This driver can also be built as a module. If so, the module + will be called "rtc-wm8350". + comment "on-CPU RTC drivers" config RTC_DRV_OMAP diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index e9e8474cc8f..7a41201e7ef 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -66,4 +66,5 @@ obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o +obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c new file mode 100644 index 00000000000..5c5e3aa9138 --- /dev/null +++ b/drivers/rtc/rtc-wm8350.c @@ -0,0 +1,514 @@ +/* + * Real Time Clock driver for Wolfson Microelectronics WM8350 + * + * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC. + * + * Author: Liam Girdwood + * linux@wolfsonmicro.com + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WM8350_SET_ALM_RETRIES 5 +#define WM8350_SET_TIME_RETRIES 5 +#define WM8350_GET_TIME_RETRIES 5 + +#define to_wm8350_from_rtc_dev(d) container_of(d, struct wm8350, rtc.pdev.dev) + +/* + * Read current time and date in RTC + */ +static int wm8350_rtc_readtime(struct device *dev, struct rtc_time *tm) +{ + struct wm8350 *wm8350 = dev_get_drvdata(dev); + u16 time1[4], time2[4]; + int retries = WM8350_GET_TIME_RETRIES, ret; + + /* + * Read the time twice and compare. + * If time1 == time2, then time is valid else retry. + */ + do { + ret = wm8350_block_read(wm8350, WM8350_RTC_SECONDS_MINUTES, + 4, time1); + if (ret < 0) + return ret; + ret = wm8350_block_read(wm8350, WM8350_RTC_SECONDS_MINUTES, + 4, time2); + if (ret < 0) + return ret; + + if (memcmp(time1, time2, sizeof(time1)) == 0) { + tm->tm_sec = time1[0] & WM8350_RTC_SECS_MASK; + + tm->tm_min = (time1[0] & WM8350_RTC_MINS_MASK) + >> WM8350_RTC_MINS_SHIFT; + + tm->tm_hour = time1[1] & WM8350_RTC_HRS_MASK; + + tm->tm_wday = ((time1[1] >> WM8350_RTC_DAY_SHIFT) + & 0x7) - 1; + + tm->tm_mon = ((time1[2] & WM8350_RTC_MTH_MASK) + >> WM8350_RTC_MTH_SHIFT) - 1; + + tm->tm_mday = (time1[2] & WM8350_RTC_DATE_MASK); + + tm->tm_year = ((time1[3] & WM8350_RTC_YHUNDREDS_MASK) + >> WM8350_RTC_YHUNDREDS_SHIFT) * 100; + tm->tm_year += time1[3] & WM8350_RTC_YUNITS_MASK; + + tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, + tm->tm_year); + tm->tm_year -= 1900; + + dev_dbg(dev, "Read (%d left): %04x %04x %04x %04x\n", + retries, + time1[0], time1[1], time1[2], time1[3]); + + return 0; + } + } while (retries--); + + dev_err(dev, "timed out reading RTC time\n"); + return -EIO; +} + +/* + * Set current time and date in RTC + */ +static int wm8350_rtc_settime(struct device *dev, struct rtc_time *tm) +{ + struct wm8350 *wm8350 = dev_get_drvdata(dev); + u16 time[4]; + u16 rtc_ctrl; + int ret, retries = WM8350_SET_TIME_RETRIES; + + time[0] = tm->tm_sec; + time[0] |= tm->tm_min << WM8350_RTC_MINS_SHIFT; + time[1] = tm->tm_hour; + time[1] |= (tm->tm_wday + 1) << WM8350_RTC_DAY_SHIFT; + time[2] = tm->tm_mday; + time[2] |= (tm->tm_mon + 1) << WM8350_RTC_MTH_SHIFT; + time[3] = ((tm->tm_year + 1900) / 100) << WM8350_RTC_YHUNDREDS_SHIFT; + time[3] |= (tm->tm_year + 1900) % 100; + + dev_dbg(dev, "Setting: %04x %04x %04x %04x\n", + time[0], time[1], time[2], time[3]); + + /* Set RTC_SET to stop the clock */ + ret = wm8350_set_bits(wm8350, WM8350_RTC_TIME_CONTROL, WM8350_RTC_SET); + if (ret < 0) + return ret; + + /* Wait until confirmation of stopping */ + do { + rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); + schedule_timeout_uninterruptible(msecs_to_jiffies(1)); + } while (retries-- && !(rtc_ctrl & WM8350_RTC_STS)); + + if (!retries) { + dev_err(dev, "timed out on set confirmation\n"); + return -EIO; + } + + /* Write time to RTC */ + ret = wm8350_block_write(wm8350, WM8350_RTC_SECONDS_MINUTES, 4, time); + if (ret < 0) + return ret; + + /* Clear RTC_SET to start the clock */ + ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL, + WM8350_RTC_SET); + return ret; +} + +/* + * Read alarm time and date in RTC + */ +static int wm8350_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct wm8350 *wm8350 = dev_get_drvdata(dev); + struct rtc_time *tm = &alrm->time; + u16 time[4]; + int ret; + + ret = wm8350_block_read(wm8350, WM8350_ALARM_SECONDS_MINUTES, 4, time); + if (ret < 0) + return ret; + + tm->tm_sec = time[0] & WM8350_RTC_ALMSECS_MASK; + if (tm->tm_sec == WM8350_RTC_ALMSECS_MASK) + tm->tm_sec = -1; + + tm->tm_min = time[0] & WM8350_RTC_ALMMINS_MASK; + if (tm->tm_min == WM8350_RTC_ALMMINS_MASK) + tm->tm_min = -1; + else + tm->tm_min >>= WM8350_RTC_ALMMINS_SHIFT; + + tm->tm_hour = time[1] & WM8350_RTC_ALMHRS_MASK; + if (tm->tm_hour == WM8350_RTC_ALMHRS_MASK) + tm->tm_hour = -1; + + tm->tm_wday = ((time[1] >> WM8350_RTC_ALMDAY_SHIFT) & 0x7) - 1; + if (tm->tm_wday > 7) + tm->tm_wday = -1; + + tm->tm_mon = time[2] & WM8350_RTC_ALMMTH_MASK; + if (tm->tm_mon == WM8350_RTC_ALMMTH_MASK) + tm->tm_mon = -1; + else + tm->tm_mon = (tm->tm_mon >> WM8350_RTC_ALMMTH_SHIFT) - 1; + + tm->tm_mday = (time[2] & WM8350_RTC_ALMDATE_MASK); + if (tm->tm_mday == WM8350_RTC_ALMDATE_MASK) + tm->tm_mday = -1; + + tm->tm_year = -1; + + alrm->enabled = !(time[3] & WM8350_RTC_ALMSTS); + + return 0; +} + +static int wm8350_rtc_stop_alarm(struct wm8350 *wm8350) +{ + int retries = WM8350_SET_ALM_RETRIES; + u16 rtc_ctrl; + int ret; + + /* Set RTC_SET to stop the clock */ + ret = wm8350_set_bits(wm8350, WM8350_RTC_TIME_CONTROL, + WM8350_RTC_ALMSET); + if (ret < 0) + return ret; + + /* Wait until confirmation of stopping */ + do { + rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); + schedule_timeout_uninterruptible(msecs_to_jiffies(1)); + } while (retries-- && !(rtc_ctrl & WM8350_RTC_ALMSTS)); + + if (!(rtc_ctrl & WM8350_RTC_ALMSTS)) + return -ETIMEDOUT; + + return 0; +} + +static int wm8350_rtc_start_alarm(struct wm8350 *wm8350) +{ + int ret; + int retries = WM8350_SET_ALM_RETRIES; + u16 rtc_ctrl; + + ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL, + WM8350_RTC_ALMSET); + if (ret < 0) + return ret; + + /* Wait until confirmation */ + do { + rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); + schedule_timeout_uninterruptible(msecs_to_jiffies(1)); + } while (retries-- && rtc_ctrl & WM8350_RTC_ALMSTS); + + if (rtc_ctrl & WM8350_RTC_ALMSTS) + return -ETIMEDOUT; + + return 0; +} + +static int wm8350_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct wm8350 *wm8350 = dev_get_drvdata(dev); + struct rtc_time *tm = &alrm->time; + u16 time[3]; + int ret; + + memset(time, 0, sizeof(time)); + + if (tm->tm_sec != -1) + time[0] |= tm->tm_sec; + else + time[0] |= WM8350_RTC_ALMSECS_MASK; + + if (tm->tm_min != -1) + time[0] |= tm->tm_min << WM8350_RTC_ALMMINS_SHIFT; + else + time[0] |= WM8350_RTC_ALMMINS_MASK; + + if (tm->tm_hour != -1) + time[1] |= tm->tm_hour; + else + time[1] |= WM8350_RTC_ALMHRS_MASK; + + if (tm->tm_wday != -1) + time[1] |= (tm->tm_wday + 1) << WM8350_RTC_ALMDAY_SHIFT; + else + time[1] |= WM8350_RTC_ALMDAY_MASK; + + if (tm->tm_mday != -1) + time[2] |= tm->tm_mday; + else + time[2] |= WM8350_RTC_ALMDATE_MASK; + + if (tm->tm_mon != -1) + time[2] |= (tm->tm_mon + 1) << WM8350_RTC_ALMMTH_SHIFT; + else + time[2] |= WM8350_RTC_ALMMTH_MASK; + + ret = wm8350_rtc_stop_alarm(wm8350); + if (ret < 0) + return ret; + + /* Write time to RTC */ + ret = wm8350_block_write(wm8350, WM8350_ALARM_SECONDS_MINUTES, + 3, time); + if (ret < 0) + return ret; + + if (alrm->enabled) + ret = wm8350_rtc_start_alarm(wm8350); + + return ret; +} + +/* + * Handle commands from user-space + */ +static int wm8350_rtc_ioctl(struct device *dev, unsigned int cmd, + unsigned long arg) +{ + struct wm8350 *wm8350 = dev_get_drvdata(dev); + + switch (cmd) { + case RTC_AIE_OFF: + return wm8350_rtc_stop_alarm(wm8350); + case RTC_AIE_ON: + return wm8350_rtc_start_alarm(wm8350); + + case RTC_UIE_OFF: + wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); + break; + case RTC_UIE_ON: + wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); + break; + + default: + return -ENOIOCTLCMD; + } + + return 0; +} + +static void wm8350_rtc_alarm_handler(struct wm8350 *wm8350, int irq, + void *data) +{ + struct rtc_device *rtc = wm8350->rtc.rtc; + int ret; + + rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF); + + /* Make it one shot */ + ret = wm8350_set_bits(wm8350, WM8350_RTC_TIME_CONTROL, + WM8350_RTC_ALMSET); + if (ret != 0) { + dev_err(&(wm8350->rtc.pdev->dev), + "Failed to disable alarm: %d\n", ret); + } +} + +static void wm8350_rtc_update_handler(struct wm8350 *wm8350, int irq, + void *data) +{ + struct rtc_device *rtc = wm8350->rtc.rtc; + + rtc_update_irq(rtc, 1, RTC_IRQF | RTC_UF); +} + +static const struct rtc_class_ops wm8350_rtc_ops = { + .ioctl = wm8350_rtc_ioctl, + .read_time = wm8350_rtc_readtime, + .set_time = wm8350_rtc_settime, + .read_alarm = wm8350_rtc_readalarm, + .set_alarm = wm8350_rtc_setalarm, +}; + +#ifdef CONFIG_PM +static int wm8350_rtc_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); + int ret = 0; + u16 reg; + + reg = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); + + if (device_may_wakeup(&wm8350->rtc.pdev->dev) && + reg & WM8350_RTC_ALMSTS) { + ret = wm8350_rtc_stop_alarm(wm8350); + if (ret != 0) + dev_err(&pdev->dev, "Failed to stop RTC alarm: %d\n", + ret); + } + + return ret; +} + +static int wm8350_rtc_resume(struct platform_device *pdev) +{ + struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev); + int ret; + + if (wm8350->rtc.alarm_enabled) { + ret = wm8350_rtc_start_alarm(wm8350); + if (ret != 0) + dev_err(&pdev->dev, + "Failed to restart RTC alarm: %d\n", ret); + } + + return 0; +} + +#else +#define wm8350_rtc_suspend NULL +#define wm8350_rtc_resume NULL +#endif + +static int wm8350_rtc_probe(struct platform_device *pdev) +{ + struct wm8350 *wm8350 = platform_get_drvdata(pdev); + struct wm8350_rtc *wm_rtc = &wm8350->rtc; + int ret = 0; + u16 timectl, power5; + + timectl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); + if (timectl & WM8350_RTC_BCD) { + dev_err(&pdev->dev, "RTC BCD mode not supported\n"); + return -EINVAL; + } + if (timectl & WM8350_RTC_12HR) { + dev_err(&pdev->dev, "RTC 12 hour mode not supported\n"); + return -EINVAL; + } + + /* enable the RTC if it's not already enabled */ + power5 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5); + if (!(power5 & WM8350_RTC_TICK_ENA)) { + dev_info(wm8350->dev, "Starting RTC\n"); + + wm8350_reg_unlock(wm8350); + + ret = wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, + WM8350_RTC_TICK_ENA); + if (ret < 0) { + dev_err(&pdev->dev, "failed to enable RTC: %d\n", ret); + return ret; + } + + wm8350_reg_lock(wm8350); + } + + if (timectl & WM8350_RTC_STS) { + int retries; + + ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL, + WM8350_RTC_SET); + if (ret < 0) { + dev_err(&pdev->dev, "failed to start: %d\n", ret); + return ret; + } + + retries = WM8350_SET_TIME_RETRIES; + do { + timectl = wm8350_reg_read(wm8350, + WM8350_RTC_TIME_CONTROL); + } while (timectl & WM8350_RTC_STS && retries--); + + if (retries == 0) { + dev_err(&pdev->dev, "failed to start: timeout\n"); + return -ENODEV; + } + } + + device_init_wakeup(&pdev->dev, 1); + + wm_rtc->rtc = rtc_device_register("wm8350", &pdev->dev, + &wm8350_rtc_ops, THIS_MODULE); + if (IS_ERR(wm_rtc->rtc)) { + ret = PTR_ERR(wm_rtc->rtc); + dev_err(&pdev->dev, "failed to register RTC: %d\n", ret); + return ret; + } + + wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); + wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_PER); + + wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC, + wm8350_rtc_update_handler, NULL); + + wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM, + wm8350_rtc_alarm_handler, NULL); + wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_ALM); + + return 0; +} + +static int __devexit wm8350_rtc_remove(struct platform_device *pdev) +{ + struct wm8350 *wm8350 = platform_get_drvdata(pdev); + struct wm8350_rtc *wm_rtc = &wm8350->rtc; + + wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); + + wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC); + wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM); + + rtc_device_unregister(wm_rtc->rtc); + + return 0; +} + +static struct platform_driver wm8350_rtc_driver = { + .probe = wm8350_rtc_probe, + .remove = __devexit_p(wm8350_rtc_remove), + .suspend = wm8350_rtc_suspend, + .resume = wm8350_rtc_resume, + .driver = { + .name = "wm8350-rtc", + }, +}; + +static int __init wm8350_rtc_init(void) +{ + return platform_driver_register(&wm8350_rtc_driver); +} +module_init(wm8350_rtc_init); + +static void __exit wm8350_rtc_exit(void) +{ + platform_driver_unregister(&wm8350_rtc_driver); +} +module_exit(wm8350_rtc_exit); + +MODULE_AUTHOR("Mark Brown "); +MODULE_DESCRIPTION("RTC driver for the WM8350"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:wm8350-rtc"); -- cgit v1.2.3 From a7fa9851b6dd18824320c4129f26947b3cdb63d8 Mon Sep 17 00:00:00 2001 From: Martyn Welch Date: Wed, 12 Nov 2008 13:27:06 -0800 Subject: rtc: basic implementation of Epson RX-8581 I2C Real Time Clock Provide the basic "get" and "set" functionality for the Epson RX-8581 I2C RTC. It currently does not support the RTC's Alarm or Fixed-cycle timer. [akpm@linux-foundation.org: need log2.h for ilog2(), remove unneeded initialisation] Signed-off-by: Martyn Welch Signed-off-by: Alessandro Zummo Cc: David Brownell Cc: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 8 ++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-rx8581.c | 281 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 290 insertions(+) create mode 100644 drivers/rtc/rtc-rx8581.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 7951ad2fd99..990020c1dae 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -277,6 +277,14 @@ config RTC_DRV_FM3130 This driver can also be built as a module. If so the module will be called rtc-fm3130. +config RTC_DRV_RX8581 + tristate "Epson RX-8581" + help + If you say yes here you will get support for the Epson RX-8581. + + This driver can also be built as a module. If so the module + will be called rtc-rx8581. + endif # I2C comment "SPI RTC drivers" diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 7a41201e7ef..16368600643 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -57,6 +57,7 @@ obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o +obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c new file mode 100644 index 00000000000..c9522f3bc21 --- /dev/null +++ b/drivers/rtc/rtc-rx8581.c @@ -0,0 +1,281 @@ +/* + * An I2C driver for the Epson RX8581 RTC + * + * Author: Martyn Welch + * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc. + * + * 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. + * + * Based on: rtc-pcf8563.c (An I2C driver for the Philips PCF8563 RTC) + * Copyright 2005-06 Tower Technologies + */ + +#include +#include +#include +#include +#include + +#define DRV_VERSION "0.1" + +#define RX8581_REG_SC 0x00 /* Second in BCD */ +#define RX8581_REG_MN 0x01 /* Minute in BCD */ +#define RX8581_REG_HR 0x02 /* Hour in BCD */ +#define RX8581_REG_DW 0x03 /* Day of Week */ +#define RX8581_REG_DM 0x04 /* Day of Month in BCD */ +#define RX8581_REG_MO 0x05 /* Month in BCD */ +#define RX8581_REG_YR 0x06 /* Year in BCD */ +#define RX8581_REG_RAM 0x07 /* RAM */ +#define RX8581_REG_AMN 0x08 /* Alarm Min in BCD*/ +#define RX8581_REG_AHR 0x09 /* Alarm Hour in BCD */ +#define RX8581_REG_ADM 0x0A +#define RX8581_REG_ADW 0x0A +#define RX8581_REG_TMR0 0x0B +#define RX8581_REG_TMR1 0x0C +#define RX8581_REG_EXT 0x0D /* Extension Register */ +#define RX8581_REG_FLAG 0x0E /* Flag Register */ +#define RX8581_REG_CTRL 0x0F /* Control Register */ + + +/* Flag Register bit definitions */ +#define RX8581_FLAG_UF 0x20 /* Update */ +#define RX8581_FLAG_TF 0x10 /* Timer */ +#define RX8581_FLAG_AF 0x08 /* Alarm */ +#define RX8581_FLAG_VLF 0x02 /* Voltage Low */ + +/* Control Register bit definitions */ +#define RX8581_CTRL_UIE 0x20 /* Update Interrupt Enable */ +#define RX8581_CTRL_TIE 0x10 /* Timer Interrupt Enable */ +#define RX8581_CTRL_AIE 0x08 /* Alarm Interrupt Enable */ +#define RX8581_CTRL_STOP 0x02 /* STOP bit */ +#define RX8581_CTRL_RESET 0x01 /* RESET bit */ + +static struct i2c_driver rx8581_driver; + +/* + * In the routines that deal directly with the rx8581 hardware, we use + * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. + */ +static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm) +{ + unsigned char date[7]; + int data, err; + + /* First we ensure that the "update flag" is not set, we read the + * time and date then re-read the "update flag". If the update flag + * has been set, we know that the time has changed during the read so + * we repeat the whole process again. + */ + data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); + if (data < 0) { + dev_err(&client->dev, "Unable to read device flags\n"); + return -EIO; + } + + do { + /* If update flag set, clear it */ + if (data & RX8581_FLAG_UF) { + err = i2c_smbus_write_byte_data(client, + RX8581_REG_FLAG, (data & ~RX8581_FLAG_UF)); + if (err != 0) { + dev_err(&client->dev, "Unable to write device " + "flags\n"); + return -EIO; + } + } + + /* Now read time and date */ + err = i2c_smbus_read_i2c_block_data(client, RX8581_REG_SC, + 7, date); + if (err < 0) { + dev_err(&client->dev, "Unable to read date\n"); + return -EIO; + } + + /* Check flag register */ + data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG); + if (data < 0) { + dev_err(&client->dev, "Unable to read device flags\n"); + return -EIO; + } + } while (data & RX8581_FLAG_UF); + + if (data & RX8581_FLAG_VLF) + dev_info(&client->dev, + "low voltage detected, date/time is not reliable.\n"); + + dev_dbg(&client->dev, + "%s: raw data is sec=%02x, min=%02x, hr=%02x, " + "wday=%02x, mday=%02x, mon=%02x, year=%02x\n", + __func__, + date[0], date[1], date[2], date[3], date[4], date[5], date[6]); + + tm->tm_sec = bcd2bin(date[RX8581_REG_SC] & 0x7F); + tm->tm_min = bcd2bin(date[RX8581_REG_MN] & 0x7F); + tm->tm_hour = bcd2bin(date[RX8581_REG_HR] & 0x3F); /* rtc hr 0-23 */ + tm->tm_wday = ilog2(date[RX8581_REG_DW] & 0x7F); + tm->tm_mday = bcd2bin(date[RX8581_REG_DM] & 0x3F); + tm->tm_mon = bcd2bin(date[RX8581_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ + tm->tm_year = bcd2bin(date[RX8581_REG_YR]); + if (tm->tm_year < 70) + tm->tm_year += 100; /* assume we are in 1970...2069 */ + + + dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " + "mday=%d, mon=%d, year=%d, wday=%d\n", + __func__, + tm->tm_sec, tm->tm_min, tm->tm_hour, + tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + + err = rtc_valid_tm(tm); + if (err < 0) + dev_err(&client->dev, "retrieved date/time is not valid.\n"); + + return err; +} + +static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm) +{ + int data, err; + unsigned char buf[7]; + + dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " + "mday=%d, mon=%d, year=%d, wday=%d\n", + __func__, + tm->tm_sec, tm->tm_min, tm->tm_hour, + tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + + /* hours, minutes and seconds */ + buf[RX8581_REG_SC] = bin2bcd(tm->tm_sec); + buf[RX8581_REG_MN] = bin2bcd(tm->tm_min); + buf[RX8581_REG_HR] = bin2bcd(tm->tm_hour); + + buf[RX8581_REG_DM] = bin2bcd(tm->tm_mday); + + /* month, 1 - 12 */ + buf[RX8581_REG_MO] = bin2bcd(tm->tm_mon + 1); + + /* year and century */ + buf[RX8581_REG_YR] = bin2bcd(tm->tm_year % 100); + buf[RX8581_REG_DW] = (0x1 << tm->tm_wday); + + /* Stop the clock */ + data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); + if (data < 0) { + dev_err(&client->dev, "Unable to read control register\n"); + return -EIO; + } + + err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, + (data | RX8581_CTRL_STOP)); + if (err < 0) { + dev_err(&client->dev, "Unable to write control register\n"); + return -EIO; + } + + /* write register's data */ + err = i2c_smbus_write_i2c_block_data(client, RX8581_REG_SC, 7, buf); + if (err < 0) { + dev_err(&client->dev, "Unable to write to date registers\n"); + return -EIO; + } + + /* Restart the clock */ + data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL); + if (data < 0) { + dev_err(&client->dev, "Unable to read control register\n"); + return -EIO; + } + + err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG, + (data | ~(RX8581_CTRL_STOP))); + if (err != 0) { + dev_err(&client->dev, "Unable to write control register\n"); + return -EIO; + } + + return 0; +} + +static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + return rx8581_get_datetime(to_i2c_client(dev), tm); +} + +static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + return rx8581_set_datetime(to_i2c_client(dev), tm); +} + +static const struct rtc_class_ops rx8581_rtc_ops = { + .read_time = rx8581_rtc_read_time, + .set_time = rx8581_rtc_set_time, +}; + +static int __devinit rx8581_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct rtc_device *rtc; + + dev_dbg(&client->dev, "%s\n", __func__); + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; + + dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); + + rtc = rtc_device_register(rx8581_driver.driver.name, + &client->dev, &rx8581_rtc_ops, THIS_MODULE); + + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + i2c_set_clientdata(client, rtc); + + return 0; +} + +static int __devexit rx8581_remove(struct i2c_client *client) +{ + struct rtc_device *rtc = i2c_get_clientdata(client); + + rtc_device_unregister(rtc); + + return 0; +} + +static const struct i2c_device_id rx8581_id[] = { + { "rx8581", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rx8581_id); + +static struct i2c_driver rx8581_driver = { + .driver = { + .name = "rtc-rx8581", + .owner = THIS_MODULE, + }, + .probe = rx8581_probe, + .remove = __devexit_p(rx8581_remove), + .id_table = rx8581_id, +}; + +static int __init rx8581_init(void) +{ + return i2c_add_driver(&rx8581_driver); +} + +static void __exit rx8581_exit(void) +{ + i2c_del_driver(&rx8581_driver); +} + +MODULE_AUTHOR("Martyn Welch "); +MODULE_DESCRIPTION("Epson RX-8581 RTC driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +module_init(rx8581_init); +module_exit(rx8581_exit); -- cgit v1.2.3 From 06de18085122b873012cb23f043e2bdcf5f50923 Mon Sep 17 00:00:00 2001 From: Mark Jackson Date: Wed, 12 Nov 2008 13:27:07 -0800 Subject: rtc: add Dallas DS1390/93/94 RTC chips Add support for the Dallas DS1390/93/94 SPI RTC chip. Signed-off-by: Mark Jackson Acked-by: Alessandro Zummo Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 11 +++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-ds1390.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 232 insertions(+) create mode 100644 drivers/rtc/rtc-ds1390.c (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 990020c1dae..123092d8a98 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -310,6 +310,17 @@ config RTC_DRV_DS1305 This driver can also be built as a module. If so, the module will be called rtc-ds1305. +config RTC_DRV_DS1390 + tristate "Dallas/Maxim DS1390/93/94" + help + If you say yes here you get support for the DS1390/93/94 chips. + + This driver only supports the RTC feature, and not other chip + features such as alarms and trickle charging. + + This driver can also be built as a module. If so, the module + will be called rtc-ds1390. + config RTC_DRV_MAX6902 tristate "Maxim MAX6902" help diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 16368600643..6e79c912bf9 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o +obj-$(CONFIG_RTC_DRV_DS1390) += rtc-ds1390.o obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c new file mode 100644 index 00000000000..599e976bf01 --- /dev/null +++ b/drivers/rtc/rtc-ds1390.c @@ -0,0 +1,220 @@ +/* + * rtc-ds1390.c -- driver for DS1390/93/94 + * + * Copyright (C) 2008 Mercury IMC Ltd + * Written by Mark Jackson + * + * 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. + * + * NOTE : Currently this driver only supports the bare minimum for read + * and write the RTC. The extra features provided by the chip family + * (alarms, trickle charger, different control registers) are unavailable. + */ + +#include +#include +#include +#include + +#define DS1390_REG_100THS 0x00 +#define DS1390_REG_SECONDS 0x01 +#define DS1390_REG_MINUTES 0x02 +#define DS1390_REG_HOURS 0x03 +#define DS1390_REG_DAY 0x04 +#define DS1390_REG_DATE 0x05 +#define DS1390_REG_MONTH_CENT 0x06 +#define DS1390_REG_YEAR 0x07 + +#define DS1390_REG_ALARM_100THS 0x08 +#define DS1390_REG_ALARM_SECONDS 0x09 +#define DS1390_REG_ALARM_MINUTES 0x0A +#define DS1390_REG_ALARM_HOURS 0x0B +#define DS1390_REG_ALARM_DAY_DATE 0x0C + +#define DS1390_REG_CONTROL 0x0D +#define DS1390_REG_STATUS 0x0E +#define DS1390_REG_TRICKLE 0x0F + +struct ds1390 { + struct rtc_device *rtc; + u8 txrx_buf[9]; /* cmd + 8 registers */ +}; + +static void ds1390_set_reg(struct device *dev, unsigned char address, + unsigned char data) +{ + struct spi_device *spi = to_spi_device(dev); + struct ds1390 *chip = dev_get_drvdata(dev); + + /* Set MSB to indicate write */ + chip->txrx_buf[0] = address | 0x80; + chip->txrx_buf[1] = data; + + /* do the i/o */ + spi_write_then_read(spi, chip->txrx_buf, 2, NULL, 0); +} + +static int ds1390_get_reg(struct device *dev, unsigned char address, + unsigned char *data) +{ + struct spi_device *spi = to_spi_device(dev); + struct ds1390 *chip = dev_get_drvdata(dev); + int status; + + if (!data) + return -EINVAL; + + /* Clear MSB to indicate read */ + chip->txrx_buf[0] = address & 0x7f; + /* do the i/o */ + status = spi_write_then_read(spi, chip->txrx_buf, 1, chip->txrx_buf, 1); + if (status != 0) + return status; + + *data = chip->txrx_buf[1]; + + return 0; +} + +static int ds1390_get_datetime(struct device *dev, struct rtc_time *dt) +{ + struct spi_device *spi = to_spi_device(dev); + struct ds1390 *chip = dev_get_drvdata(dev); + int status; + + /* build the message */ + chip->txrx_buf[0] = DS1390_REG_SECONDS; + + /* do the i/o */ + status = spi_write_then_read(spi, chip->txrx_buf, 1, chip->txrx_buf, 8); + if (status != 0) + return status; + + /* The chip sends data in this order: + * Seconds, Minutes, Hours, Day, Date, Month / Century, Year */ + dt->tm_sec = bcd2bin(chip->txrx_buf[0]); + dt->tm_min = bcd2bin(chip->txrx_buf[1]); + dt->tm_hour = bcd2bin(chip->txrx_buf[2]); + dt->tm_wday = bcd2bin(chip->txrx_buf[3]); + dt->tm_mday = bcd2bin(chip->txrx_buf[4]); + /* mask off century bit */ + dt->tm_mon = bcd2bin(chip->txrx_buf[5] & 0x7f) - 1; + /* adjust for century bit */ + dt->tm_year = bcd2bin(chip->txrx_buf[6]) + ((chip->txrx_buf[5] & 0x80) ? 100 : 0); + + return rtc_valid_tm(dt); +} + +static int ds1390_set_datetime(struct device *dev, struct rtc_time *dt) +{ + struct spi_device *spi = to_spi_device(dev); + struct ds1390 *chip = dev_get_drvdata(dev); + + /* build the message */ + chip->txrx_buf[0] = DS1390_REG_SECONDS | 0x80; + chip->txrx_buf[1] = bin2bcd(dt->tm_sec); + chip->txrx_buf[2] = bin2bcd(dt->tm_min); + chip->txrx_buf[3] = bin2bcd(dt->tm_hour); + chip->txrx_buf[4] = bin2bcd(dt->tm_wday); + chip->txrx_buf[5] = bin2bcd(dt->tm_mday); + chip->txrx_buf[6] = bin2bcd(dt->tm_mon + 1) | + ((dt->tm_year > 99) ? 0x80 : 0x00); + chip->txrx_buf[7] = bin2bcd(dt->tm_year % 100); + + /* do the i/o */ + return spi_write_then_read(spi, chip->txrx_buf, 8, NULL, 0); +} + +static int ds1390_read_time(struct device *dev, struct rtc_time *tm) +{ + return ds1390_get_datetime(dev, tm); +} + +static int ds1390_set_time(struct device *dev, struct rtc_time *tm) +{ + return ds1390_set_datetime(dev, tm); +} + +static const struct rtc_class_ops ds1390_rtc_ops = { + .read_time = ds1390_read_time, + .set_time = ds1390_set_time, +}; + +static int __devinit ds1390_probe(struct spi_device *spi) +{ + struct rtc_device *rtc; + unsigned char tmp; + struct ds1390 *chip; + int res; + + printk(KERN_DEBUG "DS1390 SPI RTC driver\n"); + + rtc = rtc_device_register("ds1390", + &spi->dev, &ds1390_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + printk(KERN_ALERT "RTC : unable to register device\n"); + return PTR_ERR(rtc); + } + + spi->mode = SPI_MODE_3; + spi->bits_per_word = 8; + spi_setup(spi); + + chip = kzalloc(sizeof *chip, GFP_KERNEL); + if (!chip) { + printk(KERN_ALERT "RTC : unable to allocate device memory\n"); + rtc_device_unregister(rtc); + return -ENOMEM; + } + chip->rtc = rtc; + dev_set_drvdata(&spi->dev, chip); + + res = ds1390_get_reg(&spi->dev, DS1390_REG_SECONDS, &tmp); + if (res) { + printk(KERN_ALERT "RTC : unable to read device\n"); + rtc_device_unregister(rtc); + return res; + } + + return 0; +} + +static int __devexit ds1390_remove(struct spi_device *spi) +{ + struct ds1390 *chip = platform_get_drvdata(spi); + struct rtc_device *rtc = chip->rtc; + + if (rtc) + rtc_device_unregister(rtc); + + kfree(chip); + + return 0; +} + +static struct spi_driver ds1390_driver = { + .driver = { + .name = "rtc-ds1390", + .owner = THIS_MODULE, + }, + .probe = ds1390_probe, + .remove = __devexit_p(ds1390_remove), +}; + +static __init int ds1390_init(void) +{ + return spi_register_driver(&ds1390_driver); +} +module_init(ds1390_init); + +static __exit void ds1390_exit(void) +{ + spi_unregister_driver(&ds1390_driver); +} +module_exit(ds1390_exit); + +MODULE_DESCRIPTION("DS1390/93/94 SPI RTC driver"); +MODULE_AUTHOR("Mark Jackson "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 34e453d45584ea9dc1f62833ace17c79a379deb4 Mon Sep 17 00:00:00 2001 From: Madhusudhan Chikkature Date: Wed, 12 Nov 2008 13:27:08 -0800 Subject: w1: export w1_read_8 function Export the w1_read_8 function for use of drivers. The OMAP HDQ driver(drivers/w1/masters/omap_hdq.c) uses this function. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Madhusudhan Chikkature Acked-by: Evgeniy Polyakov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/w1/w1.h | 1 + drivers/w1/w1_io.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h index cdaa6fffbfc..97304bd83ec 100644 --- a/drivers/w1/w1.h +++ b/drivers/w1/w1.h @@ -206,6 +206,7 @@ void w1_slave_detach(struct w1_slave *sl); u8 w1_triplet(struct w1_master *dev, int bdir); void w1_write_8(struct w1_master *, u8); +u8 w1_read_8(struct w1_master *); int w1_reset_bus(struct w1_master *); u8 w1_calc_crc8(u8 *, int); void w1_write_block(struct w1_master *, const u8 *, int); diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index f4f82f1f486..0d15b0eaf79 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c @@ -217,7 +217,7 @@ u8 w1_triplet(struct w1_master *dev, int bdir) * @param dev the master device * @return the byte read */ -static u8 w1_read_8(struct w1_master * dev) +u8 w1_read_8(struct w1_master *dev) { int i; u8 res = 0; @@ -230,6 +230,7 @@ static u8 w1_read_8(struct w1_master * dev) return res; } +EXPORT_SYMBOL_GPL(w1_read_8); /** * Writes a series of bytes. -- cgit v1.2.3 From 9f2bc79f7dd04adda1fc3be510c9b3d436f846c7 Mon Sep 17 00:00:00 2001 From: Madhusudhan Chikkature Date: Wed, 12 Nov 2008 13:27:09 -0800 Subject: hdq driver for OMAP2430/3430 The HDQ/1-Wire module of TI OMAP2430/3430 platforms implement the hardware protocol of the master functions of the Benchmark HDQ and the Dallas Semiconductor 1-Wire protocols. These protocols use a single wire for communication between the master (HDQ/1-Wire controller) and the slave (HDQ/1-Wire external compliant device). This patch provides the HDQ driver to suppport TI OMAP2430/3430 platforms. Signed-off-by: Madhusudhan Chikkature Acked-by: Felipe Balbi Acked-by: Evgeniy Polyakov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/w1/masters/Kconfig | 7 + drivers/w1/masters/Makefile | 1 + drivers/w1/masters/omap_hdq.c | 725 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 733 insertions(+) create mode 100644 drivers/w1/masters/omap_hdq.c (limited to 'drivers') diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index c4493091c65..a14d5b6e4c7 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -52,5 +52,12 @@ config W1_MASTER_GPIO This support is also available as a module. If so, the module will be called w1-gpio.ko. +config HDQ_MASTER_OMAP + tristate "OMAP HDQ driver" + depends on ARCH_OMAP2430 || ARCH_OMAP34XX + help + Say Y here if you want support for the 1-wire or HDQ Interface + on an OMAP processor. + endmenu diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index 1420b5bbdda..bc4714a75f3 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o +obj-$(CONFIG_HDQ_MASTER_OMAP) += omap_hdq.o diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c new file mode 100644 index 00000000000..1295625c482 --- /dev/null +++ b/drivers/w1/masters/omap_hdq.c @@ -0,0 +1,725 @@ +/* + * drivers/w1/masters/omap_hdq.c + * + * Copyright (C) 2007 Texas Instruments, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "../w1.h" +#include "../w1_int.h" + +#define MOD_NAME "OMAP_HDQ:" + +#define OMAP_HDQ_REVISION 0x00 +#define OMAP_HDQ_TX_DATA 0x04 +#define OMAP_HDQ_RX_DATA 0x08 +#define OMAP_HDQ_CTRL_STATUS 0x0c +#define OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK (1<<6) +#define OMAP_HDQ_CTRL_STATUS_CLOCKENABLE (1<<5) +#define OMAP_HDQ_CTRL_STATUS_GO (1<<4) +#define OMAP_HDQ_CTRL_STATUS_INITIALIZATION (1<<2) +#define OMAP_HDQ_CTRL_STATUS_DIR (1<<1) +#define OMAP_HDQ_CTRL_STATUS_MODE (1<<0) +#define OMAP_HDQ_INT_STATUS 0x10 +#define OMAP_HDQ_INT_STATUS_TXCOMPLETE (1<<2) +#define OMAP_HDQ_INT_STATUS_RXCOMPLETE (1<<1) +#define OMAP_HDQ_INT_STATUS_TIMEOUT (1<<0) +#define OMAP_HDQ_SYSCONFIG 0x14 +#define OMAP_HDQ_SYSCONFIG_SOFTRESET (1<<1) +#define OMAP_HDQ_SYSCONFIG_AUTOIDLE (1<<0) +#define OMAP_HDQ_SYSSTATUS 0x18 +#define OMAP_HDQ_SYSSTATUS_RESETDONE (1<<0) + +#define OMAP_HDQ_FLAG_CLEAR 0 +#define OMAP_HDQ_FLAG_SET 1 +#define OMAP_HDQ_TIMEOUT (HZ/5) + +#define OMAP_HDQ_MAX_USER 4 + +static DECLARE_WAIT_QUEUE_HEAD(hdq_wait_queue); +static int w1_id; + +struct hdq_data { + struct device *dev; + void __iomem *hdq_base; + /* lock status update */ + struct mutex hdq_mutex; + int hdq_usecount; + struct clk *hdq_ick; + struct clk *hdq_fck; + u8 hdq_irqstatus; + /* device lock */ + spinlock_t hdq_spinlock; + /* + * Used to control the call to omap_hdq_get and omap_hdq_put. + * HDQ Protocol: Write the CMD|REG_address first, followed by + * the data wrire or read. + */ + int init_trans; +}; + +static int __init omap_hdq_probe(struct platform_device *pdev); +static int omap_hdq_remove(struct platform_device *pdev); + +static struct platform_driver omap_hdq_driver = { + .probe = omap_hdq_probe, + .remove = omap_hdq_remove, + .driver = { + .name = "omap_hdq", + }, +}; + +static u8 omap_w1_read_byte(void *_hdq); +static void omap_w1_write_byte(void *_hdq, u8 byte); +static u8 omap_w1_reset_bus(void *_hdq); +static void omap_w1_search_bus(void *_hdq, u8 search_type, + w1_slave_found_callback slave_found); + + +static struct w1_bus_master omap_w1_master = { + .read_byte = omap_w1_read_byte, + .write_byte = omap_w1_write_byte, + .reset_bus = omap_w1_reset_bus, + .search = omap_w1_search_bus, +}; + +/* HDQ register I/O routines */ +static inline u8 hdq_reg_in(struct hdq_data *hdq_data, u32 offset) +{ + return __raw_readb(hdq_data->hdq_base + offset); +} + +static inline void hdq_reg_out(struct hdq_data *hdq_data, u32 offset, u8 val) +{ + __raw_writeb(val, hdq_data->hdq_base + offset); +} + +static inline u8 hdq_reg_merge(struct hdq_data *hdq_data, u32 offset, + u8 val, u8 mask) +{ + u8 new_val = (__raw_readb(hdq_data->hdq_base + offset) & ~mask) + | (val & mask); + __raw_writeb(new_val, hdq_data->hdq_base + offset); + + return new_val; +} + +/* + * Wait for one or more bits in flag change. + * HDQ_FLAG_SET: wait until any bit in the flag is set. + * HDQ_FLAG_CLEAR: wait until all bits in the flag are cleared. + * return 0 on success and -ETIMEDOUT in the case of timeout. + */ +static int hdq_wait_for_flag(struct hdq_data *hdq_data, u32 offset, + u8 flag, u8 flag_set, u8 *status) +{ + int ret = 0; + unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT; + + if (flag_set == OMAP_HDQ_FLAG_CLEAR) { + /* wait for the flag clear */ + while (((*status = hdq_reg_in(hdq_data, offset)) & flag) + && time_before(jiffies, timeout)) { + schedule_timeout_uninterruptible(1); + } + if (*status & flag) + ret = -ETIMEDOUT; + } else if (flag_set == OMAP_HDQ_FLAG_SET) { + /* wait for the flag set */ + while (!((*status = hdq_reg_in(hdq_data, offset)) & flag) + && time_before(jiffies, timeout)) { + schedule_timeout_uninterruptible(1); + } + if (!(*status & flag)) + ret = -ETIMEDOUT; + } else + return -EINVAL; + + return ret; +} + +/* write out a byte and fill *status with HDQ_INT_STATUS */ +static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status) +{ + int ret; + u8 tmp_status; + unsigned long irqflags; + + *status = 0; + + spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags); + /* clear interrupt flags via a dummy read */ + hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS); + /* ISR loads it with new INT_STATUS */ + hdq_data->hdq_irqstatus = 0; + spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags); + + hdq_reg_out(hdq_data, OMAP_HDQ_TX_DATA, val); + + /* set the GO bit */ + hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, OMAP_HDQ_CTRL_STATUS_GO, + OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO); + /* wait for the TXCOMPLETE bit */ + ret = wait_event_timeout(hdq_wait_queue, + hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT); + if (ret == 0) { + dev_dbg(hdq_data->dev, "TX wait elapsed\n"); + goto out; + } + + *status = hdq_data->hdq_irqstatus; + /* check irqstatus */ + if (!(*status & OMAP_HDQ_INT_STATUS_TXCOMPLETE)) { + dev_dbg(hdq_data->dev, "timeout waiting for" + "TXCOMPLETE/RXCOMPLETE, %x", *status); + ret = -ETIMEDOUT; + goto out; + } + + /* wait for the GO bit return to zero */ + ret = hdq_wait_for_flag(hdq_data, OMAP_HDQ_CTRL_STATUS, + OMAP_HDQ_CTRL_STATUS_GO, + OMAP_HDQ_FLAG_CLEAR, &tmp_status); + if (ret) { + dev_dbg(hdq_data->dev, "timeout waiting GO bit" + "return to zero, %x", tmp_status); + } + +out: + return ret; +} + +/* HDQ Interrupt service routine */ +static irqreturn_t hdq_isr(int irq, void *_hdq) +{ + struct hdq_data *hdq_data = _hdq; + unsigned long irqflags; + + spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags); + hdq_data->hdq_irqstatus = hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS); + spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags); + dev_dbg(hdq_data->dev, "hdq_isr: %x", hdq_data->hdq_irqstatus); + + if (hdq_data->hdq_irqstatus & + (OMAP_HDQ_INT_STATUS_TXCOMPLETE | OMAP_HDQ_INT_STATUS_RXCOMPLETE + | OMAP_HDQ_INT_STATUS_TIMEOUT)) { + /* wake up sleeping process */ + wake_up(&hdq_wait_queue); + } + + return IRQ_HANDLED; +} + +/* HDQ Mode: always return success */ +static u8 omap_w1_reset_bus(void *_hdq) +{ + return 0; +} + +/* W1 search callback function */ +static void omap_w1_search_bus(void *_hdq, u8 search_type, + w1_slave_found_callback slave_found) +{ + u64 module_id, rn_le, cs, id; + + if (w1_id) + module_id = w1_id; + else + module_id = 0x1; + + rn_le = cpu_to_le64(module_id); + /* + * HDQ might not obey truly the 1-wire spec. + * So calculate CRC based on module parameter. + */ + cs = w1_calc_crc8((u8 *)&rn_le, 7); + id = (cs << 56) | module_id; + + slave_found(_hdq, id); +} + +static int _omap_hdq_reset(struct hdq_data *hdq_data) +{ + int ret; + u8 tmp_status; + + hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, OMAP_HDQ_SYSCONFIG_SOFTRESET); + /* + * Select HDQ mode & enable clocks. + * It is observed that INT flags can't be cleared via a read and GO/INIT + * won't return to zero if interrupt is disabled. So we always enable + * interrupt. + */ + hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS, + OMAP_HDQ_CTRL_STATUS_CLOCKENABLE | + OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK); + + /* wait for reset to complete */ + ret = hdq_wait_for_flag(hdq_data, OMAP_HDQ_SYSSTATUS, + OMAP_HDQ_SYSSTATUS_RESETDONE, OMAP_HDQ_FLAG_SET, &tmp_status); + if (ret) + dev_dbg(hdq_data->dev, "timeout waiting HDQ reset, %x", + tmp_status); + else { + hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS, + OMAP_HDQ_CTRL_STATUS_CLOCKENABLE | + OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK); + hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, + OMAP_HDQ_SYSCONFIG_AUTOIDLE); + } + + return ret; +} + +/* Issue break pulse to the device */ +static int omap_hdq_break(struct hdq_data *hdq_data) +{ + int ret = 0; + u8 tmp_status; + unsigned long irqflags; + + ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); + if (ret < 0) { + dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); + ret = -EINTR; + goto rtn; + } + + spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags); + /* clear interrupt flags via a dummy read */ + hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS); + /* ISR loads it with new INT_STATUS */ + hdq_data->hdq_irqstatus = 0; + spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags); + + /* set the INIT and GO bit */ + hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, + OMAP_HDQ_CTRL_STATUS_INITIALIZATION | OMAP_HDQ_CTRL_STATUS_GO, + OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_INITIALIZATION | + OMAP_HDQ_CTRL_STATUS_GO); + + /* wait for the TIMEOUT bit */ + ret = wait_event_timeout(hdq_wait_queue, + hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT); + if (ret == 0) { + dev_dbg(hdq_data->dev, "break wait elapsed\n"); + ret = -EINTR; + goto out; + } + + tmp_status = hdq_data->hdq_irqstatus; + /* check irqstatus */ + if (!(tmp_status & OMAP_HDQ_INT_STATUS_TIMEOUT)) { + dev_dbg(hdq_data->dev, "timeout waiting for TIMEOUT, %x", + tmp_status); + ret = -ETIMEDOUT; + goto out; + } + /* + * wait for both INIT and GO bits rerurn to zero. + * zero wait time expected for interrupt mode. + */ + ret = hdq_wait_for_flag(hdq_data, OMAP_HDQ_CTRL_STATUS, + OMAP_HDQ_CTRL_STATUS_INITIALIZATION | + OMAP_HDQ_CTRL_STATUS_GO, OMAP_HDQ_FLAG_CLEAR, + &tmp_status); + if (ret) + dev_dbg(hdq_data->dev, "timeout waiting INIT&GO bits" + "return to zero, %x", tmp_status); + +out: + mutex_unlock(&hdq_data->hdq_mutex); +rtn: + return ret; +} + +static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val) +{ + int ret = 0; + u8 status; + unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT; + + ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); + if (ret < 0) { + ret = -EINTR; + goto rtn; + } + + if (!hdq_data->hdq_usecount) { + ret = -EINVAL; + goto out; + } + + if (!(hdq_data->hdq_irqstatus & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) { + hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, + OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO, + OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO); + /* + * The RX comes immediately after TX. It + * triggers another interrupt before we + * sleep. So we have to wait for RXCOMPLETE bit. + */ + while (!(hdq_data->hdq_irqstatus + & OMAP_HDQ_INT_STATUS_RXCOMPLETE) + && time_before(jiffies, timeout)) { + schedule_timeout_uninterruptible(1); + } + hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, 0, + OMAP_HDQ_CTRL_STATUS_DIR); + status = hdq_data->hdq_irqstatus; + /* check irqstatus */ + if (!(status & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) { + dev_dbg(hdq_data->dev, "timeout waiting for" + "RXCOMPLETE, %x", status); + ret = -ETIMEDOUT; + goto out; + } + } + /* the data is ready. Read it in! */ + *val = hdq_reg_in(hdq_data, OMAP_HDQ_RX_DATA); +out: + mutex_unlock(&hdq_data->hdq_mutex); +rtn: + return 0; + +} + +/* Enable clocks and set the controller to HDQ mode */ +static int omap_hdq_get(struct hdq_data *hdq_data) +{ + int ret = 0; + + ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); + if (ret < 0) { + ret = -EINTR; + goto rtn; + } + + if (OMAP_HDQ_MAX_USER == hdq_data->hdq_usecount) { + dev_dbg(hdq_data->dev, "attempt to exceed the max use count"); + ret = -EINVAL; + goto out; + } else { + hdq_data->hdq_usecount++; + try_module_get(THIS_MODULE); + if (1 == hdq_data->hdq_usecount) { + if (clk_enable(hdq_data->hdq_ick)) { + dev_dbg(hdq_data->dev, "Can not enable ick\n"); + ret = -ENODEV; + goto clk_err; + } + if (clk_enable(hdq_data->hdq_fck)) { + dev_dbg(hdq_data->dev, "Can not enable fck\n"); + clk_disable(hdq_data->hdq_ick); + ret = -ENODEV; + goto clk_err; + } + + /* make sure HDQ is out of reset */ + if (!(hdq_reg_in(hdq_data, OMAP_HDQ_SYSSTATUS) & + OMAP_HDQ_SYSSTATUS_RESETDONE)) { + ret = _omap_hdq_reset(hdq_data); + if (ret) + /* back up the count */ + hdq_data->hdq_usecount--; + } else { + /* select HDQ mode & enable clocks */ + hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS, + OMAP_HDQ_CTRL_STATUS_CLOCKENABLE | + OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK); + hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, + OMAP_HDQ_SYSCONFIG_AUTOIDLE); + hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS); + } + } + } + +clk_err: + clk_put(hdq_data->hdq_ick); + clk_put(hdq_data->hdq_fck); +out: + mutex_unlock(&hdq_data->hdq_mutex); +rtn: + return ret; +} + +/* Disable clocks to the module */ +static int omap_hdq_put(struct hdq_data *hdq_data) +{ + int ret = 0; + + ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); + if (ret < 0) + return -EINTR; + + if (0 == hdq_data->hdq_usecount) { + dev_dbg(hdq_data->dev, "attempt to decrement use count" + "when it is zero"); + ret = -EINVAL; + } else { + hdq_data->hdq_usecount--; + module_put(THIS_MODULE); + if (0 == hdq_data->hdq_usecount) { + clk_disable(hdq_data->hdq_ick); + clk_disable(hdq_data->hdq_fck); + } + } + mutex_unlock(&hdq_data->hdq_mutex); + + return ret; +} + +/* Read a byte of data from the device */ +static u8 omap_w1_read_byte(void *_hdq) +{ + struct hdq_data *hdq_data = _hdq; + u8 val = 0; + int ret; + + ret = hdq_read_byte(hdq_data, &val); + if (ret) { + ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); + if (ret < 0) { + dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); + return -EINTR; + } + hdq_data->init_trans = 0; + mutex_unlock(&hdq_data->hdq_mutex); + omap_hdq_put(hdq_data); + return -1; + } + + /* Write followed by a read, release the module */ + if (hdq_data->init_trans) { + ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); + if (ret < 0) { + dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); + return -EINTR; + } + hdq_data->init_trans = 0; + mutex_unlock(&hdq_data->hdq_mutex); + omap_hdq_put(hdq_data); + } + + return val; +} + +/* Write a byte of data to the device */ +static void omap_w1_write_byte(void *_hdq, u8 byte) +{ + struct hdq_data *hdq_data = _hdq; + int ret; + u8 status; + + /* First write to initialize the transfer */ + if (hdq_data->init_trans == 0) + omap_hdq_get(hdq_data); + + ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); + if (ret < 0) { + dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); + return; + } + hdq_data->init_trans++; + mutex_unlock(&hdq_data->hdq_mutex); + + ret = hdq_write_byte(hdq_data, byte, &status); + if (ret == 0) { + dev_dbg(hdq_data->dev, "TX failure:Ctrl status %x\n", status); + return; + } + + /* Second write, data transfered. Release the module */ + if (hdq_data->init_trans > 1) { + omap_hdq_put(hdq_data); + ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); + if (ret < 0) { + dev_dbg(hdq_data->dev, "Could not acquire mutex\n"); + return; + } + hdq_data->init_trans = 0; + mutex_unlock(&hdq_data->hdq_mutex); + } + + return; +} + +static int __init omap_hdq_probe(struct platform_device *pdev) +{ + struct hdq_data *hdq_data; + struct resource *res; + int ret, irq; + u8 rev; + + hdq_data = kmalloc(sizeof(*hdq_data), GFP_KERNEL); + if (!hdq_data) { + dev_dbg(&pdev->dev, "unable to allocate memory\n"); + ret = -ENOMEM; + goto err_kmalloc; + } + + hdq_data->dev = &pdev->dev; + platform_set_drvdata(pdev, hdq_data); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_dbg(&pdev->dev, "unable to get resource\n"); + ret = -ENXIO; + goto err_resource; + } + + hdq_data->hdq_base = ioremap(res->start, SZ_4K); + if (!hdq_data->hdq_base) { + dev_dbg(&pdev->dev, "ioremap failed\n"); + ret = -EINVAL; + goto err_ioremap; + } + + /* get interface & functional clock objects */ + hdq_data->hdq_ick = clk_get(&pdev->dev, "hdq_ick"); + hdq_data->hdq_fck = clk_get(&pdev->dev, "hdq_fck"); + + if (IS_ERR(hdq_data->hdq_ick) || IS_ERR(hdq_data->hdq_fck)) { + dev_dbg(&pdev->dev, "Can't get HDQ clock objects\n"); + if (IS_ERR(hdq_data->hdq_ick)) { + ret = PTR_ERR(hdq_data->hdq_ick); + goto err_clk; + } + if (IS_ERR(hdq_data->hdq_fck)) { + ret = PTR_ERR(hdq_data->hdq_fck); + clk_put(hdq_data->hdq_ick); + goto err_clk; + } + } + + hdq_data->hdq_usecount = 0; + mutex_init(&hdq_data->hdq_mutex); + + if (clk_enable(hdq_data->hdq_ick)) { + dev_dbg(&pdev->dev, "Can not enable ick\n"); + ret = -ENODEV; + goto err_intfclk; + } + + if (clk_enable(hdq_data->hdq_fck)) { + dev_dbg(&pdev->dev, "Can not enable fck\n"); + ret = -ENODEV; + goto err_fnclk; + } + + rev = hdq_reg_in(hdq_data, OMAP_HDQ_REVISION); + dev_info(&pdev->dev, "OMAP HDQ Hardware Rev %c.%c. Driver in %s mode\n", + (rev >> 4) + '0', (rev & 0x0f) + '0', "Interrupt"); + + spin_lock_init(&hdq_data->hdq_spinlock); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + ret = -ENXIO; + goto err_irq; + } + + ret = request_irq(irq, hdq_isr, IRQF_DISABLED, "omap_hdq", hdq_data); + if (ret < 0) { + dev_dbg(&pdev->dev, "could not request irq\n"); + goto err_irq; + } + + omap_hdq_break(hdq_data); + + /* don't clock the HDQ until it is needed */ + clk_disable(hdq_data->hdq_ick); + clk_disable(hdq_data->hdq_fck); + + omap_w1_master.data = hdq_data; + + ret = w1_add_master_device(&omap_w1_master); + if (ret) { + dev_dbg(&pdev->dev, "Failure in registering w1 master\n"); + goto err_w1; + } + + return 0; + +err_w1: +err_irq: + clk_disable(hdq_data->hdq_fck); + +err_fnclk: + clk_disable(hdq_data->hdq_ick); + +err_intfclk: + clk_put(hdq_data->hdq_ick); + clk_put(hdq_data->hdq_fck); + +err_clk: + iounmap(hdq_data->hdq_base); + +err_ioremap: +err_resource: + platform_set_drvdata(pdev, NULL); + kfree(hdq_data); + +err_kmalloc: + return ret; + +} + +static int omap_hdq_remove(struct platform_device *pdev) +{ + struct hdq_data *hdq_data = platform_get_drvdata(pdev); + + mutex_lock(&hdq_data->hdq_mutex); + + if (hdq_data->hdq_usecount) { + dev_dbg(&pdev->dev, "removed when use count is not zero\n"); + return -EBUSY; + } + + mutex_unlock(&hdq_data->hdq_mutex); + + /* remove module dependency */ + clk_put(hdq_data->hdq_ick); + clk_put(hdq_data->hdq_fck); + free_irq(INT_24XX_HDQ_IRQ, hdq_data); + platform_set_drvdata(pdev, NULL); + iounmap(hdq_data->hdq_base); + kfree(hdq_data); + + return 0; +} + +static int __init +omap_hdq_init(void) +{ + return platform_driver_register(&omap_hdq_driver); +} +module_init(omap_hdq_init); + +static void __exit +omap_hdq_exit(void) +{ + platform_driver_unregister(&omap_hdq_driver); +} +module_exit(omap_hdq_exit); + +module_param(w1_id, int, S_IRUSR); +MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection"); + +MODULE_AUTHOR("Texas Instruments"); +MODULE_DESCRIPTION("HDQ driver Library"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From cfbc619033d3a2eee8f7aa9314e21b96cf34d399 Mon Sep 17 00:00:00 2001 From: Madhusudhan Chikkature Date: Wed, 12 Nov 2008 13:27:11 -0800 Subject: hdq: bQ27000 HDQ Slave Interface Driver Provide the BQ27000 slave interface driver. Signed-off-by: Madhusudhan Chikkature Acked-by: Evgeniy Polyakov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/w1/slaves/Kconfig | 7 +++ drivers/w1/slaves/Makefile | 2 +- drivers/w1/slaves/w1_bq27000.c | 123 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 drivers/w1/slaves/w1_bq27000.c (limited to 'drivers') diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig index 3df29a122f8..8d0b1fb1e52 100644 --- a/drivers/w1/slaves/Kconfig +++ b/drivers/w1/slaves/Kconfig @@ -44,4 +44,11 @@ config W1_SLAVE_DS2760 If you are unsure, say N. +config W1_SLAVE_BQ27000 + tristate "BQ27000 slave support" + depends on W1 + help + Say Y here if you want to use a hdq + bq27000 slave support. + endmenu diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile index a8eb7524df1..990f400b6d2 100644 --- a/drivers/w1/slaves/Makefile +++ b/drivers/w1/slaves/Makefile @@ -6,4 +6,4 @@ obj-$(CONFIG_W1_SLAVE_THERM) += w1_therm.o obj-$(CONFIG_W1_SLAVE_SMEM) += w1_smem.o obj-$(CONFIG_W1_SLAVE_DS2433) += w1_ds2433.o obj-$(CONFIG_W1_SLAVE_DS2760) += w1_ds2760.o - +obj-$(CONFIG_W1_SLAVE_BQ27000) += w1_bq27000.o diff --git a/drivers/w1/slaves/w1_bq27000.c b/drivers/w1/slaves/w1_bq27000.c new file mode 100644 index 00000000000..8f4c91f6c68 --- /dev/null +++ b/drivers/w1/slaves/w1_bq27000.c @@ -0,0 +1,123 @@ +/* + * drivers/w1/slaves/w1_bq27000.c + * + * Copyright (C) 2007 Texas Instruments, Inc. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "../w1.h" +#include "../w1_int.h" +#include "../w1_family.h" + +#define HDQ_CMD_READ (0) +#define HDQ_CMD_WRITE (1<<7) + +static int F_ID; + +void w1_bq27000_write(struct device *dev, u8 buf, u8 reg) +{ + struct w1_slave *sl = container_of(dev, struct w1_slave, dev); + + if (!dev) { + pr_info("Could not obtain slave dev ptr\n"); + return; + } + + w1_write_8(sl->master, HDQ_CMD_WRITE | reg); + w1_write_8(sl->master, buf); +} +EXPORT_SYMBOL(w1_bq27000_write); + +int w1_bq27000_read(struct device *dev, u8 reg) +{ + u8 val; + struct w1_slave *sl = container_of(dev, struct w1_slave, dev); + + if (!dev) + return 0; + + w1_write_8(sl->master, HDQ_CMD_READ | reg); + val = w1_read_8(sl->master); + + return val; +} +EXPORT_SYMBOL(w1_bq27000_read); + +static int w1_bq27000_add_slave(struct w1_slave *sl) +{ + int ret; + int id = 1; + struct platform_device *pdev; + + pdev = platform_device_alloc("bq27000-battery", id); + if (!pdev) { + ret = -ENOMEM; + return ret; + } + pdev->dev.parent = &sl->dev; + + ret = platform_device_add(pdev); + if (ret) + goto pdev_add_failed; + + dev_set_drvdata(&sl->dev, pdev); + + goto success; + +pdev_add_failed: + platform_device_unregister(pdev); +success: + return ret; +} + +static void w1_bq27000_remove_slave(struct w1_slave *sl) +{ + struct platform_device *pdev = dev_get_drvdata(&sl->dev); + + platform_device_unregister(pdev); +} + +static struct w1_family_ops w1_bq27000_fops = { + .add_slave = w1_bq27000_add_slave, + .remove_slave = w1_bq27000_remove_slave, +}; + +static struct w1_family w1_bq27000_family = { + .fid = 1, + .fops = &w1_bq27000_fops, +}; + +static int __init w1_bq27000_init(void) +{ + if (F_ID) + w1_bq27000_family.fid = F_ID; + + return w1_register_family(&w1_bq27000_family); +} + +static void __exit w1_bq27000_exit(void) +{ + w1_unregister_family(&w1_bq27000_family); +} + + +module_init(w1_bq27000_init); +module_exit(w1_bq27000_exit); + +module_param(F_ID, int, S_IRUSR); +MODULE_PARM_DESC(F_ID, "1-wire slave FID for BQ device"); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Texas Instruments Ltd"); +MODULE_DESCRIPTION("HDQ/1-wire slave driver bq27000 battery monitor chip"); -- cgit v1.2.3 From 4e17e1db96474af5620e3259754df4cb1c46521c Mon Sep 17 00:00:00 2001 From: Rodolfo Giometti Date: Wed, 12 Nov 2008 13:27:12 -0800 Subject: Add c2 port support C2port implements a two wire serial communication protocol (bit banging) designed to enable in-system programming, debugging, and boundary-scan testing on low pin-count Silicon Labs devices. Currently this code supports only flash programming through sysfs interface but extensions shoud be easy to add. Signed-off-by: Rodolfo Giometti Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/Kconfig | 2 + drivers/misc/Makefile | 1 + drivers/misc/c2port/Kconfig | 24 + drivers/misc/c2port/Makefile | 1 + drivers/misc/c2port/core.c | 1002 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1030 insertions(+) create mode 100644 drivers/misc/c2port/Kconfig create mode 100644 drivers/misc/c2port/Makefile create mode 100644 drivers/misc/c2port/core.c (limited to 'drivers') diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index dcac7ca7693..fee7304102a 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -498,4 +498,6 @@ config SGI_GRU_DEBUG This option enables addition debugging code for the SGI GRU driver. If you are unsure, say N. +source "drivers/misc/c2port/Kconfig" + endif # MISC_DEVICES diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index bb14633d136..817f7f5ab3b 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -32,3 +32,4 @@ obj-$(CONFIG_KGDB_TESTS) += kgdbts.o obj-$(CONFIG_SGI_XP) += sgi-xp/ obj-$(CONFIG_SGI_GRU) += sgi-gru/ obj-$(CONFIG_HP_ILO) += hpilo.o +obj-$(CONFIG_C2PORT) += c2port/ diff --git a/drivers/misc/c2port/Kconfig b/drivers/misc/c2port/Kconfig new file mode 100644 index 00000000000..f1bad2b4032 --- /dev/null +++ b/drivers/misc/c2port/Kconfig @@ -0,0 +1,24 @@ +# +# C2 port devices +# + +menuconfig C2PORT + tristate "Silicon Labs C2 port support (EXPERIMENTAL)" + depends on EXPERIMENTAL + default no + help + This option enables support for Silicon Labs C2 port used to + program Silicon micro controller chips (and other 8051 compatible). + + If your board have no such micro controllers you don't need this + interface at all. + + To compile this driver as a module, choose M here: the module will + be called c2port_core. Note that you also need a client module + usually called c2port-*. + + If you are not sure, say N here. + +if C2PORT + +endif # C2PORT diff --git a/drivers/misc/c2port/Makefile b/drivers/misc/c2port/Makefile new file mode 100644 index 00000000000..3c610a2ba5e --- /dev/null +++ b/drivers/misc/c2port/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_C2PORT) += core.o diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c new file mode 100644 index 00000000000..976b35d1d03 --- /dev/null +++ b/drivers/misc/c2port/core.c @@ -0,0 +1,1002 @@ +/* + * Silicon Labs C2 port core Linux support + * + * Copyright (c) 2007 Rodolfo Giometti + * Copyright (c) 2007 Eurotech S.p.A. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRIVER_NAME "c2port" +#define DRIVER_VERSION "0.51.0" + +static DEFINE_SPINLOCK(c2port_idr_lock); +static DEFINE_IDR(c2port_idr); + +/* + * Local variables + */ + +static struct class *c2port_class; + +/* + * C2 registers & commands defines + */ + +/* C2 registers */ +#define C2PORT_DEVICEID 0x00 +#define C2PORT_REVID 0x01 +#define C2PORT_FPCTL 0x02 +#define C2PORT_FPDAT 0xB4 + +/* C2 interface commands */ +#define C2PORT_GET_VERSION 0x01 +#define C2PORT_DEVICE_ERASE 0x03 +#define C2PORT_BLOCK_READ 0x06 +#define C2PORT_BLOCK_WRITE 0x07 +#define C2PORT_PAGE_ERASE 0x08 + +/* C2 status return codes */ +#define C2PORT_INVALID_COMMAND 0x00 +#define C2PORT_COMMAND_FAILED 0x02 +#define C2PORT_COMMAND_OK 0x0d + +/* + * C2 port low level signal managements + */ + +static void c2port_reset(struct c2port_device *dev) +{ + struct c2port_ops *ops = dev->ops; + + /* To reset the device we have to keep clock line low for at least + * 20us. + */ + local_irq_disable(); + ops->c2ck_set(dev, 0); + udelay(25); + ops->c2ck_set(dev, 1); + local_irq_enable(); + + udelay(1); +} + +static void c2port_strobe_ck(struct c2port_device *dev) +{ + struct c2port_ops *ops = dev->ops; + + /* During hi-low-hi transition we disable local IRQs to avoid + * interructions since C2 port specification says that it must be + * shorter than 5us, otherwise the microcontroller may consider + * it as a reset signal! + */ + local_irq_disable(); + ops->c2ck_set(dev, 0); + udelay(1); + ops->c2ck_set(dev, 1); + local_irq_enable(); + + udelay(1); +} + +/* + * C2 port basic functions + */ + +static void c2port_write_ar(struct c2port_device *dev, u8 addr) +{ + struct c2port_ops *ops = dev->ops; + int i; + + /* START field */ + c2port_strobe_ck(dev); + + /* INS field (11b, LSB first) */ + ops->c2d_dir(dev, 0); + ops->c2d_set(dev, 1); + c2port_strobe_ck(dev); + ops->c2d_set(dev, 1); + c2port_strobe_ck(dev); + + /* ADDRESS field */ + for (i = 0; i < 8; i++) { + ops->c2d_set(dev, addr & 0x01); + c2port_strobe_ck(dev); + + addr >>= 1; + } + + /* STOP field */ + ops->c2d_dir(dev, 1); + c2port_strobe_ck(dev); +} + +static int c2port_read_ar(struct c2port_device *dev, u8 *addr) +{ + struct c2port_ops *ops = dev->ops; + int i; + + /* START field */ + c2port_strobe_ck(dev); + + /* INS field (10b, LSB first) */ + ops->c2d_dir(dev, 0); + ops->c2d_set(dev, 0); + c2port_strobe_ck(dev); + ops->c2d_set(dev, 1); + c2port_strobe_ck(dev); + + /* ADDRESS field */ + ops->c2d_dir(dev, 1); + *addr = 0; + for (i = 0; i < 8; i++) { + *addr >>= 1; /* shift in 8-bit ADDRESS field LSB first */ + + c2port_strobe_ck(dev); + if (ops->c2d_get(dev)) + *addr |= 0x80; + } + + /* STOP field */ + c2port_strobe_ck(dev); + + return 0; +} + +static int c2port_write_dr(struct c2port_device *dev, u8 data) +{ + struct c2port_ops *ops = dev->ops; + int timeout, i; + + /* START field */ + c2port_strobe_ck(dev); + + /* INS field (01b, LSB first) */ + ops->c2d_dir(dev, 0); + ops->c2d_set(dev, 1); + c2port_strobe_ck(dev); + ops->c2d_set(dev, 0); + c2port_strobe_ck(dev); + + /* LENGTH field (00b, LSB first -> 1 byte) */ + ops->c2d_set(dev, 0); + c2port_strobe_ck(dev); + ops->c2d_set(dev, 0); + c2port_strobe_ck(dev); + + /* DATA field */ + for (i = 0; i < 8; i++) { + ops->c2d_set(dev, data & 0x01); + c2port_strobe_ck(dev); + + data >>= 1; + } + + /* WAIT field */ + ops->c2d_dir(dev, 1); + timeout = 20; + do { + c2port_strobe_ck(dev); + if (ops->c2d_get(dev)) + break; + + udelay(1); + } while (--timeout > 0); + if (timeout == 0) + return -EIO; + + /* STOP field */ + c2port_strobe_ck(dev); + + return 0; +} + +static int c2port_read_dr(struct c2port_device *dev, u8 *data) +{ + struct c2port_ops *ops = dev->ops; + int timeout, i; + + /* START field */ + c2port_strobe_ck(dev); + + /* INS field (00b, LSB first) */ + ops->c2d_dir(dev, 0); + ops->c2d_set(dev, 0); + c2port_strobe_ck(dev); + ops->c2d_set(dev, 0); + c2port_strobe_ck(dev); + + /* LENGTH field (00b, LSB first -> 1 byte) */ + ops->c2d_set(dev, 0); + c2port_strobe_ck(dev); + ops->c2d_set(dev, 0); + c2port_strobe_ck(dev); + + /* WAIT field */ + ops->c2d_dir(dev, 1); + timeout = 20; + do { + c2port_strobe_ck(dev); + if (ops->c2d_get(dev)) + break; + + udelay(1); + } while (--timeout > 0); + if (timeout == 0) + return -EIO; + + /* DATA field */ + *data = 0; + for (i = 0; i < 8; i++) { + *data >>= 1; /* shift in 8-bit DATA field LSB first */ + + c2port_strobe_ck(dev); + if (ops->c2d_get(dev)) + *data |= 0x80; + } + + /* STOP field */ + c2port_strobe_ck(dev); + + return 0; +} + +static int c2port_poll_in_busy(struct c2port_device *dev) +{ + u8 addr; + int ret, timeout = 20; + + do { + ret = (c2port_read_ar(dev, &addr)); + if (ret < 0) + return -EIO; + + if (!(addr & 0x02)) + break; + + udelay(1); + } while (--timeout > 0); + if (timeout == 0) + return -EIO; + + return 0; +} + +static int c2port_poll_out_ready(struct c2port_device *dev) +{ + u8 addr; + int ret, timeout = 10000; /* erase flash needs long time... */ + + do { + ret = (c2port_read_ar(dev, &addr)); + if (ret < 0) + return -EIO; + + if (addr & 0x01) + break; + + udelay(1); + } while (--timeout > 0); + if (timeout == 0) + return -EIO; + + return 0; +} + +/* + * sysfs methods + */ + +static ssize_t c2port_show_name(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct c2port_device *c2dev = dev_get_drvdata(dev); + + return sprintf(buf, "%s\n", c2dev->name); +} + +static ssize_t c2port_show_flash_blocks_num(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct c2port_device *c2dev = dev_get_drvdata(dev); + struct c2port_ops *ops = c2dev->ops; + + return sprintf(buf, "%d\n", ops->blocks_num); +} + +static ssize_t c2port_show_flash_block_size(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct c2port_device *c2dev = dev_get_drvdata(dev); + struct c2port_ops *ops = c2dev->ops; + + return sprintf(buf, "%d\n", ops->block_size); +} + +static ssize_t c2port_show_flash_size(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct c2port_device *c2dev = dev_get_drvdata(dev); + struct c2port_ops *ops = c2dev->ops; + + return sprintf(buf, "%d\n", ops->blocks_num * ops->block_size); +} + +static ssize_t c2port_show_access(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct c2port_device *c2dev = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", c2dev->access); +} + +static ssize_t c2port_store_access(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct c2port_device *c2dev = dev_get_drvdata(dev); + struct c2port_ops *ops = c2dev->ops; + int status, ret; + + ret = sscanf(buf, "%d", &status); + if (ret != 1) + return -EINVAL; + + mutex_lock(&c2dev->mutex); + + c2dev->access = !!status; + + /* If access is "on" clock should be HIGH _before_ setting the line + * as output and data line should be set as INPUT anyway */ + if (c2dev->access) + ops->c2ck_set(c2dev, 1); + ops->access(c2dev, c2dev->access); + if (c2dev->access) + ops->c2d_dir(c2dev, 1); + + mutex_unlock(&c2dev->mutex); + + return count; +} + +static ssize_t c2port_store_reset(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct c2port_device *c2dev = dev_get_drvdata(dev); + + /* Check the device access status */ + if (!c2dev->access) + return -EBUSY; + + mutex_lock(&c2dev->mutex); + + c2port_reset(c2dev); + c2dev->flash_access = 0; + + mutex_unlock(&c2dev->mutex); + + return count; +} + +static ssize_t __c2port_show_dev_id(struct c2port_device *dev, char *buf) +{ + u8 data; + int ret; + + /* Select DEVICEID register for C2 data register accesses */ + c2port_write_ar(dev, C2PORT_DEVICEID); + + /* Read and return the device ID register */ + ret = c2port_read_dr(dev, &data); + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t c2port_show_dev_id(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct c2port_device *c2dev = dev_get_drvdata(dev); + ssize_t ret; + + /* Check the device access status */ + if (!c2dev->access) + return -EBUSY; + + mutex_lock(&c2dev->mutex); + ret = __c2port_show_dev_id(c2dev, buf); + mutex_unlock(&c2dev->mutex); + + if (ret < 0) + dev_err(dev, "cannot read from %s\n", c2dev->name); + + return ret; +} + +static ssize_t __c2port_show_rev_id(struct c2port_device *dev, char *buf) +{ + u8 data; + int ret; + + /* Select REVID register for C2 data register accesses */ + c2port_write_ar(dev, C2PORT_REVID); + + /* Read and return the revision ID register */ + ret = c2port_read_dr(dev, &data); + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", data); +} + +static ssize_t c2port_show_rev_id(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct c2port_device *c2dev = dev_get_drvdata(dev); + ssize_t ret; + + /* Check the device access status */ + if (!c2dev->access) + return -EBUSY; + + mutex_lock(&c2dev->mutex); + ret = __c2port_show_rev_id(c2dev, buf); + mutex_unlock(&c2dev->mutex); + + if (ret < 0) + dev_err(c2dev->dev, "cannot read from %s\n", c2dev->name); + + return ret; +} + +static ssize_t c2port_show_flash_access(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct c2port_device *c2dev = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", c2dev->flash_access); +} + +static ssize_t __c2port_store_flash_access(struct c2port_device *dev, + int status) +{ + int ret; + + /* Check the device access status */ + if (!dev->access) + return -EBUSY; + + dev->flash_access = !!status; + + /* If flash_access is off we have nothing to do... */ + if (dev->flash_access == 0) + return 0; + + /* Target the C2 flash programming control register for C2 data + * register access */ + c2port_write_ar(dev, C2PORT_FPCTL); + + /* Write the first keycode to enable C2 Flash programming */ + ret = c2port_write_dr(dev, 0x02); + if (ret < 0) + return ret; + + /* Write the second keycode to enable C2 Flash programming */ + ret = c2port_write_dr(dev, 0x01); + if (ret < 0) + return ret; + + /* Delay for at least 20ms to ensure the target is ready for + * C2 flash programming */ + mdelay(25); + + return 0; +} + +static ssize_t c2port_store_flash_access(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct c2port_device *c2dev = dev_get_drvdata(dev); + int status; + ssize_t ret; + + ret = sscanf(buf, "%d", &status); + if (ret != 1) + return -EINVAL; + + mutex_lock(&c2dev->mutex); + ret = __c2port_store_flash_access(c2dev, status); + mutex_unlock(&c2dev->mutex); + + if (ret < 0) { + dev_err(c2dev->dev, "cannot enable %s flash programming\n", + c2dev->name); + return ret; + } + + return count; +} + +static ssize_t __c2port_write_flash_erase(struct c2port_device *dev) +{ + u8 status; + int ret; + + /* Target the C2 flash programming data register for C2 data register + * access. + */ + c2port_write_ar(dev, C2PORT_FPDAT); + + /* Send device erase command */ + c2port_write_dr(dev, C2PORT_DEVICE_ERASE); + + /* Wait for input acknowledge */ + ret = c2port_poll_in_busy(dev); + if (ret < 0) + return ret; + + /* Should check status before starting FLASH access sequence */ + + /* Wait for status information */ + ret = c2port_poll_out_ready(dev); + if (ret < 0) + return ret; + + /* Read flash programming interface status */ + ret = c2port_read_dr(dev, &status); + if (ret < 0) + return ret; + if (status != C2PORT_COMMAND_OK) + return -EBUSY; + + /* Send a three-byte arming sequence to enable the device erase. + * If the sequence is not received correctly, the command will be + * ignored. + * Sequence is: 0xde, 0xad, 0xa5. + */ + c2port_write_dr(dev, 0xde); + ret = c2port_poll_in_busy(dev); + if (ret < 0) + return ret; + c2port_write_dr(dev, 0xad); + ret = c2port_poll_in_busy(dev); + if (ret < 0) + return ret; + c2port_write_dr(dev, 0xa5); + ret = c2port_poll_in_busy(dev); + if (ret < 0) + return ret; + + ret = c2port_poll_out_ready(dev); + if (ret < 0) + return ret; + + return 0; +} + +static ssize_t c2port_store_flash_erase(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct c2port_device *c2dev = dev_get_drvdata(dev); + int ret; + + /* Check the device and flash access status */ + if (!c2dev->access || !c2dev->flash_access) + return -EBUSY; + + mutex_lock(&c2dev->mutex); + ret = __c2port_write_flash_erase(c2dev); + mutex_unlock(&c2dev->mutex); + + if (ret < 0) { + dev_err(c2dev->dev, "cannot erase %s flash\n", c2dev->name); + return ret; + } + + return count; +} + +static ssize_t __c2port_read_flash_data(struct c2port_device *dev, + char *buffer, loff_t offset, size_t count) +{ + struct c2port_ops *ops = dev->ops; + u8 status, nread = 128; + int i, ret; + + /* Check for flash end */ + if (offset >= ops->block_size * ops->blocks_num) + return 0; + + if (ops->block_size * ops->blocks_num - offset < nread) + nread = ops->block_size * ops->blocks_num - offset; + if (count < nread) + nread = count; + if (nread == 0) + return nread; + + /* Target the C2 flash programming data register for C2 data register + * access */ + c2port_write_ar(dev, C2PORT_FPDAT); + + /* Send flash block read command */ + c2port_write_dr(dev, C2PORT_BLOCK_READ); + + /* Wait for input acknowledge */ + ret = c2port_poll_in_busy(dev); + if (ret < 0) + return ret; + + /* Should check status before starting FLASH access sequence */ + + /* Wait for status information */ + ret = c2port_poll_out_ready(dev); + if (ret < 0) + return ret; + + /* Read flash programming interface status */ + ret = c2port_read_dr(dev, &status); + if (ret < 0) + return ret; + if (status != C2PORT_COMMAND_OK) + return -EBUSY; + + /* Send address high byte */ + c2port_write_dr(dev, offset >> 8); + ret = c2port_poll_in_busy(dev); + if (ret < 0) + return ret; + + /* Send address low byte */ + c2port_write_dr(dev, offset & 0x00ff); + ret = c2port_poll_in_busy(dev); + if (ret < 0) + return ret; + + /* Send address block size */ + c2port_write_dr(dev, nread); + ret = c2port_poll_in_busy(dev); + if (ret < 0) + return ret; + + /* Should check status before reading FLASH block */ + + /* Wait for status information */ + ret = c2port_poll_out_ready(dev); + if (ret < 0) + return ret; + + /* Read flash programming interface status */ + ret = c2port_read_dr(dev, &status); + if (ret < 0) + return ret; + if (status != C2PORT_COMMAND_OK) + return -EBUSY; + + /* Read flash block */ + for (i = 0; i < nread; i++) { + ret = c2port_poll_out_ready(dev); + if (ret < 0) + return ret; + + ret = c2port_read_dr(dev, buffer+i); + if (ret < 0) + return ret; + } + + return nread; +} + +static ssize_t c2port_read_flash_data(struct kobject *kobj, + struct bin_attribute *attr, + char *buffer, loff_t offset, size_t count) +{ + struct c2port_device *c2dev = + dev_get_drvdata(container_of(kobj, + struct device, kobj)); + ssize_t ret; + + /* Check the device and flash access status */ + if (!c2dev->access || !c2dev->flash_access) + return -EBUSY; + + mutex_lock(&c2dev->mutex); + ret = __c2port_read_flash_data(c2dev, buffer, offset, count); + mutex_unlock(&c2dev->mutex); + + if (ret < 0) + dev_err(c2dev->dev, "cannot read %s flash\n", c2dev->name); + + return ret; +} + +static ssize_t __c2port_write_flash_data(struct c2port_device *dev, + char *buffer, loff_t offset, size_t count) +{ + struct c2port_ops *ops = dev->ops; + u8 status, nwrite = 128; + int i, ret; + + if (nwrite > count) + nwrite = count; + if (ops->block_size * ops->blocks_num - offset < nwrite) + nwrite = ops->block_size * ops->blocks_num - offset; + + /* Check for flash end */ + if (offset >= ops->block_size * ops->blocks_num) + return -EINVAL; + + /* Target the C2 flash programming data register for C2 data register + * access */ + c2port_write_ar(dev, C2PORT_FPDAT); + + /* Send flash block write command */ + c2port_write_dr(dev, C2PORT_BLOCK_WRITE); + + /* Wait for input acknowledge */ + ret = c2port_poll_in_busy(dev); + if (ret < 0) + return ret; + + /* Should check status before starting FLASH access sequence */ + + /* Wait for status information */ + ret = c2port_poll_out_ready(dev); + if (ret < 0) + return ret; + + /* Read flash programming interface status */ + ret = c2port_read_dr(dev, &status); + if (ret < 0) + return ret; + if (status != C2PORT_COMMAND_OK) + return -EBUSY; + + /* Send address high byte */ + c2port_write_dr(dev, offset >> 8); + ret = c2port_poll_in_busy(dev); + if (ret < 0) + return ret; + + /* Send address low byte */ + c2port_write_dr(dev, offset & 0x00ff); + ret = c2port_poll_in_busy(dev); + if (ret < 0) + return ret; + + /* Send address block size */ + c2port_write_dr(dev, nwrite); + ret = c2port_poll_in_busy(dev); + if (ret < 0) + return ret; + + /* Should check status before writing FLASH block */ + + /* Wait for status information */ + ret = c2port_poll_out_ready(dev); + if (ret < 0) + return ret; + + /* Read flash programming interface status */ + ret = c2port_read_dr(dev, &status); + if (ret < 0) + return ret; + if (status != C2PORT_COMMAND_OK) + return -EBUSY; + + /* Write flash block */ + for (i = 0; i < nwrite; i++) { + ret = c2port_write_dr(dev, *(buffer+i)); + if (ret < 0) + return ret; + + ret = c2port_poll_in_busy(dev); + if (ret < 0) + return ret; + + } + + /* Wait for last flash write to complete */ + ret = c2port_poll_out_ready(dev); + if (ret < 0) + return ret; + + return nwrite; +} + +static ssize_t c2port_write_flash_data(struct kobject *kobj, + struct bin_attribute *attr, + char *buffer, loff_t offset, size_t count) +{ + struct c2port_device *c2dev = + dev_get_drvdata(container_of(kobj, + struct device, kobj)); + int ret; + + /* Check the device access status */ + if (!c2dev->access || !c2dev->flash_access) + return -EBUSY; + + mutex_lock(&c2dev->mutex); + ret = __c2port_write_flash_data(c2dev, buffer, offset, count); + mutex_unlock(&c2dev->mutex); + + if (ret < 0) + dev_err(c2dev->dev, "cannot write %s flash\n", c2dev->name); + + return ret; +} + +/* + * Class attributes + */ + +static struct device_attribute c2port_attrs[] = { + __ATTR(name, 0444, c2port_show_name, NULL), + __ATTR(flash_blocks_num, 0444, c2port_show_flash_blocks_num, NULL), + __ATTR(flash_block_size, 0444, c2port_show_flash_block_size, NULL), + __ATTR(flash_size, 0444, c2port_show_flash_size, NULL), + __ATTR(access, 0644, c2port_show_access, c2port_store_access), + __ATTR(reset, 0200, NULL, c2port_store_reset), + __ATTR(dev_id, 0444, c2port_show_dev_id, NULL), + __ATTR(rev_id, 0444, c2port_show_rev_id, NULL), + + __ATTR(flash_access, 0644, c2port_show_flash_access, + c2port_store_flash_access), + __ATTR(flash_erase, 0200, NULL, c2port_store_flash_erase), + __ATTR_NULL, +}; + +static struct bin_attribute c2port_bin_attrs = { + .attr = { + .name = "flash_data", + .mode = 0644 + }, + .read = c2port_read_flash_data, + .write = c2port_write_flash_data, + /* .size is computed at run-time */ +}; + +/* + * Exported functions + */ + +struct c2port_device *c2port_device_register(char *name, + struct c2port_ops *ops, void *devdata) +{ + struct c2port_device *c2dev; + int id, ret; + + if (unlikely(!ops) || unlikely(!ops->access) || \ + unlikely(!ops->c2d_dir) || unlikely(!ops->c2ck_set) || \ + unlikely(!ops->c2d_get) || unlikely(!ops->c2d_set)) + return ERR_PTR(-EINVAL); + + c2dev = kmalloc(sizeof(struct c2port_device), GFP_KERNEL); + if (unlikely(!c2dev)) + return ERR_PTR(-ENOMEM); + + ret = idr_pre_get(&c2port_idr, GFP_KERNEL); + if (!ret) { + ret = -ENOMEM; + goto error_idr_get_new; + } + + spin_lock_irq(&c2port_idr_lock); + ret = idr_get_new(&c2port_idr, c2dev, &id); + spin_unlock_irq(&c2port_idr_lock); + + if (ret < 0) + goto error_idr_get_new; + c2dev->id = id; + + c2dev->dev = device_create(c2port_class, NULL, 0, c2dev, + "c2port%d", id); + if (unlikely(!c2dev->dev)) { + ret = -ENOMEM; + goto error_device_create; + } + dev_set_drvdata(c2dev->dev, c2dev); + + strncpy(c2dev->name, name, C2PORT_NAME_LEN); + c2dev->ops = ops; + mutex_init(&c2dev->mutex); + + /* Create binary file */ + c2port_bin_attrs.size = ops->blocks_num * ops->block_size; + ret = device_create_bin_file(c2dev->dev, &c2port_bin_attrs); + if (unlikely(ret)) + goto error_device_create_bin_file; + + /* By default C2 port access is off */ + c2dev->access = c2dev->flash_access = 0; + ops->access(c2dev, 0); + + dev_info(c2dev->dev, "C2 port %s added\n", name); + dev_info(c2dev->dev, "%s flash has %d blocks x %d bytes " + "(%d bytes total)\n", + name, ops->blocks_num, ops->block_size, + ops->blocks_num * ops->block_size); + + return c2dev; + +error_device_create_bin_file: + device_destroy(c2port_class, 0); + +error_device_create: + spin_lock_irq(&c2port_idr_lock); + idr_remove(&c2port_idr, id); + spin_unlock_irq(&c2port_idr_lock); + +error_idr_get_new: + kfree(c2dev); + + return ERR_PTR(ret); +} +EXPORT_SYMBOL(c2port_device_register); + +void c2port_device_unregister(struct c2port_device *c2dev) +{ + if (!c2dev) + return; + + dev_info(c2dev->dev, "C2 port %s removed\n", c2dev->name); + + device_remove_bin_file(c2dev->dev, &c2port_bin_attrs); + spin_lock_irq(&c2port_idr_lock); + idr_remove(&c2port_idr, c2dev->id); + spin_unlock_irq(&c2port_idr_lock); + + device_destroy(c2port_class, c2dev->id); + + kfree(c2dev); +} +EXPORT_SYMBOL(c2port_device_unregister); + +/* + * Module stuff + */ + +static int __init c2port_init(void) +{ + printk(KERN_INFO "Silicon Labs C2 port support v. " DRIVER_VERSION + " - (C) 2007 Rodolfo Giometti\n"); + + c2port_class = class_create(THIS_MODULE, "c2port"); + if (!c2port_class) { + printk(KERN_ERR "c2port: failed to allocate class\n"); + return -ENOMEM; + } + c2port_class->dev_attrs = c2port_attrs; + + return 0; +} + +static void __exit c2port_exit(void) +{ + class_destroy(c2port_class); +} + +module_init(c2port_init); +module_exit(c2port_exit); + +MODULE_AUTHOR("Rodolfo Giometti "); +MODULE_DESCRIPTION("Silicon Labs C2 port support v. " DRIVER_VERSION); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 65131cd52b9e7c5814298e05c3b7843f13e78d24 Mon Sep 17 00:00:00 2001 From: Rodolfo Giometti Date: Wed, 12 Nov 2008 13:27:14 -0800 Subject: c2port: add c2port support for Eurotech Duramar 2150 Signed-off-by: Rodolfo Giometti Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/c2port/Kconfig | 11 +++ drivers/misc/c2port/Makefile | 2 + drivers/misc/c2port/c2port-duramar2150.c | 158 +++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 drivers/misc/c2port/c2port-duramar2150.c (limited to 'drivers') diff --git a/drivers/misc/c2port/Kconfig b/drivers/misc/c2port/Kconfig index f1bad2b4032..e46af9a5810 100644 --- a/drivers/misc/c2port/Kconfig +++ b/drivers/misc/c2port/Kconfig @@ -21,4 +21,15 @@ menuconfig C2PORT if C2PORT +config C2PORT_DURAMAR_2150 + tristate "C2 port support for Eurotech's Duramar 2150 (EXPERIMENTAL)" + depends on X86 && C2PORT + default no + help + This option enables C2 support for the Eurotech's Duramar 2150 + on board micro controller. + + To compile this driver as a module, choose M here: the module will + be called c2port-duramar2150. + endif # C2PORT diff --git a/drivers/misc/c2port/Makefile b/drivers/misc/c2port/Makefile index 3c610a2ba5e..3b2cf43d60f 100644 --- a/drivers/misc/c2port/Makefile +++ b/drivers/misc/c2port/Makefile @@ -1 +1,3 @@ obj-$(CONFIG_C2PORT) += core.o + +obj-$(CONFIG_C2PORT_DURAMAR_2150) += c2port-duramar2150.o diff --git a/drivers/misc/c2port/c2port-duramar2150.c b/drivers/misc/c2port/c2port-duramar2150.c new file mode 100644 index 00000000000..338dcc12150 --- /dev/null +++ b/drivers/misc/c2port/c2port-duramar2150.c @@ -0,0 +1,158 @@ +/* + * Silicon Labs C2 port Linux support for Eurotech Duramar 2150 + * + * Copyright (c) 2008 Rodolfo Giometti + * Copyright (c) 2008 Eurotech S.p.A. + * + * 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 +#include +#include +#include +#include +#include +#include + +#define DATA_PORT 0x325 +#define DIR_PORT 0x326 +#define C2D (1 << 0) +#define C2CK (1 << 1) + +static DEFINE_MUTEX(update_lock); + +/* + * C2 port operations + */ + +static void duramar2150_c2port_access(struct c2port_device *dev, int status) +{ + u8 v; + + mutex_lock(&update_lock); + + v = inb(DIR_PORT); + + /* 0 = input, 1 = output */ + if (status) + outb(v | (C2D | C2CK), DIR_PORT); + else + /* When access is "off" is important that both lines are set + * as inputs or hi-impedence */ + outb(v & ~(C2D | C2CK), DIR_PORT); + + mutex_unlock(&update_lock); +} + +static void duramar2150_c2port_c2d_dir(struct c2port_device *dev, int dir) +{ + u8 v; + + mutex_lock(&update_lock); + + v = inb(DIR_PORT); + + if (dir) + outb(v & ~C2D, DIR_PORT); + else + outb(v | C2D, DIR_PORT); + + mutex_unlock(&update_lock); +} + +static int duramar2150_c2port_c2d_get(struct c2port_device *dev) +{ + return inb(DATA_PORT) & C2D; +} + +static void duramar2150_c2port_c2d_set(struct c2port_device *dev, int status) +{ + u8 v; + + mutex_lock(&update_lock); + + v = inb(DATA_PORT); + + if (status) + outb(v | C2D, DATA_PORT); + else + outb(v & ~C2D, DATA_PORT); + + mutex_unlock(&update_lock); +} + +static void duramar2150_c2port_c2ck_set(struct c2port_device *dev, int status) +{ + u8 v; + + mutex_lock(&update_lock); + + v = inb(DATA_PORT); + + if (status) + outb(v | C2CK, DATA_PORT); + else + outb(v & ~C2CK, DATA_PORT); + + mutex_unlock(&update_lock); +} + +static struct c2port_ops duramar2150_c2port_ops = { + .block_size = 512, /* bytes */ + .blocks_num = 30, /* total flash size: 15360 bytes */ + + .access = duramar2150_c2port_access, + .c2d_dir = duramar2150_c2port_c2d_dir, + .c2d_get = duramar2150_c2port_c2d_get, + .c2d_set = duramar2150_c2port_c2d_set, + .c2ck_set = duramar2150_c2port_c2ck_set, +}; + +static struct c2port_device *duramar2150_c2port_dev; + +/* + * Module stuff + */ + +static int __init duramar2150_c2port_init(void) +{ + struct resource *res; + int ret = 0; + + res = request_region(0x325, 2, "c2port"); + if (!res) + return -EBUSY; + + duramar2150_c2port_dev = c2port_device_register("uc", + &duramar2150_c2port_ops, NULL); + if (!duramar2150_c2port_dev) { + ret = -ENODEV; + goto free_region; + } + + return 0; + +free_region: + release_region(0x325, 2); + return ret; +} + +static void __exit duramar2150_c2port_exit(void) +{ + /* Setup the GPIOs as input by default (access = 0) */ + duramar2150_c2port_access(duramar2150_c2port_dev, 0); + + c2port_device_unregister(duramar2150_c2port_dev); + + release_region(0x325, 2); +} + +module_init(duramar2150_c2port_init); +module_exit(duramar2150_c2port_exit); + +MODULE_AUTHOR("Rodolfo Giometti "); +MODULE_DESCRIPTION("Silicon Labs C2 port Linux support for Duramar 2150"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From bff4056c8b868a4311d5ebd6cbbf09a2c10f4551 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 13 Nov 2008 15:28:21 +0900 Subject: i2c: fix i2c-sh_mobile rx underrun Fix receive path underrun in i2c-sh_mobile driver. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/i2c/busses/i2c-sh_mobile.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 640cbb23732..3384a717fec 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -318,7 +318,8 @@ static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd) } else data = i2c_op(pd, OP_RX, 0); - pd->msg->buf[real_pos] = data; + if (real_pos >= 0) + pd->msg->buf[real_pos] = data; } while (0); pd->pos++; -- cgit v1.2.3 From 272966c070237c8cb540fe67e06df51bc6ea9cc2 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 13 Nov 2008 17:46:06 +0900 Subject: serial: sh-sci: Reorder the SCxTDR write after the TDxE clear. Under qemu there is a race between the TDxE read-and-clear and the SCxTDR write. While on hardware it can be gauranteed that the read-and-clear will happen prior to the character being written out, no such assumption can be made under emulation. As this path happens with IRQs off and the hardware itself doesn't care about the ordering, move the SCxTDR write until after the read-and-clear. Signed-off-by: Vladimir Prus Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 518c0321e4d..165fc010978 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -144,9 +144,9 @@ static void put_char(struct uart_port *port, char c) status = sci_in(port, SCxSR); } while (!(status & SCxSR_TDxE(port))); - sci_out(port, SCxTDR, c); sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); + sci_out(port, SCxTDR, c); spin_unlock_irqrestore(&port->lock, flags); } -- cgit v1.2.3 From 7d672cd7506165818aacf97fdc448cffc72bde37 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 31 Oct 2008 00:07:23 +0100 Subject: HID: fix locking in hidraw_open() As open needs to sleep hidraw was wrong to call it with a spinlock held. Furthermore, open can of course fail which needs to be handled. Signed-off-by: Oliver Neukum Signed-off-by: Jiri Kosina --- drivers/hid/hidraw.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 894d52e05bf..7685ae6808c 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -38,7 +38,7 @@ static int hidraw_major; static struct cdev hidraw_cdev; static struct class *hidraw_class; static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; -static DEFINE_SPINLOCK(minors_lock); +static DEFINE_MUTEX(minors_lock); static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { @@ -159,13 +159,13 @@ static int hidraw_open(struct inode *inode, struct file *file) struct hidraw_list *list; int err = 0; - lock_kernel(); if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) { err = -ENOMEM; goto out; } - spin_lock(&minors_lock); + lock_kernel(); + mutex_lock(&minors_lock); if (!hidraw_table[minor]) { printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n", minor); @@ -180,13 +180,16 @@ static int hidraw_open(struct inode *inode, struct file *file) file->private_data = list; dev = hidraw_table[minor]; - if (!dev->open++) - dev->hid->ll_driver->open(dev->hid); + if (!dev->open++) { + err = dev->hid->ll_driver->open(dev->hid); + if (err < 0) + dev->open--; + } out_unlock: - spin_unlock(&minors_lock); -out: + mutex_unlock(&minors_lock); unlock_kernel(); +out: return err; } @@ -310,7 +313,7 @@ int hidraw_connect(struct hid_device *hid) result = -EINVAL; - spin_lock(&minors_lock); + mutex_lock(&minors_lock); for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) { if (hidraw_table[minor]) @@ -320,9 +323,8 @@ int hidraw_connect(struct hid_device *hid) break; } - spin_unlock(&minors_lock); - if (result) { + mutex_unlock(&minors_lock); kfree(dev); goto out; } @@ -331,14 +333,14 @@ int hidraw_connect(struct hid_device *hid) NULL, "%s%d", "hidraw", minor); if (IS_ERR(dev->dev)) { - spin_lock(&minors_lock); hidraw_table[minor] = NULL; - spin_unlock(&minors_lock); + mutex_unlock(&minors_lock); result = PTR_ERR(dev->dev); kfree(dev); goto out; } + mutex_unlock(&minors_lock); init_waitqueue_head(&dev->wait); INIT_LIST_HEAD(&dev->list); @@ -360,9 +362,9 @@ void hidraw_disconnect(struct hid_device *hid) hidraw->exist = 0; - spin_lock(&minors_lock); + mutex_lock(&minors_lock); hidraw_table[hidraw->minor] = NULL; - spin_unlock(&minors_lock); + mutex_unlock(&minors_lock); device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); -- cgit v1.2.3 From a96d6ef34751093797c3a6c6080733dd7af23d35 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Tue, 4 Nov 2008 20:03:45 +0100 Subject: HID: support for new unibody macbooks The unibody MacBook 5 and MacBook Pro 5 come with a new version of the bcm5974 trackpad. This patch adds the USB device ids and all the appropriate quirks, including hid_blacklist. Signed-off-by: Henrik Rydberg Signed-off-by: Jiri Kosina --- drivers/hid/hid-apple.c | 6 ++++++ drivers/hid/hid-core.c | 6 ++++++ drivers/hid/hid-ids.h | 3 +++ 3 files changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index c6ab4ba60c5..ce3c39938f9 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -418,6 +418,12 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index d3671b4049c..4f0b92edb4d 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1250,6 +1250,9 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, @@ -1573,6 +1576,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index f05bcbbbb0d..d70075dd3d8 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -82,6 +82,9 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 +#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 +#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 +#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 -- cgit v1.2.3 From 437184ae8bd1ef923a40b009e37801deae66ad55 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Tue, 4 Nov 2008 13:31:38 +0100 Subject: HID: map macbook keys for "Expose" and "Dashboard" On macbooks there are specific keys for the user-space functions Expose and Dashboard, which currently has no counterpart in input.h. This patch adds KEY_SCALE and KEY_DASHBOARD, and maps the keyboard accordingly. Acked-by: Dmitry Torokhov Signed-off-by: Henrik Rydberg Signed-off-by: Jiri Kosina --- drivers/hid/hid-apple.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index ce3c39938f9..9b97795e45a 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -55,10 +55,11 @@ struct apple_key_translation { static struct apple_key_translation apple_fn_keys[] = { { KEY_BACKSPACE, KEY_DELETE }, + { KEY_ENTER, KEY_INSERT }, { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, - { KEY_F3, KEY_FN_F5, APPLE_FLAG_FKEY }, /* Exposé */ - { KEY_F4, KEY_FN_F4, APPLE_FLAG_FKEY }, /* Dashboard */ + { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY }, + { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY }, { KEY_F5, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY }, { KEY_F6, KEY_KBDILLUMUP, APPLE_FLAG_FKEY }, { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY }, -- cgit v1.2.3 From 43ff3a48c13f3ddc085271c2eea2985d28c8aa08 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 10 Nov 2008 22:51:50 +0100 Subject: HID: use single threaded work queue for hid_compat Use single threaded work queue for hid_compat I doubt HID really needs to scale over multiple CPUs. So only use a single threaded workqueue for HID_COMPAT. This avoids some excessive thread use on systems with a larger number of CPUs. Signed-off-by: Andi Kleen Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 4f0b92edb4d..e158aa83b92 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1736,7 +1736,7 @@ static int __init hid_init(void) goto err_bus; #ifdef CONFIG_HID_COMPAT - hid_compat_wq = create_workqueue("hid_compat"); + hid_compat_wq = create_singlethread_workqueue("hid_compat"); if (!hid_compat_wq) { hidraw_exit(); goto err; -- cgit v1.2.3 From e3e14de50dff86331b8f0d701e910146c0049bf5 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sat, 1 Nov 2008 23:41:46 +0100 Subject: HID: fix start/stop cycle in usbhid driver `stop' left out usbhid->urb* pointers and so the next `start' thought it needs to allocate nothing and used the memory pointers previously pointed to. This led to memory corruption and device malfunction. Also don't forget to clear disconnect flag on start which was left set by the previous `stop'. This fixes echo DEVICE > /sys/bus/hid/drivers/DRIVER/unbind echo DEVICE > /sys/bus/hid/drivers/DRIVER/bind failures. Signed-off-by: Jiri Slaby Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 18e5ddd722c..f0339aefc79 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -781,6 +781,8 @@ static int usbhid_start(struct hid_device *hid) unsigned int n, insize = 0; int ret; + clear_bit(HID_DISCONNECTED, &usbhid->iofl); + usbhid->bufsize = HID_MIN_BUFFER_SIZE; hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); @@ -888,6 +890,9 @@ fail: usb_free_urb(usbhid->urbin); usb_free_urb(usbhid->urbout); usb_free_urb(usbhid->urbctrl); + usbhid->urbin = NULL; + usbhid->urbout = NULL; + usbhid->urbctrl = NULL; hid_free_buffers(dev, hid); mutex_unlock(&usbhid->setup); return ret; @@ -924,6 +929,9 @@ static void usbhid_stop(struct hid_device *hid) usb_free_urb(usbhid->urbin); usb_free_urb(usbhid->urbctrl); usb_free_urb(usbhid->urbout); + usbhid->urbin = NULL; /* don't mess up next start */ + usbhid->urbctrl = NULL; + usbhid->urbout = NULL; hid_free_buffers(hid_to_usb_dev(hid), hid); mutex_unlock(&usbhid->setup); -- cgit v1.2.3 From c91c21c5a6facddce936d82e5bc0c655d04288aa Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Thu, 13 Nov 2008 10:36:11 +0100 Subject: HID: fix kworld fm700 radio hidquirks This patch fixes kworld fm700 usb-radio hidqurks that handled by radio-si470x. Removes it from blacklist entry and places it in ignore entry in hid/hid-core.c The bug went in through the V4L/DVB tree by commit 6a13378a without HID maintainer being involved at all. Signed-off-by: Alexey Klimov Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index e158aa83b92..4b33d145286 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1268,7 +1268,6 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, @@ -1489,6 +1488,7 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) }, { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) }, { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) }, { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) }, -- cgit v1.2.3 From 62a56582e01b1c5139b235004548e233201df9aa Mon Sep 17 00:00:00 2001 From: Alexey Klimov Date: Thu, 13 Nov 2008 05:44:50 +0300 Subject: HID: fix radio-mr800 hidquirks This patch fixes radio-mr800 hidqurks. Removes it from blacklist entry and places it in ignore entry in hid/hid-core.c Signed-off-by: Alexey Klimov Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 4b33d145286..147ec591a80 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1255,7 +1255,6 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, - { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, @@ -1411,6 +1410,7 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)}, { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2)}, + { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) }, { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) }, -- cgit v1.2.3 From d9a682a592ff5905d328c648fd30ee7fa12ce8ab Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 13 Nov 2008 14:53:08 +0000 Subject: [ARM] cdb89712,clps7500,h720x: avoid namespace clash for FLASH_* constants Signed-off-by: Russell King --- drivers/mtd/maps/cdb89712.c | 4 +++- drivers/mtd/maps/h720x-flash.c | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/maps/cdb89712.c b/drivers/mtd/maps/cdb89712.c index e5059aa3c72..d7bc4299b19 100644 --- a/drivers/mtd/maps/cdb89712.c +++ b/drivers/mtd/maps/cdb89712.c @@ -15,7 +15,9 @@ #include - +#define FLASH_START 0x00000000 +#define FLASH_SIZE 0x800000 +#define FLASH_WIDTH 4 static struct mtd_info *flash_mtd; diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c index 35fef655ccc..3b959fad1c4 100644 --- a/drivers/mtd/maps/h720x-flash.c +++ b/drivers/mtd/maps/h720x-flash.c @@ -24,8 +24,8 @@ static struct mtd_info *mymtd; static struct map_info h720x_map = { .name = "H720X", .bankwidth = 4, - .size = FLASH_SIZE, - .phys = FLASH_PHYS, + .size = H720X_FLASH_SIZE, + .phys = H720X_FLASH_PHYS, }; static struct mtd_partition h720x_partitions[] = { @@ -70,7 +70,7 @@ int __init h720x_mtd_init(void) char *part_type = NULL; - h720x_map.virt = ioremap(FLASH_PHYS, FLASH_SIZE); + h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size); if (!h720x_map.virt) { printk(KERN_ERR "H720x-MTD: ioremap failed\n"); -- cgit v1.2.3 From 8959dabdf2f8f9ce982a2c4cfe6d1652a2fb6320 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 13 Nov 2008 15:02:41 +0000 Subject: [ARM] cdb89712: avoid namespace clashes with SRAM_ and BOOTROM_ constants Signed-off-by: Russell King --- drivers/mtd/maps/cdb89712.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/maps/cdb89712.c b/drivers/mtd/maps/cdb89712.c index d7bc4299b19..8d92d8db9a9 100644 --- a/drivers/mtd/maps/cdb89712.c +++ b/drivers/mtd/maps/cdb89712.c @@ -14,11 +14,20 @@ #include #include - +/* dynamic ioremap() areas */ #define FLASH_START 0x00000000 #define FLASH_SIZE 0x800000 #define FLASH_WIDTH 4 +#define SRAM_START 0x60000000 +#define SRAM_SIZE 0xc000 +#define SRAM_WIDTH 4 + +#define BOOTROM_START 0x70000000 +#define BOOTROM_SIZE 0x80 +#define BOOTROM_WIDTH 4 + + static struct mtd_info *flash_mtd; struct map_info cdb89712_flash_map = { -- cgit v1.2.3 From 6c5ab376b0b579cf58f9217dcd7a94d817f7a043 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 31 Oct 2008 10:09:57 -0700 Subject: USB: vstusb: fix compiler warning on x86-64 This fixes a reported compiler warning. Reported-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/vstusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c index 8648470c81c..63dff9ba73c 100644 --- a/drivers/usb/misc/vstusb.c +++ b/drivers/usb/misc/vstusb.c @@ -620,7 +620,7 @@ static long vstusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) __func__); retval = -EFAULT; } else { - dev_dbg(&dev->dev, "%s: recv %d bytes from pipe %d\n", + dev_dbg(&dev->dev, "%s: recv %zd bytes from pipe %d\n", __func__, usb_data.count, usb_data.pipe); } -- cgit v1.2.3 From 0047ca0a45c6a481abd467fb52d2a480ffc8c6b9 Mon Sep 17 00:00:00 2001 From: Paul Ready Date: Wed, 29 Oct 2008 14:25:50 -0700 Subject: USB: add Nikon D300 camera to unusual_devs Addresses http://bugzilla.kernel.org/show_bug.cgi?id=11685 When A Nikon D300 camera is connected to a system it is seen in /proc/bus/pci/devices but is not accessible. This is seen in the above file: T: Bus=01 Lev=01 Prnt=01 Port=05 Cnt=03 Dev#= 11 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=04b0 ProdID=041a Rev= 1.03 S: Manufacturer=NIKON S: Product=NIKON DSC D300 S: SerialNumber=000008014379 C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr= 2mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=06(still) Sub=01 Prot=01 Driver=usbfs E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=03(Int.) MxPS= 8 Ivl=32ms Cc: Alan Stern Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index fb9e20e624c..f379291d538 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -418,6 +418,13 @@ UNUSUAL_DEV( 0x04b0, 0x0417, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), +/* Reported by paul ready */ +UNUSUAL_DEV( 0x04b0, 0x0419, 0x0100, 0x0200, + "NIKON", + "NIKON DSC D300", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), + /* Reported by Doug Maxey (dwm@austin.ibm.com) */ UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110, "IBM", -- cgit v1.2.3 From 352d026338378b1f13f044e33c1047da6e470056 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 29 Oct 2008 15:16:58 -0400 Subject: USB: don't register endpoints for interfaces that are going away This patch (as1155) fixes a bug in usbcore. When interfaces are deleted, either because the device was disconnected or because of a configuration change, the extra attribute files and child endpoint devices may get left behind. This is because the core removes them before calling device_del(). But during device_del(), after the driver is unbound the core will reinstall altsetting 0 and recreate those extra attributes and children. The patch prevents this by adding a flag to record when the interface is in the midst of being unregistered. When the flag is set, the attribute files and child devices will not be created. Signed-off-by: Alan Stern Cc: stable [2.6.27, 2.6.26, 2.6.25] Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 1 + drivers/usb/core/sysfs.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 887738577b2..6d1048faf08 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1091,6 +1091,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) continue; dev_dbg(&dev->dev, "unregistering interface %s\n", dev_name(&interface->dev)); + interface->unregistering = 1; usb_remove_sysfs_intf_files(interface); device_del(&interface->dev); } diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index f66fba11fbd..4fb65fdc9dc 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -840,7 +840,7 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf) struct usb_host_interface *alt = intf->cur_altsetting; int retval; - if (intf->sysfs_files_created) + if (intf->sysfs_files_created || intf->unregistering) return 0; /* The interface string may be present in some altsettings -- cgit v1.2.3 From f82a689faeb328ba7c194782f42cc438519d508e Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Wed, 29 Oct 2008 15:10:31 +0200 Subject: usb: musb: Fix for isochronous IN transfer Fixes blurred capture images in dma mode. Isochronous error field in urb and source data buffer pointer were not updated properly in dma mode. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_host.c | 77 ++++++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 3133990f04e..981d49738ec 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1507,10 +1507,29 @@ void musb_host_rx(struct musb *musb, u8 epnum) musb_writew(hw_ep->regs, MUSB_RXCSR, val); #ifdef CONFIG_USB_INVENTRA_DMA + if (usb_pipeisoc(pipe)) { + struct usb_iso_packet_descriptor *d; + + d = urb->iso_frame_desc + qh->iso_idx; + d->actual_length = xfer_len; + + /* even if there was an error, we did the dma + * for iso_frame_desc->length + */ + if (d->status != EILSEQ && d->status != -EOVERFLOW) + d->status = 0; + + if (++qh->iso_idx >= urb->number_of_packets) + done = true; + else + done = false; + + } else { /* done if urb buffer is full or short packet is recd */ done = (urb->actual_length + xfer_len >= urb->transfer_buffer_length || dma->actual_len < qh->maxpacket); + } /* send IN token for next packet, without AUTOREQ */ if (!done) { @@ -1547,7 +1566,8 @@ void musb_host_rx(struct musb *musb, u8 epnum) if (dma) { struct dma_controller *c; u16 rx_count; - int ret; + int ret, length; + dma_addr_t buf; rx_count = musb_readw(epio, MUSB_RXCOUNT); @@ -1560,6 +1580,35 @@ void musb_host_rx(struct musb *musb, u8 epnum) c = musb->dma_controller; + if (usb_pipeisoc(pipe)) { + int status = 0; + struct usb_iso_packet_descriptor *d; + + d = urb->iso_frame_desc + qh->iso_idx; + + if (iso_err) { + status = -EILSEQ; + urb->error_count++; + } + if (rx_count > d->length) { + if (status == 0) { + status = -EOVERFLOW; + urb->error_count++; + } + DBG(2, "** OVERFLOW %d into %d\n",\ + rx_count, d->length); + + length = d->length; + } else + length = rx_count; + d->status = status; + buf = urb->transfer_dma + d->offset; + } else { + length = rx_count; + buf = urb->transfer_dma + + urb->actual_length; + } + dma->desired_mode = 0; #ifdef USE_MODE1 /* because of the issue below, mode 1 will @@ -1571,6 +1620,12 @@ void musb_host_rx(struct musb *musb, u8 epnum) urb->actual_length) > qh->maxpacket) dma->desired_mode = 1; + if (rx_count < hw_ep->max_packet_sz_rx) { + length = rx_count; + dma->bDesiredMode = 0; + } else { + length = urb->transfer_buffer_length; + } #endif /* Disadvantage of using mode 1: @@ -1608,12 +1663,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) */ ret = c->channel_program( dma, qh->maxpacket, - dma->desired_mode, - urb->transfer_dma - + urb->actual_length, - (dma->desired_mode == 0) - ? rx_count - : urb->transfer_buffer_length); + dma->desired_mode, buf, length); if (!ret) { c->channel_release(dma); @@ -1631,19 +1681,6 @@ void musb_host_rx(struct musb *musb, u8 epnum) } } - if (dma && usb_pipeisoc(pipe)) { - struct usb_iso_packet_descriptor *d; - int iso_stat = status; - - d = urb->iso_frame_desc + qh->iso_idx; - d->actual_length += xfer_len; - if (iso_err) { - iso_stat = -EILSEQ; - urb->error_count++; - } - d->status = iso_stat; - } - finish: urb->actual_length += xfer_len; qh->offset += xfer_len; -- cgit v1.2.3 From 14a2c96f72e0939cb817b6624346b0161b5603db Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 29 Oct 2008 15:10:36 +0200 Subject: usb: musb: tusb6010: kill compile warning Add an errno to failing case. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/tusb6010.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index b73b036f3d7..ee8fca92a4a 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -605,7 +605,7 @@ void musb_platform_set_mode(struct musb *musb, u8 musb_mode) if (musb->board_mode != MUSB_OTG) { ERR("Changing mode currently only supported in OTG mode\n"); - return; + return -EINVAL; } otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); -- cgit v1.2.3 From eef767b761bdd08200fbbfc910ab815d03787326 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Wed, 29 Oct 2008 15:10:38 +0200 Subject: usb: musb: Removes compilation warning in gadget mode Fixes compilation warning when musb is configured in gadget mode. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/omap2430.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 9d2dcb121c5..ce6c162920f 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -53,7 +53,9 @@ static void musb_do_idle(unsigned long _musb) { struct musb *musb = (void *)_musb; unsigned long flags; +#ifdef CONFIG_USB_MUSB_HDRC_HCD u8 power; +#endif u8 devctl; devctl = musb_readb(musb->mregs, MUSB_DEVCTL); -- cgit v1.2.3 From b60c72abdbd44ed2a63fa80455d0b7f18ce76d2b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 29 Oct 2008 15:10:39 +0200 Subject: usb: musb: fix debug global variable name In order to avoid namespace conflicts, add a prefix to our kernel-wise symbol. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 6 +++--- drivers/usb/musb/musb_debug.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 4a35745b30b..5280dba9b1f 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -114,8 +114,8 @@ -unsigned debug; -module_param(debug, uint, S_IRUGO | S_IWUSR); +unsigned musb_debug; +module_param(musb_debug, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug message level. Default = 0"); #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia" @@ -2248,7 +2248,7 @@ static int __init musb_init(void) "host" #endif ", debug=%d\n", - musb_driver_name, debug); + musb_driver_name, musb_debug); return platform_driver_probe(&musb_driver, musb_probe); } diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h index 4d2794441b1..9fc1db44c72 100644 --- a/drivers/usb/musb/musb_debug.h +++ b/drivers/usb/musb/musb_debug.h @@ -48,11 +48,11 @@ __func__, __LINE__ , ## args); \ } } while (0) -extern unsigned debug; +extern unsigned musb_debug; static inline int _dbg_level(unsigned l) { - return debug >= l; + return musb_debug >= l; } #define DBG(level, fmt, args...) xprintk(level, KERN_DEBUG, fmt, ## args) -- cgit v1.2.3 From 23d15e070c2fe5d341ca04275f6ea1b5a5fcb26f Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Wed, 29 Oct 2008 15:10:35 +0200 Subject: usb: musb: fix BULK request on different available endpoints Fixes co-working issue of usb serial device with usb/net devices while oter endpoints are free and can be used.This patch implements the policy that if endpoint resources are available then different BULK request goes to different endpoint otherwise they are multiplexed to one reserved endpoint as currently done. Switch statement case is reordered in musb_giveback() to take care of bulk request both in multiplex scenario and otherwise. NAK limit scheme has to be added for multiplexed BULK request scenario to avoid endpoint starvation due to usb/net devices. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_host.c | 82 ++++++++++++++++++++++++-------------------- drivers/usb/musb/musb_host.h | 1 + 2 files changed, 46 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 981d49738ec..e45e70bcc5e 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -378,6 +378,19 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) switch (qh->type) { + case USB_ENDPOINT_XFER_CONTROL: + case USB_ENDPOINT_XFER_BULK: + /* fifo policy for these lists, except that NAKing + * should rotate a qh to the end (for fairness). + */ + if (qh->mux == 1) { + head = qh->ring.prev; + list_del(&qh->ring); + kfree(qh); + qh = first_qh(head); + break; + } + case USB_ENDPOINT_XFER_ISOC: case USB_ENDPOINT_XFER_INT: /* this is where periodic bandwidth should be @@ -388,17 +401,6 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) kfree(qh); qh = NULL; break; - - case USB_ENDPOINT_XFER_CONTROL: - case USB_ENDPOINT_XFER_BULK: - /* fifo policy for these lists, except that NAKing - * should rotate a qh to the end (for fairness). - */ - head = qh->ring.prev; - list_del(&qh->ring); - kfree(qh); - qh = first_qh(head); - break; } } return qh; @@ -1708,22 +1710,9 @@ static int musb_schedule( struct list_head *head = NULL; /* use fixed hardware for control and bulk */ - switch (qh->type) { - case USB_ENDPOINT_XFER_CONTROL: + if (qh->type == USB_ENDPOINT_XFER_CONTROL) { head = &musb->control; hw_ep = musb->control_ep; - break; - case USB_ENDPOINT_XFER_BULK: - hw_ep = musb->bulk_ep; - if (is_in) - head = &musb->in_bulk; - else - head = &musb->out_bulk; - break; - } - if (head) { - idle = list_empty(head); - list_add_tail(&qh->ring, head); goto success; } @@ -1762,19 +1751,34 @@ static int musb_schedule( else diff = hw_ep->max_packet_sz_tx - qh->maxpacket; - if (diff > 0 && best_diff > diff) { + if (diff >= 0 && best_diff > diff) { best_diff = diff; best_end = epnum; } } - if (best_end < 0) + /* use bulk reserved ep1 if no other ep is free */ + if (best_end > 0 && qh->type == USB_ENDPOINT_XFER_BULK) { + hw_ep = musb->bulk_ep; + if (is_in) + head = &musb->in_bulk; + else + head = &musb->out_bulk; + goto success; + } else if (best_end < 0) { return -ENOSPC; + } idle = 1; + qh->mux = 0; hw_ep = musb->endpoints + best_end; musb->periodic[best_end] = qh; DBG(4, "qh %p periodic slot %d\n", qh, best_end); success: + if (head) { + idle = list_empty(head); + list_add_tail(&qh->ring, head); + qh->mux = 1; + } qh->hw_ep = hw_ep; qh->hep->hcpriv = qh; if (idle) @@ -2052,11 +2056,13 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) sched = &musb->control; break; case USB_ENDPOINT_XFER_BULK: - if (usb_pipein(urb->pipe)) - sched = &musb->in_bulk; - else - sched = &musb->out_bulk; - break; + if (qh->mux == 1) { + if (usb_pipein(urb->pipe)) + sched = &musb->in_bulk; + else + sched = &musb->out_bulk; + break; + } default: /* REVISIT when we get a schedule tree, periodic * transfers won't always be at the head of a @@ -2104,11 +2110,13 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) sched = &musb->control; break; case USB_ENDPOINT_XFER_BULK: - if (is_in) - sched = &musb->in_bulk; - else - sched = &musb->out_bulk; - break; + if (qh->mux == 1) { + if (is_in) + sched = &musb->in_bulk; + else + sched = &musb->out_bulk; + break; + } default: /* REVISIT when we get a schedule tree, periodic transfers * won't always be at the head of a singleton queue... diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h index 77bcdb9d5b3..0b7fbcd2196 100644 --- a/drivers/usb/musb/musb_host.h +++ b/drivers/usb/musb/musb_host.h @@ -53,6 +53,7 @@ struct musb_qh { struct list_head ring; /* of musb_qh */ /* struct musb_qh *next; */ /* for periodic tree */ + u8 mux; /* qh multiplexed to hw_ep */ unsigned offset; /* in urb->transfer_buffer */ unsigned segsize; /* current xfer fragment */ -- cgit v1.2.3 From c6206faa4f18bcc837a12552b8c184ab1668fdea Mon Sep 17 00:00:00 2001 From: Leslie Watter Date: Wed, 12 Nov 2008 15:10:07 -0200 Subject: USB: Add YISO u893 usb modem vendor and product IDs to option driver This patch adds YISO u893 usb modem vendor and product ID to option.c. I had a better experience using this modification and the same system. Signed-off-by: Leslie Harlley Watter Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index bd07eaa300b..6fa1ec441b6 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -160,6 +160,11 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po #define NOVATELWIRELESS_VENDOR_ID 0x1410 +/* YISO PRODUCTS */ + +#define YISO_VENDOR_ID 0x0EAB +#define YISO_PRODUCT_U893 0xC893 + /* MERLIN EVDO PRODUCTS */ #define NOVATELWIRELESS_PRODUCT_V640 0x1100 #define NOVATELWIRELESS_PRODUCT_V620 0x1110 @@ -408,6 +413,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) }, { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) }, { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) }, + { USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004) }, -- cgit v1.2.3 From 2870fde780bbdf6442e9efe7ca5fc11bcdd2a09a Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Sun, 9 Nov 2008 11:40:30 +0530 Subject: USB: mention URB_FREE_BUFFER in usb_free_urb documentation The usb_free_urb comment says that the transfer buffer will not be freed, but this is not the case when URB_FREE_BUFFER is set. Signed-off-by: Rabin Vincent Acked-by: Marcel Holtmann Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/urb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 4342bd9c3bb..1f68af9db3f 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -85,8 +85,8 @@ EXPORT_SYMBOL_GPL(usb_alloc_urb); * Must be called when a user of a urb is finished with it. When the last user * of the urb calls this function, the memory of the urb is freed. * - * Note: The transfer buffer associated with the urb is not freed, that must be - * done elsewhere. + * Note: The transfer buffer associated with the urb is not freed unless the + * URB_FREE_BUFFER transfer flag is set. */ void usb_free_urb(struct urb *urb) { -- cgit v1.2.3 From 881e3c9867c585e632dfa4ccb0848b62debc64c7 Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Sun, 9 Nov 2008 20:17:54 +0000 Subject: USB: CP2101 Add device ID for AMB2560 This patch adds the device vendor and product IDs for Amber Wireless AMB2560 Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 8008d0bc80a..f073b589774 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -85,6 +85,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ + { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ -- cgit v1.2.3 From ad0b65efd12d020b046cde8d6f474e37bb98dd73 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Thu, 6 Nov 2008 11:19:11 -0800 Subject: USB: cdc-acm.c: fix recursive lock in acm_start_wb error path Fixes an obvious bug in cdc-acm by avoiding a recursive lock on acm_start_wb()'s error path. Should apply towards 2.6.27 stable and 2.6.28. ============================================= [ INFO: possible recursive locking detected ] 2.6.27-2-pae #109 --------------------------------------------- python/31449 is trying to acquire lock: (&acm->write_lock){++..}, at: [] acm_start_wb+0x5c/0x7b [cdc_acm] but task is already holding lock: (&acm->write_lock){++..}, at: [] acm_tty_write+0xe1/0x167 [cdc_acm] other info that might help us debug this: 2 locks held by python/31449: #0: (&tty->atomic_write_lock){--..}, at: [] tty_write_lock+0x14/0x3b #1: (&acm->write_lock){++..}, at: [] acm_tty_write+0xe1/0x167 [cdc_acm] stack backtrace: Pid: 31449, comm: python Not tainted 2.6.27-2-pae #109 [] ? printk+0xf/0x18 [] __lock_acquire+0xc7b/0x1316 [] lock_acquire+0x70/0x97 [] ? acm_start_wb+0x5c/0x7b [cdc_acm] [] _spin_lock_irqsave+0x37/0x47 [] ? acm_start_wb+0x5c/0x7b [cdc_acm] [] acm_start_wb+0x5c/0x7b [cdc_acm] [] acm_tty_write+0x143/0x167 [cdc_acm] [] write_chan+0x1cd/0x297 [] ? default_wake_function+0x0/0xd [] tty_write+0x149/0x1b9 [] ? write_chan+0x0/0x297 [] ? rw_verify_area+0x76/0x98 [] ? tty_write+0x0/0x1b9 [] vfs_write+0x8c/0x136 [] sys_write+0x3b/0x60 [] sysenter_do_call+0x12/0x3f ======================= Signed-off-by: Brandon Philips Cc: Oliver Neukum Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 20104443081..d50a99f70ae 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -158,16 +158,12 @@ static int acm_wb_is_avail(struct acm *acm) } /* - * Finish write. + * Finish write. Caller must hold acm->write_lock */ static void acm_write_done(struct acm *acm, struct acm_wb *wb) { - unsigned long flags; - - spin_lock_irqsave(&acm->write_lock, flags); wb->use = 0; acm->transmitting--; - spin_unlock_irqrestore(&acm->write_lock, flags); } /* @@ -482,6 +478,7 @@ static void acm_write_bulk(struct urb *urb) { struct acm_wb *wb = urb->context; struct acm *acm = wb->instance; + unsigned long flags; if (verbose || urb->status || (urb->actual_length != urb->transfer_buffer_length)) @@ -490,7 +487,9 @@ static void acm_write_bulk(struct urb *urb) urb->transfer_buffer_length, urb->status); + spin_lock_irqsave(&acm->write_lock, flags); acm_write_done(acm, wb); + spin_unlock_irqrestore(&acm->write_lock, flags); if (ACM_READY(acm)) schedule_work(&acm->work); else -- cgit v1.2.3 From 8010e06cc90367b4d3fba3b0ec3ced32360ac890 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 4 Nov 2008 11:33:35 -0500 Subject: USB: unusual_devs entry for Argosy USB mass-storage interface This patch (as1162) adds an unusual_devs entry for Argosy's USB-IDE interface. This fixes Bugzilla #11843. Signed-off-by: Alan Stern Tested-by: Luciano Rocha Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index f379291d538..b2ec1520852 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1265,6 +1265,13 @@ UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), +/* Reported by Luciano Rocha */ +UNUSUAL_DEV( 0x0840, 0x0082, 0x0001, 0x0001, + "Argosy", + "Storage", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), + /* Entry and supporting patch by Theodore Kilgore . * Flag will support Bulk devices which use a standards-violating 32-byte * Command Block Wrapper. Here, the "DC2MEGA" cameras (several brands) with -- cgit v1.2.3 From ddcb01ff9bf49c4dbbb058423559f7bc90b89374 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Fri, 31 Oct 2008 13:52:54 -0700 Subject: USB: Fix PS3 USB shutdown problems Add ehci_shutdown() or ohci_shutdown() calls to the USB PS3 bus glue. ehci_shutdown() and ohci_shutdown() do some controller specific cleanups not done by usb_remove_hcd(). Fixes errors on shutdown or reboot similar to these: ps3-ehci-driver sb_07: HC died; cleaning up irq 51: nobody cared (try booting with the "irqpoll" option) Related bugzilla reports: http://bugzilla.kernel.org/show_bug.cgi?id=11819 http://bugzilla.terrasoftsolutions.com/show_bug.cgi?id=317 Signed-off-by: Geoff Levand Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-ps3.c | 1 + drivers/usb/host/ohci-ps3.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 0eba894bcb0..9c9da35abc6 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c @@ -205,6 +205,7 @@ static int ps3_ehci_remove(struct ps3_system_bus_device *dev) tmp = hcd->irq; + ehci_shutdown(hcd); usb_remove_hcd(hcd); ps3_system_bus_set_driver_data(dev, NULL); diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c index 2089d8a46c4..3c1a3b5f89f 100644 --- a/drivers/usb/host/ohci-ps3.c +++ b/drivers/usb/host/ohci-ps3.c @@ -192,7 +192,7 @@ fail_start: return result; } -static int ps3_ohci_remove (struct ps3_system_bus_device *dev) +static int ps3_ohci_remove(struct ps3_system_bus_device *dev) { unsigned int tmp; struct usb_hcd *hcd = @@ -205,6 +205,7 @@ static int ps3_ohci_remove (struct ps3_system_bus_device *dev) tmp = hcd->irq; + ohci_shutdown(hcd); usb_remove_hcd(hcd); ps3_system_bus_set_driver_data(dev, NULL); -- cgit v1.2.3 From 659d643462fba8187f90f7604a9e0be144e242bc Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Thu, 30 Oct 2008 08:42:43 -0700 Subject: USB: storage: adjust comment in Kconfig Since commit 65934a9 ("Make USB storage depend on SCSI rather than selecting it [try #6]") the comment at the top of drivers/usb/storage/Kconfig is incorrect. Adjust it to the current situation. Signed-off-by: Paul Bolle Signed-off-by: Matthew Dharm Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 3d9249632ae..c68b738900b 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -2,8 +2,8 @@ # USB Storage driver configuration # -comment "NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'" -comment "may also be needed; see USB_STORAGE Help for more information" +comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;" +comment "see USB_STORAGE Help for more information" depends on USB config USB_STORAGE -- cgit v1.2.3 From 9a18e75fc443d24d25ee0fcf892a64a9741f6294 Mon Sep 17 00:00:00 2001 From: Damir N Abdullin Date: Thu, 30 Oct 2008 13:52:38 -0700 Subject: + usb-serial-cp2101-add-enfora-gsm2228.patch added to -mm tree Enfora GSM2228 based on Cygnal Integrated Products chip uses the same cp2101 driver. Signed-off-by: Damir N Abdullin Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index f073b589774..9035d7256b0 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -67,6 +67,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */ { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ + { USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */ { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ -- cgit v1.2.3 From ff30bf1ca4b548c0928dae6bfce89458b95e5bf4 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Sun, 2 Nov 2008 15:25:42 +0100 Subject: USB: remove optional bus bindings in isp1760, fixing runtime warning Roland Reported the following: | kmem_cache_create: duplicate cache isp1760_qtd | Pid: 461, comm: modprobe Tainted: G W 2.6.28-rc2-git3-default #4 | Call Trace: | [] kmem_cache_create+0xc9/0x3a3 | [] free_pages_bulk+0x16c/0x1c9 | [] isp1760_init+0x0/0xb [isp1760] | [] init_kmem_once+0x18/0x5f [isp1760] | [] isp1760_init+0x5/0xb [isp1760] | [] _stext+0x4d/0x148 | [] load_module+0x12cd/0x142e | [] kmem_cache_destroy+0x0/0xd7 | [] sys_init_module+0x87/0x176 | [] sysenter_do_call+0x12/0x2f The reason, is that ret is initialized with ENODEV instead of 0 _or_ the kmem cache is not freed in error case with no bus binding. The difference between OF+PCI and OF only is | 15148 804 32 15984 3e70 isp1760-of-pci.o | 13748 676 8 14432 3860 isp1760-of.o about 1.5 KiB. Until there is a checkbox where the user *must* select atleast one item, and may select multiple entries I don't make it selectable anymore. Having a driver which can't be used under any circumstances is broken anyway and I've seen distros shipping it that way. Reported-by: Roland Kletzing Signed-off-by: Sebastian Andrzej Siewior a Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 23 ++++++----------------- drivers/usb/host/isp1760-if.c | 22 +++++++++++----------- 2 files changed, 17 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 56f592dc0b3..f3a75a929e0 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -110,29 +110,18 @@ config USB_ISP116X_HCD config USB_ISP1760_HCD tristate "ISP 1760 HCD support" - depends on USB && EXPERIMENTAL + depends on USB && EXPERIMENTAL && (PCI || PPC_OF) ---help--- The ISP1760 chip is a USB 2.0 host controller. This driver does not support isochronous transfers or OTG. + This USB controller is usually attached to a non-DMA-Master + capable bus. NXP's eval kit brings this chip on PCI card + where the chip itself is behind a PLB to simulate such + a bus. To compile this driver as a module, choose M here: the - module will be called isp1760-hcd. - -config USB_ISP1760_PCI - bool "Support for the PCI bus" - depends on USB_ISP1760_HCD && PCI - ---help--- - Enables support for the device present on the PCI bus. - This should only be required if you happen to have the eval kit from - NXP and you are going to test it. - -config USB_ISP1760_OF - bool "Support for the OF platform bus" - depends on USB_ISP1760_HCD && PPC_OF - ---help--- - Enables support for the device present on the PowerPC - OpenFirmware platform bus. + module will be called isp1760. config USB_OHCI_HCD tristate "OHCI HCD support" diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index af849f59613..b87ca7cf4b3 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -14,16 +14,16 @@ #include "../core/hcd.h" #include "isp1760-hcd.h" -#ifdef CONFIG_USB_ISP1760_OF +#ifdef CONFIG_PPC_OF #include #include #endif -#ifdef CONFIG_USB_ISP1760_PCI +#ifdef CONFIG_PCI #include #endif -#ifdef CONFIG_USB_ISP1760_OF +#ifdef CONFIG_PPC_OF static int of_isp1760_probe(struct of_device *dev, const struct of_device_id *match) { @@ -128,7 +128,7 @@ static struct of_platform_driver isp1760_of_driver = { }; #endif -#ifdef CONFIG_USB_ISP1760_PCI +#ifdef CONFIG_PCI static u32 nxp_pci_io_base; static u32 iolength; static u32 pci_mem_phy0; @@ -288,28 +288,28 @@ static struct pci_driver isp1761_pci_driver = { static int __init isp1760_init(void) { - int ret = -ENODEV; + int ret; init_kmem_once(); -#ifdef CONFIG_USB_ISP1760_OF +#ifdef CONFIG_PPC_OF ret = of_register_platform_driver(&isp1760_of_driver); if (ret) { deinit_kmem_cache(); return ret; } #endif -#ifdef CONFIG_USB_ISP1760_PCI +#ifdef CONFIG_PCI ret = pci_register_driver(&isp1761_pci_driver); if (ret) goto unreg_of; #endif return ret; -#ifdef CONFIG_USB_ISP1760_PCI +#ifdef CONFIG_PCI unreg_of: #endif -#ifdef CONFIG_USB_ISP1760_OF +#ifdef CONFIG_PPC_OF of_unregister_platform_driver(&isp1760_of_driver); #endif deinit_kmem_cache(); @@ -319,10 +319,10 @@ module_init(isp1760_init); static void __exit isp1760_exit(void) { -#ifdef CONFIG_USB_ISP1760_OF +#ifdef CONFIG_PPC_OF of_unregister_platform_driver(&isp1760_of_driver); #endif -#ifdef CONFIG_USB_ISP1760_PCI +#ifdef CONFIG_PCI pci_unregister_driver(&isp1761_pci_driver); #endif deinit_kmem_cache(); -- cgit v1.2.3 From ed4103b3fcf38985995e732dab6c3e2b9693f6cb Mon Sep 17 00:00:00 2001 From: Ricky Wong Date: Tue, 4 Nov 2008 19:13:45 +0800 Subject: usb: unusual devs patch for Nokia 7610 Supernova Additional sectors were reported by the Nokia 7610 Supernova phone in usb storage mode. The following patch rectifies the aforementioned problem. Signed-off-by: Ricky Wong Yung Fei Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index b2ec1520852..d4e5fc86e43 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -253,6 +253,14 @@ UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0591, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Submitted by Ricky Wong Yung Fei */ +/* Nokia 7610 Supernova - Too many sectors reported in usb storage mode */ +UNUSUAL_DEV( 0x0421, 0x00f5, 0x0000, 0x0470, + "Nokia", + "7610 Supernova", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Reported by Olaf Hering from novell bug #105878 */ UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, "SMSC", -- cgit v1.2.3 From 859ff4072027ea7741121b902c59763f090e00c2 Mon Sep 17 00:00:00 2001 From: Albert Comerma Date: Tue, 4 Nov 2008 10:44:01 -0800 Subject: USB: SISUSB2VGA driver: add 0x0711, 0x0903 Signed-off-by: Albert Comerma Cc: Alan Cox Cc: David Brownell Cc: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 69c34a58e20..b4ec716de7d 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -3270,6 +3270,7 @@ static struct usb_device_id sisusb_table [] = { { USB_DEVICE(0x0711, 0x0900) }, { USB_DEVICE(0x0711, 0x0901) }, { USB_DEVICE(0x0711, 0x0902) }, + { USB_DEVICE(0x0711, 0x0903) }, { USB_DEVICE(0x0711, 0x0918) }, { USB_DEVICE(0x182d, 0x021c) }, { USB_DEVICE(0x182d, 0x0269) }, -- cgit v1.2.3 From d73b7aff28bc53c04e1f2e5ccaa5ea43089fb4a4 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Mon, 10 Nov 2008 21:11:11 -0700 Subject: ub: stub pre_reset and post_reset to fix oops Due to recent changes to usb_reset_device, the following hang occurs: events/0 D 0000000000000000 0 6 2 ffff880037477cc0 0000000000000046 ffff880037477c50 ffffffff80237434 ffffffff80574c80 00000001000a015c 0000000000000286 ffff8800374757d0 ffff88002a31c860 ffff880037475a00 0000000036779140 ffff880037475a00 Call Trace: [] try_to_del_timer_sync+0x52/0x5b [] dma_pool_free+0x1a7/0x1ec [] ub_disconnect+0x8e/0x1ad [ub] [] autoremove_wake_function+0x0/0x2e [] usb_unbind_interface+0x5c/0xb7 [] __device_release_driver+0x95/0xbd [] device_release_driver+0x21/0x2d [] usb_driver_release_interface+0x44/0x83 [] usb_forced_unbind_intf+0x17/0x1d [] usb_reset_device+0x7d/0x114 [] ub_reset_task+0x0/0x293 [ub] [] ub_reset_task+0x1c4/0x293 [ub] [] flush_to_ldisc+0x0/0x1cd [] ub_reset_task+0x0/0x293 [ub] [] run_workqueue+0x87/0x114 [] worker_thread+0xd8/0xe7 [] autoremove_wake_function+0x0/0x2e [] worker_thread+0x0/0xe7 [] kthread+0x47/0x73 [] schedule_tail+0x27/0x60 [] child_rip+0xa/0x11 [] kthread+0x0/0x73 [] child_rip+0x0/0x11 This is because usb_reset_device now unbinds, and that calls disconnect, which in case of ub waits until the reset completes... which deadlocks. Worse, this deadlocks keventd and this takes whole box down. I'm going to fix this properly later, but let's unbreak the driver quickly for non-composite devices at least. Signed-off-by: Pete Zaitcev Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/block/ub.c b/drivers/block/ub.c index fccac18d311..048d71d244d 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -1546,8 +1546,6 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd) /* * Reset management - * XXX Move usb_reset_device to khubd. Hogging kevent is not a good thing. - * XXX Make usb_sync_reset asynchronous. */ static void ub_reset_enter(struct ub_dev *sc, int try) @@ -1632,6 +1630,22 @@ static void ub_reset_task(struct work_struct *work) spin_unlock_irqrestore(sc->lock, flags); } +/* + * XXX Reset brackets are too much hassle to implement, so just stub them + * in order to prevent forced unbinding (which deadlocks solid when our + * ->disconnect method waits for the reset to complete and this kills keventd). + * + * XXX Tell Alan to move usb_unlock_device inside of usb_reset_device, + * or else the post_reset is invoked, and restats I/O on a locked device. + */ +static int ub_pre_reset(struct usb_interface *iface) { + return 0; +} + +static int ub_post_reset(struct usb_interface *iface) { + return 0; +} + /* * This is called from a process context. */ @@ -2446,6 +2460,8 @@ static struct usb_driver ub_driver = { .probe = ub_probe, .disconnect = ub_disconnect, .id_table = ub_usb_ids, + .pre_reset = ub_pre_reset, + .post_reset = ub_post_reset, }; static int __init ub_init(void) -- cgit v1.2.3 From 5863964608489f6dbf4b5f3118b45b3750a8274d Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 11 Nov 2008 16:47:21 +0900 Subject: usb: r8a66597-hcd: fix wrong data access in SuperH on-chip USB When I used SuperH on-chip USB, there was the problem that accessed r8a66597_root_hub which was not allocated. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/r8a66597-hcd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index c18d8790c41..2376f24f3c8 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1763,11 +1763,12 @@ static void r8a66597_timer(unsigned long _r8a66597) { struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597; unsigned long flags; + int port; spin_lock_irqsave(&r8a66597->lock, flags); - r8a66597_root_hub_control(r8a66597, 0); - r8a66597_root_hub_control(r8a66597, 1); + for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) + r8a66597_root_hub_control(r8a66597, port); spin_unlock_irqrestore(&r8a66597->lock, flags); } -- cgit v1.2.3 From 67b2e029743a52670d77864723b4d0d40f7733b5 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 12 Nov 2008 17:04:53 -0500 Subject: USB: EHCI: fix handling of dead controllers This patch (as1165) makes a few small changes in the logic used by ehci-hcd when it encounters a controller error: Instead of printing out the masked status, it prints the original status as read directly from the hardware. It doesn't check for the STS_HALT status bit before taking action. The mere fact that the STS_FATAL bit is set means that something bad has happened and the controller needs to be reset. With the old code this test could never succeed because the STS_HALT bit was masked out from the status. I anticipate that this will prevent the occasional "irq X: nobody cared" problem people encounter when their EHCI controllers die. Signed-off-by: Alan Stern Cc: David Brownell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 15a803b206b..4725d15d096 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -643,7 +643,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, cmd; + u32 status, masked_status, pcd_status = 0, cmd; int bh; spin_lock (&ehci->lock); @@ -656,14 +656,14 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) goto dead; } - status &= INTR_MASK; - if (!status) { /* irq sharing? */ + masked_status = status & INTR_MASK; + if (!masked_status) { /* irq sharing? */ spin_unlock(&ehci->lock); return IRQ_NONE; } /* clear (just) interrupts */ - ehci_writel(ehci, status, &ehci->regs->status); + ehci_writel(ehci, masked_status, &ehci->regs->status); cmd = ehci_readl(ehci, &ehci->regs->command); bh = 0; @@ -734,18 +734,17 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* PCI errors [4.15.2.4] */ if (unlikely ((status & STS_FATAL) != 0)) { + ehci_err(ehci, "fatal error\n"); dbg_cmd(ehci, "fatal", cmd); dbg_status(ehci, "fatal", status); - if (status & STS_HALT) { - ehci_err (ehci, "fatal error\n"); + ehci_halt(ehci); dead: - ehci_reset (ehci); - ehci_writel(ehci, 0, &ehci->regs->configured_flag); - /* generic layer kills/unlinks all urbs, then - * uses ehci_stop to clean up the rest - */ - bh = 1; - } + ehci_reset(ehci); + ehci_writel(ehci, 0, &ehci->regs->configured_flag); + /* generic layer kills/unlinks all urbs, then + * uses ehci_stop to clean up the rest + */ + bh = 1; } if (bh) -- cgit v1.2.3 From 372dd6e8ed924e876f3beb598721e813ad7fa323 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 12 Nov 2008 17:02:57 -0500 Subject: USB: EHCI: fix divide-by-zero bug This patch (as1164) fixes a bug in the EHCI scheduler. The interval value it uses is already in linear format, not logarithmically coded. The existing code can sometimes crash the system by trying to divide by zero. Signed-off-by: Alan Stern Cc: David Brownell Cc: Stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 4a0c5a78b2e..a081ee65bde 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -918,7 +918,7 @@ iso_stream_init ( */ stream->usecs = HS_USECS_ISO (maxp); bandwidth = stream->usecs * 8; - bandwidth /= 1 << (interval - 1); + bandwidth /= interval; } else { u32 addr; @@ -951,7 +951,7 @@ iso_stream_init ( } else stream->raw_mask = smask_out [hs_transfers - 1]; bandwidth = stream->usecs + stream->c_usecs; - bandwidth /= 1 << (interval + 2); + bandwidth /= interval << 3; /* stream->splits gets created from raw_mask later */ stream->address = cpu_to_hc32(ehci, addr); -- cgit v1.2.3 From e50ae572b33646656fa7037541613834dcadedfb Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 12 Nov 2008 11:35:13 -0800 Subject: USB: gadget: cdc-acm deadlock fix This fixes a deadlock appearing with some USB peripheral drivers when running CDC ACM gadget code. The newish (2.6.27) CDC ACM event notification mechanism sends messages (IN to the host) which are short enough to fit in most FIFOs. That means that with some peripheral controller drivers (evidently not the ones used to verify the notification code!!) the completion callback can be issued before queue() returns. The deadlock would come because the completion callback and the event-issuing code shared a spinlock. Fix is trivial: drop that lock while queueing the message. Signed-off-by: David Brownell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_acm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index 5ee1590b8e9..c1d34df0b15 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -463,7 +463,11 @@ static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value, notify->wLength = cpu_to_le16(length); memcpy(buf, data, length); + /* ep_queue() can complete immediately if it fills the fifo... */ + spin_unlock(&acm->lock); status = usb_ep_queue(ep, req, GFP_ATOMIC); + spin_lock(&acm->lock); + if (status < 0) { ERROR(acm->port.func.config->cdev, "acm ttyGS%d can't notify serial state, %d\n", -- cgit v1.2.3 From ccf95402d0ae6f433f29ce88cfd589cec8fc81ad Mon Sep 17 00:00:00 2001 From: Jason Cooper Date: Tue, 11 Nov 2008 13:02:53 -0500 Subject: USB: net: asix: add support for Cables-to-Go USB Ethernet adapter Add support to drivers/net/usb/asix.c for the Cables-to-Go "USB 2.0 to 10/100 Ethernet Adapter". USB id 0b95:772a. Signed-off-by: Jason Cooper Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/asix.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 37ecf845edf..e12cdb4543b 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -1444,6 +1444,10 @@ static const struct usb_device_id products [] = { // Apple USB Ethernet Adapter USB_DEVICE(0x05ac, 0x1402), .driver_info = (unsigned long) &ax88772_info, +}, { + // Cables-to-Go USB Ethernet Adapter + USB_DEVICE(0x0b95, 0x772a), + .driver_info = (unsigned long) &ax88772_info, }, { }, // END }; -- cgit v1.2.3 From 18776c7316545482a02bfaa2629a2aa1afc48357 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 13 Nov 2008 23:38:52 +0000 Subject: dm raid1: flush workqueue before destruction We queue work on keventd queue --- so this queue must be flushed in the destructor. Otherwise, keventd could access mirror_set after it was freed. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon Cc: stable@kernel.org --- drivers/md/dm-raid1.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 9d7b53ed75b..ec43f9fa4b2 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -1032,6 +1032,7 @@ static void mirror_dtr(struct dm_target *ti) del_timer_sync(&ms->timer); flush_workqueue(ms->kmirrord_wq); + flush_scheduled_work(); dm_kcopyd_client_destroy(ms->kcopyd_client); destroy_workqueue(ms->kmirrord_wq); free_context(ms, ti, ms->nr_mirrors); -- cgit v1.2.3 From 6edebdee48729ab4ba564bbfcb8dbf6a6cd68a39 Mon Sep 17 00:00:00 2001 From: Heinz Mauelshagen Date: Thu, 13 Nov 2008 23:38:56 +0000 Subject: dm stripe: fix init failure Don't proceed if dm_stripe_init() fails to register itself as a dm target. Signed-off-by: Heinz Mauelshagen Signed-off-by: Alasdair G Kergon --- drivers/md/dm-stripe.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index a2d068dbe9e..9e4ef88d421 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -320,8 +320,10 @@ int __init dm_stripe_init(void) int r; r = dm_register_target(&stripe_target); - if (r < 0) + if (r < 0) { DMWARN("target registration failed"); + return r; + } kstriped = create_singlethread_workqueue("kstriped"); if (!kstriped) { -- cgit v1.2.3 From b81aa1c79201cb424114fd198607951900babe18 Mon Sep 17 00:00:00 2001 From: Chandra Seetharaman Date: Thu, 13 Nov 2008 23:39:00 +0000 Subject: dm mpath: avoid attempting to activate null path Path activation code is called even when the pgpath is NULL. This could lead to a panic in activate_path(). Such a panic is seen in -rt kernel. This problem has been there before the pg_init() was moved to a workqueue. Signed-off-by: Chandra Seetharaman Signed-off-by: Alasdair G Kergon --- drivers/md/dm-mpath.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 4840733cd90..58b1015260f 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -441,13 +441,13 @@ static void process_queued_ios(struct work_struct *work) __choose_pgpath(m); pgpath = m->current_pgpath; - m->pgpath_to_activate = m->current_pgpath; if ((pgpath && !m->queue_io) || (!pgpath && !m->queue_if_no_path)) must_queue = 0; - if (m->pg_init_required && !m->pg_init_in_progress) { + if (m->pg_init_required && !m->pg_init_in_progress && pgpath) { + m->pgpath_to_activate = pgpath; m->pg_init_count++; m->pg_init_required = 0; m->pg_init_in_progress = 1; -- cgit v1.2.3 From 14e98c5ca8bed825f65cbf11cb0ffd2c09dac2f4 Mon Sep 17 00:00:00 2001 From: Chandra Seetharaman Date: Thu, 13 Nov 2008 23:39:06 +0000 Subject: dm mpath: warn if args ignored Currently dm ignores the parameters provided to hardware handlers without providing any notifications to the user. This patch just prints a warning message so that the user knows that the arguments are ignored. Signed-off-by: Chandra Seetharaman Signed-off-by: Alasdair G Kergon --- drivers/md/dm-mpath.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 58b1015260f..3d7f4923cd1 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -708,6 +708,10 @@ static int parse_hw_handler(struct arg_set *as, struct multipath *m) m->hw_handler_name = NULL; return -EINVAL; } + + if (hw_argc > 1) + DMWARN("Ignoring user-specified arguments for " + "hardware handler \"%s\"", m->hw_handler_name); consume(as, hw_argc - 1); return 0; -- cgit v1.2.3 From d221d2e77696e70e94b13989ea15db2ba5b34f8e Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 13 Nov 2008 23:39:10 +0000 Subject: dm: move pending queue wake_up end_io_acct This doesn't fix any bug, just moves wake_up immediately after decrementing md->pending, for better code readability. It must be clear to anyone manipulating md->pending to wake up the queue if md->pending reaches zero, so move the wakeup as close to the decrementing as possible. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 6963ad14840..dc25d8a07bc 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -375,7 +375,7 @@ static void start_io_acct(struct dm_io *io) dm_disk(md)->part0.in_flight = atomic_inc_return(&md->pending); } -static int end_io_acct(struct dm_io *io) +static void end_io_acct(struct dm_io *io) { struct mapped_device *md = io->md; struct bio *bio = io->bio; @@ -391,7 +391,9 @@ static int end_io_acct(struct dm_io *io) dm_disk(md)->part0.in_flight = pending = atomic_dec_return(&md->pending); - return !pending; + /* nudge anyone waiting on suspend queue */ + if (!pending) + wake_up(&md->wait); } /* @@ -499,9 +501,7 @@ static void dec_pending(struct dm_io *io, int error) spin_unlock_irqrestore(&io->md->pushback_lock, flags); } - if (end_io_acct(io)) - /* nudge anyone waiting on suspend queue */ - wake_up(&io->md->wait); + end_io_acct(io); if (io->error != DM_ENDIO_REQUEUE) { blk_add_trace_bio(io->md->queue, io->bio, -- cgit v1.2.3 From 8a57dfc6f943c92b861c9a19b0c86ddcb2aba768 Mon Sep 17 00:00:00 2001 From: Chandra Seetharaman Date: Thu, 13 Nov 2008 23:39:14 +0000 Subject: dm: avoid destroying table in dm_any_congested dm_any_congested() just checks for the DMF_BLOCK_IO and has no code to make sure that suspend waits for dm_any_congested() to complete. This patch adds such a check. Without it, a race can occur with dm_table_put() attempting to destroying the table in the wrong thread, the one running dm_any_congested() which is meant to be quick and return immediately. Two examples of problems: 1. Sleeping functions called from congested code, the caller of which holds a spin lock. 2. An ABBA deadlock between pdflush and multipathd. The two locks in contention are inode lock and kernel lock. Signed-off-by: Chandra Seetharaman Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm.c b/drivers/md/dm.c index dc25d8a07bc..c99e4728ff4 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -937,16 +937,24 @@ static void dm_unplug_all(struct request_queue *q) static int dm_any_congested(void *congested_data, int bdi_bits) { - int r; - struct mapped_device *md = (struct mapped_device *) congested_data; - struct dm_table *map = dm_get_table(md); + int r = bdi_bits; + struct mapped_device *md = congested_data; + struct dm_table *map; - if (!map || test_bit(DMF_BLOCK_IO, &md->flags)) - r = bdi_bits; - else - r = dm_table_any_congested(map, bdi_bits); + atomic_inc(&md->pending); + + if (!test_bit(DMF_BLOCK_IO, &md->flags)) { + map = dm_get_table(md); + if (map) { + r = dm_table_any_congested(map, bdi_bits); + dm_table_put(map); + } + } + + if (!atomic_dec_return(&md->pending)) + /* nudge anyone waiting on suspend queue */ + wake_up(&md->wait); - dm_table_put(map); return r; } -- cgit v1.2.3 From 847cdf42d589882aca683b6fb65b2c7832e92231 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 14 Nov 2008 05:19:00 -0700 Subject: powerpc/mpc5200: fix bestcomm Kconfig dependencies Without this patch it is possible to select drivers which require bestcomm support without bestcomm support being selected. This patch reworks the bestcomm dependencies to ensure the correct bestcomm tasks are always enabled. Reported-by: Hans Lehmann Signed-off-by: Grant Likely --- drivers/net/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 11f143f4adf..231eeaf1d55 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1825,9 +1825,10 @@ config FEC2 config FEC_MPC52xx tristate "MPC52xx FEC driver" - depends on PPC_MPC52xx && PPC_BESTCOMM_FEC + depends on PPC_MPC52xx && PPC_BESTCOMM select CRC32 select PHYLIB + select PPC_BESTCOMM_FEC ---help--- This option enables support for the MPC5200's on-chip Fast Ethernet Controller -- cgit v1.2.3 From 131d3a7a009d56a96cc7117b4e9d0c90c2e2a1dc Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 14 Nov 2008 12:03:47 +0100 Subject: HID: don't grab devices with no input Some devices have no input interrupt endpoint. These won't be handled by usbhid, but currently they are not refused and reside on hid bus. Perform this checking earlier so that we refuse to control such a device early enough (and not pass it to the hid bus at all). Signed-off-by: Jiri Slaby Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index f0339aefc79..d746bf8284d 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -849,12 +849,6 @@ static int usbhid_start(struct hid_device *hid) } } - if (!usbhid->urbin) { - err_hid("couldn't find an input interrupt endpoint"); - ret = -ENODEV; - goto fail; - } - init_waitqueue_head(&usbhid->wait); INIT_WORK(&usbhid->reset_work, hid_reset); setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); @@ -948,15 +942,26 @@ static struct hid_ll_driver usb_hid_driver = { static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) { + struct usb_host_interface *interface = intf->cur_altsetting; struct usb_device *dev = interface_to_usbdev(intf); struct usbhid_device *usbhid; struct hid_device *hid; + unsigned int n, has_in = 0; size_t len; int ret; dbg_hid("HID probe called for ifnum %d\n", intf->altsetting->desc.bInterfaceNumber); + for (n = 0; n < interface->desc.bNumEndpoints; n++) + if (usb_endpoint_is_int_in(&interface->endpoint[n].desc)) + has_in++; + if (!has_in) { + dev_err(&intf->dev, "couldn't find an input interrupt " + "endpoint\n"); + return -ENODEV; + } + hid = hid_allocate_device(); if (IS_ERR(hid)) return PTR_ERR(hid); -- cgit v1.2.3 From 5c6533510335ab291dcc0e9cdb98e67b50f6b2e9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Nov 2008 13:06:33 -0300 Subject: V4L/DVB (9613): tvaudio: fix a memory leak Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index b59e47272ab..3332df890f0 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1481,6 +1481,7 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) } if (desc->name == NULL) { v4l_dbg(1, debug, client, "no matching chip description found\n"); + kfree(chip); return -EIO; } v4l_info(client, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name); -- cgit v1.2.3 From 04e6f99025475a8cf2ccf2e39ffa48a6194a3b47 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Nov 2008 13:10:11 -0300 Subject: V4L/DVB (9615): tvaudio: instead of using a magic number, use ARRAY_SIZE Also, the default standard is the first one. So, fix the comment at the array. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 3332df890f0..cb8bf6d6f3d 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -777,7 +777,7 @@ static struct tda9874a_MODES { char *name; audiocmd cmd; } tda9874a_modelist[9] = { - { "A2, B/G", + { "A2, B/G", /* default */ { 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x77,0xA0,0x00, 0x00,0x00 }} }, { "A2, M (Korea)", { 9, { TDA9874A_C1FRA, 0x5D,0xC0,0x00, 0x62,0x6A,0xAA, 0x20,0x22 }} }, @@ -791,7 +791,7 @@ static struct tda9874a_MODES { { 9, { TDA9874A_C1FRA, 0x7D,0x00,0x00, 0x88,0x8A,0xAA, 0x08,0x33 }} }, { "NICAM, B/G", { 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x79,0xEA,0xAA, 0x08,0x33 }} }, - { "NICAM, D/K", /* default */ + { "NICAM, D/K", { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x08,0x33 }} }, { "NICAM, L", { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x09,0x33 }} } @@ -981,7 +981,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) { if (tda9874a_SIF > 2) tda9874a_SIF = 1; - if (tda9874a_STD > 8) + if (tda9874a_STD >= ARRAY_SIZE(tda9874a_modelist)) tda9874a_STD = 0; if(tda9874a_AMSEL > 1) tda9874a_AMSEL = 0; -- cgit v1.2.3 From af1a9951fc5c89518c25c4d9f2c4b391b2e72b83 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Nov 2008 13:14:15 -0300 Subject: V4L/DVB (9616): tvaudio: cleanup - group all callbacks together Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index cb8bf6d6f3d..1fa481ca086 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1260,6 +1260,7 @@ static struct CHIPDESC chiplist[] = { .addr_hi = I2C_ADDR_TDA9840 >> 1, .registers = 5, + /* callbacks */ .checkit = tda9840_checkit, .getmode = tda9840_getmode, .setmode = tda9840_setmode, @@ -1270,13 +1271,14 @@ static struct CHIPDESC chiplist[] = { }, { .name = "tda9873h", - .checkit = tda9873_checkit, .insmodopt = &tda9873, .addr_lo = I2C_ADDR_TDA985x_L >> 1, .addr_hi = I2C_ADDR_TDA985x_H >> 1, .registers = 3, .flags = CHIP_HAS_INPUTSEL, + /* callbacks */ + .checkit = tda9873_checkit, .getmode = tda9873_getmode, .setmode = tda9873_setmode, .checkmode = generic_checkmode, @@ -1290,12 +1292,13 @@ static struct CHIPDESC chiplist[] = { }, { .name = "tda9874h/a", - .checkit = tda9874a_checkit, - .initialize = tda9874a_initialize, .insmodopt = &tda9874a, .addr_lo = I2C_ADDR_TDA9874 >> 1, .addr_hi = I2C_ADDR_TDA9874 >> 1, + /* callbacks */ + .initialize = tda9874a_initialize, + .checkit = tda9874a_checkit, .getmode = tda9874a_getmode, .setmode = tda9874a_setmode, .checkmode = generic_checkmode, @@ -1324,10 +1327,11 @@ static struct CHIPDESC chiplist[] = { .rightreg = TDA9855_VR, .bassreg = TDA9855_BA, .treblereg = TDA9855_TR, + + /* callbacks */ .volfunc = tda9855_volume, .bassfunc = tda9855_bass, .treblefunc = tda9855_treble, - .getmode = tda985x_getmode, .setmode = tda985x_setmode, @@ -1348,6 +1352,8 @@ static struct CHIPDESC chiplist[] = { .rightreg = TEA6300_VL, .bassreg = TEA6300_BA, .treblereg = TEA6300_TR, + + /* callbacks */ .volfunc = tea6300_shift10, .bassfunc = tea6300_shift12, .treblefunc = tea6300_shift12, @@ -1358,7 +1364,6 @@ static struct CHIPDESC chiplist[] = { }, { .name = "tea6320", - .initialize = tea6320_initialize, .insmodopt = &tea6320, .addr_lo = I2C_ADDR_TEA6300 >> 1, .addr_hi = I2C_ADDR_TEA6300 >> 1, @@ -1369,6 +1374,9 @@ static struct CHIPDESC chiplist[] = { .rightreg = TEA6320_V, .bassreg = TEA6320_BA, .treblereg = TEA6320_TR, + + /* callbacks */ + .initialize = tea6320_initialize, .volfunc = tea6320_volume, .bassfunc = tea6320_shift11, .treblefunc = tea6320_shift11, @@ -1401,16 +1409,18 @@ static struct CHIPDESC chiplist[] = { .rightreg = TDA8425_VR, .bassreg = TDA8425_BA, .treblereg = TDA8425_TR, + + /* callbacks */ + .initialize = tda8425_initialize, .volfunc = tda8425_shift10, .bassfunc = tda8425_shift12, .treblefunc = tda8425_shift12, + .setmode = tda8425_setmode, .inputreg = TDA8425_S1, .inputmap = { TDA8425_S1_CH1, TDA8425_S1_CH1, TDA8425_S1_CH1 }, .inputmute = TDA8425_S1_OFF, - .setmode = tda8425_setmode, - .initialize = tda8425_initialize, }, { .name = "pic16c54 (PV951)", @@ -1435,6 +1445,7 @@ static struct CHIPDESC chiplist[] = { .addr_hi = I2C_ADDR_TDA9840 >> 1, .registers = 2, + /* callbacks */ .getmode = ta8874z_getmode, .setmode = ta8874z_setmode, .checkmode = generic_checkmode, -- cgit v1.2.3 From dd03e970a18f266faf120e47355349d224f64e3f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Nov 2008 13:55:39 -0300 Subject: V4L/DVB (9617): tvtime: remove generic_checkmode callback generic_checkmode() were called, via a callback, for some tvaudio chips. There's just one callback code used on all those boards. So, it makes no sense on keeping this as a callback. Since there were some OOPS reported on tvaudio on kerneloops.org, this patch removes this callback, adding the code at the only place were it is called: inside chip_tread. A flag were added to indicate the need for a kernel thread to set stereo mode on cards that needs it. Using this more direct approach simplifies the code, making it more robust against human errors. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 71 +++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 1fa481ca086..1387c54b7f0 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -58,7 +58,6 @@ typedef int (*checkit)(struct CHIPSTATE*); typedef int (*initialize)(struct CHIPSTATE*); typedef int (*getmode)(struct CHIPSTATE*); typedef void (*setmode)(struct CHIPSTATE*, int mode); -typedef void (*checkmode)(struct CHIPSTATE*); /* i2c command */ typedef struct AUDIOCMD { @@ -79,6 +78,7 @@ struct CHIPDESC { #define CHIP_HAS_VOLUME 1 #define CHIP_HAS_BASSTREBLE 2 #define CHIP_HAS_INPUTSEL 4 +#define CHIP_NEED_CHECKMODE 8 /* various i2c command sequences */ audiocmd init; @@ -96,9 +96,6 @@ struct CHIPDESC { getmode getmode; setmode setmode; - /* check / autoswitch audio after channel switches */ - checkmode checkmode; - /* input switch register + values for v4l inputs */ int inputreg; int inputmap[4]; @@ -264,6 +261,7 @@ static int chip_thread(void *data) { struct CHIPSTATE *chip = data; struct CHIPDESC *desc = chiplist + chip->type; + int mode; v4l_dbg(1, debug, chip->c, "%s: thread started\n", chip->c->name); set_freezable(); @@ -282,7 +280,26 @@ static int chip_thread(void *data) continue; /* have a look what's going on */ - desc->checkmode(chip); + mode = desc->getmode(chip); + if (mode == chip->prevmode) + continue; + + /* chip detected a new audio mode - set it */ + v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n", + chip->c->name); + + chip->prevmode = mode; + + if (mode & V4L2_TUNER_MODE_STEREO) + desc->setmode(chip, V4L2_TUNER_MODE_STEREO); + if (mode & V4L2_TUNER_MODE_LANG1_LANG2) + desc->setmode(chip, V4L2_TUNER_MODE_STEREO); + else if (mode & V4L2_TUNER_MODE_LANG1) + desc->setmode(chip, V4L2_TUNER_MODE_LANG1); + else if (mode & V4L2_TUNER_MODE_LANG2) + desc->setmode(chip, V4L2_TUNER_MODE_LANG2); + else + desc->setmode(chip, V4L2_TUNER_MODE_MONO); /* schedule next check */ mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); @@ -292,29 +309,6 @@ static int chip_thread(void *data) return 0; } -static void generic_checkmode(struct CHIPSTATE *chip) -{ - struct CHIPDESC *desc = chiplist + chip->type; - int mode = desc->getmode(chip); - - if (mode == chip->prevmode) - return; - - v4l_dbg(1, debug, chip->c, "%s: thread checkmode\n", chip->c->name); - chip->prevmode = mode; - - if (mode & V4L2_TUNER_MODE_STEREO) - desc->setmode(chip,V4L2_TUNER_MODE_STEREO); - if (mode & V4L2_TUNER_MODE_LANG1_LANG2) - desc->setmode(chip,V4L2_TUNER_MODE_STEREO); - else if (mode & V4L2_TUNER_MODE_LANG1) - desc->setmode(chip,V4L2_TUNER_MODE_LANG1); - else if (mode & V4L2_TUNER_MODE_LANG2) - desc->setmode(chip,V4L2_TUNER_MODE_LANG2); - else - desc->setmode(chip,V4L2_TUNER_MODE_MONO); -} - /* ---------------------------------------------------------------------- */ /* audio chip descriptions - defines+functions for tda9840 */ @@ -1259,12 +1253,12 @@ static struct CHIPDESC chiplist[] = { .addr_lo = I2C_ADDR_TDA9840 >> 1, .addr_hi = I2C_ADDR_TDA9840 >> 1, .registers = 5, + .flags = CHIP_NEED_CHECKMODE, /* callbacks */ .checkit = tda9840_checkit, .getmode = tda9840_getmode, .setmode = tda9840_setmode, - .checkmode = generic_checkmode, .init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN /* ,TDA9840_SW, TDA9840_MONO */} } @@ -1275,13 +1269,12 @@ static struct CHIPDESC chiplist[] = { .addr_lo = I2C_ADDR_TDA985x_L >> 1, .addr_hi = I2C_ADDR_TDA985x_H >> 1, .registers = 3, - .flags = CHIP_HAS_INPUTSEL, + .flags = CHIP_HAS_INPUTSEL | CHIP_NEED_CHECKMODE, /* callbacks */ .checkit = tda9873_checkit, .getmode = tda9873_getmode, .setmode = tda9873_setmode, - .checkmode = generic_checkmode, .init = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } }, .inputreg = TDA9873_SW, @@ -1295,13 +1288,13 @@ static struct CHIPDESC chiplist[] = { .insmodopt = &tda9874a, .addr_lo = I2C_ADDR_TDA9874 >> 1, .addr_hi = I2C_ADDR_TDA9874 >> 1, + .flags = CHIP_NEED_CHECKMODE, /* callbacks */ .initialize = tda9874a_initialize, .checkit = tda9874a_checkit, .getmode = tda9874a_getmode, .setmode = tda9874a_setmode, - .checkmode = generic_checkmode, }, { .name = "tda9850", @@ -1444,11 +1437,11 @@ static struct CHIPDESC chiplist[] = { .addr_lo = I2C_ADDR_TDA9840 >> 1, .addr_hi = I2C_ADDR_TDA9840 >> 1, .registers = 2, + .flags = CHIP_NEED_CHECKMODE, /* callbacks */ .getmode = ta8874z_getmode, .setmode = ta8874z_setmode, - .checkmode = generic_checkmode, .init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}}, }, @@ -1531,7 +1524,7 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) } chip->thread = NULL; - if (desc->checkmode) { + if (desc->flags & CHIP_NEED_CHECKMODE) { /* start async thread */ init_timer(&chip->wt); chip->wt.function = chip_thread_wake; @@ -1804,12 +1797,18 @@ static int chip_command(struct i2c_client *client, break; case VIDIOC_S_FREQUENCY: chip->mode = 0; /* automatic */ - if (desc->checkmode && desc->setmode) { + + /* For chips that provide getmode, setmode and checkmode, + a kthread is created to automatically to set the audio + standard. In this case, start with MONO and wait 2 seconds + for the decoding to stablize. Then, run kthread to change + to stereo, if carrier detected. + */ + if (chip->thread) { desc->setmode(chip,V4L2_TUNER_MODE_MONO); if (chip->prevmode != V4L2_TUNER_MODE_MONO) chip->prevmode = -1; /* reset previous mode */ mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000)); - /* the thread will call checkmode() later */ } break; -- cgit v1.2.3 From 099b7fcc770764ec06441066fddd90b97d868e11 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Nov 2008 14:01:15 -0300 Subject: V4L/DVB (9618): tvaudio: add additional logic to avoid OOPS This patch checks for volume, bass, treble, set mode and get mode callbacks before actually enabling the code that would use them. Instead of aborting the driver for load, this patch will allow it to load with a reduced number of functionatities. This prevents OOPS if some board entry is missing a needed callback. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 45 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 1387c54b7f0..6c920bf7497 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1511,20 +1511,49 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) chip_cmd(chip,"init",&desc->init); if (desc->flags & CHIP_HAS_VOLUME) { - chip->left = desc->leftinit ? desc->leftinit : 65535; - chip->right = desc->rightinit ? desc->rightinit : 65535; - chip_write(chip,desc->leftreg,desc->volfunc(chip->left)); - chip_write(chip,desc->rightreg,desc->volfunc(chip->right)); + if (!desc->volfunc) { + /* This shouldn't be happen. Warn user, but keep working + without volume controls + */ + v4l_info(chip->c, "volume callback undefined!\n"); + desc->flags &= ~CHIP_HAS_VOLUME; + } else { + chip->left = desc->leftinit ? desc->leftinit : 65535; + chip->right = desc->rightinit ? desc->rightinit : 65535; + chip_write(chip, desc->leftreg, + desc->volfunc(chip->left)); + chip_write(chip, desc->rightreg, + desc->volfunc(chip->right)); + } } if (desc->flags & CHIP_HAS_BASSTREBLE) { - chip->treble = desc->trebleinit ? desc->trebleinit : 32768; - chip->bass = desc->bassinit ? desc->bassinit : 32768; - chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass)); - chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble)); + if (!desc->bassfunc || !desc->treblefunc) { + /* This shouldn't be happen. Warn user, but keep working + without bass/treble controls + */ + v4l_info(chip->c, "bass/treble callbacks undefined!\n"); + desc->flags &= ~CHIP_HAS_BASSTREBLE; + } else { + chip->treble = desc->trebleinit ? + desc->trebleinit : 32768; + chip->bass = desc->bassinit ? + desc->bassinit : 32768; + chip_write(chip, desc->bassreg, + desc->bassfunc(chip->bass)); + chip_write(chip, desc->treblereg, + desc->treblefunc(chip->treble)); + } } chip->thread = NULL; if (desc->flags & CHIP_NEED_CHECKMODE) { + if (!desc->getmode || !desc->setmode) { + /* This shouldn't be happen. Warn user, but keep working + without kthread + */ + v4l_info(chip->c, "set/get mode callbacks undefined!\n"); + return 0; + } /* start async thread */ init_timer(&chip->wt); chip->wt.function = chip_thread_wake; -- cgit v1.2.3 From b4ab114cf750a49d91fc292439f8ef69a35a0fab Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Nov 2008 14:07:54 -0300 Subject: V4L/DVB (9619): tvaudio: update initial comments A driver used on several bttv boards since 2000 is not experimental anymore ;) Remove it from the comments. While there, update copyrights addind a quick note about the "recent" updates since 2005. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 6c920bf7497..ee6aca4ccd9 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1,5 +1,5 @@ /* - * experimental driver for simple i2c audio chips. + * Driver for simple i2c audio chips. * * Copyright (c) 2000 Gerd Knorr * based on code by: @@ -7,6 +7,10 @@ * Steve VanDeBogart (vandebo@uclink.berkeley.edu) * Greg Alexander (galexand@acm.org) * + * Copyright(c) 2005-2008 Mauro Carvalho Chehab + * - Some cleanups, code fixes, etc + * - Convert it to V4L2 API + * * This code is placed under the terms of the GNU General Public License * * OPTIONS: -- cgit v1.2.3 From 81cb5c4f7fbe6971d9c61401bc47193290fd59b7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Nov 2008 16:22:53 -0300 Subject: V4L/DVB (9620): tvaudio: use a direct reference for chip description Instead of storing the pointer for the proper entry at chip description table, the driver were storing an indirect reference, by using an index. Better to reference directly the data. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index ee6aca4ccd9..5ec369d54e6 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -112,8 +112,9 @@ static struct CHIPDESC chiplist[]; struct CHIPSTATE { struct i2c_client *c; - /* index into CHIPDESC array */ - int type; + /* chip-specific description - should point to + an entry at CHIPDESC table */ + struct CHIPDESC *desc; /* shadow register set */ audiocmd shadow; @@ -264,7 +265,7 @@ static void chip_thread_wake(unsigned long data) static int chip_thread(void *data) { struct CHIPSTATE *chip = data; - struct CHIPDESC *desc = chiplist + chip->type; + struct CHIPDESC *desc = chip->desc; int mode; v4l_dbg(1, debug, chip->c, "%s: thread started\n", chip->c->name); @@ -1087,7 +1088,7 @@ static int tda8425_shift12(int val) { return (val >> 12) | 0xf0; } static int tda8425_initialize(struct CHIPSTATE *chip) { - struct CHIPDESC *desc = chiplist + chip->type; + struct CHIPDESC *desc = chip->desc; int inputmap[4] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1, /* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF}; @@ -1503,7 +1504,7 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id) /* fill required data structures */ if (!id) strlcpy(client->name, desc->name, I2C_NAME_SIZE); - chip->type = desc-chiplist; + chip->desc = desc; chip->shadow.count = desc->registers+1; chip->prevmode = -1; chip->audmode = V4L2_TUNER_MODE_LANG1; @@ -1590,7 +1591,7 @@ static int chip_remove(struct i2c_client *client) static int tvaudio_get_ctrl(struct CHIPSTATE *chip, struct v4l2_control *ctrl) { - struct CHIPDESC *desc = chiplist + chip->type; + struct CHIPDESC *desc = chip->desc; switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -1630,7 +1631,7 @@ static int tvaudio_get_ctrl(struct CHIPSTATE *chip, static int tvaudio_set_ctrl(struct CHIPSTATE *chip, struct v4l2_control *ctrl) { - struct CHIPDESC *desc = chiplist + chip->type; + struct CHIPDESC *desc = chip->desc; switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: @@ -1706,7 +1707,7 @@ static int chip_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct CHIPSTATE *chip = i2c_get_clientdata(client); - struct CHIPDESC *desc = chiplist + chip->type; + struct CHIPDESC *desc = chip->desc; v4l_dbg(1, debug, chip->c, "%s: chip_command 0x%x\n", chip->c->name, cmd); -- cgit v1.2.3 From 494264379d186bf806613d27aafb7d88d42f4212 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Nov 2008 17:03:28 -0300 Subject: V4L/DVB (9621): Avoid writing outside shadow.bytes[] array There were no check about the limits of shadow.bytes array. This offers a risk of writing values outside the limits, overriding other data areas. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 5ec369d54e6..55b39b9a33d 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -154,7 +154,7 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) { unsigned char buffer[2]; - if (-1 == subaddr) { + if (subaddr < 0) { v4l_dbg(1, debug, chip->c, "%s: chip_write: 0x%x\n", chip->c->name, val); chip->shadow.bytes[1] = val; @@ -165,6 +165,13 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) return -1; } } else { + if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) { + v4l_info(chip->c, + "Tried to access a non-existent register: %d\n", + subaddr); + return -EINVAL; + } + v4l_dbg(1, debug, chip->c, "%s: chip_write: reg%d=0x%x\n", chip->c->name, subaddr, val); chip->shadow.bytes[subaddr+1] = val; @@ -179,12 +186,20 @@ static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) return 0; } -static int chip_write_masked(struct CHIPSTATE *chip, int subaddr, int val, int mask) +static int chip_write_masked(struct CHIPSTATE *chip, + int subaddr, int val, int mask) { if (mask != 0) { - if (-1 == subaddr) { + if (subaddr < 0) { val = (chip->shadow.bytes[1] & ~mask) | (val & mask); } else { + if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) { + v4l_info(chip->c, + "Tried to access a non-existent register: %d\n", + subaddr); + return -EINVAL; + } + val = (chip->shadow.bytes[subaddr+1] & ~mask) | (val & mask); } } @@ -230,6 +245,15 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd) if (0 == cmd->count) return 0; + if (cmd->count + cmd->bytes[0] - 1 >= ARRAY_SIZE(chip->shadow.bytes)) { + v4l_info(chip->c, + "Tried to access a non-existent register range: %d to %d\n", + cmd->bytes[0] + 1, cmd->bytes[0] + cmd->count - 1); + return -EINVAL; + } + + /* FIXME: it seems that the shadow bytes are wrong bellow !*/ + /* update our shadow register set; print bytes if (debug > 0) */ v4l_dbg(1, debug, chip->c, "%s: chip_cmd(%s): reg=%d, data:", chip->c->name, name,cmd->bytes[0]); -- cgit v1.2.3 From 41f5230f3fc6296d0d88ab9f4c3c07fcbbe53e59 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Nov 2008 17:25:04 -0300 Subject: V4L/DVB (9622): tvaudio: Improve comments and remove a unneeded prototype Some comments are not clear enough. Improve it to allow a better understanding of the driver behavior. While there, remove an unneeded struct prototype. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 55b39b9a33d..779ce7f865c 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -106,7 +106,6 @@ struct CHIPDESC { int inputmute; int inputmask; }; -static struct CHIPDESC chiplist[]; /* current state of the chip */ struct CHIPSTATE { @@ -1856,11 +1855,13 @@ static int chip_command(struct i2c_client *client, case VIDIOC_S_FREQUENCY: chip->mode = 0; /* automatic */ - /* For chips that provide getmode, setmode and checkmode, - a kthread is created to automatically to set the audio - standard. In this case, start with MONO and wait 2 seconds - for the decoding to stablize. Then, run kthread to change - to stereo, if carrier detected. + /* For chips that provide getmode and setmode, and doesn't + automatically follows the stereo carrier, a kthread is + created to set the audio standard. In this case, when then + the video channel is changed, tvaudio starts on MONO mode. + After waiting for 2 seconds, the kernel thread is called, + to follow whatever audio standard is pointed by the + audio carrier. */ if (chip->thread) { desc->setmode(chip,V4L2_TUNER_MODE_MONO); @@ -1905,9 +1906,3 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = { .legacy_probe = chip_legacy_probe, .id_table = chip_id, }; - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ -- cgit v1.2.3 From c6241b6c64dbe759e0eccaee913bdcf4d7960367 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Nov 2008 18:12:43 -0300 Subject: V4L/DVB (9623): tvaudio: Improve debug msg by printing something more human Before the patch, the used ioctl were printed as an hexadecimal code, hard to be understand without consulting the way _IO macros work. Instead, use the V4L default handler for printing such errors into a way that would be easier to understand. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 779ce7f865c..fb46ce4a109 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -1732,7 +1733,10 @@ static int chip_command(struct i2c_client *client, struct CHIPSTATE *chip = i2c_get_clientdata(client); struct CHIPDESC *desc = chip->desc; - v4l_dbg(1, debug, chip->c, "%s: chip_command 0x%x\n", chip->c->name, cmd); + if (debug > 0) { + v4l_i2c_print_ioctl(chip->c, cmd); + printk("\n"); + } switch (cmd) { case AUDC_SET_RADIO: -- cgit v1.2.3 From 01a1a3cc1e3fbe718bd06a2a5d4d1a2d0fb4d7d9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 14 Nov 2008 10:46:59 -0300 Subject: V4L/DVB (9624): CVE-2008-5033: fix OOPS on tvaudio when controlling bass/treble This bug were supposed to be fixed by 5ba2f67afb02c5302b2898949ed6fc3b3d37dcf1, where a call to NULL happens. Not all tvaudio chips allow controlling bass/treble. So, the driver has a table with a flag to indicate if the chip does support it. Unfortunately, the handling of this logic were broken for a very long time (probably since the first module version). Due to that, an OOPS were generated for devices that don't support bass/treble. This were the resulting OOPS message before the patch, with debug messages enabled: tvaudio' 1-005b: VIDIOC_S_CTRL BUG: unable to handle kernel NULL pointer dereference at 00000000 IP: [<00000000>] *pde = 22fda067 *pte = 00000000 Oops: 0000 [#1] SMP Modules linked in: snd_hda_intel snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd_hwdep snd soundcore tuner_simple tuner_types tea5767 tuner tvaudio bttv bridgebnep rfcomm l2cap bluetooth it87 hwmon_vid hwmon fuse sunrpc ipt_REJECT nf_conntrack_ipv4 iptable_filter ip_tables ip6t_REJECT xt_tcpudp nf_conntrack_ipv6 xt_state nf_conntrack ip6table_filter ip6_tables x_tables ipv6 dm_mirrordm_multipath dm_mod configfs videodev v4l1_compat ir_common 8139cp compat_ioctl32 v4l2_common 8139too videobuf_dma_sg videobuf_core mii btcx_risc tveeprom i915 button snd_page_alloc serio_raw drm pcspkr i2c_algo_bit i2c_i801 i2c_core iTCO_wdt iTCO_vendor_support sr_mod cdrom sg ata_generic pata_acpi ata_piix libata sd_mod scsi_mod ext3 jbdmbcache uhci_hcd ohci_hcd ehci_hcd [last unloaded: soundcore] Pid: 15413, comm: qv4l2 Not tainted (2.6.25.14-108.fc9.i686 #1) EIP: 0060:[<00000000>] EFLAGS: 00210246 CPU: 0 EIP is at 0x0 EAX: 00008000 EBX: ebd21600 ECX: e2fd9ec4 EDX: 00200046 ESI: f8c0f0c4 EDI: f8c0f0c4 EBP: e2fd9d50 ESP: e2fd9d2c DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 Process qv4l2 (pid: 15413, ti=e2fd9000 task=ebe44000 task.ti=e2fd9000) Stack: f8c0c6ae e2ff2a00 00000d00 e2fd9ec4 ebc4e000 e2fd9d5c f8c0c448 00000000 f899c12a e2fd9d5c f899c154 e2fd9d68 e2fd9d80 c0560185 e2fd9d88 f8f3e1d8 f8f3e1dc ebc4e034 f8f3e18c e2fd9ec4 00000000 e2fd9d90 f899c286 c008561c Call Trace: [] ? chip_command+0x266/0x4b6 [tvaudio] [] ? chip_command+0x0/0x4b6 [tvaudio] [] ? i2c_cmd+0x0/0x2f [i2c_core] [] ? i2c_cmd+0x2a/0x2f [i2c_core] [] ? device_for_each_child+0x21/0x49 [] ? i2c_clients_command+0x1c/0x1e [i2c_core] [] ? bttv_call_i2c_clients+0x14/0x16 [bttv] [] ? bttv_s_ctrl+0x1bc/0x313 [bttv] [] ? bttv_s_ctrl+0x0/0x313 [bttv] [] ? __video_do_ioctl+0x1f84/0x3726 [videodev] [] ? sock_aio_write+0x100/0x10d [] ? kmap_atomic_prot+0x1dd/0x1df [] ? enqueue_hrtimer+0xc2/0xcd [] ? copy_from_user+0x39/0x121 [] ? __video_ioctl2+0x1aa/0x24a [videodev] [] ? do_notify_resume+0x768/0x795 [] ? getnstimeofday+0x34/0xd1 [] ? autoremove_wake_function+0x0/0x33 [] ? video_ioctl2+0xf/0x13 [videodev] [] ? vfs_ioctl+0x50/0x69 [] ? do_vfs_ioctl+0x239/0x24c [] ? sys_ioctl+0x40/0x5b [] ? syscall_call+0x7/0xb [] ? cpuid4_cache_sysfs_exit+0x3d/0x69 ======================= Code: Bad EIP value. EIP: [<00000000>] 0x0 SS:ESP 0068:e2fd9d2c Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index fb46ce4a109..3720f0e03a1 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1639,13 +1639,13 @@ static int tvaudio_get_ctrl(struct CHIPSTATE *chip, return 0; } case V4L2_CID_AUDIO_BASS: - if (desc->flags & CHIP_HAS_BASSTREBLE) + if (!(desc->flags & CHIP_HAS_BASSTREBLE)) break; ctrl->value = chip->bass; return 0; case V4L2_CID_AUDIO_TREBLE: - if (desc->flags & CHIP_HAS_BASSTREBLE) - return -EINVAL; + if (!(desc->flags & CHIP_HAS_BASSTREBLE)) + break; ctrl->value = chip->treble; return 0; } @@ -1705,16 +1705,15 @@ static int tvaudio_set_ctrl(struct CHIPSTATE *chip, return 0; } case V4L2_CID_AUDIO_BASS: - if (desc->flags & CHIP_HAS_BASSTREBLE) + if (!(desc->flags & CHIP_HAS_BASSTREBLE)) break; chip->bass = ctrl->value; chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass)); return 0; case V4L2_CID_AUDIO_TREBLE: - if (desc->flags & CHIP_HAS_BASSTREBLE) - return -EINVAL; - + if (!(desc->flags & CHIP_HAS_BASSTREBLE)) + break; chip->treble = ctrl->value; chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble)); @@ -1761,7 +1760,7 @@ static int chip_command(struct i2c_client *client, break; case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_TREBLE: - if (desc->flags & CHIP_HAS_BASSTREBLE) + if (!(desc->flags & CHIP_HAS_BASSTREBLE)) return -EINVAL; break; default: -- cgit v1.2.3 From a108096878aa6cb744b5280ca59395b6c0152d14 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 14 Nov 2008 09:59:48 -0700 Subject: powerpc/virtex: fix various format/casting printk mismatches Various printk format string in code used by the Xilinx Virtex platform are not 32-bit/64-bit safe. Add correct casting to fix the bugs. Reported-by: Josh Boyer Signed-off-by: Grant Likely Acked-by: Josh Boyer --- drivers/block/xsysace.c | 4 ++-- drivers/char/xilinx_hwicap/xilinx_hwicap.c | 9 +++++---- drivers/serial/uartlite.c | 4 ++-- drivers/video/xilinxfb.c | 5 +++-- 4 files changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index ecab9e67d47..e28fc3abf0b 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -628,8 +628,8 @@ static void ace_fsm_dostate(struct ace_device *ace) /* Okay, it's a data request, set it up for transfer */ dev_dbg(ace->dev, - "request: sec=%lx hcnt=%lx, ccnt=%x, dir=%i\n", - req->sector, req->hard_nr_sectors, + "request: sec=%llx hcnt=%lx, ccnt=%x, dir=%i\n", + (unsigned long long) req->sector, req->hard_nr_sectors, req->current_nr_sectors, rq_data_dir(req)); ace->req = req; diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index ed132fe55d3..d1613194909 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -626,7 +626,7 @@ static int __devinit hwicap_setup(struct device *dev, int id, if (!request_mem_region(drvdata->mem_start, drvdata->mem_size, DRIVER_NAME)) { dev_err(dev, "Couldn't lock memory region at %Lx\n", - regs_res->start); + (unsigned long long) regs_res->start); retval = -EBUSY; goto failed1; } @@ -645,9 +645,10 @@ static int __devinit hwicap_setup(struct device *dev, int id, mutex_init(&drvdata->sem); drvdata->is_open = 0; - dev_info(dev, "ioremap %lx to %p with size %Lx\n", - (unsigned long int)drvdata->mem_start, - drvdata->base_address, drvdata->mem_size); + dev_info(dev, "ioremap %llx to %p with size %llx\n", + (unsigned long long) drvdata->mem_start, + drvdata->base_address, + (unsigned long long) drvdata->mem_size); cdev_init(&drvdata->cdev, &hwicap_fops); drvdata->cdev.owner = THIS_MODULE; diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index 6a3f8fb0c9d..3317148a4b9 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c @@ -286,8 +286,8 @@ static void ulite_release_port(struct uart_port *port) static int ulite_request_port(struct uart_port *port) { - pr_debug("ulite console: port=%p; port->mapbase=%x\n", - port, port->mapbase); + pr_debug("ulite console: port=%p; port->mapbase=%llx\n", + port, (unsigned long long) port->mapbase); if (!request_mem_region(port->mapbase, ULITE_REGION, "uartlite")) { dev_err(port->dev, "Memory region busy\n"); diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 5da3d2423cc..40a3a2afbfe 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c @@ -298,8 +298,9 @@ static int xilinxfb_assign(struct device *dev, unsigned long physaddr, /* Put a banner in the log (for DEBUG) */ dev_dbg(dev, "regs: phys=%lx, virt=%p\n", physaddr, drvdata->regs); - dev_dbg(dev, "fb: phys=%p, virt=%p, size=%x\n", - (void*)drvdata->fb_phys, drvdata->fb_virt, fbsize); + dev_dbg(dev, "fb: phys=%llx, virt=%p, size=%x\n", + (unsigned long long) drvdata->fb_phys, drvdata->fb_virt, + fbsize); return 0; /* success */ -- cgit v1.2.3 From 675be97a32a5f12650b86391b7431f1e10811f1e Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Fri, 14 Nov 2008 18:18:01 +0100 Subject: [S390] sclp: emit error message if assign storage fails Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp_cmd.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index eb5f1b8bc57..ec9c0bcf66e 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c @@ -324,6 +324,9 @@ static int do_assign_storage(sclp_cmdw_t cmd, u16 rn) case 0x0120: break; default: + pr_warning("assign storage failed (cmd=0x%08x, " + "response=0x%04x, rn=0x%04x)\n", cmd, + sccb->header.response_code, rn); rc = -EIO; break; } -- cgit v1.2.3 From cc835f7872adef35076e4a3b6632ef79bb4805be Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Fri, 14 Nov 2008 18:18:02 +0100 Subject: [S390] kvm_s390: Fix oops in virtio device detection with "mem=" The current virtio model on s390 has the descriptor page above the main memory. The guest virtio detection will oops if the mem= parameter is used to reduce/change the memory size. We have to use real_memory_size instead of max_pfn to detect the virtio descriptor pages. Signed-off-by: Christian Borntraeger --- drivers/s390/kvm/kvm_virtio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index ff4a6931bb8..3d442444c61 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c @@ -322,13 +322,13 @@ static int __init kvm_devices_init(void) return rc; } - rc = vmem_add_mapping(PFN_PHYS(max_pfn), PAGE_SIZE); + rc = vmem_add_mapping(real_memory_size, PAGE_SIZE); if (rc) { s390_root_dev_unregister(kvm_root); return rc; } - kvm_devices = (void *) PFN_PHYS(max_pfn); + kvm_devices = (void *) real_memory_size; ctl_set_bit(0, 9); register_external_interrupt(0x2603, kvm_extint_handler); -- cgit v1.2.3 From 85acc407bf1c49fb40b8f461c2c7526af736d87e Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 14 Nov 2008 18:18:06 +0100 Subject: [S390] cio: Fix refcount after moving devices. In ccw_device_move_to_orphanage(), a replacing ccw_device is searched via get_{disc,orphaned}_ccwdev_by_dev_id() which obtain a reference on the returned ccw_device. This reference must be given up again after the device has been moved to its new parent. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 4e78c82194b..4e4008325e2 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -874,11 +874,15 @@ void ccw_device_move_to_orphanage(struct work_struct *work) replacing_cdev = get_disc_ccwdev_by_dev_id(&dev_id, cdev); if (replacing_cdev) { sch_attach_disconnected_device(sch, replacing_cdev); + /* Release reference from get_disc_ccwdev_by_dev_id() */ + put_device(&cdev->dev); return; } replacing_cdev = get_orphaned_ccwdev_by_dev_id(css, &dev_id); if (replacing_cdev) { sch_attach_orphaned_device(sch, replacing_cdev); + /* Release reference from get_orphaned_ccwdev_by_dev_id() */ + put_device(&cdev->dev); return; } sch_create_and_recog_new_device(sch); -- cgit v1.2.3 From a9cffb227d59db526286cc9f84bf258e68a97470 Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Fri, 14 Nov 2008 18:18:08 +0100 Subject: [S390] dasd: log sense for fatal errors The logging of sense data for fatal errors was accidentally removed during Hyper PAV implementation. Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 4b76fca64a6..363bd1303d2 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1746,6 +1746,11 @@ restart: goto restart; } + /* log sense for fatal error */ + if (cqr->status == DASD_CQR_FAILED) { + dasd_log_sense(cqr, &cqr->irb); + } + /* First of all call extended error reporting. */ if (dasd_eer_enabled(base) && cqr->status == DASD_CQR_FAILED) { -- cgit v1.2.3 From c14464bf796d5ead1e735225ead78c566d3344ae Mon Sep 17 00:00:00 2001 From: Yuri Tikhonov Date: Fri, 14 Nov 2008 10:21:57 -0700 Subject: xsysace: Fix driver to use resource_size_t instead of unsigned long This patch is a bug fix to the SystemACE driver to use resource_size_t for physical address instead of unsigned long. This makes the driver work correctly on 32 bit systems with 64-bit resources (e.g. PowerPC 440). Signed-off-by: Yuri Tikhonov Signed-off-by: Ilya Yanok Signed-off-by: Grant Likely --- drivers/block/xsysace.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index e28fc3abf0b..29e1dfafb7c 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -194,7 +194,7 @@ struct ace_device { int in_irq; /* Details of hardware device */ - unsigned long physaddr; + resource_size_t physaddr; void __iomem *baseaddr; int irq; int bus_width; /* 0 := 8 bit; 1 := 16 bit */ @@ -935,7 +935,8 @@ static int __devinit ace_setup(struct ace_device *ace) int rc; dev_dbg(ace->dev, "ace_setup(ace=0x%p)\n", ace); - dev_dbg(ace->dev, "physaddr=0x%lx irq=%i\n", ace->physaddr, ace->irq); + dev_dbg(ace->dev, "physaddr=0x%llx irq=%i\n", + (unsigned long long)ace->physaddr, ace->irq); spin_lock_init(&ace->lock); init_completion(&ace->id_completion); @@ -1017,8 +1018,8 @@ static int __devinit ace_setup(struct ace_device *ace) /* Print the identification */ dev_info(ace->dev, "Xilinx SystemACE revision %i.%i.%i\n", (version >> 12) & 0xf, (version >> 8) & 0x0f, version & 0xff); - dev_dbg(ace->dev, "physaddr 0x%lx, mapped to 0x%p, irq=%i\n", - ace->physaddr, ace->baseaddr, ace->irq); + dev_dbg(ace->dev, "physaddr 0x%llx, mapped to 0x%p, irq=%i\n", + (unsigned long long) ace->physaddr, ace->baseaddr, ace->irq); ace->media_change = 1; ace_revalidate_disk(ace->gd); @@ -1035,8 +1036,8 @@ err_alloc_disk: err_blk_initq: iounmap(ace->baseaddr); err_ioremap: - dev_info(ace->dev, "xsysace: error initializing device at 0x%lx\n", - ace->physaddr); + dev_info(ace->dev, "xsysace: error initializing device at 0x%llx\n", + (unsigned long long) ace->physaddr); return -ENOMEM; } @@ -1059,7 +1060,7 @@ static void __devexit ace_teardown(struct ace_device *ace) } static int __devinit -ace_alloc(struct device *dev, int id, unsigned long physaddr, +ace_alloc(struct device *dev, int id, resource_size_t physaddr, int irq, int bus_width) { struct ace_device *ace; @@ -1119,7 +1120,7 @@ static void __devexit ace_free(struct device *dev) static int __devinit ace_probe(struct platform_device *dev) { - unsigned long physaddr = 0; + resource_size_t physaddr = 0; int bus_width = ACE_BUS_WIDTH_16; /* FIXME: should not be hard coded */ int id = dev->id; int irq = NO_IRQ; @@ -1165,7 +1166,7 @@ static int __devinit ace_of_probe(struct of_device *op, const struct of_device_id *match) { struct resource res; - unsigned long physaddr; + resource_size_t physaddr; const u32 *id; int irq, bus_width, rc; -- cgit v1.2.3 From 31c00fc15ebd35c1647775dbfc167a15d46657fd Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 13 Nov 2008 21:33:24 +0000 Subject: Create/use more directory structure in the Documentation/ tree. Create Documentation/blockdev/ sub-directory and populate it. Populate the Documentation/serial/ sub-directory. Move MSI-HOWTO.txt to Documentation/PCI/. Move ioctl-number.txt to Documentation/ioctl/. Update all relevant 00-INDEX files. Update all relevant Kconfig files and source files. Signed-off-by: Randy Dunlap --- drivers/block/Kconfig | 29 +++++++++++++++-------------- drivers/block/floppy.c | 2 +- drivers/char/Kconfig | 24 ++++++++++++------------ drivers/char/specialix.c | 2 +- 4 files changed, 29 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 61ad8d639ba..0344a8a8321 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -21,7 +21,8 @@ config BLK_DEV_FD ---help--- If you want to use the floppy disk drive(s) of your PC under Linux, say Y. Information about this driver, especially important for IBM - Thinkpad users, is contained in . + Thinkpad users, is contained in + . That file also contains the location of the Floppy driver FAQ as well as location of the fdutils package used to configure additional parameters of the driver at run time. @@ -76,7 +77,7 @@ config PARIDE your computer's parallel port. Most of them are actually IDE devices using a parallel port IDE adapter. This option enables the PARIDE subsystem which contains drivers for many of these external drives. - Read for more information. + Read for more information. If you have said Y to the "Parallel-port support" configuration option, you may share a single port between your printer and other @@ -114,9 +115,9 @@ config BLK_CPQ_DA help This is the driver for Compaq Smart Array controllers. Everyone using these boards should say Y here. See the file - for the current list of boards - supported by this driver, and for further information on the use of - this driver. + for the current list of + boards supported by this driver, and for further information on the + use of this driver. config BLK_CPQ_CISS_DA tristate "Compaq Smart Array 5xxx support" @@ -124,7 +125,7 @@ config BLK_CPQ_CISS_DA help This is the driver for Compaq Smart Array 5xxx controllers. Everyone using these boards should say Y here. - See for the current list of + See for the current list of boards supported by this driver, and for further information on the use of this driver. @@ -135,7 +136,7 @@ config CISS_SCSI_TAPE help When enabled (Y), this option allows SCSI tape drives and SCSI medium changers (tape robots) to be accessed via a Compaq 5xxx array - controller. (See for more details.) + controller. (See for more details.) "SCSI support" and "SCSI tape support" must also be enabled for this option to work. @@ -149,8 +150,8 @@ config BLK_DEV_DAC960 help This driver adds support for the Mylex DAC960, AcceleRAID, and eXtremeRAID PCI RAID controllers. See the file - for further information about - this driver. + for further information + about this driver. To compile this driver as a module, choose M here: the module will be called DAC960. @@ -278,9 +279,9 @@ config BLK_DEV_NBD userland (making server and client physically the same computer, communicating using the loopback network device). - Read for more information, especially - about where to find the server code, which runs in user space and - does not need special kernel support. + Read for more information, + especially about where to find the server code, which runs in user + space and does not need special kernel support. Note that this has nothing to do with the network file systems NFS or Coda; you can say N here even if you intend to use NFS or Coda. @@ -321,8 +322,8 @@ config BLK_DEV_RAM store a copy of a minimal root file system off of a floppy into RAM during the initial install of Linux. - Note that the kernel command line option "ramdisk=XX" is now - obsolete. For details, read . + Note that the kernel command line option "ramdisk=XX" is now obsolete. + For details, read . To compile this driver as a module, choose M here: the module will be called rd. diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 14db747a636..cf29cc4e6ab 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4124,7 +4124,7 @@ static int __init floppy_setup(char *str) printk("\n"); } else DPRINT("botched floppy option\n"); - DPRINT("Read Documentation/floppy.txt\n"); + DPRINT("Read Documentation/blockdev/floppy.txt\n"); return 0; } diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 43b35d0369d..43d6ba83a19 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -124,7 +124,7 @@ config COMPUTONE which give you many serial ports. You would need something like this to connect more than two modems to your Linux box, for instance in order to become a dial-in server. If you have a card like that, say - Y here and read . + Y here and read . To compile this driver as module, choose M here: the module will be called ip2. @@ -136,7 +136,7 @@ config ROCKETPORT This driver supports Comtrol RocketPort and RocketModem PCI boards. These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or modems. For information about the RocketPort/RocketModem boards - and this driver read . + and this driver read . To compile this driver as a module, choose M here: the module will be called rocket. @@ -154,7 +154,7 @@ config CYCLADES your Linux box, for instance in order to become a dial-in server. For information about the Cyclades-Z card, read - . + . To compile this driver as a module, choose M here: the module will be called cyclades. @@ -183,7 +183,7 @@ config DIGIEPCA box, for instance in order to become a dial-in server. This driver supports the original PC (ISA) boards as well as PCI, and EISA. If you have a card like this, say Y here and read the file - . + . To compile this driver as a module, choose M here: the module will be called epca. @@ -289,7 +289,7 @@ config RISCOM8 which gives you many serial ports. You would need something like this to connect more than two modems to your Linux box, for instance in order to become a dial-in server. If you have a card like that, - say Y here and read the file . + say Y here and read the file . Also it's possible to say M here and compile this driver as kernel loadable module; the module will be called riscom8. @@ -304,8 +304,8 @@ config SPECIALIX your Linux box, for instance in order to become a dial-in server. If you have a card like that, say Y here and read the file - . Also it's possible to say M here - and compile this driver as kernel loadable module which will be + . Also it's possible to say + M here and compile this driver as kernel loadable module which will be called specialix. config SX @@ -313,7 +313,7 @@ config SX depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) help This is a driver for the SX and SI multiport serial cards. - Please read the file for details. + Please read the file for details. This driver can only be built as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -344,8 +344,8 @@ config STALDRV like this to connect more than two modems to your Linux box, for instance in order to become a dial-in server. If you say Y here, you will be asked for your specific card model in the next - questions. Make sure to read in - this case. If you have never heard about all this, it's safe to + questions. Make sure to read + in this case. If you have never heard about all this, it's safe to say N. config STALLION @@ -354,7 +354,7 @@ config STALLION help If you have an EasyIO or EasyConnection 8/32 multiport Stallion card, then this is for you; say Y. Make sure to read - . + . To compile this driver as a module, choose M here: the module will be called stallion. @@ -365,7 +365,7 @@ config ISTALLION help If you have an EasyConnection 8/64, ONboard, Brumby or Stallion serial multiport card, say Y here. Make sure to read - . + . To compile this driver as a module, choose M here: the module will be called istallion. diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 242fd46fda2..a16b94f12eb 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -72,7 +72,7 @@ /* * There is a bunch of documentation about the card, jumpers, config * settings, restrictions, cables, device names and numbers in - * Documentation/specialix.txt + * Documentation/serial/specialix.txt */ #include -- cgit v1.2.3 From e3e081e1d5c4791f4416ed57b7a2f143ab9e5b09 Mon Sep 17 00:00:00 2001 From: Santwona Behera Date: Fri, 14 Nov 2008 14:44:08 -0800 Subject: NIU: Add Sun CP3260 ATCA blade support This patch adds support for the Sun CP3260 ATCA blade which is a N2 based ATCA blade with 2 NIU ports. The NIU ports do not have on-board PHY. Signed-off-by: Santwona Behera Signed-off-by: David S. Miller --- drivers/net/niu.c | 286 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- drivers/net/niu.h | 13 +++ 2 files changed, 293 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/niu.c b/drivers/net/niu.c index d8463b1c3df..be6b4d7e2bb 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -406,7 +406,7 @@ static int esr2_set_rx_cfg(struct niu *np, unsigned long channel, u32 val) } /* Mode is always 10G fiber. */ -static int serdes_init_niu(struct niu *np) +static int serdes_init_niu_10g_fiber(struct niu *np) { struct niu_link_config *lp = &np->link_config; u32 tx_cfg, rx_cfg; @@ -443,6 +443,223 @@ static int serdes_init_niu(struct niu *np) return 0; } +static int serdes_init_niu_1g_serdes(struct niu *np) +{ + struct niu_link_config *lp = &np->link_config; + u16 pll_cfg, pll_sts; + int max_retry = 100; + u64 sig, mask, val; + u32 tx_cfg, rx_cfg; + unsigned long i; + int err; + + tx_cfg = (PLL_TX_CFG_ENTX | PLL_TX_CFG_SWING_1375MV | + PLL_TX_CFG_RATE_HALF); + rx_cfg = (PLL_RX_CFG_ENRX | PLL_RX_CFG_TERM_0P8VDDT | + PLL_RX_CFG_ALIGN_ENA | PLL_RX_CFG_LOS_LTHRESH | + PLL_RX_CFG_RATE_HALF); + + if (np->port == 0) + rx_cfg |= PLL_RX_CFG_EQ_LP_ADAPTIVE; + + if (lp->loopback_mode == LOOPBACK_PHY) { + u16 test_cfg = PLL_TEST_CFG_LOOPBACK_CML_DIS; + + mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, + ESR2_TI_PLL_TEST_CFG_L, test_cfg); + + tx_cfg |= PLL_TX_CFG_ENTEST; + rx_cfg |= PLL_RX_CFG_ENTEST; + } + + /* Initialize PLL for 1G */ + pll_cfg = (PLL_CFG_ENPLL | PLL_CFG_MPY_8X); + + err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, + ESR2_TI_PLL_CFG_L, pll_cfg); + if (err) { + dev_err(np->device, PFX "NIU Port %d " + "serdes_init_niu_1g_serdes: " + "mdio write to ESR2_TI_PLL_CFG_L failed", np->port); + return err; + } + + pll_sts = PLL_CFG_ENPLL; + + err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, + ESR2_TI_PLL_STS_L, pll_sts); + if (err) { + dev_err(np->device, PFX "NIU Port %d " + "serdes_init_niu_1g_serdes: " + "mdio write to ESR2_TI_PLL_STS_L failed", np->port); + return err; + } + + udelay(200); + + /* Initialize all 4 lanes of the SERDES. */ + for (i = 0; i < 4; i++) { + err = esr2_set_tx_cfg(np, i, tx_cfg); + if (err) + return err; + } + + for (i = 0; i < 4; i++) { + err = esr2_set_rx_cfg(np, i, rx_cfg); + if (err) + return err; + } + + switch (np->port) { + case 0: + val = (ESR_INT_SRDY0_P0 | ESR_INT_DET0_P0); + mask = val; + break; + + case 1: + val = (ESR_INT_SRDY0_P1 | ESR_INT_DET0_P1); + mask = val; + break; + + default: + return -EINVAL; + } + + while (max_retry--) { + sig = nr64(ESR_INT_SIGNALS); + if ((sig & mask) == val) + break; + + mdelay(500); + } + + if ((sig & mask) != val) { + dev_err(np->device, PFX "Port %u signal bits [%08x] are not " + "[%08x]\n", np->port, (int) (sig & mask), (int) val); + return -ENODEV; + } + + return 0; +} + +static int serdes_init_niu_10g_serdes(struct niu *np) +{ + struct niu_link_config *lp = &np->link_config; + u32 tx_cfg, rx_cfg, pll_cfg, pll_sts; + int max_retry = 100; + u64 sig, mask, val; + unsigned long i; + int err; + + tx_cfg = (PLL_TX_CFG_ENTX | PLL_TX_CFG_SWING_1375MV); + rx_cfg = (PLL_RX_CFG_ENRX | PLL_RX_CFG_TERM_0P8VDDT | + PLL_RX_CFG_ALIGN_ENA | PLL_RX_CFG_LOS_LTHRESH | + PLL_RX_CFG_EQ_LP_ADAPTIVE); + + if (lp->loopback_mode == LOOPBACK_PHY) { + u16 test_cfg = PLL_TEST_CFG_LOOPBACK_CML_DIS; + + mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, + ESR2_TI_PLL_TEST_CFG_L, test_cfg); + + tx_cfg |= PLL_TX_CFG_ENTEST; + rx_cfg |= PLL_RX_CFG_ENTEST; + } + + /* Initialize PLL for 10G */ + pll_cfg = (PLL_CFG_ENPLL | PLL_CFG_MPY_10X); + + err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, + ESR2_TI_PLL_CFG_L, pll_cfg & 0xffff); + if (err) { + dev_err(np->device, PFX "NIU Port %d " + "serdes_init_niu_10g_serdes: " + "mdio write to ESR2_TI_PLL_CFG_L failed", np->port); + return err; + } + + pll_sts = PLL_CFG_ENPLL; + + err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, + ESR2_TI_PLL_STS_L, pll_sts & 0xffff); + if (err) { + dev_err(np->device, PFX "NIU Port %d " + "serdes_init_niu_10g_serdes: " + "mdio write to ESR2_TI_PLL_STS_L failed", np->port); + return err; + } + + udelay(200); + + /* Initialize all 4 lanes of the SERDES. */ + for (i = 0; i < 4; i++) { + err = esr2_set_tx_cfg(np, i, tx_cfg); + if (err) + return err; + } + + for (i = 0; i < 4; i++) { + err = esr2_set_rx_cfg(np, i, rx_cfg); + if (err) + return err; + } + + /* check if serdes is ready */ + + switch (np->port) { + case 0: + mask = ESR_INT_SIGNALS_P0_BITS; + val = (ESR_INT_SRDY0_P0 | + ESR_INT_DET0_P0 | + ESR_INT_XSRDY_P0 | + ESR_INT_XDP_P0_CH3 | + ESR_INT_XDP_P0_CH2 | + ESR_INT_XDP_P0_CH1 | + ESR_INT_XDP_P0_CH0); + break; + + case 1: + mask = ESR_INT_SIGNALS_P1_BITS; + val = (ESR_INT_SRDY0_P1 | + ESR_INT_DET0_P1 | + ESR_INT_XSRDY_P1 | + ESR_INT_XDP_P1_CH3 | + ESR_INT_XDP_P1_CH2 | + ESR_INT_XDP_P1_CH1 | + ESR_INT_XDP_P1_CH0); + break; + + default: + return -EINVAL; + } + + while (max_retry--) { + sig = nr64(ESR_INT_SIGNALS); + if ((sig & mask) == val) + break; + + mdelay(500); + } + + if ((sig & mask) != val) { + pr_info(PFX "NIU Port %u signal bits [%08x] are not " + "[%08x] for 10G...trying 1G\n", + np->port, (int) (sig & mask), (int) val); + + /* 10G failed, try initializing at 1G */ + err = serdes_init_niu_1g_serdes(np); + if (!err) { + np->flags &= ~NIU_FLAGS_10G; + np->mac_xcvr = MAC_XCVR_PCS; + } else { + dev_err(np->device, PFX "Port %u 10G/1G SERDES " + "Link Failed \n", np->port); + return -ENODEV; + } + } + return 0; +} + static int esr_read_rxtx_ctrl(struct niu *np, unsigned long chan, u32 *val) { int err; @@ -1954,13 +2171,23 @@ static const struct niu_phy_ops phy_ops_10g_serdes = { .link_status = link_status_10g_serdes, }; +static const struct niu_phy_ops phy_ops_10g_serdes_niu = { + .serdes_init = serdes_init_niu_10g_serdes, + .link_status = link_status_10g_serdes, +}; + +static const struct niu_phy_ops phy_ops_1g_serdes_niu = { + .serdes_init = serdes_init_niu_1g_serdes, + .link_status = link_status_1g_serdes, +}; + static const struct niu_phy_ops phy_ops_1g_rgmii = { .xcvr_init = xcvr_init_1g_rgmii, .link_status = link_status_1g_rgmii, }; static const struct niu_phy_ops phy_ops_10g_fiber_niu = { - .serdes_init = serdes_init_niu, + .serdes_init = serdes_init_niu_10g_fiber, .xcvr_init = xcvr_init_10g, .link_status = link_status_10g, }; @@ -1998,11 +2225,21 @@ struct niu_phy_template { u32 phy_addr_base; }; -static const struct niu_phy_template phy_template_niu = { +static const struct niu_phy_template phy_template_niu_10g_fiber = { .ops = &phy_ops_10g_fiber_niu, .phy_addr_base = 16, }; +static const struct niu_phy_template phy_template_niu_10g_serdes = { + .ops = &phy_ops_10g_serdes_niu, + .phy_addr_base = 0, +}; + +static const struct niu_phy_template phy_template_niu_1g_serdes = { + .ops = &phy_ops_1g_serdes_niu, + .phy_addr_base = 0, +}; + static const struct niu_phy_template phy_template_10g_fiber = { .ops = &phy_ops_10g_fiber, .phy_addr_base = 8, @@ -2182,8 +2419,25 @@ static int niu_determine_phy_disposition(struct niu *np) u32 phy_addr_off = 0; if (plat_type == PLAT_TYPE_NIU) { - tp = &phy_template_niu; - phy_addr_off += np->port; + switch (np->flags & + (NIU_FLAGS_10G | + NIU_FLAGS_FIBER | + NIU_FLAGS_XCVR_SERDES)) { + case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES: + /* 10G Serdes */ + tp = &phy_template_niu_10g_serdes; + break; + case NIU_FLAGS_XCVR_SERDES: + /* 1G Serdes */ + tp = &phy_template_niu_1g_serdes; + break; + case NIU_FLAGS_10G | NIU_FLAGS_FIBER: + /* 10G Fiber */ + default: + tp = &phy_template_niu_10g_fiber; + phy_addr_off += np->port; + break; + } } else { switch (np->flags & (NIU_FLAGS_10G | @@ -7213,6 +7467,12 @@ static int __devinit niu_phy_type_prop_decode(struct niu *np, np->flags |= NIU_FLAGS_10G; np->flags &= ~NIU_FLAGS_FIBER; np->mac_xcvr = MAC_XCVR_XPCS; + } else if (!strcmp(phy_prop, "xgsd") || !strcmp(phy_prop, "gsd")) { + /* 10G Serdes or 1G Serdes, default to 10G */ + np->flags |= NIU_FLAGS_10G; + np->flags &= ~NIU_FLAGS_FIBER; + np->flags |= NIU_FLAGS_XCVR_SERDES; + np->mac_xcvr = MAC_XCVR_XPCS; } else { return -EINVAL; } @@ -7741,6 +8001,8 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent) u32 val; int err; + num_10g = num_1g = 0; + if (!strcmp(np->vpd.model, NIU_ALONSO_MDL_STR) || !strcmp(np->vpd.model, NIU_KIMI_MDL_STR)) { num_10g = 0; @@ -7757,6 +8019,16 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent) parent->num_ports = 2; val = (phy_encode(PORT_TYPE_10G, 0) | phy_encode(PORT_TYPE_10G, 1)); + } else if ((np->flags & NIU_FLAGS_XCVR_SERDES) && + (parent->plat_type == PLAT_TYPE_NIU)) { + /* this is the Monza case */ + if (np->flags & NIU_FLAGS_10G) { + val = (phy_encode(PORT_TYPE_10G, 0) | + phy_encode(PORT_TYPE_10G, 1)); + } else { + val = (phy_encode(PORT_TYPE_1G, 0) | + phy_encode(PORT_TYPE_1G, 1)); + } } else { err = fill_phy_probe_info(np, parent, info); if (err) @@ -8656,7 +8928,9 @@ static void __devinit niu_device_announce(struct niu *np) dev->name, (np->flags & NIU_FLAGS_XMAC ? "XMAC" : "BMAC"), (np->flags & NIU_FLAGS_10G ? "10G" : "1G"), - (np->flags & NIU_FLAGS_FIBER ? "FIBER" : "COPPER"), + (np->flags & NIU_FLAGS_FIBER ? "FIBER" : + (np->flags & NIU_FLAGS_XCVR_SERDES ? "SERDES" : + "COPPER")), (np->mac_xcvr == MAC_XCVR_MII ? "MII" : (np->mac_xcvr == MAC_XCVR_PCS ? "PCS" : "XPCS")), np->vpd.phy_type); diff --git a/drivers/net/niu.h b/drivers/net/niu.h index c6fa883daa2..180ca8ae93d 100644 --- a/drivers/net/niu.h +++ b/drivers/net/niu.h @@ -1048,6 +1048,13 @@ #define PLL_CFG_LD_SHIFT 8 #define PLL_CFG_MPY 0x0000001e #define PLL_CFG_MPY_SHIFT 1 +#define PLL_CFG_MPY_4X 0x0 +#define PLL_CFG_MPY_5X 0x00000002 +#define PLL_CFG_MPY_6X 0x00000004 +#define PLL_CFG_MPY_8X 0x00000008 +#define PLL_CFG_MPY_10X 0x0000000a +#define PLL_CFG_MPY_12X 0x0000000c +#define PLL_CFG_MPY_12P5X 0x0000000e #define PLL_CFG_ENPLL 0x00000001 #define ESR2_TI_PLL_STS_L (ESR2_BASE + 0x002) @@ -1093,6 +1100,9 @@ #define PLL_TX_CFG_INVPAIR 0x00000080 #define PLL_TX_CFG_RATE 0x00000060 #define PLL_TX_CFG_RATE_SHIFT 5 +#define PLL_TX_CFG_RATE_FULL 0x0 +#define PLL_TX_CFG_RATE_HALF 0x20 +#define PLL_TX_CFG_RATE_QUAD 0x40 #define PLL_TX_CFG_BUSWIDTH 0x0000001c #define PLL_TX_CFG_BUSWIDTH_SHIFT 2 #define PLL_TX_CFG_ENTEST 0x00000002 @@ -1132,6 +1142,9 @@ #define PLL_RX_CFG_INVPAIR 0x00000080 #define PLL_RX_CFG_RATE 0x00000060 #define PLL_RX_CFG_RATE_SHIFT 5 +#define PLL_RX_CFG_RATE_FULL 0x0 +#define PLL_RX_CFG_RATE_HALF 0x20 +#define PLL_RX_CFG_RATE_QUAD 0x40 #define PLL_RX_CFG_BUSWIDTH 0x0000001c #define PLL_RX_CFG_BUSWIDTH_SHIFT 2 #define PLL_RX_CFG_ENTEST 0x00000002 -- cgit v1.2.3 From d8c3e23d06c1020f38b7b6290135a9522a2e3052 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 14 Nov 2008 14:47:29 -0800 Subject: niu: Bump driver version and release date. This driver is pretty mature, and the worst of the known problems has been fixed (the 32-bit failures due to readq implementation). So let's finally give it a version of 1.0 Signed-off-by: David S. Miller --- drivers/net/niu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/niu.c b/drivers/net/niu.c index be6b4d7e2bb..1b6f548c441 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -33,8 +33,8 @@ #define DRV_MODULE_NAME "niu" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "0.9" -#define DRV_MODULE_RELDATE "May 4, 2008" +#define DRV_MODULE_VERSION "1.0" +#define DRV_MODULE_RELDATE "Nov 14, 2008" static char version[] __devinitdata = DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; -- cgit v1.2.3 From 18acfa2597d57c19249346d130fc3334244557b4 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Thu, 13 Nov 2008 21:26:27 +0300 Subject: net/ucc_geth: Fix oops in uec_get_ethtool_stats() p_{tx,rx}_fw_statistics_pram are special: they're available only when a device is open. If the device is closed, we should just fill the data with zeroes. Fixes the following oops: root@b1:~# ifconfig eth1 down root@b1:~# ethtool -S eth1 Unable to handle kernel paging request for data at address 0x00000000 Faulting instruction address: 0xc01e1dcc Oops: Kernel access of bad area, sig: 11 [#1] [...] NIP [c01e1dcc] uec_get_ethtool_stats+0x98/0x124 LR [c0287cc8] ethtool_get_stats+0xfc/0x23c Call Trace: [cfaadde0] [c0287ca8] ethtool_get_stats+0xdc/0x23c (unreliable) [cfaade20] [c0288340] dev_ethtool+0x2fc/0x588 [cfaade50] [c0285648] dev_ioctl+0x290/0x33c [cfaadea0] [c0272238] sock_ioctl+0x80/0x2ec [cfaadec0] [c00b5ae4] vfs_ioctl+0x40/0xc0 [cfaadee0] [c00b5fa8] do_vfs_ioctl+0x78/0x20c [cfaadf10] [c00b617c] sys_ioctl+0x40/0x74 [cfaadf40] [c00142d8] ret_from_syscall+0x0/0x38 [...] ---[ end trace b941007b2dfb9759 ]--- Segmentation fault p.s. While at it, also remove u64 casts, they aren't needed. Signed-off-by: Anton Vorontsov Signed-off-by: Jeff Garzik --- drivers/net/ucc_geth_ethtool.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ucc_geth_ethtool.c index 85f38a6b6a4..68a7f541413 100644 --- a/drivers/net/ucc_geth_ethtool.c +++ b/drivers/net/ucc_geth_ethtool.c @@ -323,17 +323,17 @@ static void uec_get_ethtool_stats(struct net_device *netdev, if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) { base = (u32 __iomem *)&ugeth->ug_regs->tx64; for (i = 0; i < UEC_HW_STATS_LEN; i++) - data[j++] = (u64)in_be32(&base[i]); + data[j++] = in_be32(&base[i]); } if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) { base = (u32 __iomem *)ugeth->p_tx_fw_statistics_pram; for (i = 0; i < UEC_TX_FW_STATS_LEN; i++) - data[j++] = (u64)in_be32(&base[i]); + data[j++] = base ? in_be32(&base[i]) : 0; } if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) { base = (u32 __iomem *)ugeth->p_rx_fw_statistics_pram; for (i = 0; i < UEC_RX_FW_STATS_LEN; i++) - data[j++] = (u64)in_be32(&base[i]); + data[j++] = base ? in_be32(&base[i]) : 0; } } -- cgit v1.2.3 From 81183059e89c36f9b4c41f9332d642c2e0bff971 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Wed, 12 Nov 2008 10:07:11 -0600 Subject: gianfar: Fix DMA unmap invocations We weren't unmapping DMA memory, which will break when gianfar gets used on systems with more than 32-bits of memory. Also, it's just plain wrong. Signed-off-by: Andy Fleming Signed-off-by: Jeff Garzik --- drivers/net/gianfar.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 83a5cb6aa23..c4af949bf86 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1407,6 +1407,10 @@ static int gfar_clean_tx_ring(struct net_device *dev) if (bdp->status & TXBD_DEF) dev->stats.collisions++; + /* Unmap the DMA memory */ + dma_unmap_single(&priv->dev->dev, bdp->bufPtr, + bdp->length, DMA_TO_DEVICE); + /* Free the sk buffer associated with this TxBD */ dev_kfree_skb_irq(priv->tx_skbuff[priv->skb_dirtytx]); @@ -1666,6 +1670,9 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) skb = priv->rx_skbuff[priv->skb_currx]; + dma_unmap_single(&priv->dev->dev, bdp->bufPtr, + priv->rx_buffer_size, DMA_FROM_DEVICE); + /* We drop the frame if we failed to allocate a new buffer */ if (unlikely(!newskb || !(bdp->status & RXBD_LAST) || bdp->status & RXBD_ERR)) { @@ -1674,14 +1681,8 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) if (unlikely(!newskb)) newskb = skb; - if (skb) { - dma_unmap_single(&priv->dev->dev, - bdp->bufPtr, - priv->rx_buffer_size, - DMA_FROM_DEVICE); - + if (skb) dev_kfree_skb_any(skb); - } } else { /* Increment the number of packets */ dev->stats.rx_packets++; -- cgit v1.2.3 From 7ee0fddfe05f105d3346aa8774695e7130697836 Mon Sep 17 00:00:00 2001 From: "J. K. Cliburn" Date: Tue, 11 Nov 2008 16:21:48 -0600 Subject: atl1e: fix broken multicast by removing unnecessary crc inversion Inverting the crc after calling ether_crc_le() is unnecessary and breaks multicast. Remove it. Tested-by: David Madore Signed-off-by: Jay Cliburn Cc: stable@kernel.org Signed-off-by: Jeff Garzik --- drivers/net/atl1e/atl1e_hw.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/atl1e/atl1e_hw.c b/drivers/net/atl1e/atl1e_hw.c index 8cbc1b59bd6..4a770062011 100644 --- a/drivers/net/atl1e/atl1e_hw.c +++ b/drivers/net/atl1e/atl1e_hw.c @@ -163,9 +163,6 @@ int atl1e_read_mac_addr(struct atl1e_hw *hw) * atl1e_hash_mc_addr * purpose * set hash value for a multicast address - * hash calcu processing : - * 1. calcu 32bit CRC for multicast address - * 2. reverse crc with MSB to LSB */ u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr) { @@ -174,7 +171,6 @@ u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr) int i; crc32 = ether_crc_le(6, mc_addr); - crc32 = ~crc32; for (i = 0; i < 32; i++) value |= (((crc32 >> i) & 1) << (31 - i)); -- cgit v1.2.3 From 3b259e365998291a02488225e32b9f2b73723b3e Mon Sep 17 00:00:00 2001 From: "J. K. Cliburn" Date: Sun, 9 Nov 2008 15:05:30 -0600 Subject: atl1: Do not enumerate options unsupported by chip Of the various WOL options provided in include/linux/ethtool.h, the L1 NIC supports only magic packet. Remove all options except magic packet from the atl1 driver. Signed-off-by: Jay Cliburn Signed-off-by: Jeff Garzik --- drivers/net/atlx/atl1.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 246d92b4263..aef403d299e 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -3404,14 +3404,8 @@ static void atl1_get_wol(struct net_device *netdev, { struct atl1_adapter *adapter = netdev_priv(netdev); - wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC; + wol->supported = WAKE_MAGIC; wol->wolopts = 0; - if (adapter->wol & ATLX_WUFC_EX) - wol->wolopts |= WAKE_UCAST; - if (adapter->wol & ATLX_WUFC_MC) - wol->wolopts |= WAKE_MCAST; - if (adapter->wol & ATLX_WUFC_BC) - wol->wolopts |= WAKE_BCAST; if (adapter->wol & ATLX_WUFC_MAG) wol->wolopts |= WAKE_MAGIC; return; @@ -3422,15 +3416,10 @@ static int atl1_set_wol(struct net_device *netdev, { struct atl1_adapter *adapter = netdev_priv(netdev); - if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) + if (wol->wolopts & (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | + WAKE_ARP | WAKE_MAGICSECURE)) return -EOPNOTSUPP; adapter->wol = 0; - if (wol->wolopts & WAKE_UCAST) - adapter->wol |= ATLX_WUFC_EX; - if (wol->wolopts & WAKE_MCAST) - adapter->wol |= ATLX_WUFC_MC; - if (wol->wolopts & WAKE_BCAST) - adapter->wol |= ATLX_WUFC_BC; if (wol->wolopts & WAKE_MAGIC) adapter->wol |= ATLX_WUFC_MAG; return 0; -- cgit v1.2.3 From 3e44017b589f001941723dfdfede2ca6284dddce Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 9 Nov 2008 05:34:47 +0100 Subject: phylib: fix premature freeing of struct mii_bus Commit 46abc02175b3c246dd5141d878f565a8725060c9 ("phylib: give mdio buses a device tree presence") added a call to device_unregister() in a situation where the caller did not intend for the device to be freed yet, but apart from just unregistering the device from the system, device_unregister() does an additional put_device() that is intended to free it. The right function to use in this situation is device_del(), which unregisters the device from the system like device_unregister() does, but without dropping the reference count an additional time. Bug report from Bryan Wu . Signed-off-by: Lennert Buytenhek Tested-by: Bryan Wu Signed-off-by: Jeff Garzik --- drivers/net/phy/mdio_bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index d0ed1ef284a..536bda1f428 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -136,7 +136,7 @@ void mdiobus_unregister(struct mii_bus *bus) BUG_ON(bus->state != MDIOBUS_REGISTERED); bus->state = MDIOBUS_UNREGISTERED; - device_unregister(&bus->dev); + device_del(&bus->dev); for (i = 0; i < PHY_MAX_ADDR; i++) { if (bus->phy_map[i]) device_unregister(&bus->phy_map[i]->dev); -- cgit v1.2.3 From 6a6b97d360702b98c02c7fca4c4e088dcf3a2985 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 13 Nov 2008 10:04:46 +0900 Subject: libata: improve phantom device detection Currently libata uses four methods to detect device presence. 1. PHY status if available. 2. TF register R/W test (only promotes presence, never demotes) 3. device signature after reset 4. IDENTIFY failure detection in SFF state machine Combination of the above works well in most cases but recently there have been a few reports where a phantom device causes unnecessary delay during probe. In both cases, PHY status wasn't available. In one case, it passed #2 and #3 and failed IDENTIFY with ATA_ERR which didn't qualify as #4. The other failed #2 but as it passed #3 and #4, it still caused failure. In both cases, phantom device reported diagnostic failure, so these cases can be safely worked around by considering any !ATA_DRQ IDENTIFY failure as NODEV_HINT if diagnostic failure is set. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-sff.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 4b473948632..9033d164c4e 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -1227,10 +1227,19 @@ fsm_start: /* ATA PIO protocol */ if (unlikely((status & ATA_DRQ) == 0)) { /* handle BSY=0, DRQ=0 as error */ - if (likely(status & (ATA_ERR | ATA_DF))) + if (likely(status & (ATA_ERR | ATA_DF))) { /* device stops HSM for abort/error */ qc->err_mask |= AC_ERR_DEV; - else { + + /* If diagnostic failed and this is + * IDENTIFY, it's likely a phantom + * device. Mark hint. + */ + if (qc->dev->horkage & + ATA_HORKAGE_DIAGNOSTIC) + qc->err_mask |= + AC_ERR_NODEV_HINT; + } else { /* HSM violation. Let EH handle this. * Phantom devices also trigger this * condition. Mark hint. -- cgit v1.2.3 From cecf61bdee426a3e0a014f7e26990d09c71ed458 Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Fri, 14 Nov 2008 16:37:54 -0800 Subject: rtc: rtc-sun4v fixes, revised - simplified code - use platform_driver_probe - removed locking: it's provided by rtc subsystem Signed-off-by: Alessandro Zummo Signed-off-by: David S. Miller --- drivers/rtc/rtc-sun4v.c | 69 ++++++++++++++----------------------------------- 1 file changed, 19 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-sun4v.c b/drivers/rtc/rtc-sun4v.c index 2012ccbb4a5..5b2261052a6 100644 --- a/drivers/rtc/rtc-sun4v.c +++ b/drivers/rtc/rtc-sun4v.c @@ -1,4 +1,4 @@ -/* rtc-sun4c.c: Hypervisor based RTC for SUN4V systems. +/* rtc-sun4v.c: Hypervisor based RTC for SUN4V systems. * * Copyright (C) 2008 David S. Miller */ @@ -7,21 +7,11 @@ #include #include #include -#include #include #include #include -MODULE_AUTHOR("David S. Miller "); -MODULE_DESCRIPTION("SUN4V RTC driver"); -MODULE_LICENSE("GPL"); - -struct sun4v_rtc { - struct rtc_device *rtc; - spinlock_t lock; -}; - static unsigned long hypervisor_get_time(void) { unsigned long ret, time; @@ -45,15 +35,7 @@ retry: static int sun4v_read_time(struct device *dev, struct rtc_time *tm) { - struct sun4v_rtc *p = dev_get_drvdata(dev); - unsigned long flags, secs; - - spin_lock_irqsave(&p->lock, flags); - secs = hypervisor_get_time(); - spin_unlock_irqrestore(&p->lock, flags); - - rtc_time_to_tm(secs, tm); - + rtc_time_to_tm(hypervisor_get_time(), tm); return 0; } @@ -80,19 +62,14 @@ retry: static int sun4v_set_time(struct device *dev, struct rtc_time *tm) { - struct sun4v_rtc *p = dev_get_drvdata(dev); - unsigned long flags, secs; + unsigned long secs; int err; err = rtc_tm_to_time(tm, &secs); if (err) return err; - spin_lock_irqsave(&p->lock, flags); - err = hypervisor_set_time(secs); - spin_unlock_irqrestore(&p->lock, flags); - - return err; + return hypervisor_set_time(secs); } static const struct rtc_class_ops sun4v_rtc_ops = { @@ -100,33 +77,22 @@ static const struct rtc_class_ops sun4v_rtc_ops = { .set_time = sun4v_set_time, }; -static int __devinit sun4v_rtc_probe(struct platform_device *pdev) +static int __init sun4v_rtc_probe(struct platform_device *pdev) { - struct sun4v_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL); - - if (!p) - return -ENOMEM; - - spin_lock_init(&p->lock); - - p->rtc = rtc_device_register("sun4v", &pdev->dev, + struct rtc_device *rtc = rtc_device_register("sun4v", &pdev->dev, &sun4v_rtc_ops, THIS_MODULE); - if (IS_ERR(p->rtc)) { - int err = PTR_ERR(p->rtc); - kfree(p); - return err; - } - platform_set_drvdata(pdev, p); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + platform_set_drvdata(pdev, rtc); return 0; } -static int __devexit sun4v_rtc_remove(struct platform_device *pdev) +static int __exit sun4v_rtc_remove(struct platform_device *pdev) { - struct sun4v_rtc *p = platform_get_drvdata(pdev); - - rtc_device_unregister(p->rtc); - kfree(p); + struct rtc_device *rtc = platform_get_drvdata(pdev); + rtc_device_unregister(rtc); return 0; } @@ -135,13 +101,12 @@ static struct platform_driver sun4v_rtc_driver = { .name = "rtc-sun4v", .owner = THIS_MODULE, }, - .probe = sun4v_rtc_probe, - .remove = __devexit_p(sun4v_rtc_remove), + .remove = __exit_p(sun4v_rtc_remove), }; static int __init sun4v_rtc_init(void) { - return platform_driver_register(&sun4v_rtc_driver); + return platform_driver_probe(&sun4v_rtc_driver, sun4v_rtc_probe); } static void __exit sun4v_rtc_exit(void) @@ -151,3 +116,7 @@ static void __exit sun4v_rtc_exit(void) module_init(sun4v_rtc_init); module_exit(sun4v_rtc_exit); + +MODULE_AUTHOR("David S. Miller "); +MODULE_DESCRIPTION("SUN4V RTC driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From df81d2371aeca0f7474f197a3090830899016e39 Mon Sep 17 00:00:00 2001 From: Miquel van Smoorenburg Date: Wed, 5 Nov 2008 00:09:12 +0100 Subject: [SCSI] dpt_i2o: fix transferred data length for scsi_set_resid() dpt_i2o.c::adpt_i2o_to_scsi() reads the value at (reply+5) which should contain the length in bytes of the transferred data. This would be correct if reply was a u32 *. However it is a void * here, so we need to read the value at (reply+20) instead. The value at (reply+5) is usually 0xff0000, which is apparently 'large enough' and didn't cause any trouble until 2.6.27 where commit 427e59f09fdba387547106de7bab980b7fff77be Author: James Bottomley Date: Sat Mar 8 18:24:17 2008 -0600 [SCSI] make use of the residue value caused this to become visible through e.g. iostat -x . Signed-off-by: Miquel van Smoorenburg Cc: Stable Tree Signed-off-by: James Bottomley --- drivers/scsi/dpt_i2o.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 8aba4fdfb52..6194ed5d02c 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -2445,7 +2445,7 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) hba_status = detailed_status >> 8; // calculate resid for sg - scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+5)); + scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+20)); pHba = (adpt_hba*) cmd->device->host->hostdata[0]; @@ -2456,7 +2456,7 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) case I2O_SCSI_DSC_SUCCESS: cmd->result = (DID_OK << 16); // handle underflow - if(readl(reply+5) < cmd->underflow ) { + if (readl(reply+20) < cmd->underflow) { cmd->result = (DID_ERROR <<16); printk(KERN_WARNING"%s: SCSI CMD underflow\n",pHba->name); } -- cgit v1.2.3 From fb75109834ca5c5e2f0f17f0c9e20182ea55b65f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 14 Nov 2008 08:54:46 +0100 Subject: misc: C2port needs m68k allmodconfig: | drivers/misc/c2port/core.c: In function 'c2port_reset': | drivers/misc/c2port/core.c:73: error: dereferencing pointer to incomplete type | drivers/misc/c2port/core.c: In function 'c2port_strobe_ck': | drivers/misc/c2port/core.c:91: error: dereferencing pointer to incomplete type Include to fix it, as m68k's local_irq_enable() needs to know about struct task_struct. Signed-off-by: Geert Uytterhoeven Signed-off-by: Linus Torvalds --- drivers/misc/c2port/core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c index 976b35d1d03..0207dd59090 100644 --- a/drivers/misc/c2port/core.c +++ b/drivers/misc/c2port/core.c @@ -18,6 +18,7 @@ #include #include #include +#include #include -- cgit v1.2.3 From 0d3b71009737511ea937ac405205fd8214b898bb Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Thu, 13 Nov 2008 20:14:17 +0800 Subject: LIS3LV02Dx: remove unused #include The file(s) below do not use LINUX_VERSION_CODE nor KERNEL_VERSION. drivers/hwmon/lis3lv02d.c This patch removes the said #include . Signed-off-by: Huang Weiyi Signed-off-by: Linus Torvalds --- drivers/hwmon/lis3lv02d.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c index 752b5c44df9..c002144c76b 100644 --- a/drivers/hwmon/lis3lv02d.c +++ b/drivers/hwmon/lis3lv02d.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From d53b93f2603554c3420e301bd13ee2c354a15ceb Mon Sep 17 00:00:00 2001 From: Yevgeny Petrilin Date: Wed, 5 Nov 2008 04:48:36 +0000 Subject: mlx4_en: Pause parameters per port Before the change the driver reported the same pause parameters for all the ports, even only one of them was modified. Signed-off-by: Yevgeny Petrilin Signed-off-by: David S. Miller --- drivers/net/mlx4/en_netdev.c | 8 ++++---- drivers/net/mlx4/en_params.c | 30 ++++++++++++++++-------------- drivers/net/mlx4/mlx4_en.h | 8 ++++---- 3 files changed, 24 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index a3f732418c4..96e709d6440 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c @@ -656,10 +656,10 @@ static int mlx4_en_start_port(struct net_device *dev) /* Configure port */ err = mlx4_SET_PORT_general(mdev->dev, priv->port, priv->rx_skb_size + ETH_FCS_LEN, - mdev->profile.tx_pause, - mdev->profile.tx_ppp, - mdev->profile.rx_pause, - mdev->profile.rx_ppp); + priv->prof->tx_pause, + priv->prof->tx_ppp, + priv->prof->rx_pause, + priv->prof->rx_ppp); if (err) { mlx4_err(mdev, "Failed setting port general configurations" " for port %d, with error %d\n", priv->port, err); diff --git a/drivers/net/mlx4/en_params.c b/drivers/net/mlx4/en_params.c index c2e69b1bcd0..95706ee1c01 100644 --- a/drivers/net/mlx4/en_params.c +++ b/drivers/net/mlx4/en_params.c @@ -90,6 +90,7 @@ MLX4_EN_PARM_INT(rx_ring_size2, MLX4_EN_AUTO_CONF, "Rx ring size for port 2"); int mlx4_en_get_profile(struct mlx4_en_dev *mdev) { struct mlx4_en_profile *params = &mdev->profile; + int i; params->rx_moder_cnt = min_t(int, rx_moder_cnt, MLX4_EN_AUTO_CONF); params->rx_moder_time = min_t(int, rx_moder_time, MLX4_EN_AUTO_CONF); @@ -97,11 +98,13 @@ int mlx4_en_get_profile(struct mlx4_en_dev *mdev) params->rss_xor = (rss_xor != 0); params->rss_mask = rss_mask & 0x1f; params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS); - params->rx_pause = pprx; - params->rx_ppp = pfcrx; - params->tx_pause = pptx; - params->tx_ppp = pfctx; - if (params->rx_ppp || params->tx_ppp) { + for (i = 1; i <= MLX4_MAX_PORTS; i++) { + params->prof[i].rx_pause = pprx; + params->prof[i].rx_ppp = pfcrx; + params->prof[i].tx_pause = pptx; + params->prof[i].tx_ppp = pfctx; + } + if (pfcrx || pfctx) { params->prof[1].tx_ring_num = MLX4_EN_TX_RING_NUM; params->prof[2].tx_ring_num = MLX4_EN_TX_RING_NUM; } else { @@ -407,14 +410,14 @@ static int mlx4_en_set_pauseparam(struct net_device *dev, struct mlx4_en_dev *mdev = priv->mdev; int err; - mdev->profile.tx_pause = pause->tx_pause != 0; - mdev->profile.rx_pause = pause->rx_pause != 0; + priv->prof->tx_pause = pause->tx_pause != 0; + priv->prof->rx_pause = pause->rx_pause != 0; err = mlx4_SET_PORT_general(mdev->dev, priv->port, priv->rx_skb_size + ETH_FCS_LEN, - mdev->profile.tx_pause, - mdev->profile.tx_ppp, - mdev->profile.rx_pause, - mdev->profile.rx_ppp); + priv->prof->tx_pause, + priv->prof->tx_ppp, + priv->prof->rx_pause, + priv->prof->rx_ppp); if (err) mlx4_err(mdev, "Failed setting pause params to\n"); @@ -425,10 +428,9 @@ static void mlx4_en_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *pause) { struct mlx4_en_priv *priv = netdev_priv(dev); - struct mlx4_en_dev *mdev = priv->mdev; - pause->tx_pause = mdev->profile.tx_pause; - pause->rx_pause = mdev->profile.rx_pause; + pause->tx_pause = priv->prof->tx_pause; + pause->rx_pause = priv->prof->rx_pause; } static void mlx4_en_get_ringparam(struct net_device *dev, diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index 11fb17c6e97..98ddc0811f9 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h @@ -322,6 +322,10 @@ struct mlx4_en_port_profile { u32 rx_ring_num; u32 tx_ring_size; u32 rx_ring_size; + u8 rx_pause; + u8 rx_ppp; + u8 tx_pause; + u8 tx_ppp; }; struct mlx4_en_profile { @@ -333,10 +337,6 @@ struct mlx4_en_profile { int rx_moder_cnt; int rx_moder_time; int auto_moder; - u8 rx_pause; - u8 rx_ppp; - u8 tx_pause; - u8 tx_ppp; u8 no_reset; struct mlx4_en_port_profile prof[MLX4_MAX_PORTS + 1]; }; -- cgit v1.2.3 From 605f196efbf8dcbb3581e76ddd0573899dffcf1f Mon Sep 17 00:00:00 2001 From: Ron Madrid Date: Thu, 6 Nov 2008 09:05:26 +0000 Subject: phy: Add support for Marvell 88E1118 PHY This patch will add support for the Marvell 88E1118 PHY which supports gigabit ethernet among other things. Signed-off-by: Ron Madrid Signed-off-by: David S. Miller --- drivers/net/phy/marvell.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'drivers') diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 4aa54794704..eb6411c4694 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -227,6 +227,59 @@ static int m88e1111_config_init(struct phy_device *phydev) return 0; } +static int m88e1118_config_aneg(struct phy_device *phydev) +{ + int err; + + err = phy_write(phydev, MII_BMCR, BMCR_RESET); + if (err < 0) + return err; + + err = phy_write(phydev, MII_M1011_PHY_SCR, + MII_M1011_PHY_SCR_AUTO_CROSS); + if (err < 0) + return err; + + err = genphy_config_aneg(phydev); + return 0; +} + +static int m88e1118_config_init(struct phy_device *phydev) +{ + int err; + + /* Change address */ + err = phy_write(phydev, 0x16, 0x0002); + if (err < 0) + return err; + + /* Enable 1000 Mbit */ + err = phy_write(phydev, 0x15, 0x1070); + if (err < 0) + return err; + + /* Change address */ + err = phy_write(phydev, 0x16, 0x0003); + if (err < 0) + return err; + + /* Adjust LED Control */ + err = phy_write(phydev, 0x10, 0x021e); + if (err < 0) + return err; + + /* Reset address */ + err = phy_write(phydev, 0x16, 0x0); + if (err < 0) + return err; + + err = phy_write(phydev, MII_BMCR, BMCR_RESET); + if (err < 0) + return err; + + return 0; +} + static int m88e1145_config_init(struct phy_device *phydev) { int err; @@ -415,6 +468,19 @@ static struct phy_driver marvell_drivers[] = { .config_intr = &marvell_config_intr, .driver = { .owner = THIS_MODULE }, }, + { + .phy_id = 0x01410e10, + .phy_id_mask = 0xfffffff0, + .name = "Marvell 88E1118", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &m88e1118_config_init, + .config_aneg = &m88e1118_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .driver = {.owner = THIS_MODULE,}, + }, { .phy_id = 0x01410cd0, .phy_id_mask = 0xfffffff0, -- cgit v1.2.3 From 5f5c4bdb144bf285727867bbd75c13c5a99150c9 Mon Sep 17 00:00:00 2001 From: Joey Zhuo Date: Sun, 16 Nov 2008 00:39:35 -0800 Subject: via-velocity: enable perfect filtering for multicast packets Signed-off-by: Joey Zhuo Acked-by: Francois Romieu Signed-off-by: David S. Miller --- drivers/net/via-velocity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 3590ea5a902..11cb3e504e1 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -2296,7 +2296,7 @@ static void velocity_set_multi(struct net_device *dev) } mac_set_cam_mask(regs, vptr->mCAMmask); - rx_mode = (RCR_AM | RCR_AB); + rx_mode = RCR_AM | RCR_AB | RCR_AP; } if (dev->mtu > 1500) rx_mode |= RCR_AL; -- cgit v1.2.3 From 6ff68026f4757d68461b7fbeca5c944e1f5f8b44 Mon Sep 17 00:00:00 2001 From: "\\\"Rafael J. Wysocki\\" Date: Wed, 12 Nov 2008 09:52:32 +0000 Subject: e1000e: Use device_set_wakeup_enable Since dev->power.should_wakeup bit is used by the PCI core to decide whether the device should wake up the system from sleep states, set/unset this bit whenever WOL is enabled/disabled using e1000_set_wol(). Accordingly, use device_can_wakeup() for checking if wake-up is supported by the device. Signed-off-by: "Rafael J. Wysocki" Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/ethtool.c | 8 ++++++-- drivers/net/e1000e/netdev.c | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 70c11c811a0..62421ce9631 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -1713,7 +1713,8 @@ static void e1000_get_wol(struct net_device *netdev, wol->supported = 0; wol->wolopts = 0; - if (!(adapter->flags & FLAG_HAS_WOL)) + if (!(adapter->flags & FLAG_HAS_WOL) || + !device_can_wakeup(&adapter->pdev->dev)) return; wol->supported = WAKE_UCAST | WAKE_MCAST | @@ -1751,7 +1752,8 @@ static int e1000_set_wol(struct net_device *netdev, if (wol->wolopts & WAKE_MAGICSECURE) return -EOPNOTSUPP; - if (!(adapter->flags & FLAG_HAS_WOL)) + if (!(adapter->flags & FLAG_HAS_WOL) || + !device_can_wakeup(&adapter->pdev->dev)) return wol->wolopts ? -EOPNOTSUPP : 0; /* these settings will always override what we currently have */ @@ -1770,6 +1772,8 @@ static int e1000_set_wol(struct net_device *netdev, if (wol->wolopts & WAKE_ARP) adapter->wol |= E1000_WUFC_ARP; + device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); + return 0; } diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index abd492b7336..2c8dffdc889 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -4970,6 +4970,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, /* initialize the wol settings based on the eeprom settings */ adapter->wol = adapter->eeprom_wol; + device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); /* reset the hardware with the new settings */ e1000e_reset(adapter); -- cgit v1.2.3 From de1264896c8012a261c1cba17e6a61199c276ad3 Mon Sep 17 00:00:00 2001 From: "\\\"Rafael J. Wysocki\\" Date: Fri, 7 Nov 2008 20:30:19 +0000 Subject: e1000: Use device_set_wakeup_enable Since dev->power.should_wakeup bit is used by the PCI core to decide whether the device should wake up the system from sleep states, set/unset this bit whenever WOL is enabled/disabled using e1000_set_wol(). Accordingly, use device_can_wakeup() for checking if wake-up is supported by the device. Signed-off-by: "Rafael J. Wysocki" Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_ethtool.c | 8 ++++++-- drivers/net/e1000/e1000_main.c | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 6a3893acfe0..c854c96f5ab 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -1774,7 +1774,8 @@ static void e1000_get_wol(struct net_device *netdev, /* this function will set ->supported = 0 and return 1 if wol is not * supported by this hardware */ - if (e1000_wol_exclusion(adapter, wol)) + if (e1000_wol_exclusion(adapter, wol) || + !device_can_wakeup(&adapter->pdev->dev)) return; /* apply any specific unsupported masks here */ @@ -1811,7 +1812,8 @@ static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) return -EOPNOTSUPP; - if (e1000_wol_exclusion(adapter, wol)) + if (e1000_wol_exclusion(adapter, wol) || + !device_can_wakeup(&adapter->pdev->dev)) return wol->wolopts ? -EOPNOTSUPP : 0; switch (hw->device_id) { @@ -1838,6 +1840,8 @@ static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) if (wol->wolopts & WAKE_MAGIC) adapter->wol |= E1000_WUFC_MAG; + device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); + return 0; } diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index fac82152e4c..872799b746f 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1179,6 +1179,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, /* initialize the wol settings based on the eeprom settings */ adapter->wol = adapter->eeprom_wol; + device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); /* print bus type/speed/width info */ DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ", -- cgit v1.2.3 From e1b86d8479f90aadee57a3d07d8e61c815c202d9 Mon Sep 17 00:00:00 2001 From: "\\\"Rafael J. Wysocki\\" Date: Fri, 7 Nov 2008 20:30:37 +0000 Subject: igb: Use device_set_wakeup_enable Since dev->power.should_wakeup bit is used by the PCI core to decide whether the device should wake up the system from sleep states, set/unset this bit whenever WOL is enabled/disabled using igb_set_wol(). Accordingly, use device_can_wakeup() for checking if wake-up is supported by the device. Signed-off-by: "Rafael J. Wysocki" Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_ethtool.c | 8 ++++++-- drivers/net/igb/igb_main.c | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 58906c984be..89964fa739a 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1776,7 +1776,8 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) /* this function will set ->supported = 0 and return 1 if wol is not * supported by this hardware */ - if (igb_wol_exclusion(adapter, wol)) + if (igb_wol_exclusion(adapter, wol) || + !device_can_wakeup(&adapter->pdev->dev)) return; /* apply any specific unsupported masks here */ @@ -1805,7 +1806,8 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) return -EOPNOTSUPP; - if (igb_wol_exclusion(adapter, wol)) + if (igb_wol_exclusion(adapter, wol) || + !device_can_wakeup(&adapter->pdev->dev)) return wol->wolopts ? -EOPNOTSUPP : 0; switch (hw->device_id) { @@ -1825,6 +1827,8 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) if (wol->wolopts & WAKE_MAGIC) adapter->wol |= E1000_WUFC_MAG; + device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); + return 0; } diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 1f397cd9941..0a9801516ae 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1244,6 +1244,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, /* initialize the wol settings based on the eeprom settings */ adapter->wol = adapter->eeprom_wol; + device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); /* reset the hardware with the new settings */ igb_reset(adapter); -- cgit v1.2.3 From 0f807044980dd51fdf9aa2df8d503d4757501b20 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Tue, 11 Nov 2008 07:54:54 +0000 Subject: qla3xxx: Cleanup: Fix link print statements. Removed debug print statements and improved conditionals around informational statements. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qla3xxx.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 3cdd07c45b6..508452c0215 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -1515,9 +1515,6 @@ static u32 ql_get_link_state(struct ql3_adapter *qdev) linkState = LS_UP; } else { linkState = LS_DOWN; - if (netif_msg_link(qdev)) - printk(KERN_WARNING PFX - "%s: Link is down.\n", qdev->ndev->name); } return linkState; } @@ -1581,10 +1578,6 @@ static int ql_finish_auto_neg(struct ql3_adapter *qdev) ql_mac_enable(qdev, 1); } - if (netif_msg_link(qdev)) - printk(KERN_DEBUG PFX - "%s: Change port_link_state LS_DOWN to LS_UP.\n", - qdev->ndev->name); qdev->port_link_state = LS_UP; netif_start_queue(qdev->ndev); netif_carrier_on(qdev->ndev); @@ -1655,14 +1648,9 @@ static void ql_link_state_machine_work(struct work_struct *work) /* Fall Through */ case LS_DOWN: - if (netif_msg_link(qdev)) - printk(KERN_DEBUG PFX - "%s: port_link_state = LS_DOWN.\n", - qdev->ndev->name); if (curr_link_state == LS_UP) { if (netif_msg_link(qdev)) - printk(KERN_DEBUG PFX - "%s: curr_link_state = LS_UP.\n", + printk(KERN_INFO PFX "%s: Link is up.\n", qdev->ndev->name); if (ql_is_auto_neg_complete(qdev)) ql_finish_auto_neg(qdev); @@ -1670,6 +1658,7 @@ static void ql_link_state_machine_work(struct work_struct *work) if (qdev->port_link_state == LS_UP) ql_link_down_detect_clear(qdev); + qdev->port_link_state = LS_UP; } break; @@ -1678,12 +1667,14 @@ static void ql_link_state_machine_work(struct work_struct *work) * See if the link is currently down or went down and came * back up */ - if ((curr_link_state == LS_DOWN) || ql_link_down_detect(qdev)) { + if (curr_link_state == LS_DOWN) { if (netif_msg_link(qdev)) printk(KERN_INFO PFX "%s: Link is down.\n", qdev->ndev->name); qdev->port_link_state = LS_DOWN; } + if (ql_link_down_detect(qdev)) + qdev->port_link_state = LS_DOWN; break; } spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); -- cgit v1.2.3 From ac450208dea8cf1b9aa8feabd06a7209a282d749 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 13 Nov 2008 06:20:10 +0000 Subject: igb: use dev_printk instead of printk Use dev_printk() instead of printk() to give a little more context and use consistent format. Signed-off-by: Bjorn Helgaas Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 0a9801516ae..1cbae85b142 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1019,10 +1019,9 @@ static int __devinit igb_probe(struct pci_dev *pdev, state &= ~PCIE_LINK_STATE_L0S; pci_write_config_word(us_dev, pos + PCI_EXP_LNKCTL, state); - printk(KERN_INFO "Disabling ASPM L0s upstream switch " - "port %x:%x.%x\n", us_dev->bus->number, - PCI_SLOT(us_dev->devfn), - PCI_FUNC(us_dev->devfn)); + dev_info(&pdev->dev, + "Disabling ASPM L0s upstream switch port %s\n", + pci_name(us_dev)); } default: break; -- cgit v1.2.3 From 773c9c1f77174429ad2feb1735a3beb33ff3b6c0 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 14 Nov 2008 13:51:54 +0000 Subject: e100: fix dma error in direction for mapping The e100 driver triggers BUG_ON(buf->direction != dir) by doing pci_map_single(..., PCI_DMA_BIDIRECTIONAL) and pci_dma_sync_single_for_device(..., PCI_DMA_TODEVICE). Changing the DMA direction, especially with dmabounce will result in unexpected behaviour. Reported-by: Anders Grafstrom Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e100.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 3d69fae781c..e8bfcce6b31 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -166,7 +166,7 @@ #define DRV_NAME "e100" #define DRV_EXT "-NAPI" -#define DRV_VERSION "3.5.23-k4"DRV_EXT +#define DRV_VERSION "3.5.23-k6"DRV_EXT #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" #define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" #define PFX DRV_NAME ": " @@ -1804,7 +1804,7 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; put_unaligned_le32(rx->dma_addr, &prev_rfd->link); pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); + sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); } return 0; @@ -1823,7 +1823,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, /* Need to sync before taking a peek at cb_complete bit */ pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_FROMDEVICE); + sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); rfd_status = le16_to_cpu(rfd->status); DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); @@ -1850,7 +1850,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, /* Get data */ pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); + RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); /* If this buffer has the el bit, but we think the receiver * is still running, check to see if it really stopped while @@ -1943,7 +1943,7 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done, new_before_last_rfd->command |= cpu_to_le16(cb_el); pci_dma_sync_single_for_device(nic->pdev, new_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_TODEVICE); + PCI_DMA_BIDIRECTIONAL); /* Now that we have a new stopping point, we can clear the old * stopping point. We must sync twice to get the proper @@ -1951,11 +1951,11 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done, old_before_last_rfd->command &= ~cpu_to_le16(cb_el); pci_dma_sync_single_for_device(nic->pdev, old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_TODEVICE); + PCI_DMA_BIDIRECTIONAL); old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); pci_dma_sync_single_for_device(nic->pdev, old_before_last_rx->dma_addr, sizeof(struct rfd), - PCI_DMA_TODEVICE); + PCI_DMA_BIDIRECTIONAL); } if(restart_required) { @@ -1978,7 +1978,7 @@ static void e100_rx_clean_list(struct nic *nic) for(rx = nic->rxs, i = 0; i < count; rx++, i++) { if(rx->skb) { pci_unmap_single(nic->pdev, rx->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); + RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); dev_kfree_skb(rx->skb); } } @@ -2021,7 +2021,7 @@ static int e100_rx_alloc_list(struct nic *nic) before_last->command |= cpu_to_le16(cb_el); before_last->size = 0; pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, - sizeof(struct rfd), PCI_DMA_TODEVICE); + sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); nic->rx_to_use = nic->rx_to_clean = nic->rxs; nic->ru_running = RU_SUSPENDED; @@ -2222,7 +2222,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) msleep(10); pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, - RFD_BUF_LEN, PCI_DMA_FROMDEVICE); + RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), skb->data, ETH_DATA_LEN)) -- cgit v1.2.3 From 3ee82383f0098a2e13acc8cf1be8e47512f41e5a Mon Sep 17 00:00:00 2001 From: Giulio Benetti Date: Thu, 13 Nov 2008 21:53:13 +0000 Subject: phy: fix phy address bug PHYID returns 0xffff and not 0xffffffff when not found and in some case(at91sam9263) 0x0. Maybe this patch could be useful. Signed-off-by: Giulio Benetti Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index e11b03b2b25..8fb1faca883 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -227,8 +227,8 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr) if (r) return ERR_PTR(r); - /* If the phy_id is all Fs, there is no device there */ - if (0xffffffff == phy_id) + /* If the phy_id is all Fs or all 0s, there is no device there */ + if ((0xffff == phy_id) || (0x00 == phy_id)) return NULL; dev = phy_device_create(bus, addr, phy_id); -- cgit v1.2.3 From 2a3a59e5c977654d3aad5bc11cc0aca2303a7f44 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 11 Nov 2008 13:42:35 -0600 Subject: [SCSI] Fix hang in starved list processing Close possible infinite loop with interrupts off when devices are added back to the starved list. Fixes: http://bugzilla.kernel.org/show_bug.cgi?id=11898 Reported-by: Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index f5d3b96890d..fa45a1a6686 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -567,15 +567,18 @@ static inline int scsi_host_is_busy(struct Scsi_Host *shost) */ static void scsi_run_queue(struct request_queue *q) { - struct scsi_device *starved_head = NULL, *sdev = q->queuedata; + struct scsi_device *sdev = q->queuedata; struct Scsi_Host *shost = sdev->host; + LIST_HEAD(starved_list); unsigned long flags; if (scsi_target(sdev)->single_lun) scsi_single_lun_run(sdev); spin_lock_irqsave(shost->host_lock, flags); - while (!list_empty(&shost->starved_list) && !scsi_host_is_busy(shost)) { + list_splice_init(&shost->starved_list, &starved_list); + + while (!list_empty(&starved_list)) { int flagset; /* @@ -588,24 +591,18 @@ static void scsi_run_queue(struct request_queue *q) * scsi_request_fn must get the host_lock before checking * or modifying starved_list or starved_entry. */ - sdev = list_entry(shost->starved_list.next, - struct scsi_device, starved_entry); - /* - * The *queue_ready functions can add a device back onto the - * starved list's tail, so we must check for a infinite loop. - */ - if (sdev == starved_head) + if (scsi_host_is_busy(shost)) break; - if (!starved_head) - starved_head = sdev; + sdev = list_entry(starved_list.next, + struct scsi_device, starved_entry); + list_del_init(&sdev->starved_entry); if (scsi_target_is_busy(scsi_target(sdev))) { list_move_tail(&sdev->starved_entry, &shost->starved_list); continue; } - list_del_init(&sdev->starved_entry); spin_unlock(shost->host_lock); spin_lock(sdev->request_queue->queue_lock); @@ -621,6 +618,8 @@ static void scsi_run_queue(struct request_queue *q) spin_lock(shost->host_lock); } + /* put any unprocessed entries back */ + list_splice(&starved_list, &shost->starved_list); spin_unlock_irqrestore(shost->host_lock, flags); blk_run_queue(q); -- cgit v1.2.3 From 77fb61a04a0483ad274ce5c51b02c46c12db3693 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 16 Nov 2008 10:09:34 -0800 Subject: acpi: fix oops in acpi_system_wakeup_device_seq_show MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 0794469da3f7b2093575cbdfc1108308dd3641ce: ("ACPI: struct device - replace bus_id with dev_name(), dev_set_name()") introduced a bug by testing 'dev_name(ldev)' instead of 'ldev->bus' for NULL when printing out the bus information. So if ldev->bus was NULL, we'd oops. Reported-and-tested-by: Bruno Prémont Cc: Kay Sievers Cc: Len Brown Cc: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/acpi/sleep/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 64e591ba86f..4dbc2271acf 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c @@ -366,7 +366,7 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) dev->wakeup.state.enabled ? "enabled" : "disabled"); if (ldev) seq_printf(seq, "%s:%s", - dev_name(ldev) ? ldev->bus->name : "no-bus", + ldev->bus ? ldev->bus->name : "no-bus", dev_name(ldev)); seq_printf(seq, "\n"); put_device(ldev); -- cgit v1.2.3 From b1ccbdc4a2af5ffcd6082c3a7a6fbd0e134031f2 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sat, 8 Nov 2008 01:28:19 +0100 Subject: mfd: fix event masking for da9030 Signed-off-by: Mike Rapoport Acked-by: Eric Miao Signed-off-by: Samuel Ortiz --- drivers/mfd/da903x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c index b57326ae464..0b5bd85dfce 100644 --- a/drivers/mfd/da903x.c +++ b/drivers/mfd/da903x.c @@ -267,7 +267,7 @@ static int da9030_mask_events(struct da903x_chip *chip, unsigned int events) { uint8_t v[3]; - chip->events_mask &= ~events; + chip->events_mask |= events; v[0] = (chip->events_mask & 0xff); v[1] = (chip->events_mask >> 8) & 0xff; -- cgit v1.2.3 From 898d8054ec0cb5ba0ec1b15c78042a23ed103c02 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Wed, 12 Nov 2008 17:34:02 +0100 Subject: mfd: Correct WM8350 I2C return code usage The vendor BSP used for the WM8350 development provided an I2C driver which incorrectly returned zero on succesful sends rather than the number of transmitted bytes, an error which was then propagated into the WM8350 I2C accessors. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/mfd/wm8350-i2c.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c index 8dfe21bb3bd..3e0ce0e50ea 100644 --- a/drivers/mfd/wm8350-i2c.c +++ b/drivers/mfd/wm8350-i2c.c @@ -30,7 +30,12 @@ static int wm8350_i2c_read_device(struct wm8350 *wm8350, char reg, ret = i2c_master_send(wm8350->i2c_client, ®, 1); if (ret < 0) return ret; - return i2c_master_recv(wm8350->i2c_client, dest, bytes); + ret = i2c_master_recv(wm8350->i2c_client, dest, bytes); + if (ret < 0) + return ret; + if (ret != bytes) + return -EIO; + return 0; } static int wm8350_i2c_write_device(struct wm8350 *wm8350, char reg, @@ -38,13 +43,19 @@ static int wm8350_i2c_write_device(struct wm8350 *wm8350, char reg, { /* we add 1 byte for device register */ u8 msg[(WM8350_MAX_REGISTER << 1) + 1]; + int ret; if (bytes > ((WM8350_MAX_REGISTER << 1) + 1)) return -EINVAL; msg[0] = reg; memcpy(&msg[1], src, bytes); - return i2c_master_send(wm8350->i2c_client, msg, bytes + 1); + ret = i2c_master_send(wm8350->i2c_client, msg, bytes + 1); + if (ret < 0) + return ret; + if (ret != bytes + 1) + return -EIO; + return 0; } static int wm8350_i2c_probe(struct i2c_client *i2c, -- cgit v1.2.3 From 5181e594512faeac7d7fd9620ce91105f45bf643 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Mon, 17 Nov 2008 01:44:38 +0100 Subject: HID: fix blacklist entries for greenasia/pantherlord Fix misplaced quirk entries for devices driven by hid-pl driver. The devices shouls be only blacklisted by generic HID driver, not completely ignored. Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 147ec591a80..69b1ce800f7 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1266,6 +1266,8 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) }, { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, @@ -1420,7 +1422,6 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) }, { HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) }, { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) }, @@ -1436,7 +1437,6 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2) }, { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, { HID_USB_DEVICE(USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY) }, { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE) }, { HID_USB_DEVICE(USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB) }, -- cgit v1.2.3 From d7c31a1e754b5140eefeeb10c3c3be17f3702452 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Tue, 11 Nov 2008 23:27:59 -0300 Subject: V4L/DVB (9601): ttusb_dec: Add NULL pointer validation Added validation for NULL pointer Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index ab33fec8a19..c1386e9b13d 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -1157,6 +1157,12 @@ static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec) ISO_BUF_COUNT), &dec->iso_dma_handle); + if (!dec->iso_buffer) { + dprintk("%s: pci_alloc_consistent - not enough memory\n", + __func__); + return -ENOMEM; + } + memset(dec->iso_buffer, 0, ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT)); -- cgit v1.2.3 From 11eb260a70b992b83fa2d15bb777cda3ee326c05 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Tue, 11 Nov 2008 23:30:49 -0300 Subject: V4L/DVB (9602): dvb-ttusb-budget: Add NULL pointer validation Added validation for NULL pointer Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 66ab0c6e978..5faeee3f70b 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -808,6 +808,12 @@ static int ttusb_alloc_iso_urbs(struct ttusb *ttusb) ISO_BUF_COUNT, &ttusb->iso_dma_handle); + if (!ttusb->iso_buffer) { + dprintk("%s: pci_alloc_consistent - not enough memory\n", + __func__); + return -ENOMEM; + } + memset(ttusb->iso_buffer, 0, ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT); -- cgit v1.2.3 From b7ed785b5f6a8dbdbd0cf8688a51c42e35205a4e Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Tue, 11 Nov 2008 23:37:39 -0300 Subject: V4L/DVB (9603): dvb-ttusb-budget: Add validation for ttusb_alloc_iso_urbs Added validation for ttusb_alloc_iso_urbs Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 5faeee3f70b..4a3f2b8ea37 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -1665,7 +1665,14 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i ttusb_setup_interfaces(ttusb); - ttusb_alloc_iso_urbs(ttusb); + result = ttusb_alloc_iso_urbs(ttusb); + if (result < 0) { + dprintk("%s: ttusb_alloc_iso_urbs - failed\n", __func__); + mutex_unlock(&ttusb->semi2c); + kfree(ttusb); + return result; + } + if (ttusb_init_controller(ttusb)) printk("ttusb_init_controller: error\n"); -- cgit v1.2.3 From 7935eeae793ff24e2d6053a9df63be71323ad634 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Tue, 11 Nov 2008 23:47:57 -0300 Subject: V4L/DVB (9604): ttusb_dec: fix memory leak Free allocated memory Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index c1386e9b13d..0aa96df80fc 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -1260,6 +1260,7 @@ static int ttusb_dec_init_usb(struct ttusb_dec *dec) dec->irq_buffer = usb_buffer_alloc(dec->udev,IRQ_PACKET_SIZE, GFP_ATOMIC, &dec->irq_dma_handle); if(!dec->irq_buffer) { + usb_free_urb(dec->irq_urb); return -ENOMEM; } usb_fill_int_urb(dec->irq_urb, dec->udev,dec->irq_pipe, -- cgit v1.2.3 From 4faf1004c32819035c5325879a466f27e189feb5 Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Tue, 11 Nov 2008 23:56:56 -0300 Subject: V4L/DVB (9605): usb-urb: fix memory leak Free allocated memory Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/usb-urb.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/usb-urb.c b/drivers/media/dvb/dvb-usb/usb-urb.c index 397f51a7b2a..da93b9e982c 100644 --- a/drivers/media/dvb/dvb-usb/usb-urb.c +++ b/drivers/media/dvb/dvb-usb/usb-urb.c @@ -135,7 +135,7 @@ stream->buf_list[stream->buf_num], (long long)stream->dma_addr[stream->buf_num]) static int usb_bulk_urb_init(struct usb_data_stream *stream) { - int i; + int i, j; if ((i = usb_allocate_stream_buffers(stream,stream->props.count, stream->props.u.bulk.buffersize)) < 0) @@ -143,9 +143,13 @@ static int usb_bulk_urb_init(struct usb_data_stream *stream) /* allocate the URBs */ for (i = 0; i < stream->props.count; i++) { - if ((stream->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC)) == NULL) + stream->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC); + if (!stream->urb_list[i]) { + deb_mem("not enough memory for urb_alloc_urb!.\n"); + for (j = 0; j < i; j++) + usb_free_urb(stream->urb_list[i]); return -ENOMEM; - + } usb_fill_bulk_urb( stream->urb_list[i], stream->udev, usb_rcvbulkpipe(stream->udev,stream->props.endpoint), stream->buf_list[i], @@ -170,9 +174,14 @@ static int usb_isoc_urb_init(struct usb_data_stream *stream) for (i = 0; i < stream->props.count; i++) { struct urb *urb; int frame_offset = 0; - if ((stream->urb_list[i] = - usb_alloc_urb(stream->props.u.isoc.framesperurb,GFP_ATOMIC)) == NULL) + + stream->urb_list[i] = usb_alloc_urb(stream->props.u.isoc.framesperurb, GFP_ATOMIC); + if (!stream->urb_list[i]) { + deb_mem("not enough memory for urb_alloc_urb!\n"); + for (j = 0; j < i; j++) + usb_free_urb(stream->urb_list[i]); return -ENOMEM; + } urb = stream->urb_list[i]; -- cgit v1.2.3 From df4533af7f45e87a4be470502fa3cea2f6c96da9 Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Tue, 11 Nov 2008 18:09:28 -0300 Subject: V4L/DVB (9608): Fix section mismatch warning for dm1105 during make -- Signed-off-by: Igor M. Liplianin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dm1105/dm1105.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 14e627ef646..c1d92f838ca 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c @@ -376,7 +376,7 @@ static void dm1105dvb_dma_unmap(struct dm1105dvb *dm1105dvb) pci_free_consistent(dm1105dvb->pdev, 6*DM1105_DMA_BYTES, dm1105dvb->ts_buf, dm1105dvb->dma_addr); } -static void __devinit dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb) +static void dm1105dvb_enable_irqs(struct dm1105dvb *dm1105dvb) { outb(INTMAK_ALLMASK, dm_io_mem(DM1105_INTMAK)); outb(1, dm_io_mem(DM1105_CR)); -- cgit v1.2.3 From c41109fc9a13c6af0e4069dd92fdb4c5c8046649 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 15 Nov 2008 23:44:14 -0300 Subject: V4L/DVB (9627): em28xx: Avoid i2c register error for boards without eeprom Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-i2c.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index 3bab56b997f..2360c61ddca 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -337,9 +337,9 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) /* Check if board has eeprom */ err = i2c_master_recv(&dev->i2c_client, &buf, 0); if (err < 0) { - em28xx_errdev("%s: i2c_master_recv failed! err [%d]\n", - __func__, err); - return err; + em28xx_errdev("board has no eeprom\n"); + memset(eedata, 0, len); + return -ENODEV; } buf = 0; @@ -609,14 +609,16 @@ int em28xx_i2c_register(struct em28xx *dev) dev->i2c_client.adapter = &dev->i2c_adap; retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); - if (retval < 0) { + if ((retval < 0) && (retval != -ENODEV)) { em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", __func__, retval); + return retval; } if (i2c_scan) em28xx_do_i2c_scan(dev); + return 0; } -- cgit v1.2.3 From 3fa37deb1a287e100c7db5b4f964784fd664bee9 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 16 Nov 2008 00:33:32 -0300 Subject: V4L/DVB (9631): Make s2api work for ATSC support ATSC should be considered a legacy delivery system, or else fields such as p->u.vsb.modulation do not get populated (resulting in set_frontend failures) Cc: Steven Toth Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 8557bf12cfb..b38cebe3ac1 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -934,7 +934,8 @@ void dtv_property_dump(struct dtv_property *tvp) int is_legacy_delivery_system(fe_delivery_system_t s) { if((s == SYS_UNDEFINED) || (s == SYS_DVBC_ANNEX_AC) || - (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS)) + (s == SYS_DVBC_ANNEX_B) || (s == SYS_DVBT) || (s == SYS_DVBS) || + (s == SYS_ATSC)) return 1; return 0; -- cgit v1.2.3 From 3f9b46c154da5ec4facca88f82d1820eb329fd3e Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sat, 15 Nov 2008 17:16:11 -0300 Subject: V4L/DVB (9632): make em28xx aux audio input work The attached patch makes the em28xx auxillary audio input work. Tested with the HVR-950. em28xx: make auxillary audio input work The tuner audio input was working but the aux input wasn't. Tested with the HVR-950. Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 5d837c16ee2..038da614a73 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -270,6 +270,8 @@ static int em28xx_set_audio_source(struct em28xx *dev) break; case EM28XX_AMUX_LINE_IN: input = EM28XX_AUDIO_SRC_LINE; + video = disable; + line = enable; break; case EM28XX_AMUX_AC97_VIDEO: input = EM28XX_AUDIO_SRC_LINE; -- cgit v1.2.3 From 41286d972530b7a47acb48376d714b6b121a6c22 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sun, 16 Nov 2008 00:44:52 -0300 Subject: V4L/DVB (9634): Make sure the i2c gate is open before powering down tuner It is not safe to assume that the i2c gate will be open before issuing the command to power down the tuner. In fact, many demods only open the gate long enough to issue the tuning command. This fix allows power management to work properly for those tuners behind an i2c gate (in my case the problem was with the HVR-950Q) Signed-off-by: Devin Heitmueller Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index b38cebe3ac1..7a421e9dba5 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -585,6 +585,8 @@ restart: if (fe->ops.set_voltage) fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF); if (fe->ops.tuner_ops.sleep) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); fe->ops.tuner_ops.sleep(fe); if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); -- cgit v1.2.3 From deaf53e3c8e717169669ee6c2594b5c33d1af93b Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Sat, 15 Nov 2008 01:10:14 -0300 Subject: V4L/DVB (9635): v4l: s2255drv fix firmware test on big-endian Noticed by sparse: drivers/media/video/s2255drv.c:2531:6: warning: restricted __le32 degrades to integer Cc: Dean Anderson Signed-off-by: Harvey Harrison Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s2255drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c index 5272926db73..3c3f8cf7310 100644 --- a/drivers/media/video/s2255drv.c +++ b/drivers/media/video/s2255drv.c @@ -192,7 +192,7 @@ struct s2255_dmaqueue { #define S2255_FW_FAILED 3 #define S2255_FW_DISCONNECTING 4 -#define S2255_FW_MARKER 0x22552f2f +#define S2255_FW_MARKER cpu_to_le32(0x22552f2f) /* 2255 read states */ #define S2255_READ_IDLE 0 #define S2255_READ_FRAME 1 -- cgit v1.2.3 From 99afb989b05b9fb1c7b3831ce4b7a000b214acdb Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Sat, 15 Nov 2008 07:13:07 -0300 Subject: V4L/DVB (9639): Make dib0700 remote control support work with firmware v1.20 The format for reading the IR controller changed in firmware 1.20. It now provides the events on bulk endpoint 1 instead of using a control request. Support the new format, providing backward compatibility for users who might be using older firmware. Thanks to Patrick Boettcher for providing the required information on how the version 1.20 firmware works. Signed-off-by: Devin Heitmueller Signed-off-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/dib0700.h | 5 +- drivers/media/dvb/dvb-usb/dib0700_core.c | 16 ++++ drivers/media/dvb/dvb-usb/dib0700_devices.c | 139 +++++++++++++++++++++++++++- 3 files changed, 158 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h index 739193943c1..8b544fe79b0 100644 --- a/drivers/media/dvb/dvb-usb/dib0700.h +++ b/drivers/media/dvb/dvb-usb/dib0700.h @@ -22,7 +22,7 @@ extern int dvb_usb_dib0700_debug; #define REQUEST_I2C_READ 0x2 #define REQUEST_I2C_WRITE 0x3 -#define REQUEST_POLL_RC 0x4 +#define REQUEST_POLL_RC 0x4 /* deprecated in firmware v1.20 */ #define REQUEST_JUMPRAM 0x8 #define REQUEST_SET_CLOCK 0xB #define REQUEST_SET_GPIO 0xC @@ -40,11 +40,14 @@ struct dib0700_state { u16 mt2060_if1[2]; u8 rc_toggle; u8 rc_counter; + u8 rc_func_version; u8 is_dib7000pc; u8 fw_use_new_i2c_api; u8 disable_streaming_master_mode; }; +extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, + u32 *romversion, u32 *ramversion, u32 *fwtype); extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val); extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3); extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen); diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c index dd53cee3896..200b215f4d8 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_core.c +++ b/drivers/media/dvb/dvb-usb/dib0700_core.c @@ -19,6 +19,22 @@ MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (defau DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + +int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion, + u32 *romversion, u32 *ramversion, u32 *fwtype) +{ + u8 b[16]; + int ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), + REQUEST_GET_VERSION, + USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, + b, sizeof(b), USB_CTRL_GET_TIMEOUT); + *hwversion = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; + *romversion = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | b[7]; + *ramversion = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11]; + *fwtype = (b[12] << 24) | (b[13] << 16) | (b[14] << 8) | b[15]; + return ret; +} + /* expecting rx buffer: request data[0] data[1] ... data[2] */ static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen) { diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index 0cfccc24b19..f28d3ae59e0 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c @@ -38,6 +38,7 @@ static struct mt2060_config bristol_mt2060_config[2] = { } }; + static struct dibx000_agc_config bristol_dib3000p_mt2060_agc_config = { .band_caps = BAND_VHF | BAND_UHF, .setup = (1 << 8) | (5 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (2 << 0), @@ -451,8 +452,13 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; /* Number of keypresses to ignore before start repeating */ #define RC_REPEAT_DELAY 2 +#define RC_REPEAT_DELAY_V1_20 5 -static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) + + +/* Used by firmware versions < 1.20 (deprecated) */ +static int dib0700_rc_query_legacy(struct dvb_usb_device *d, u32 *event, + int *state) { u8 key[4]; int i; @@ -529,6 +535,137 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) return 0; } +/* This is the structure of the RC response packet starting in firmware 1.20 */ +struct dib0700_rc_response { + u8 report_id; + u8 data_state; + u8 system_msb; + u8 system_lsb; + u8 data; + u8 not_data; +}; + +/* This supports the new IR response format for firmware v1.20 */ +static int dib0700_rc_query_v1_20(struct dvb_usb_device *d, u32 *event, + int *state) +{ + struct dvb_usb_rc_key *keymap = d->props.rc_key_map; + struct dib0700_state *st = d->priv; + struct dib0700_rc_response poll_reply; + u8 buf[6]; + int i; + int status; + int actlen; + int found = 0; + + /* Set initial results in case we exit the function early */ + *event = 0; + *state = REMOTE_NO_KEY_PRESSED; + + /* Firmware v1.20 provides RC data via bulk endpoint 1 */ + status = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev, 1), buf, + sizeof(buf), &actlen, 50); + if (status < 0) { + /* No data available (meaning no key press) */ + return 0; + } + + if (actlen != sizeof(buf)) { + /* We didn't get back the 6 byte message we expected */ + err("Unexpected RC response size [%d]", actlen); + return -1; + } + + poll_reply.report_id = buf[0]; + poll_reply.data_state = buf[1]; + poll_reply.system_msb = buf[2]; + poll_reply.system_lsb = buf[3]; + poll_reply.data = buf[4]; + poll_reply.not_data = buf[5]; + + /* + info("rid=%02x ds=%02x sm=%02x sl=%02x d=%02x nd=%02x\n", + poll_reply.report_id, poll_reply.data_state, + poll_reply.system_msb, poll_reply.system_lsb, + poll_reply.data, poll_reply.not_data); + */ + + if ((poll_reply.data + poll_reply.not_data) != 0xff) { + /* Key failed integrity check */ + err("key failed integrity check: %02x %02x %02x %02x", + poll_reply.system_msb, poll_reply.system_lsb, + poll_reply.data, poll_reply.not_data); + return -1; + } + + /* Find the key in the map */ + for (i = 0; i < d->props.rc_key_map_size; i++) { + if (keymap[i].custom == poll_reply.system_lsb && + keymap[i].data == poll_reply.data) { + *event = keymap[i].event; + found = 1; + break; + } + } + + if (found == 0) { + err("Unknown remote controller key: %02x %02x %02x %02x", + poll_reply.system_msb, poll_reply.system_lsb, + poll_reply.data, poll_reply.not_data); + d->last_event = 0; + return 0; + } + + if (poll_reply.data_state == 1) { + /* New key hit */ + st->rc_counter = 0; + *event = keymap[i].event; + *state = REMOTE_KEY_PRESSED; + d->last_event = keymap[i].event; + } else if (poll_reply.data_state == 2) { + /* Key repeated */ + st->rc_counter++; + + /* prevents unwanted double hits */ + if (st->rc_counter > RC_REPEAT_DELAY_V1_20) { + *event = d->last_event; + *state = REMOTE_KEY_PRESSED; + st->rc_counter = RC_REPEAT_DELAY_V1_20; + } + } else { + err("Unknown data state [%d]", poll_reply.data_state); + } + + return 0; +} + +static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +{ + struct dib0700_state *st = d->priv; + + /* Because some people may have improperly named firmware files, + let's figure out whether to use the new firmware call or the legacy + call based on the firmware version embedded in the file */ + if (st->rc_func_version == 0) { + u32 hwver, romver, ramver, fwtype; + int ret = dib0700_get_version(d, &hwver, &romver, &ramver, + &fwtype); + if (ret < 0) { + err("Could not determine version info"); + return -1; + } + if (ramver < 0x10200) + st->rc_func_version = 1; + else + st->rc_func_version = 2; + } + + if (st->rc_func_version == 2) + return dib0700_rc_query_v1_20(d, event, state); + else + return dib0700_rc_query_legacy(d, event, state); +} + static struct dvb_usb_rc_key dib0700_rc_keys[] = { /* Key codes for the tiny Pinnacle remote*/ { 0x07, 0x00, KEY_MUTE }, -- cgit v1.2.3 From e82f54ba030b429c06b5240cbe7eeaaa03a8db11 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Fri, 14 Nov 2008 06:45:07 +0000 Subject: e1000e: fix warn_on reload after phy_id error If the driver fails to initialize the first time due to the failure in the phy_id check the kernel triggers a warn_on on the second try to load the driver because the driver did not free the msi/x resources in the first load because of the previous failure in phy_id check. Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/netdev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 2c8dffdc889..f6ebebb8cfa 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -5009,6 +5009,7 @@ err_hw_init: err_sw_init: if (adapter->hw.flash_address) iounmap(adapter->hw.flash_address); + e1000e_reset_interrupt_capability(adapter); err_flashmap: iounmap(adapter->hw.hw_addr); err_ioremap: -- cgit v1.2.3 From eb7c3adb1ca92450870dbb0d347fc986cd5e2af4 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Fri, 14 Nov 2008 06:45:23 +0000 Subject: e1000e: fix IPMI traffic Some users reported that they have machines with BMCs enabled that cannot receive IPMI traffic after e1000e is loaded. http://marc.info/?l=e1000-devel&m=121909039127414&w=2 http://marc.info/?l=e1000-devel&m=121365543823387&w=2 This fixes the issue if they load with the new parameter = 0 by disabling crc stripping, but leaves the performance feature on for most users. Based on work done by Hong Zhang. Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: David S. Miller --- drivers/net/e1000e/e1000.h | 5 +++++ drivers/net/e1000e/netdev.c | 23 +++++++++++++++++++++-- drivers/net/e1000e/param.c | 25 +++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index c55de1c027a..c55fd6fdb91 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -299,6 +299,7 @@ struct e1000_adapter { unsigned long led_status; unsigned int flags; + unsigned int flags2; struct work_struct downshift_task; struct work_struct update_phy_task; }; @@ -306,6 +307,7 @@ struct e1000_adapter { struct e1000_info { enum e1000_mac_type mac; unsigned int flags; + unsigned int flags2; u32 pba; s32 (*get_variants)(struct e1000_adapter *); struct e1000_mac_operations *mac_ops; @@ -347,6 +349,9 @@ struct e1000_info { #define FLAG_RX_RESTART_NOW (1 << 30) #define FLAG_MSI_TEST_FAILED (1 << 31) +/* CRC Stripping defines */ +#define FLAG2_CRC_STRIPPING (1 << 0) + #define E1000_RX_DESC_PS(R, i) \ (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) #define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index f6ebebb8cfa..91795f78c3e 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -499,6 +499,10 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, goto next_desc; } + /* adjust length to remove Ethernet CRC */ + if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) + length -= 4; + total_rx_bytes += length; total_rx_packets++; @@ -804,6 +808,10 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, pci_dma_sync_single_for_device(pdev, ps_page->dma, PAGE_SIZE, PCI_DMA_FROMDEVICE); + /* remove the CRC */ + if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) + l1 -= 4; + skb_put(skb, l1); goto copydone; } /* if */ @@ -825,6 +833,12 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, skb->truesize += length; } + /* strip the ethernet crc, problem is we're using pages now so + * this whole operation can get a little cpu intensive + */ + if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) + pskb_trim(skb, skb->len - 4); + copydone: total_rx_bytes += skb->len; total_rx_packets++; @@ -2301,8 +2315,12 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) else rctl |= E1000_RCTL_LPE; - /* Enable hardware CRC frame stripping */ - rctl |= E1000_RCTL_SECRC; + /* Some systems expect that the CRC is included in SMBUS traffic. The + * hardware strips the CRC before sending to both SMBUS (BMC) and to + * host memory when this is enabled + */ + if (adapter->flags2 & FLAG2_CRC_STRIPPING) + rctl |= E1000_RCTL_SECRC; /* Setup buffer sizes */ rctl &= ~E1000_RCTL_SZ_4096; @@ -4766,6 +4784,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, adapter->ei = ei; adapter->pba = ei->pba; adapter->flags = ei->flags; + adapter->flags2 = ei->flags2; adapter->hw.adapter = adapter; adapter->hw.mac.type = ei->mac; adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1; diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c index 77a3d7207a5..e909f96698e 100644 --- a/drivers/net/e1000e/param.c +++ b/drivers/net/e1000e/param.c @@ -151,6 +151,16 @@ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); */ E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]"); +/* + * Enable CRC Stripping + * + * Valid Range: 0, 1 + * + * Default Value: 1 (enabled) + */ +E1000_PARAM(CrcStripping, "Enable CRC Stripping, disable if your BMC needs " \ + "the CRC"); + struct e1000_option { enum { enable_option, range_option, list_option } type; const char *name; @@ -404,6 +414,21 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) adapter->flags |= FLAG_SMART_POWER_DOWN; } } + { /* CRC Stripping */ + const struct e1000_option opt = { + .type = enable_option, + .name = "CRC Stripping", + .err = "defaulting to enabled", + .def = OPTION_ENABLED + }; + + if (num_CrcStripping > bd) { + unsigned int crc_stripping = CrcStripping[bd]; + e1000_validate_option(&crc_stripping, &opt, adapter); + if (crc_stripping == OPTION_ENABLED) + adapter->flags2 |= FLAG2_CRC_STRIPPING; + } + } { /* Kumeran Lock Loss Workaround */ const struct e1000_option opt = { .type = enable_option, -- cgit v1.2.3 From 584c650b4e6fa16f9ab45d382f86ad6d9c625227 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Sun, 16 Nov 2008 23:03:45 -0800 Subject: isdn: remove extra byteswap in isdn_net_ciscohdlck_slarp_send_reply commit a144ea4b7a13087081ab5402fa9ad0bcfd249e67 [IPV4]: annotate struct in_ifaddr Missed this extra byteswap as the isdn inlines hide the htonl inside put_u32 which causes an extra byteswap on little-endian arches. Signed-off-by: Harvey Harrison Signed-off-by: David S. Miller --- drivers/isdn/i4l/isdn_net.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index bb904a0a98b..1bfc55d7a26 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -1641,8 +1641,10 @@ isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp) /* slarp reply, send own ip/netmask; if values are nonsense remote * should think we are unable to provide it with an address via SLARP */ p += put_u32(p, CISCO_SLARP_REPLY); - p += put_u32(p, addr); // address - p += put_u32(p, mask); // netmask + *(__be32 *)p = addr; // address + p += 4; + *(__be32 *)p = mask; // netmask + p += 4; p += put_u16(p, 0); // unused isdn_net_write_super(lp, skb); -- cgit v1.2.3 From 26a3e99160cfb06a0a33e25b9fb0d516e2cc680d Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Mon, 17 Nov 2008 09:35:00 -0800 Subject: xen: fix scrub_page() Impact: fix guest kernel crash with CONFIG_XEN_SCRUB_PAGES=y Jens noticed that scrub_page() has a buggy unmap of the wrong thing. (virtual address instead of page) Linus pointed out that the whole scrub_page() code is an unnecessary reimplementation of clear_highpage() to begin with. Just use clear_highpage() rather than reimplementing it poorly. Reported-by: Jens Axboe Signed-off-by: Jeremy Fitzhardinge Signed-off-by: Ingo Molnar --- drivers/xen/balloon.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index a0fb5eac407..526c191e84e 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -122,14 +122,7 @@ static struct timer_list balloon_timer; static void scrub_page(struct page *page) { #ifdef CONFIG_XEN_SCRUB_PAGES - if (PageHighMem(page)) { - void *v = kmap(page); - clear_page(v); - kunmap(v); - } else { - void *v = page_address(page); - clear_page(v); - } + clear_highpage(page); #endif } -- cgit v1.2.3 From 68aee07f9bad2c830a898cf6d6bfc11ea24efc40 Mon Sep 17 00:00:00 2001 From: Zhaolei Date: Fri, 14 Nov 2008 09:44:33 +0100 Subject: Release old elevator on change elevator We should release old elevator when change to use a new one. Signed-off-by: Zhao Lei Signed-off-by: Jens Axboe --- drivers/block/xen-blkfront.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index b220c686089..2d19f0cc47f 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -338,12 +338,18 @@ wait: static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size) { struct request_queue *rq; + elevator_t *old_e; rq = blk_init_queue(do_blkif_request, &blkif_io_lock); if (rq == NULL) return -1; - elevator_init(rq, "noop"); + old_e = rq->elevator; + if (IS_ERR_VALUE(elevator_init(rq, "noop"))) + printk(KERN_WARNING + "blkfront: Switch elevator failed, use default\n"); + else + elevator_exit(old_e); /* Hard sector size and max sectors impersonate the equiv. hardware. */ blk_queue_hardsect_size(rq, sector_size); -- cgit v1.2.3 From 66359f849074c55fb80d15235ea5b99f1918663c Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 18 Nov 2008 15:12:42 +0800 Subject: Parport driver: disable pc-style parport on Blackfin systems Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Signed-off-by: Linus Torvalds --- drivers/parport/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig index 209b4a464bc..855f389eea4 100644 --- a/drivers/parport/Kconfig +++ b/drivers/parport/Kconfig @@ -36,7 +36,7 @@ if PARPORT config PARPORT_PC tristate "PC-style hardware" depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && \ - (!M68K || ISA) && !MN10300 && !AVR32 + (!M68K || ISA) && !MN10300 && !AVR32 && !BLACKFIN ---help--- You should say Y here if you have a PC-style parallel port. All IBM PC compatible computers and some Alphas have PC-style -- cgit v1.2.3 From 9b44fb89cab6e01816cdc05d6b59fdcf8100b8c3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 29 Oct 2008 23:24:14 +0100 Subject: libertas_tf: fix skb tail pointer skb->tail can't be meant here because it's not the same across 32/64 bit compilations. This means there's no way the current driver can work on 64-bit architectures. Signed-off-by: Johannes Berg Cc: stable@kernel.org [2.6.27] Signed-off-by: John W. Linville --- drivers/net/wireless/libertas_tf/if_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index 1cc03a8dd67..59634c33b1f 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c @@ -331,7 +331,7 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, /* Fill the receive configuration URB and initialise the Rx call back */ usb_fill_bulk_urb(cardp->rx_urb, cardp->udev, usb_rcvbulkpipe(cardp->udev, cardp->ep_in), - (void *) (skb->tail), + skb_tail_pointer(skb), MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp); cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; -- cgit v1.2.3 From 8e3bad65a59915f2ddc40f62a180ad81695d8440 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 17 Nov 2008 10:59:59 +0100 Subject: mac80211: remove ieee80211_notify_mac Before ieee80211_notify_mac() was added, it was presented with the use case of using it to tell mac80211 that the association may have been lost because the firmware crashed/reset. Since then, it has also been used by iwlwifi to (slightly) speed up re-association after resume, a workaround around the fact that mac80211 has no suspend/resume handling yet. It is also not used by any other drivers, so clearly it cannot be necessary for "good enough" suspend/resume. Unfortunately, the callback suffers from a severe problem: It only works for station mode. If suspend/resume happens while in IBSS or any other mode (but station), then the callback is pointless. Recently, it has created a number of locking issues, first because it required rtnl locking rather than RCU due to calling sleeping functions within the critical section, and now because it's called by iwlwifi from the mac80211 workqueue that may not use the rtnl because it is flushed under rtnl. (cf. http://bugzilla.kernel.org/show_bug.cgi?id=12046) I think, therefore, that we should take a step back, remove it entirely for now and add the small feature it provided properly. For suspend and resume we will need to introduce new hooks, and for the case where the firmware was reset the driver will probably simply just pretend it has done a suspend/resume cycle to get mac80211 to reprogram the hardware completely, not just try to connect to the current AP again in station mode. When doing so, we will need to take into account locking issues and possibly defer to schedule_work from within mac80211 for the resume operation, while the suspend operation must be done directly. Proper suspend/resume should also not necessarily try to reconnect to the current AP, the time spent in suspend may have been short enough to not be disconnected from the AP, mac80211 will detect that the AP went out of range quickly if it did, and if the association is lost then the AP will disassoc as soon as a data frame is sent. We might also take into account WWOL then, and have mac80211 program the hardware into such a mode where it is available and requested. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8d690a0eb1a..6751bb2b8ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2341,7 +2341,6 @@ static void iwl_bg_alive_start(struct work_struct *data) mutex_lock(&priv->mutex); iwl_alive_start(priv); mutex_unlock(&priv->mutex); - ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); } static void iwl4965_bg_rf_kill(struct work_struct *work) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 285b53e7e26..45a6b0c3569 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6012,7 +6012,6 @@ static void iwl3945_bg_alive_start(struct work_struct *data) mutex_lock(&priv->mutex); iwl3945_alive_start(priv); mutex_unlock(&priv->mutex); - ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); } static void iwl3945_bg_rf_kill(struct work_struct *work) -- cgit v1.2.3 From 4018517a1a69a85c3d61b20fa02f187b80773137 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 18 Nov 2008 01:47:21 +0100 Subject: iwlagn: fix RX skb alignment So I dug deeper into the DMA problems I had with iwlagn and a kind soul helped me in that he said something about pci-e alignment and mentioned the iwl_rx_allocate function to check for crossing 4KB boundaries. Since there's 8KB A-MPDU support, crossing 4k boundaries didn't seem like something the device would fail with, but when I looked into the function for a minute anyway I stumbled over this little gem: BUG_ON(rxb->dma_addr & (~DMA_BIT_MASK(36) & 0xff)); Clearly, that is a totally bogus check, one would hope the compiler removes it entirely. (Think about it) After fixing it, I obviously ran into it, nothing guarantees the alignment the way you want it, because of the way skbs and their headroom are allocated. I won't explain that here nor double-check that I'm right, that goes beyond what most of the CC'ed people care about. So then I came up with the patch below, and so far my system has survived minutes with 64K pages, when it would previously fail in seconds. And I haven't seen a single instance of the TX bug either. But when you see the patch it'll be pretty obvious to you why. This should fix the following reported kernel bugs: http://bugzilla.kernel.org/show_bug.cgi?id=11596 http://bugzilla.kernel.org/show_bug.cgi?id=11393 http://bugzilla.kernel.org/show_bug.cgi?id=11983 I haven't checked if there are any elsewhere, but I suppose RHBZ will have a few instances too... I'd like to ask anyone who is CC'ed (those are people I know ran into the bug) to try this patch. I am convinced that this patch is correct in spirit, but I haven't understood why, for example, there are so many unmap calls. I'm not entirely convinced that this is the only bug leading to the TX reply errors. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 ++- drivers/net/wireless/iwlwifi/iwl-rx.c | 26 +++++++++++++++++--------- 3 files changed, 22 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6751bb2b8ae..444c5cc05f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1384,7 +1384,7 @@ void iwl_rx_handle(struct iwl_priv *priv) rxq->queue[i] = NULL; - pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr, + pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->aligned_dma_addr, priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE); pkt = (struct iwl_rx_packet *)rxb->skb->data; @@ -1436,8 +1436,8 @@ void iwl_rx_handle(struct iwl_priv *priv) rxb->skb = NULL; } - pci_unmap_single(priv->pci_dev, rxb->dma_addr, - priv->hw_params.rx_buf_size, + pci_unmap_single(priv->pci_dev, rxb->real_dma_addr, + priv->hw_params.rx_buf_size + 256, PCI_DMA_FROMDEVICE); spin_lock_irqsave(&rxq->lock, flags); list_add_tail(&rxb->list, &priv->rxq.rx_used); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c018121085e..9966d4e384c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -89,7 +89,8 @@ extern struct iwl_cfg iwl5100_abg_cfg; #define DEFAULT_LONG_RETRY_LIMIT 4U struct iwl_rx_mem_buffer { - dma_addr_t dma_addr; + dma_addr_t real_dma_addr; + dma_addr_t aligned_dma_addr; struct sk_buff *skb; struct list_head list; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 7cde9d76ff5..0509c16dbe7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -204,7 +204,7 @@ int iwl_rx_queue_restock(struct iwl_priv *priv) list_del(element); /* Point to Rx buffer via next RBD in circular buffer */ - rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->dma_addr); + rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->aligned_dma_addr); rxq->queue[rxq->write] = rxb; rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; rxq->free_count--; @@ -251,7 +251,7 @@ void iwl_rx_allocate(struct iwl_priv *priv) rxb = list_entry(element, struct iwl_rx_mem_buffer, list); /* Alloc a new receive buffer */ - rxb->skb = alloc_skb(priv->hw_params.rx_buf_size, + rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256, __GFP_NOWARN | GFP_ATOMIC); if (!rxb->skb) { if (net_ratelimit()) @@ -266,9 +266,17 @@ void iwl_rx_allocate(struct iwl_priv *priv) list_del(element); /* Get physical address of RB/SKB */ - rxb->dma_addr = - pci_map_single(priv->pci_dev, rxb->skb->data, - priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE); + rxb->real_dma_addr = pci_map_single( + priv->pci_dev, + rxb->skb->data, + priv->hw_params.rx_buf_size + 256, + PCI_DMA_FROMDEVICE); + /* dma address must be no more than 36 bits */ + BUG_ON(rxb->real_dma_addr & ~DMA_BIT_MASK(36)); + /* and also 256 byte aligned! */ + rxb->aligned_dma_addr = ALIGN(rxb->real_dma_addr, 256); + skb_reserve(rxb->skb, rxb->aligned_dma_addr - rxb->real_dma_addr); + list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; } @@ -300,8 +308,8 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { if (rxq->pool[i].skb != NULL) { pci_unmap_single(priv->pci_dev, - rxq->pool[i].dma_addr, - priv->hw_params.rx_buf_size, + rxq->pool[i].real_dma_addr, + priv->hw_params.rx_buf_size + 256, PCI_DMA_FROMDEVICE); dev_kfree_skb(rxq->pool[i].skb); } @@ -354,8 +362,8 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) * to an SKB, so we need to unmap and free potential storage */ if (rxq->pool[i].skb != NULL) { pci_unmap_single(priv->pci_dev, - rxq->pool[i].dma_addr, - priv->hw_params.rx_buf_size, + rxq->pool[i].real_dma_addr, + priv->hw_params.rx_buf_size + 256, PCI_DMA_FROMDEVICE); priv->alloc_rxb_skb--; dev_kfree_skb(rxq->pool[i].skb); -- cgit v1.2.3 From b4e0f9eb8aeceb22c48fee005378bd19e25216fc Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 19 Nov 2008 13:53:42 +0900 Subject: intel-iommu: fix compile warnings Impact: cleanup I got the following warnings on IA64: linux-2.6/drivers/pci/intel-iommu.c: In function 'init_dmars': linux-2.6/drivers/pci/intel-iommu.c:1658: warning: format '%Lx' expects type 'long long unsigned int', but argument 2 has type 'u64' linux-2.6/drivers/pci/intel-iommu.c:1663: warning: format '%Lx' expects type 'long long unsigned int', but argument 2 has type 'u64' Another victim of int-ll64.h versus int-l64.h confusion between platforms. ->reg_base_addr has a type of u64 - which can only be printed out consistently if we cast its type up to LL. [ Eventually reg_base_addr should be converted to phys_addr_t, for which we have the %pR printk helper - but that is out of the scope of late -rc's. ] Signed-off-by: FUJITA Tomonori Signed-off-by: Ingo Molnar --- drivers/pci/intel-iommu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index a2692724b68..5c8baa43ac9 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1655,12 +1655,14 @@ int __init init_dmars(void) iommu->flush.flush_context = __iommu_flush_context; iommu->flush.flush_iotlb = __iommu_flush_iotlb; printk(KERN_INFO "IOMMU 0x%Lx: using Register based " - "invalidation\n", drhd->reg_base_addr); + "invalidation\n", + (unsigned long long)drhd->reg_base_addr); } else { iommu->flush.flush_context = qi_flush_context; iommu->flush.flush_iotlb = qi_flush_iotlb; printk(KERN_INFO "IOMMU 0x%Lx: using Queued " - "invalidation\n", drhd->reg_base_addr); + "invalidation\n", + (unsigned long long)drhd->reg_base_addr); } } -- cgit v1.2.3 From 5f4ba04ffd8fc9f6b15b92270ef0517ae52dcf3a Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 14 Nov 2008 13:32:42 -0500 Subject: Input: i8042 - add Compal Hel80 laptop to nomux blacklist Reported-by: Jaime Cura Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 5db1d0b7456..29e686388a2 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -344,6 +344,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"), }, }, + { + .ident = "Compal HEL80I", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"), + DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"), + }, + }, { } }; -- cgit v1.2.3 From 1df8fb3d5f078f9cab901b6106ef2c9b74eef7df Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Tue, 11 Nov 2008 17:17:45 +0800 Subject: PCI: Fix disable IRQ 0 in pci_reset_function() Before initialization, dev->irq may be zero. Make sure we don't disable it at reset time in that case. Reviewed-by: Matthew Wilcox Signed-off-by: Sheng Yang Signed-off-by: Jesse Barnes --- drivers/pci/pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 21f2ac639ca..28af496b441 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1832,7 +1832,7 @@ int pci_reset_function(struct pci_dev *dev) if (!(cap & PCI_EXP_DEVCAP_FLR)) return -ENOTTY; - if (!dev->msi_enabled && !dev->msix_enabled) + if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0) disable_irq(dev->irq); pci_save_state(dev); @@ -1841,7 +1841,7 @@ int pci_reset_function(struct pci_dev *dev) r = pci_execute_reset_function(dev); pci_restore_state(dev); - if (!dev->msi_enabled && !dev->msix_enabled) + if (!dev->msi_enabled && !dev->msix_enabled && dev->irq != 0) enable_irq(dev->irq); return r; -- cgit v1.2.3 From 79aefa45b20940cbb9104464548ff74f80f2395e Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 19 Nov 2008 14:17:02 -0800 Subject: ixgbe: fix compilation with gcc-3.4 CC [M] drivers/net/ixgbe/ixgbe_main.o drivers/net/ixgbe/ixgbe_main.c: In function `ixgbe_intr': drivers/net/ixgbe/ixgbe_main.c:1290: sorry, unimplemented: inlining failed in call to 'ixgbe_irq_enable': function body not available drivers/net/ixgbe/ixgbe_main.c:1312: sorry, unimplemented: called from here make[4]: *** [drivers/net/ixgbe/ixgbe_main.o] Error 1 Signed-off-by: Alexey Dobriyan Acked-by: Peter P Waskiewicz Jr Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 58 ++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 7548fb7360d..36f2bb666bf 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1287,7 +1287,34 @@ static void ixgbe_set_itr(struct ixgbe_adapter *adapter) return; } -static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter); +/** + * ixgbe_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + **/ +static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) +{ + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); + IXGBE_WRITE_FLUSH(&adapter->hw); + if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { + int i; + for (i = 0; i < adapter->num_msix_vectors; i++) + synchronize_irq(adapter->msix_entries[i].vector); + } else { + synchronize_irq(adapter->pdev->irq); + } +} + +/** + * ixgbe_irq_enable - Enable default interrupt generation settings + * @adapter: board private structure + **/ +static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) +{ + u32 mask; + mask = IXGBE_EIMS_ENABLE_MASK; + IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); + IXGBE_WRITE_FLUSH(&adapter->hw); +} /** * ixgbe_intr - legacy mode Interrupt Handler @@ -1393,35 +1420,6 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter) } } -/** - * ixgbe_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure - **/ -static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) -{ - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); - IXGBE_WRITE_FLUSH(&adapter->hw); - if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { - int i; - for (i = 0; i < adapter->num_msix_vectors; i++) - synchronize_irq(adapter->msix_entries[i].vector); - } else { - synchronize_irq(adapter->pdev->irq); - } -} - -/** - * ixgbe_irq_enable - Enable default interrupt generation settings - * @adapter: board private structure - **/ -static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) -{ - u32 mask; - mask = IXGBE_EIMS_ENABLE_MASK; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask); - IXGBE_WRITE_FLUSH(&adapter->hw); -} - /** * ixgbe_configure_msi_and_legacy - Initialize PIN (INTA...) and MSI interrupts * -- cgit v1.2.3 From 31c221c49f92d17632e0d662eb62a27e8b425805 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 19 Nov 2008 15:50:59 -0800 Subject: net: jme.c rxdesc.flags is __le16, other missing endian swaps This is the minimal patch to fix endian mismatches. These are probably bugs on big-endian arches, noops on little endian. jme_rxsum_ok could be improved to directly take a __le16 and change all of the masks/sets to be in little-endian, but has not been done here to keep the patch small. Signed-off-by: Harvey Harrison Signed-off-by: David S. Miller --- drivers/net/jme.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/jme.c b/drivers/net/jme.c index 81c6cdc3851..665e70d620f 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -912,23 +912,23 @@ jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx) skb_put(skb, framesize); skb->protocol = eth_type_trans(skb, jme->dev); - if (jme_rxsum_ok(jme, rxdesc->descwb.flags)) + if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags))) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb->ip_summed = CHECKSUM_NONE; - if (rxdesc->descwb.flags & RXWBFLAG_TAGON) { + if (rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_TAGON)) { if (jme->vlgrp) { jme->jme_vlan_rx(skb, jme->vlgrp, - le32_to_cpu(rxdesc->descwb.vlan)); + le16_to_cpu(rxdesc->descwb.vlan)); NET_STAT(jme).rx_bytes += 4; } } else { jme->jme_rx(skb); } - if ((le16_to_cpu(rxdesc->descwb.flags) & RXWBFLAG_DEST) == - RXWBFLAG_DEST_MUL) + if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_DEST)) == + cpu_to_le16(RXWBFLAG_DEST_MUL)) ++(NET_STAT(jme).multicast); jme->dev->last_rx = jiffies; @@ -961,7 +961,7 @@ jme_process_receive(struct jme_adapter *jme, int limit) rxdesc = rxring->desc; rxdesc += i; - if ((rxdesc->descwb.flags & RXWBFLAG_OWN) || + if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_OWN)) || !(rxdesc->descwb.desccnt & RXWBDCNT_WBCPL)) goto out; @@ -1763,10 +1763,9 @@ jme_expand_header(struct jme_adapter *jme, struct sk_buff *skb) } static int -jme_tx_tso(struct sk_buff *skb, - u16 *mss, u8 *flags) +jme_tx_tso(struct sk_buff *skb, __le16 *mss, u8 *flags) { - *mss = skb_shinfo(skb)->gso_size << TXDESC_MSS_SHIFT; + *mss = cpu_to_le16(skb_shinfo(skb)->gso_size << TXDESC_MSS_SHIFT); if (*mss) { *flags |= TXFLAG_LSEN; @@ -1826,11 +1825,11 @@ jme_tx_csum(struct jme_adapter *jme, struct sk_buff *skb, u8 *flags) } static inline void -jme_tx_vlan(struct sk_buff *skb, u16 *vlan, u8 *flags) +jme_tx_vlan(struct sk_buff *skb, __le16 *vlan, u8 *flags) { if (vlan_tx_tag_present(skb)) { *flags |= TXFLAG_TAGON; - *vlan = vlan_tx_tag_get(skb); + *vlan = cpu_to_le16(vlan_tx_tag_get(skb)); } } -- cgit v1.2.3 From de339c2aa7fea18410b1abeab5674bfbd4073a63 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Wed, 19 Nov 2008 15:52:41 -0800 Subject: phylib: Fix auto-negotiation restart avoidance A previous patch, 51e2a3846eab18711f4eb59cd0a4c33054e2980a, made genphy_config_aneg() not restart aneg by calling genphy_restart_aneg() if the advertisement hadn't changed. But, genphy_restart_aneg() doesn't just restart aneg, it may also *enable* aneg or un-isolate the PHY from the MII (those functions are controlled by the same register). The code to avoid calling genphy_restart_aneg() didn't consider this. So, modify genphy_config_aneg() to also check if the PHY needs to have aneg enabled or be un-isolated before deciding not to restart aneg. This caused a problem with certain Davicom PHYs, as that driver isolates the PHY (why?) before calling genphy_config_aneg() and expects the PHY to be un-isolated by that function. Signed-off-by: Trent Piepho Reported-by: Scott Wood Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 8fb1faca883..55bc24b234e 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -564,20 +564,32 @@ EXPORT_SYMBOL(genphy_restart_aneg); */ int genphy_config_aneg(struct phy_device *phydev) { - int result = 0; + int result; - if (AUTONEG_ENABLE == phydev->autoneg) { - int result = genphy_config_advert(phydev); + if (AUTONEG_ENABLE != phydev->autoneg) + return genphy_setup_forced(phydev); + + result = genphy_config_advert(phydev); + + if (result < 0) /* error */ + return result; - if (result < 0) /* error */ - return result; + if (result == 0) { + /* Advertisment hasn't changed, but maybe aneg was never on to + * begin with? Or maybe phy was isolated? */ + int ctl = phy_read(phydev, MII_BMCR); + + if (ctl < 0) + return ctl; + + if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE)) + result = 1; /* do restart aneg */ + } - /* Only restart aneg if we are advertising something different - * than we were before. */ - if (result > 0) - result = genphy_restart_aneg(phydev); - } else - result = genphy_setup_forced(phydev); + /* Only restart aneg if we are advertising something different + * than we were before. */ + if (result > 0) + result = genphy_restart_aneg(phydev); return result; } -- cgit v1.2.3 From b88ed5cc884e4c28d787cf0912b8635376f16a87 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 19 Nov 2008 15:54:38 -0800 Subject: net: ipg.c fix bracing on endian swapping rxfd->frag_info is a __le64, IPG_RFI_FRAGLEN is a cpu-endian constant and wants to be outside of the le64_to_cpu. Fixed in multiple places. Also an occurrence where le64_to_cpu was used instead of cpu_to_le64 Signed-off-by: Harvey Harrison Signed-off-by: David S. Miller --- drivers/net/ipg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c index 7373dafbb3f..059369885be 100644 --- a/drivers/net/ipg.c +++ b/drivers/net/ipg.c @@ -1112,7 +1112,7 @@ static void ipg_nic_rx_free_skb(struct net_device *dev) struct ipg_rx *rxfd = sp->rxd + entry; pci_unmap_single(sp->pdev, - le64_to_cpu(rxfd->frag_info & ~IPG_RFI_FRAGLEN), + le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN, sp->rx_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb_irq(sp->rx_buff[entry]); sp->rx_buff[entry] = NULL; @@ -1179,7 +1179,7 @@ static int ipg_nic_rx_check_error(struct net_device *dev) */ if (sp->rx_buff[entry]) { pci_unmap_single(sp->pdev, - le64_to_cpu(rxfd->frag_info & ~IPG_RFI_FRAGLEN), + le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN, sp->rx_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb_irq(sp->rx_buff[entry]); @@ -1246,7 +1246,7 @@ static void ipg_nic_rx_with_start(struct net_device *dev, if (jumbo->found_start) dev_kfree_skb_irq(jumbo->skb); - pci_unmap_single(pdev, le64_to_cpu(rxfd->frag_info & ~IPG_RFI_FRAGLEN), + pci_unmap_single(pdev, le64_to_cpu(rxfd->frag_info) & ~IPG_RFI_FRAGLEN, sp->rx_buf_sz, PCI_DMA_FROMDEVICE); skb_put(skb, sp->rxfrag_size); @@ -1349,7 +1349,7 @@ static int ipg_nic_rx_jumbo(struct net_device *dev) unsigned int entry = curr % IPG_RFDLIST_LENGTH; struct ipg_rx *rxfd = sp->rxd + entry; - if (!(rxfd->rfs & le64_to_cpu(IPG_RFS_RFDDONE))) + if (!(rxfd->rfs & cpu_to_le64(IPG_RFS_RFDDONE))) break; switch (ipg_nic_rx_check_frame_type(dev)) { -- cgit v1.2.3 From 9ca791bbd464d7968db1530b433cc397a4c348c1 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Wed, 19 Nov 2008 15:36:06 -0800 Subject: hwmon: applesmc: Add support for iMac 6 Add temperature sensor support for iMac 6. Signed-off-by: Henrik Rydberg Tested-by: Caleb Hyde Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/applesmc.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 488e45cd43d..10977b3d201 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -128,6 +128,9 @@ static const char* temperature_sensors_sets[][36] = { /* Set 13: iMac 8,1 */ { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P", "TL0P", "TO0P", "TW0P", "Tm0P", "Tp0P", NULL }, +/* Set 14: iMac 6,1 */ + { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P", + "TO0P", "Tp0P", NULL }, }; /* List of keys used to read/write fan speeds */ @@ -1296,6 +1299,8 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { { .accelerometer = 1, .light = 1, .temperature_set = 12 }, /* iMac 8: light sensor only, temperature set 13 */ { .accelerometer = 0, .light = 0, .temperature_set = 13 }, +/* iMac 6: light sensor only, temperature set 14 */ + { .accelerometer = 0, .light = 0, .temperature_set = 14 }, }; /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". @@ -1353,6 +1358,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") }, &applesmc_dmi_data[13]}, + { applesmc_dmi_match, "Apple iMac 6", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "iMac6") }, + &applesmc_dmi_data[14]}, { applesmc_dmi_match, "Apple iMac 5", { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "iMac5") }, -- cgit v1.2.3 From cf7b9a1e11993a064f445d332fecf22819b87a5e Mon Sep 17 00:00:00 2001 From: Julien Brunel Date: Wed, 19 Nov 2008 15:36:07 -0800 Subject: drivers/video: bad error test before a dereference The error test that follows the call to backlight_device_register semms not to concern the right variable. A simplified version of the semantic match that finds this problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @def0@ expression x; position p0; @@ x@p0 = backlight_device_register(...) @protected@ expression def0.x,E; position def0.p0; position p; statement S; @@ x@p0 ... when != x = E if (!IS_ERR(x) && ...) {<... x@p ...>} else S @unprotected@ expression def0.x; identifier fld; position def0.p0; position p != protected.p; @@ x@p0 ... when != x = E * x@p->fld // Signed-off-by: Julien Brunel Signed-off-by: Julia Lawall Acked-by: Nicolas Ferre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/atmel_lcdfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index f8d0a57a07c..9a577a800db 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -132,7 +132,7 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo) bl = backlight_device_register("backlight", &sinfo->pdev->dev, sinfo, &atmel_lcdc_bl_ops); - if (IS_ERR(sinfo->backlight)) { + if (IS_ERR(bl)) { dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n", PTR_ERR(bl)); return; -- cgit v1.2.3 From cf7ee554f3a324e98181b0ea249d9d5be3a0acb8 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Wed, 19 Nov 2008 15:36:10 -0800 Subject: fbdev: clean the penguin's dirty feet When booting in a direct color mode, the penguin has dirty feet, i.e., some pixels have the wrong color. This is caused by fb_set_logo_directpalette() which does not initialize the last 32 palette entries. Signed-off-by: Clemens Ladisch Acked-by: Geert Uytterhoeven Cc: Krzysztof Helt Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/fbmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 1d5ae39cb27..3c65b0d6761 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -230,7 +230,7 @@ static void fb_set_logo_directpalette(struct fb_info *info, greenshift = info->var.green.offset; blueshift = info->var.blue.offset; - for (i = 32; i < logo->clutsize; i++) + for (i = 32; i < 32 + logo->clutsize; i++) palette[i] = i << redshift | i << greenshift | i << blueshift; } -- cgit v1.2.3 From 6e8ba729b6332f2a75572e02480936d2b51665aa Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Wed, 19 Nov 2008 15:36:17 -0800 Subject: gpiolib: extend gpio label column width in debugfs file There are already various drivers having bigger label than 12 bytes. Most of them fit well under 20 bytes but make column width exact so that oversized labels don't mess up output alignment. Signed-off-by: Jarkko Nikula Acked-by: David Brownell Cc: [2.6.26.x, 2.6.26.x, 2.6.27.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/gpio/gpiolib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index faa1cc66e9c..82020abc329 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1134,7 +1134,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) continue; is_out = test_bit(FLAG_IS_OUT, &gdesc->flags); - seq_printf(s, " gpio-%-3d (%-12s) %s %s", + seq_printf(s, " gpio-%-3d (%-20.20s) %s %s", gpio, gdesc->label, is_out ? "out" : "in ", chip->get -- cgit v1.2.3 From 415d8cfa845ec9dac42e7b354b1f80485805455b Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Wed, 19 Nov 2008 15:36:18 -0800 Subject: GRU: fix for debug option Enable -D DEBUG in the GRU Makefile if CONFIG_SGI_GRU_DEBUG is selected. Signed-off-by: Jack Steiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/sgi-gru/Makefile | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/sgi-gru/Makefile b/drivers/misc/sgi-gru/Makefile index d03597a521b..9e9170b3599 100644 --- a/drivers/misc/sgi-gru/Makefile +++ b/drivers/misc/sgi-gru/Makefile @@ -1,3 +1,7 @@ +ifdef CONFIG_SGI_GRU_DEBUG + EXTRA_CFLAGS += -DDEBUG +endif + obj-$(CONFIG_SGI_GRU) := gru.o gru-y := grufile.o grumain.o grufault.o grutlbpurge.o gruprocfs.o grukservices.o -- cgit v1.2.3 From a495a6d35a026826d54a69d01f373681e14f59ac Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 19 Nov 2008 15:36:19 -0800 Subject: tmiofb: fix compilation with ACCEL disabled Restore support for compiling tmiofb with acceleration disabled. Signed-off-by: Dmitry Baryshkov Cc: Krzysztof Helt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/tmiofb.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c index 2a380011e9b..7baf2dd12d5 100644 --- a/drivers/video/tmiofb.c +++ b/drivers/video/tmiofb.c @@ -222,6 +222,9 @@ static irqreturn_t tmiofb_irq(int irq, void *__info) unsigned int bbisc = tmio_ioread16(par->lcr + LCR_BBISC); + tmio_iowrite16(bbisc, par->lcr + LCR_BBISC); + +#ifdef CONFIG_FB_TMIO_ACCELL /* * We were in polling mode and now we got correct irq. * Switch back to IRQ-based sync of command FIFO @@ -231,9 +234,6 @@ static irqreturn_t tmiofb_irq(int irq, void *__info) par->use_polling = false; } - tmio_iowrite16(bbisc, par->lcr + LCR_BBISC); - -#ifdef CONFIG_FB_TMIO_ACCELL if (bbisc & 1) wake_up(&par->wait_acc); #endif @@ -938,7 +938,9 @@ static void tmiofb_dump_regs(struct platform_device *dev) static int tmiofb_suspend(struct platform_device *dev, pm_message_t state) { struct fb_info *info = platform_get_drvdata(dev); +#ifdef CONFIG_FB_TMIO_ACCELL struct tmiofb_par *par = info->par; +#endif struct mfd_cell *cell = dev->dev.platform_data; int retval = 0; @@ -950,12 +952,14 @@ static int tmiofb_suspend(struct platform_device *dev, pm_message_t state) info->fbops->fb_sync(info); +#ifdef CONFIG_FB_TMIO_ACCELL /* * The fb should be usable even if interrupts are disabled (and they are * during suspend/resume). Switch temporary to forced polling. */ printk(KERN_INFO "tmiofb: switching to polling\n"); par->use_polling = true; +#endif tmiofb_hw_stop(dev); if (cell->suspend) -- cgit v1.2.3 From 393df744e056ba24e9531d0657d09fc3c7c0dd22 Mon Sep 17 00:00:00 2001 From: Ned Forrester Date: Wed, 19 Nov 2008 15:36:21 -0800 Subject: pxa2xx_spi: bugfix full duplex dma data corruption Fixes a data corruption bug in pxa2xx_spi.c when operating in full duplex mode with DMA and using buffers that overlap. SPI transmit and receive buffers are allowed to be the same or to overlap. However, this driver fails if such overlap is attempted in DMA mode because it maps the rx and tx buffers in the wrong order. By mapping DMA_FROM_DEVICE (read) before DMA_TO_DEVICE (write), it invalidates the cache before flushing it, thus discarding data which should have been transmitted. The patch corrects the order of mapping. This bug exists in all versions of pxa2xx_spi.c; similar bugs are in the drivers for two other SPI controllers (au1500, imx). A version of this patch has been tested on kernel 2.6.20 using verification of loopback data with: random transfer length, random bits-per-word, random positive offsets (both larger and smaller than transfer length) between the start of the rx and tx buffers, and varying clock rates. Signed-off-by: Ned Forrester Cc: Vernon Sauder Cc: J. Scott Merritt Signed-off-by: David Brownell Cc: [2.6.27.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/pxa2xx_spi.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index dae87b1a4c6..cf12f2d84be 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -352,21 +352,21 @@ static int map_dma_buffers(struct driver_data *drv_data) } else drv_data->tx_map_len = drv_data->len; - /* Stream map the rx buffer */ - drv_data->rx_dma = dma_map_single(dev, drv_data->rx, - drv_data->rx_map_len, - DMA_FROM_DEVICE); - if (dma_mapping_error(dev, drv_data->rx_dma)) - return 0; - - /* Stream map the tx buffer */ + /* Stream map the tx buffer. Always do DMA_TO_DEVICE first + * so we flush the cache *before* invalidating it, in case + * the tx and rx buffers overlap. + */ drv_data->tx_dma = dma_map_single(dev, drv_data->tx, - drv_data->tx_map_len, - DMA_TO_DEVICE); + drv_data->tx_map_len, DMA_TO_DEVICE); + if (dma_mapping_error(dev, drv_data->tx_dma)) + return 0; - if (dma_mapping_error(dev, drv_data->tx_dma)) { - dma_unmap_single(dev, drv_data->rx_dma, + /* Stream map the rx buffer */ + drv_data->rx_dma = dma_map_single(dev, drv_data->rx, drv_data->rx_map_len, DMA_FROM_DEVICE); + if (dma_mapping_error(dev, drv_data->rx_dma)) { + dma_unmap_single(dev, drv_data->tx_dma, + drv_data->tx_map_len, DMA_TO_DEVICE); return 0; } -- cgit v1.2.3 From c267fd777a478d74fa8959628538b64088f67fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Pr=C3=A9mont?= Date: Wed, 19 Nov 2008 15:36:23 -0800 Subject: viafb: fix releasing of /proc/viafb/ subtree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When unloading viafb module it does not remove it's /proc/viafb/ subtree which causes multiple viafb directories to appear below proc when mobprobing viafb and also lets kernel WARN() on duplicate proc entries: [ 145.458387] WARNING: at /usr/src/linux-2.6.28-rc3-git6/fs/proc/generic.c:551 proc_register+0xe6/0x160() [ 145.458945] proc_dir_entry '/proc/viafb' already registered [ 145.459278] Modules linked in: viafb(+) i2c_algo_bit cfbcopyarea cfbimgblt cfbfillrect snd_hda_intel snd_pcm snd_timer snd soundcore snd_page_alloc sg via_agp agpgart [last unloaded: drm] [ 145.460647] Pid: 1904, comm: modprobe Tainted: G W 2.6.28-rc3-git6 #4 [ 145.461064] Call Trace: [ 145.461248] [] ? dump_stack+0x1/0x80 [ 145.461533] [] warn_slowpath+0x63/0x80 [ 145.461851] [] ? idr_get_empty_slot+0xe9/0x250 [ 145.462186] [] ? ida_get_new_above+0xf0/0x150 [ 145.462528] [] proc_register+0xe6/0x160 [ 145.462827] [] proc_mkdir_mode+0x36/0x50 [ 145.463135] [] proc_mkdir+0xf/0x20 [ 145.463457] [] viafb_init+0x73c/0xc86 [viafb] [ 145.463823] [] ? viafb_init+0x0/0xc86 [viafb] [ 145.464147] [] do_one_initcall+0x2d/0x160 [ 145.464460] [] ? sysfs_add_file+0x13/0x20 [ 145.464786] [] ? vfree+0x21/0x30 [ 145.465049] [] ? load_module+0x1215/0x1500 [ 145.465381] [] ? __alloc_pages_internal+0x95/0x400 [ 145.465755] [] sys_init_module+0x83/0x1a0 [ 145.466065] [] ? sys_read+0x3d/0x70 [ 145.466354] [] sysenter_do_call+0x12/0x25 [ 145.466653] ---[ end trace c84b37826e16748c ]--- Signed-off-by: Bruno Prémont Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/via/viafbdev.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 0132eae06f5..73ac754ad80 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -2036,30 +2036,30 @@ static int viafb_vt1636_proc_write(struct file *file, return count; } -static void viafb_init_proc(struct proc_dir_entry *viafb_entry) +static void viafb_init_proc(struct proc_dir_entry **viafb_entry) { struct proc_dir_entry *entry; - viafb_entry = proc_mkdir("viafb", NULL); + *viafb_entry = proc_mkdir("viafb", NULL); if (viafb_entry) { - entry = create_proc_entry("dvp0", 0, viafb_entry); + entry = create_proc_entry("dvp0", 0, *viafb_entry); if (entry) { entry->owner = THIS_MODULE; entry->read_proc = viafb_dvp0_proc_read; entry->write_proc = viafb_dvp0_proc_write; } - entry = create_proc_entry("dvp1", 0, viafb_entry); + entry = create_proc_entry("dvp1", 0, *viafb_entry); if (entry) { entry->owner = THIS_MODULE; entry->read_proc = viafb_dvp1_proc_read; entry->write_proc = viafb_dvp1_proc_write; } - entry = create_proc_entry("dfph", 0, viafb_entry); + entry = create_proc_entry("dfph", 0, *viafb_entry); if (entry) { entry->owner = THIS_MODULE; entry->read_proc = viafb_dfph_proc_read; entry->write_proc = viafb_dfph_proc_write; } - entry = create_proc_entry("dfpl", 0, viafb_entry); + entry = create_proc_entry("dfpl", 0, *viafb_entry); if (entry) { entry->owner = THIS_MODULE; entry->read_proc = viafb_dfpl_proc_read; @@ -2068,7 +2068,7 @@ static void viafb_init_proc(struct proc_dir_entry *viafb_entry) if (VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info. lvds_chip_name || VT1636_LVDS == viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { - entry = create_proc_entry("vt1636", 0, viafb_entry); + entry = create_proc_entry("vt1636", 0, *viafb_entry); if (entry) { entry->owner = THIS_MODULE; entry->read_proc = viafb_vt1636_proc_read; @@ -2087,6 +2087,7 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) remove_proc_entry("dfpl", viafb_entry); remove_proc_entry("vt1636", viafb_entry); remove_proc_entry("vt1625", viafb_entry); + remove_proc_entry("viafb", NULL); } static int __devinit via_pci_probe(void) @@ -2348,7 +2349,7 @@ static int __devinit via_pci_probe(void) viafbinfo->node, viafbinfo->fix.id, default_var.xres, default_var.yres, default_var.bits_per_pixel); - viafb_init_proc(viaparinfo->proc_entry); + viafb_init_proc(&viaparinfo->proc_entry); viafb_init_dac(IGA2); return 0; } -- cgit v1.2.3 From b3b4dc8840a8fdbe495723d35cd976d781fd42fa Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 19 Nov 2008 15:36:25 -0800 Subject: lcd: fix oops if driver only interested in .set_power The LCD driver core calls LCD drivers when either the blanking state or the display mode has changed, but does not make any check to see if the called driver has a .set_mode method. This means if a driver only has a .set_power method then the system will OOPS on changing mode (and with the console semaphore held so you cannot easily see the problem). Fix the problem by ensuring that either callback is valid before use. Signed-off-by: Ben Dooks Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/lcd.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 8e1731d3b22..680e57b616c 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -42,10 +42,13 @@ static int fb_notifier_callback(struct notifier_block *self, mutex_lock(&ld->ops_lock); if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) { - if (event == FB_EVENT_BLANK) - ld->ops->set_power(ld, *(int *)evdata->data); - else - ld->ops->set_mode(ld, evdata->data); + if (event == FB_EVENT_BLANK) { + if (ld->ops->set_power) + ld->ops->set_power(ld, *(int *)evdata->data); + } else { + if (ld->ops->set_mode) + ld->ops->set_mode(ld, evdata->data); + } } mutex_unlock(&ld->ops_lock); return 0; -- cgit v1.2.3 From 3b45d6380c392e402adc460e4ccf7d41e0caf82a Mon Sep 17 00:00:00 2001 From: Andrea Paterniani Date: Wed, 19 Nov 2008 15:36:26 -0800 Subject: spi_imx: full duplex dma corruption bugfix Fix unsafe order in dma mapping operation: always flush data from the cache *BEFORE* invalidating it, to allow full duplex transfers where the same buffer may be used for both writes and reads. Signed-off-by: Andrea Paterniani Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/spi_imx.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index 61ba147e384..0b4db0ce78d 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c @@ -506,20 +506,6 @@ static int map_dma_buffers(struct driver_data *drv_data) if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx)) return -1; - /* NULL rx means write-only transfer and no map needed - since rx DMA will not be used */ - if (drv_data->rx) { - buf = drv_data->rx; - drv_data->rx_dma = dma_map_single( - dev, - buf, - drv_data->len, - DMA_FROM_DEVICE); - if (dma_mapping_error(dev, drv_data->rx_dma)) - return -1; - drv_data->rx_dma_needs_unmap = 1; - } - if (drv_data->tx == NULL) { /* Read only message --> use drv_data->dummy_dma_buf for dummy writes to achive reads */ @@ -533,18 +519,31 @@ static int map_dma_buffers(struct driver_data *drv_data) buf, drv_data->tx_map_len, DMA_TO_DEVICE); - if (dma_mapping_error(dev, drv_data->tx_dma)) { - if (drv_data->rx_dma) { - dma_unmap_single(dev, - drv_data->rx_dma, - drv_data->len, - DMA_FROM_DEVICE); - drv_data->rx_dma_needs_unmap = 0; - } + if (dma_mapping_error(dev, drv_data->tx_dma)) return -1; - } drv_data->tx_dma_needs_unmap = 1; + /* NULL rx means write-only transfer and no map needed + * since rx DMA will not be used */ + if (drv_data->rx) { + buf = drv_data->rx; + drv_data->rx_dma = dma_map_single(dev, + buf, + drv_data->len, + DMA_FROM_DEVICE); + if (dma_mapping_error(dev, drv_data->rx_dma)) { + if (drv_data->tx_dma) { + dma_unmap_single(dev, + drv_data->tx_dma, + drv_data->tx_map_len, + DMA_TO_DEVICE); + drv_data->tx_dma_needs_unmap = 0; + } + return -1; + } + drv_data->rx_dma_needs_unmap = 1; + } + return 0; } -- cgit v1.2.3 From c0d861afa5c986f7fe23647fbe411cd300f7c927 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 19 Nov 2008 15:36:41 -0800 Subject: drivers/video/backlight/da903x.c: introduce missing kfree Error handling code following a kzalloc should free the allocated data. The semantic match that finds the problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; statement S; expression E; identifier f,l; position p1,p2; expression *ptr != NULL; @@ ( if ((x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...)) == NULL) S | x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...); ... if (x == NULL) S ) <... when != x when != if (...) { <+...x...+> } x->f = E ...> ( return \(0\|<+...x...+>\|ptr\); | return@p2 ...; ) @script:python@ p1 << r.p1; p2 << r.p2; @@ print "* file: %s kmalloc %s return %s" % (p1[0].file,p1[0].line,p2[0].line) // Signed-off-by: Julia Lawall Cc: Mike Rapoport Cc: Richard Purdie Cc: Eric Miao Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/da903x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/video/backlight/da903x.c b/drivers/video/backlight/da903x.c index 242c3825016..75388b95943 100644 --- a/drivers/video/backlight/da903x.c +++ b/drivers/video/backlight/da903x.c @@ -119,6 +119,7 @@ static int da903x_backlight_probe(struct platform_device *pdev) default: dev_err(&pdev->dev, "invalid backlight device ID(%d)\n", pdev->id); + kfree(data); return -EINVAL; } -- cgit v1.2.3 From 45a3a36b6333b9ddfb0c57602d959a8d05bc47e4 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Wed, 19 Nov 2008 15:36:42 -0800 Subject: drivers/hwmon/applesmc.c: add generic MacPro support In order to analyze the SMC of the newer MacPros, applesmc needs to recognize the machine. This patch adds the missing generic dmi_match entry for MacPro models. Signed-off-by: Henrik Rydberg Cc: Nicolas Boichat Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/applesmc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 10977b3d201..f7dce8b9f64 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -1354,6 +1354,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") }, &applesmc_dmi_data[4]}, + { applesmc_dmi_match, "Apple MacPro", { + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), + DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") }, + &applesmc_dmi_data[4]}, { applesmc_dmi_match, "Apple iMac 8", { DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") }, -- cgit v1.2.3 From ee11940f8e7a2f064af22d52180cb5f9643eef61 Mon Sep 17 00:00:00 2001 From: Vlada Peric Date: Wed, 19 Nov 2008 15:36:45 -0800 Subject: cirrusfb: remove unused variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After commit a1d35a7a (cirrusfb: use modedb and add mode_option parameter), these variables are no longer used, so remove them to fix compilation warning. Signed-off-by: Vlada Periæ Acked-by: Krzysztof Helt Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/cirrusfb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 8a8760230bc..a2aa6ddffbe 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -2462,8 +2462,7 @@ static int __init cirrusfb_init(void) #ifndef MODULE static int __init cirrusfb_setup(char *options) { - char *this_opt, s[32]; - int i; + char *this_opt; DPRINTK("ENTER\n"); -- cgit v1.2.3 From f55491a4bcbe8bab337bc00830ca12d703ea2613 Mon Sep 17 00:00:00 2001 From: Mike Rapoport <[mailto:mike@compulab.co.il]> Date: Wed, 19 Nov 2008 15:36:49 -0800 Subject: drivers/video/backlight/da903x.c: introduce one more missing kfree One more error handling code should have kfree as well Signed-off-by: Mike Rapoport Acked-by: Eric Miao Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/backlight/da903x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/video/backlight/da903x.c b/drivers/video/backlight/da903x.c index 75388b95943..93bb4340cc6 100644 --- a/drivers/video/backlight/da903x.c +++ b/drivers/video/backlight/da903x.c @@ -131,6 +131,7 @@ static int da903x_backlight_probe(struct platform_device *pdev) data, &da903x_backlight_ops); if (IS_ERR(bl)) { dev_err(&pdev->dev, "failed to register backlight\n"); + kfree(data); return PTR_ERR(bl); } -- cgit v1.2.3 From 06b0d4dc14a44dd9b57321c24f7eeb10b345abd8 Mon Sep 17 00:00:00 2001 From: "Stanley.Miao" Date: Wed, 19 Nov 2008 15:36:50 -0800 Subject: W1 OMAP: Fix OMAP LDP boot crash OMAP LDP boot crash. This is because w1 subsystem changed the search interface, so update omap_hdq's search interface to follow the change. Signed-off-by: Stanley.Miao Signed-off-by: Evgeniy Polyakov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/w1/masters/omap_hdq.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c index 1295625c482..c973889110c 100644 --- a/drivers/w1/masters/omap_hdq.c +++ b/drivers/w1/masters/omap_hdq.c @@ -86,8 +86,8 @@ static struct platform_driver omap_hdq_driver = { static u8 omap_w1_read_byte(void *_hdq); static void omap_w1_write_byte(void *_hdq, u8 byte); static u8 omap_w1_reset_bus(void *_hdq); -static void omap_w1_search_bus(void *_hdq, u8 search_type, - w1_slave_found_callback slave_found); +static void omap_w1_search_bus(void *_hdq, struct w1_master *master_dev, + u8 search_type, w1_slave_found_callback slave_found); static struct w1_bus_master omap_w1_master = { @@ -231,8 +231,8 @@ static u8 omap_w1_reset_bus(void *_hdq) } /* W1 search callback function */ -static void omap_w1_search_bus(void *_hdq, u8 search_type, - w1_slave_found_callback slave_found) +static void omap_w1_search_bus(void *_hdq, struct w1_master *master_dev, + u8 search_type, w1_slave_found_callback slave_found) { u64 module_id, rn_le, cs, id; @@ -249,7 +249,7 @@ static void omap_w1_search_bus(void *_hdq, u8 search_type, cs = w1_calc_crc8((u8 *)&rn_le, 7); id = (cs << 56) | module_id; - slave_found(_hdq, id); + slave_found(master_dev, id); } static int _omap_hdq_reset(struct hdq_data *hdq_data) -- cgit v1.2.3 From 9f92f4719764acf1c9185a5958200887a43e3483 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 19 Nov 2008 15:36:51 -0800 Subject: cciss: fix DEBUG printk formats Fix printk format warnings when CCISS_DEBUG is defined. drivers/block/cciss.c:2856: warning: format '%d' expects type 'int', but argument 2 has type 'long unsigned int' drivers/block/cciss.c:3205: warning: format '%x' expects type 'unsigned int', but argument 2 has type 'long unsigned int' drivers/block/cciss.c:3236: warning: format '%x' expects type 'unsigned int', but argument 2 has type '__u64' drivers/block/cciss.c:3246: warning: format '%x' expects type 'unsigned int', but argument 2 has type '__u64' Signed-off-by: Randy Dunlap Cc: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/cciss.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 12de1fdaa6c..9364dc55425 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2847,7 +2847,7 @@ static void do_cciss_request(struct request_queue *q) h->maxSG = seg; #ifdef CCISS_DEBUG - printk(KERN_DEBUG "cciss: Submitting %d sectors in %d segments\n", + printk(KERN_DEBUG "cciss: Submitting %lu sectors in %d segments\n", creq->nr_sectors, seg); #endif /* CCISS_DEBUG */ @@ -3197,7 +3197,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) c->paddr = pci_resource_start(pdev, 0); /* addressing mode bits already removed */ #ifdef CCISS_DEBUG - printk("address 0 = %x\n", c->paddr); + printk("address 0 = %lx\n", c->paddr); #endif /* CCISS_DEBUG */ c->vaddr = remap_pci_mem(c->paddr, 0x250); @@ -3224,7 +3224,8 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) #endif /* CCISS_DEBUG */ cfg_base_addr_index = find_PCI_BAR_index(pdev, cfg_base_addr); #ifdef CCISS_DEBUG - printk("cfg base address index = %x\n", cfg_base_addr_index); + printk("cfg base address index = %llx\n", + (unsigned long long)cfg_base_addr_index); #endif /* CCISS_DEBUG */ if (cfg_base_addr_index == -1) { printk(KERN_WARNING "cciss: Cannot find cfg_base_addr_index\n"); @@ -3234,7 +3235,7 @@ static int __devinit cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) cfg_offset = readl(c->vaddr + SA5_CTMEM_OFFSET); #ifdef CCISS_DEBUG - printk("cfg offset = %x\n", cfg_offset); + printk("cfg offset = %llx\n", (unsigned long long)cfg_offset); #endif /* CCISS_DEBUG */ c->cfgtable = remap_pci_mem(pci_resource_start(pdev, cfg_base_addr_index) + -- cgit v1.2.3 From b09bc6cbae4dd3a2d35722668ef2c502a7b8b093 Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Fri, 14 Nov 2008 11:42:29 +0800 Subject: USB: fix SB700 usb subsystem hang bug This patch is required for AMD SB700 south bridge revision A12 and A13 to avoid USB subsystem hang symptom. The USB subsystem hang symptom is observed when the system has multiple USB devices connected to it. In some cases a USB hub may be required to observe this symptom. This patch works around the problem by correcting the internal register setting that will help by changing the behavior of the internal logic to avoid the USB subsystem hang issue. The change in the behavior of the logic does not impact the normal operation of the USB subsystem. Reported-by: Volker Armin Hemmann Tested-by: Volker Armin Hemmann Signed-off-by: Andiry Xu Signed-off-by: Libin Yang Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pci.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index c46a58f9181..9d0ea573aef 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -66,6 +66,8 @@ static int ehci_pci_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + struct pci_dev *p_smbus; + u8 rev; u32 temp; int retval; @@ -166,6 +168,25 @@ static int ehci_pci_setup(struct usb_hcd *hcd) pci_write_config_byte(pdev, 0x4b, tmp | 0x20); } break; + case PCI_VENDOR_ID_ATI: + /* SB700 old version has a bug in EHCI controller, + * which causes usb devices lose response in some cases. + */ + if (pdev->device == 0x4396) { + p_smbus = pci_get_device(PCI_VENDOR_ID_ATI, + PCI_DEVICE_ID_ATI_SBX00_SMBUS, + NULL); + if (!p_smbus) + break; + rev = p_smbus->revision; + if ((rev == 0x3a) || (rev == 0x3b)) { + u8 tmp; + pci_read_config_byte(pdev, 0x53, &tmp); + pci_write_config_byte(pdev, 0x53, tmp | (1<<3)); + } + pci_dev_put(p_smbus); + } + break; } ehci_reset(ehci); -- cgit v1.2.3 From aa5cbbecd903e5692b64f871c385ece1c5508eac Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 17 Nov 2008 09:08:16 +0200 Subject: usb: musb: fix bug in musb_schedule This bug was introduced recently. Fix it before bigger problems appear. Signed-off-by: Felipe Balbi Cc: Sergei Shtylyov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index e45e70bcc5e..cc64462d4c4 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1757,7 +1757,7 @@ static int musb_schedule( } } /* use bulk reserved ep1 if no other ep is free */ - if (best_end > 0 && qh->type == USB_ENDPOINT_XFER_BULK) { + if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) { hw_ep = musb->bulk_ep; if (is_in) head = &musb->in_bulk; -- cgit v1.2.3 From 9beba53dc5c330d781ecc0ad8ea081c2d100ff9f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 17 Nov 2008 16:12:32 -0500 Subject: USB: storage: updates unusual_devs entry for the Nokia 6300 This patch (as1169) modifies the unusual_devs entry for the Nokia 6300. According to Maciej Gierok and David McBride , the revision limits need to be wider. This fixes Bugzilla #11768. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index d4e5fc86e43..096a439baa3 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -240,7 +240,7 @@ UNUSUAL_DEV( 0x0421, 0x04b9, 0x0551, 0x0551, US_FL_FIX_CAPACITY ), /* Reported by Richard Nauber */ -UNUSUAL_DEV( 0x0421, 0x04fa, 0x0601, 0x0601, +UNUSUAL_DEV( 0x0421, 0x04fa, 0x0550, 0x0660, "Nokia", "6300", US_SC_DEVICE, US_PR_DEVICE, NULL, -- cgit v1.2.3 From 589afd3bec907f02c133d7b8185b8af534f14a8e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 17 Nov 2008 14:32:16 -0500 Subject: USB: storage: update unusual_devs entries for Nokia 5300 and 5310 This patch (as1168) updates the unusual_devs entry for the Nokia 5300. According to Jorge Lucangeli Obes , some existing models have a revision number lower than the lower limit of the current entry. The patch also moves the entry for the Nokia 5310 to its correct place in the file. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 096a439baa3..6da9a7a962a 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -167,6 +167,13 @@ UNUSUAL_DEV( 0x0421, 0x005d, 0x0001, 0x0600, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Patch for Nokia 5310 capacity */ +UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0591, + "Nokia", + "5310", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Reported by Mario Rettig */ UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100, "Nokia", @@ -233,7 +240,7 @@ UNUSUAL_DEV( 0x0421, 0x0495, 0x0370, 0x0370, US_FL_MAX_SECTORS_64 ), /* Reported by Cedric Godin */ -UNUSUAL_DEV( 0x0421, 0x04b9, 0x0551, 0x0551, +UNUSUAL_DEV( 0x0421, 0x04b9, 0x0500, 0x0551, "Nokia", "5300", US_SC_DEVICE, US_PR_DEVICE, NULL, -- cgit v1.2.3 From 9c264521a9f836541c122b00f505cfd60cc5bbb5 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sat, 15 Nov 2008 19:53:21 -0800 Subject: USB: gadget rndis: stop windows self-immolation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Somewhere in the conversion of the RNDIS gadget code to the new framework, the descriptor of its data interface seems to have been copied from the CDC Ethernet driver. Unfortunately that means it got a nonzero altsetting ... which is incorrect. Issue uncovered by Richard Röjfors . This patch fixes that problem, and resolves at least some cases of Windows XP bluescreening itself. Tested-by: Richard Röjfors . Signed-off-by: David Brownell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_rndis.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 659b3d9671c..8afb14a4a72 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -172,7 +172,6 @@ static struct usb_interface_descriptor rndis_data_intf __initdata = { .bDescriptorType = USB_DT_INTERFACE, /* .bInterfaceNumber = DYNAMIC */ - .bAlternateSetting = 1, .bNumEndpoints = 2, .bInterfaceClass = USB_CLASS_CDC_DATA, .bInterfaceSubClass = 0, -- cgit v1.2.3 From ff3495052af48f7a2bf7961b131dc9e161dae19c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20R=C3=B6jfors?= Date: Sat, 15 Nov 2008 19:53:24 -0800 Subject: USB: gadget rndis: send notifications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It turns out that atomic_inc_return() returns the *new* value not the original one, so the logic in rndis_response_available() kept the first RNDIS response notification from getting out. This prevented interoperation with MS-Windows (but not Linux). Fix this to make RNDIS behave again. Signed-off-by: Richard Röjfors Signed-off-by: David Brownell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_rndis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 8afb14a4a72..428b5993575 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -302,7 +302,7 @@ static void rndis_response_available(void *_rndis) __le32 *data = req->buf; int status; - if (atomic_inc_return(&rndis->notify_count)) + if (atomic_inc_return(&rndis->notify_count) != 1) return; /* Send RNDIS RESPONSE_AVAILABLE notification; a -- cgit v1.2.3 From f1c0a2a3aff53698f4855968d576464041d49b39 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Fri, 14 Nov 2008 09:47:41 -0700 Subject: USB: usbmon: fix read(2) There's a bug in the usbmon binary reader: When using read() to fetch the packets and a packet's data is partially read, the next read call will once again return up to len_cap bytes of data. The b_read counter is not regarded when determining the remaining chunk size. So, when dumping USB data with "cat /dev/usbmon0 > usbmon.trace" while reading from a USB storage device and analyzing the dump file afterwards it will get out of sync after a couple of packets. Signed-off-by: Ingo van Lil Signed-off-by: Pete Zaitcev Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/mon/mon_bin.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index c9de3f027aa..e06810aef2d 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -687,7 +687,10 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf, } if (rp->b_read >= sizeof(struct mon_bin_hdr)) { - step_len = min(nbytes, (size_t)ep->len_cap); + step_len = ep->len_cap; + step_len -= rp->b_read - sizeof(struct mon_bin_hdr); + if (step_len > nbytes) + step_len = nbytes; offset = rp->b_out + PKT_SIZE; offset += rp->b_read - sizeof(struct mon_bin_hdr); if (offset >= rp->b_size) -- cgit v1.2.3 From 5091b58751d9bf51e92aa9e07f3332dcacc2af1c Mon Sep 17 00:00:00 2001 From: M Kondrin Date: Fri, 14 Nov 2008 13:02:45 +0300 Subject: USB: ACE1001 patch for cp2101.c The patch which adds IDs for AKTAKOM USB->RS232 cable (http://www.aktakom.ru/product/kio/ace-1001.htm) is attached. From: M Kondrin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 9035d7256b0..cfaf1f08553 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -56,6 +56,7 @@ static void cp2101_shutdown(struct usb_serial *); static int debug; static struct usb_device_id id_table [] = { + { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ -- cgit v1.2.3 From fb5e2f9b9410a4362897d12dc1ed4f7cec1b0d45 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Mon, 17 Nov 2008 20:29:58 +0000 Subject: sh: sh_eth: Update to change of mii_bus Update to change of mii_bus interface and fix some warning. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: David S. Miller --- drivers/net/sh_eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index a24bb68887a..59f242a6771 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -927,7 +927,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev) struct sh_eth_private *mdp = netdev_priv(ndev); struct sh_eth_txdesc *txdesc; u32 entry; - int flags; + unsigned long flags; spin_lock_irqsave(&mdp->lock, flags); if ((mdp->cur_tx - mdp->dirty_tx) >= (TX_RING_SIZE - 4)) { @@ -1141,7 +1141,7 @@ static int sh_mdio_init(struct net_device *ndev, int id) /* Hook up MII support for ethtool */ mdp->mii_bus->name = "sh_mii"; mdp->mii_bus->parent = &ndev->dev; - mdp->mii_bus->id[0] = id; + snprintf(mdp->mii_bus->id, MII_BUS_ID_SIZE, "%x", id); /* PHY IRQ */ mdp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); -- cgit v1.2.3 From bcb3336ce4354395e38df7e2da110fca61f86a84 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 18 Nov 2008 04:28:35 +0000 Subject: mv643xx_eth: fix the order of mdiobus_{unregister, free}() calls Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index b9dcdbd369f..baa7e845a01 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2435,8 +2435,8 @@ static int mv643xx_eth_shared_remove(struct platform_device *pdev) struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data; if (pd == NULL || pd->shared_smi == NULL) { - mdiobus_free(msp->smi_bus); mdiobus_unregister(msp->smi_bus); + mdiobus_free(msp->smi_bus); } if (msp->err_interrupt != NO_IRQ) free_irq(msp->err_interrupt, msp); -- cgit v1.2.3 From 11b4aa03b212cbaa969df25e723fbd400a6e24b9 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Tue, 18 Nov 2008 04:28:58 +0000 Subject: mv643xx_eth: fix recycle check bound When mv643xx_eth allocates skbuffs, it adds 'dma_get_cache_alignment() - 1' to the length it needs, so that it can align the skb's ->data pointer to a cache boundary. When checking whether a transmitted skbuff can be reused as a receive buffer, these bytes needs to be included into the minimum bound for the recycle check. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index baa7e845a01..e513f76f2a9 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -899,7 +899,8 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) if (skb != NULL) { if (skb_queue_len(&mp->rx_recycle) < mp->default_rx_ring_size && - skb_recycle_check(skb, mp->skb_size)) + skb_recycle_check(skb, mp->skb_size + + dma_get_cache_alignment() - 1)) __skb_queue_head(&mp->rx_recycle, skb); else dev_kfree_skb(skb); -- cgit v1.2.3 From a7f75c0c9cfb628512b30795bcba02c8a97e03a0 Mon Sep 17 00:00:00 2001 From: Pantelis Koukousoulas Date: Thu, 20 Nov 2008 01:48:46 -0800 Subject: asix: Fix asix-based cards connecting to 10/100Mbs LAN. Add AX_MEDIUM_ENCK also when speed = 10/100Mbps. This allows my belkin f5d5055 to work with my 100Mbps switch and with an old 10Mbps ISA card. Without this patch, the card is recognized and the interface is brought up fine, but no packets actually flow through the interface. Signed-off-by: Pantelis Koukousoulas Acked-by: David Hollis Signed-off-by: David S. Miller --- drivers/net/usb/asix.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index e12cdb4543b..de57490103f 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -1102,12 +1102,14 @@ static int ax88178_link_reset(struct usbnet *dev) mode = AX88178_MEDIUM_DEFAULT; if (ecmd.speed == SPEED_1000) - mode |= AX_MEDIUM_GM | AX_MEDIUM_ENCK; + mode |= AX_MEDIUM_GM; else if (ecmd.speed == SPEED_100) mode |= AX_MEDIUM_PS; else mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM); + mode |= AX_MEDIUM_ENCK; + if (ecmd.duplex == DUPLEX_FULL) mode |= AX_MEDIUM_FD; else -- cgit v1.2.3 From eafdcb433f854c8cb06747a80fa3df7c72147be6 Mon Sep 17 00:00:00 2001 From: Vernon Sauder Date: Thu, 20 Nov 2008 01:56:08 -0800 Subject: smc911x: Fix printf format typo in smc911x driver. Signed-off-by: Vernon Sauder Signed-off-by: David S. Miller --- drivers/net/smc911x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 1f26ab0e798..b185cd12269 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -1813,7 +1813,7 @@ static int __init smc911x_probe(struct net_device *dev) val = SMC_GET_BYTE_TEST(lp); DBG(SMC_DEBUG_MISC, "%s: endian probe returned 0x%04x\n", CARDNAME, val); if (val != 0x87654321) { - printk(KERN_ERR "Invalid chip endian 0x08%x\n",val); + printk(KERN_ERR "Invalid chip endian 0x%08x\n",val); retval = -ENODEV; goto err_out; } -- cgit v1.2.3 From 06d2148ed3b3fa997fa5a848f6405709c464b3ba Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 20 Nov 2008 11:22:17 +0100 Subject: HID: unignore mouse on unibody macbooks In commit a96d6ef34, the mouse interfaces on the unibody macbooks were put into hid mouse ignore list. This was a little bit too premature though, as the corresponding bcm5974 changes are scheduled for 2.6.29. Remove these devices from the ignore list for now, in order to provide at least basic functionality with the HID driver. Will be reintroduced in 2.6.29 Reported-by: Henrik Rydberg Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 69b1ce800f7..5000711999e 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1576,9 +1576,6 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { } -- cgit v1.2.3 From a849854fc7e200d5e5a437dec9c1d0e8b105e50f Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Thu, 20 Nov 2008 04:18:25 -0800 Subject: atl2: don't request irq on resume if netif running If the device is suspended with the cable disconnected, then resumed with the cable connected, dev->open is called before resume. During resume, we request an IRQ, but the IRQ was already assigned during dev->open, resulting in the warning shown below. Don't request an IRQ if the device is running. Call Trace: [] warn_on_slowpath+0x40/0x59 [] raw_pci_read+0x4d/0x55 [] pci_read+0x1c/0x21 [] __pci_find_next_cap_ttl+0x44/0x70 [] __pci_find_next_cap+0x1a/0x1f [] pci_find_capability+0x28/0x2c [] pci_msi_check_device+0x53/0x62 [] pci_enable_msi+0x3a/0x1cd [] atl2_write_phy_reg+0x40/0x5f [atl2] [] dma_generic_alloc_coherent+0x0/0xd7 [] atl2_request_irq+0x15/0x49 [atl2] [] atl2_open+0x20b/0x297 [atl2] [] dev_open+0x62/0x91 [] dev_change_flags+0x93/0x141 [] do_setlink+0x238/0x2d5 [] rtnl_setlink+0xa9/0xbf [] mutex_lock+0xb/0x19 [] rtnl_dump_ifinfo+0x0/0x69 [] rtnl_setlink+0x0/0xbf [] rtnetlink_rcv_msg+0x185/0x19f [] sock_rmalloc+0x23/0x57 [] rtnetlink_rcv_msg+0x0/0x19f [] netlink_rcv_skb+0x2d/0x71 [] rtnetlink_rcv+0x14/0x1a [] netlink_unicast+0x184/0x1e4 [] netlink_sendmsg+0x233/0x240 [] sock_sendmsg+0xb7/0xd0 [] autoremove_wake_function+0x0/0x2b [] autoremove_wake_function+0x0/0x2b [] mempool_alloc+0x2d/0x9e [] scsi_pool_alloc_command+0x35/0x4f [] mutex_lock+0xb/0x19 [] unix_stream_recvmsg+0x357/0x3e2 [] copy_from_user+0x23/0x4f [] verify_iovec+0x3e/0x6c [] sys_sendmsg+0x18d/0x1f0 [] sys_recvmsg+0x146/0x1c8 [] sys_recvmsg+0x1b4/0x1c8 [] __wake_up+0xf/0x15 [] netlink_table_ungrab+0x17/0x19 [] copy_to_user+0x25/0x3b [] move_addr_to_user+0x50/0x68 [] sys_getsockname+0x6f/0x9a [] sys_getsockname+0x89/0x9a [] do_wp_page+0x3ae/0x41a [] handle_mm_fault+0x4c5/0x540 [] sys_socketcall+0x176/0x1b0 [] sysenter_do_call+0x12/0x21 Signed-off-by: Alan Jenkins Signed-off-by: Jay Cliburn Signed-off-by: David S. Miller --- drivers/net/atlx/atl2.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c index f5bdc92c1a6..8571e8c0bc6 100644 --- a/drivers/net/atlx/atl2.c +++ b/drivers/net/atlx/atl2.c @@ -1690,9 +1690,11 @@ static int atl2_resume(struct pci_dev *pdev) ATL2_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); - err = atl2_request_irq(adapter); - if (netif_running(netdev) && err) - return err; + if (netif_running(netdev)) { + err = atl2_request_irq(adapter); + if (err) + return err; + } atl2_reset_hw(&adapter->hw); -- cgit v1.2.3 From 578f3a35fecabff49bad808c5301313f785b5462 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 20 Nov 2008 15:55:38 +0100 Subject: HID: add USB ID for another dual gameron adapter 0x0810/0x0002 needs the very same handling as 0x0001. Reported-by: Steve Conklin Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + drivers/hid/hid-pl.c | 2 ++ 3 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 5000711999e..026a46333fd 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1267,6 +1267,7 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) }, { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index d70075dd3d8..39289699c32 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -163,6 +163,7 @@ #define USB_VENDOR_ID_GAMERON 0x0810 #define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001 +#define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c index acd81558618..46941f979b9 100644 --- a/drivers/hid/hid-pl.c +++ b/drivers/hid/hid-pl.c @@ -178,6 +178,8 @@ err: static const struct hid_device_id pl_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR), .driver_data = 1 }, /* Twin USB Joystick */ + { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR), + .driver_data = 1 }, /* Twin USB Joystick */ { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003), }, /* GreenAsia Inc. USB Joystick */ { } }; -- cgit v1.2.3 From 625ff1679456d8adb9af0c980394ea3954e727a8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 Nov 2008 10:23:19 -0300 Subject: V4L/DVB (9645): em28xx: Avoid memory leaks if registration fails em28xx_init_dev() has some error conditions that are not properly de-allocating dev var, nor freeing the device number for a future usage. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index a1ab2ef4557..bca5955339b 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1953,8 +1953,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, errCode = em28xx_config(dev); if (errCode) { em28xx_errdev("error configuring device\n"); - em28xx_devused &= ~(1<devno); - kfree(dev); return -ENOMEM; } @@ -2088,7 +2086,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, fail_unreg: em28xx_release_resources(dev); mutex_unlock(&dev->lock); - kfree(dev); return retval; } @@ -2231,8 +2228,12 @@ static int em28xx_usb_probe(struct usb_interface *interface, /* allocate device struct */ retval = em28xx_init_dev(&dev, udev, nr); - if (retval) + if (retval) { + em28xx_devused &= ~(1<devno); + kfree(dev); + return retval; + } em28xx_info("Found %s\n", em28xx_boards[dev->model].name); -- cgit v1.2.3 From c4a98793a63c423c9e1af51822325969e23c16d4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 Nov 2008 14:51:08 -0300 Subject: V4L/DVB (9646): em28xx: avoid allocating/dealocating memory on every control urb Before this patch, every register setup on em28xx were dynamically allocating a temporary buffer for control URB's to be handled. To avoid this ping-pong, use, instead a pre-allocated buffer. Also, be sure that read control URB's also use the buffer, instead of relying on a stack buffer. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 48 +++++++++++++++++--------------- drivers/media/video/em28xx/em28xx.h | 5 ++++ 2 files changed, 31 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 038da614a73..9551b8ab8c4 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -69,19 +69,29 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, int ret, byte; if (dev->state & DEV_DISCONNECTED) - return(-ENODEV); + return -ENODEV; + + if (len > URB_MAX_CTRL_SIZE) + return -EINVAL; em28xx_regdbg("req=%02x, reg=%02x ", req, reg); ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0000, reg, buf, len, HZ); + 0x0000, reg, dev->urb_buf, len, HZ); + if (ret < 0) { + if (reg_debug) + printk(" failed!\n"); + return ret; + } + + if (len) + memcpy(buf, dev->urb_buf, len); if (reg_debug) { - printk(ret < 0 ? " failed!\n" : "%02x values: ", ret); + printk("%02x values: ", ret); for (byte = 0; byte < len; byte++) printk(" %02x", (unsigned char)buf[byte]); - printk("\n"); } @@ -104,14 +114,16 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0000, reg, &val, 1, HZ); + 0x0000, reg, dev->urb_buf, 1, HZ); + if (ret < 0) { + printk(" failed!\n"); + return ret; + } - if (reg_debug) - printk(ret < 0 ? " failed!\n" : - "%02x\n", (unsigned char) val); + val = dev->urb_buf[0]; - if (ret < 0) - return ret; + if (reg_debug) + printk("%02x\n", (unsigned char) val); return val; } @@ -130,19 +142,13 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, { int ret; - /*usb_control_msg seems to expect a kmalloced buffer */ - unsigned char *bufs; - if (dev->state & DEV_DISCONNECTED) return -ENODEV; - if (len < 1) + if ((len < 1) || (len > URB_MAX_CTRL_SIZE)) return -EINVAL; - bufs = kmalloc(len, GFP_KERNEL); - em28xx_regdbg("req=%02x reg=%02x:", req, reg); - if (reg_debug) { int i; for (i = 0; i < len; ++i) @@ -150,16 +156,14 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, printk("\n"); } - if (!bufs) - return -ENOMEM; - memcpy(bufs, buf, len); + memcpy(dev->urb_buf, buf, len); ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0000, reg, bufs, len, HZ); + 0x0000, reg, dev->urb_buf, len, HZ); + if (dev->wait_after_write) msleep(dev->wait_after_write); - kfree(bufs); return ret; } diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 82781178e0a..1adf3d9d9bf 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -102,6 +102,9 @@ #define EM28XX_MIN_BUF 4 #define EM28XX_DEF_BUF 8 +/*Limits the max URB message size */ +#define URB_MAX_CTRL_SIZE 80 + /* Params for validated field */ #define EM28XX_BOARD_NOT_VALIDATED 1 #define EM28XX_BOARD_VALIDATED 0 @@ -451,6 +454,8 @@ struct em28xx { unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */ + char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ + /* helper funcs that call usb_control_msg */ int (*em28xx_write_regs) (struct em28xx *dev, u16 reg, char *buf, int len); -- cgit v1.2.3 From f2a2e4910502e866833732f31ee697d15b3e56fd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 19 Nov 2008 06:17:44 -0300 Subject: V4L/DVB (9647): em28xx: void having two concurrent control URB's Now that we have a polling task for IR, there's a race condition, since IR can be polling while other operations are being doing. Also, we are now sharing the same urb_buf for both read and write control urb operations. So, we need a mutex. Thanks to Davin Heitmueller for warning me. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-core.c | 12 ++++++++++-- drivers/media/video/em28xx/em28xx-video.c | 1 + drivers/media/video/em28xx/em28xx.h | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 9551b8ab8c4..15e2b525310 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -76,18 +76,22 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, em28xx_regdbg("req=%02x, reg=%02x ", req, reg); + mutex_lock(&dev->ctrl_urb_lock); ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0000, reg, dev->urb_buf, len, HZ); if (ret < 0) { if (reg_debug) printk(" failed!\n"); + mutex_unlock(&dev->ctrl_urb_lock); return ret; } if (len) memcpy(buf, dev->urb_buf, len); + mutex_unlock(&dev->ctrl_urb_lock); + if (reg_debug) { printk("%02x values: ", ret); for (byte = 0; byte < len; byte++) @@ -112,16 +116,18 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) em28xx_regdbg("req=%02x, reg=%02x:", req, reg); + mutex_lock(&dev->ctrl_urb_lock); ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0000, reg, dev->urb_buf, 1, HZ); + val = dev->urb_buf[0]; + mutex_unlock(&dev->ctrl_urb_lock); + if (ret < 0) { printk(" failed!\n"); return ret; } - val = dev->urb_buf[0]; - if (reg_debug) printk("%02x\n", (unsigned char) val); @@ -156,10 +162,12 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, printk("\n"); } + mutex_lock(&dev->ctrl_urb_lock); memcpy(dev->urb_buf, buf, len); ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0x0000, reg, dev->urb_buf, len, HZ); + mutex_unlock(&dev->ctrl_urb_lock); if (dev->wait_after_write) msleep(dev->wait_after_write); diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index bca5955339b..c32fc7d24a4 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1936,6 +1936,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->udev = udev; mutex_init(&dev->lock); + mutex_init(&dev->ctrl_urb_lock); spin_lock_init(&dev->slock); init_waitqueue_head(&dev->open); init_waitqueue_head(&dev->wait_frame); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 1adf3d9d9bf..5956e9b3062 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -433,6 +433,7 @@ struct em28xx { /* locks */ struct mutex lock; + struct mutex ctrl_urb_lock; /* protects urb_buf */ /* spinlock_t queue_lock; */ struct list_head inqueue, outqueue; wait_queue_head_t open, wait_frame, wait_stream; -- cgit v1.2.3 From cce257109f534b4954a5d04aa4ba6905f4682f93 Mon Sep 17 00:00:00 2001 From: Jose Alberto Reguero Date: Thu, 13 Nov 2008 14:14:18 -0300 Subject: V4L/DVB (9664): af9015: don't reconnect device in USB-bus Don't reconnect device in the USB-bus. Reconnect command was not executed every time by device firmware and that causes harm. Reconnection is not needed so remove it. Signed-off-by: Jose Alberto Reguero Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 847d8fdd9ec..e9ab0249d13 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -681,12 +681,6 @@ static int af9015_download_firmware(struct usb_device *udev, goto error; } - /* firmware is running, reconnect device in the usb bus */ - req.cmd = RECONNECT_USB; - ret = af9015_rw_udev(udev, &req); - if (ret) - err("reconnect failed: %d", ret); - error: return ret; } @@ -1208,6 +1202,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .usb_ctrl = DEVICE_SPECIFIC, .download_firmware = af9015_download_firmware, .firmware = "dvb-usb-af9015.fw", + .no_reconnect = 1, .size_of_priv = sizeof(struct af9015_state), \ @@ -1306,6 +1301,7 @@ static struct dvb_usb_device_properties af9015_properties[] = { .usb_ctrl = DEVICE_SPECIFIC, .download_firmware = af9015_download_firmware, .firmware = "dvb-usb-af9015.fw", + .no_reconnect = 1, .size_of_priv = sizeof(struct af9015_state), \ -- cgit v1.2.3 From 818a557eeb9c16a9a2dc93df348b0ff68fbc487f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 20 Nov 2008 10:30:26 -0300 Subject: V4L/DVB (9668): em28xx: fix a race condition with hald Newer versions of hald tries to open it to call QUERYCAP. Due to the lack of a proper locking, it is possible to open the device before it finishes initialization. This patch adds a lock to avoid this risk, and to protect the list of em28xx devices. While here, remove the uneeded BKL lock. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 128 +++++++++++++++++------------- 1 file changed, 75 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index c32fc7d24a4..90a11b5ac0b 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -73,6 +73,7 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); static LIST_HEAD(em28xx_devlist); +static DEFINE_MUTEX(em28xx_devlist_mutex); static unsigned int card[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET }; @@ -1519,7 +1520,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) struct em28xx_fh *fh; enum v4l2_buf_type fh_type = 0; - lock_kernel(); + mutex_lock(&em28xx_devlist_mutex); list_for_each_entry(h, &em28xx_devlist, devlist) { if (h->vdev->minor == minor) { dev = h; @@ -1535,10 +1536,11 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev = h; } } - if (NULL == dev) { - unlock_kernel(); + mutex_unlock(&em28xx_devlist_mutex); + if (NULL == dev) return -ENODEV; - } + + mutex_lock(&dev->lock); em28xx_videodbg("open minor=%d type=%s users=%d\n", minor, v4l2_type_names[fh_type], dev->users); @@ -1547,10 +1549,9 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL); if (!fh) { em28xx_errdev("em28xx-video.c: Out of memory?!\n"); - unlock_kernel(); + mutex_unlock(&dev->lock); return -ENOMEM; } - mutex_lock(&dev->lock); fh->dev = dev; fh->radio = radio; fh->type = fh_type; @@ -1584,7 +1585,6 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) sizeof(struct em28xx_buffer), fh); mutex_unlock(&dev->lock); - unlock_kernel(); return errCode; } @@ -1871,6 +1871,7 @@ int em28xx_register_extension(struct em28xx_ops *ops) { struct em28xx *dev = NULL; + mutex_lock(&em28xx_devlist_mutex); mutex_lock(&em28xx_extension_devlist_lock); list_add_tail(&ops->next, &em28xx_extension_devlist); list_for_each_entry(dev, &em28xx_devlist, devlist) { @@ -1879,6 +1880,7 @@ int em28xx_register_extension(struct em28xx_ops *ops) } printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); mutex_unlock(&em28xx_extension_devlist_lock); + mutex_unlock(&em28xx_devlist_mutex); return 0; } EXPORT_SYMBOL(em28xx_register_extension); @@ -1887,6 +1889,7 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) { struct em28xx *dev = NULL; + mutex_lock(&em28xx_devlist_mutex); list_for_each_entry(dev, &em28xx_devlist, devlist) { if (dev) ops->fini(dev); @@ -1896,6 +1899,7 @@ void em28xx_unregister_extension(struct em28xx_ops *ops) printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); list_del(&ops->next); mutex_unlock(&em28xx_extension_devlist_lock); + mutex_unlock(&em28xx_devlist_mutex); } EXPORT_SYMBOL(em28xx_unregister_extension); @@ -1921,6 +1925,60 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev, } +static int register_analog_devices(struct em28xx *dev) +{ + int ret; + + /* allocate and fill video video_device struct */ + dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); + if (!dev->vdev) { + em28xx_errdev("cannot allocate video_device.\n"); + return -ENODEV; + } + + /* register v4l2 video video_device */ + ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER, + video_nr[dev->devno]); + if (ret) { + em28xx_errdev("unable to register video device (error=%i).\n", + ret); + return ret; + } + + /* Allocate and fill vbi video_device struct */ + dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, "vbi"); + + /* register v4l2 vbi video_device */ + ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, + vbi_nr[dev->devno]); + if (ret < 0) { + em28xx_errdev("unable to register vbi device\n"); + return ret; + } + + if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) { + dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio"); + if (!dev->radio_dev) { + em28xx_errdev("cannot allocate video_device.\n"); + return -ENODEV; + } + ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, + radio_nr[dev->devno]); + if (ret < 0) { + em28xx_errdev("can't register radio device\n"); + return ret; + } + em28xx_info("Registered radio device as /dev/radio%d\n", + dev->radio_dev->num); + } + + em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", + dev->vdev->num, dev->vbi_dev->num); + + return 0; +} + + /* * em28xx_init_dev() * allocates and inits the device structs, registers i2c bus and v4l device @@ -2000,50 +2058,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, return errCode; } - list_add_tail(&dev->devlist, &em28xx_devlist); - - /* allocate and fill video video_device struct */ - dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video"); - if (NULL == dev->vdev) { - em28xx_errdev("cannot allocate video_device.\n"); - goto fail_unreg; - } - - /* register v4l2 video video_device */ - retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, - video_nr[dev->devno]); - if (retval) { - em28xx_errdev("unable to register video device (error=%i).\n", - retval); - goto fail_unreg; - } - - /* Allocate and fill vbi video_device struct */ - dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template, "vbi"); - /* register v4l2 vbi video_device */ - if (video_register_device(dev->vbi_dev, VFL_TYPE_VBI, - vbi_nr[dev->devno]) < 0) { - em28xx_errdev("unable to register vbi device\n"); - retval = -ENODEV; - goto fail_unreg; - } - - if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) { - dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template, "radio"); - if (NULL == dev->radio_dev) { - em28xx_errdev("cannot allocate video_device.\n"); - goto fail_unreg; - } - retval = video_register_device(dev->radio_dev, VFL_TYPE_RADIO, - radio_nr[dev->devno]); - if (retval < 0) { - em28xx_errdev("can't register radio device\n"); - goto fail_unreg; - } - em28xx_info("Registered radio device as /dev/radio%d\n", - dev->radio_dev->num); - } - /* init video dma queues */ INIT_LIST_HEAD(&dev->vidq.active); INIT_LIST_HEAD(&dev->vidq.queued); @@ -2070,8 +2084,14 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, video_mux(dev, 0); - em28xx_info("V4L2 device registered as /dev/video%d and /dev/vbi%d\n", - dev->vdev->num, dev->vbi_dev->num); + mutex_lock(&em28xx_devlist_mutex); + list_add_tail(&dev->devlist, &em28xx_devlist); + retval = register_analog_devices(dev); + if (retval < 0) { + em28xx_release_resources(dev); + mutex_unlock(&em28xx_devlist_mutex); + goto fail_reg_devices; + } mutex_lock(&em28xx_extension_devlist_lock); if (!list_empty(&em28xx_extension_devlist)) { @@ -2081,11 +2101,13 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, } } mutex_unlock(&em28xx_extension_devlist_lock); + mutex_unlock(&em28xx_devlist_mutex); return 0; fail_unreg: em28xx_release_resources(dev); +fail_reg_devices: mutex_unlock(&dev->lock); return retval; } -- cgit v1.2.3 From 75e07fc3d87ba9b3255e1fcd735186a533ea0754 Mon Sep 17 00:00:00 2001 From: Andreas Petlund Date: Thu, 20 Nov 2008 20:42:25 -0800 Subject: pci: Added quirk to disable msi for MCP55 NIC on Asus P5N32-SLI Premium Signed-off-by: Andreas Petlund Signed-off-by: David S. Miller --- drivers/pci/quirks.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 5049a47030a..5f4f85f56cb 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "pci.h" int isa_dma_bridge_buggy; @@ -1828,6 +1829,22 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB, ht_enable_msi_mapping); +/* The P5N32-SLI Premium motherboard from Asus has a problem with msi + * for the MCP55 NIC. It is not yet determined whether the msi problem + * also affects other devices. As for now, turn off msi for this device. + */ +static void __devinit nvenet_msi_disable(struct pci_dev *dev) +{ + if (dmi_name_in_vendors("P5N32-SLI PREMIUM")) { + dev_info(&dev->dev, + "Disabling msi for MCP55 NIC on P5N32-SLI Premium\n"); + dev->no_msi = 1; + } +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, + PCI_DEVICE_ID_NVIDIA_NVENET_15, + nvenet_msi_disable); + static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) { struct pci_dev *host_bridge; -- cgit v1.2.3 From 6436cbcd735a11fc93bf3353c68914bc545e6d1e Mon Sep 17 00:00:00 2001 From: Giuseppe Cavallaro Date: Thu, 20 Nov 2008 20:43:18 -0800 Subject: phy: fix phy_id detection also for broken hardware. This patch fixes the case when the phy_ids is mostly Fs and in some case 0x0 due to broken hardware. Signed-off-by: Giuseppe Cavallaro Signed-off-by: David S. Miller --- drivers/net/phy/phy_device.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 55bc24b234e..25acbbde4a6 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -227,8 +227,17 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr) if (r) return ERR_PTR(r); - /* If the phy_id is all Fs or all 0s, there is no device there */ - if ((0xffff == phy_id) || (0x00 == phy_id)) + /* If the phy_id is mostly Fs, there is no device there */ + if ((phy_id & 0x1fffffff) == 0x1fffffff) + return NULL; + + /* + * Broken hardware is sometimes missing the pull down resistor on the + * MDIO line, which results in reads to non-existent devices returning + * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent + * device as well. + */ + if (phy_id == 0) return NULL; dev = phy_device_create(bus, addr, phy_id); -- cgit v1.2.3 From f80e919bb42c191bbe60ab078a59b30336d11d3b Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 24 Oct 2008 19:52:56 +0200 Subject: [WATCHDOG] fix mtx1_wdt compilation failure Using spin_lock_irqsave with a local variable called flags without declaring is a bad idea, fix this by declaring it. Signed-off-by: Florian Fainelli Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/mtx-1_wdt.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index b4b7b0a4c11..3acce623f20 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -98,6 +98,8 @@ static void mtx1_wdt_reset(void) static void mtx1_wdt_start(void) { + unsigned long flags; + spin_lock_irqsave(&mtx1_wdt_device.lock, flags); if (!mtx1_wdt_device.queue) { mtx1_wdt_device.queue = 1; @@ -110,6 +112,8 @@ static void mtx1_wdt_start(void) static int mtx1_wdt_stop(void) { + unsigned long flags; + spin_lock_irqsave(&mtx1_wdt_device.lock, flags); if (mtx1_wdt_device.queue) { mtx1_wdt_device.queue = 0; -- cgit v1.2.3 From 7cd5b08be3c489df11b559fef210b81133764ad4 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Wed, 19 Nov 2008 19:39:58 +0000 Subject: [WATCHDOG] iTCO_wdt : problem with rebooting on new ICH9 based motherboards Bugzilla #9868: On Intel motherboards with the ICH9 based I/O controllers (Like DP35DP and DG33FB) the iTCO timer counts but it doesn't reboot the system after the counter expires. This patch fixes this by moving the enabling & disabling of the TCO_EN bit in the SMI_EN register into the start and stop code. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_vendor_support.c | 31 ++++--------------------- drivers/watchdog/iTCO_wdt.c | 41 +++++++++++++++++++++++----------- 2 files changed, 32 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/iTCO_vendor_support.c b/drivers/watchdog/iTCO_vendor_support.c index ca344a85eb9..2474ebca88f 100644 --- a/drivers/watchdog/iTCO_vendor_support.c +++ b/drivers/watchdog/iTCO_vendor_support.c @@ -1,7 +1,7 @@ /* * intel TCO vendor specific watchdog driver support * - * (c) Copyright 2006 Wim Van Sebroeck . + * (c) Copyright 2006-2008 Wim Van Sebroeck . * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -19,8 +19,7 @@ /* Module and version information */ #define DRV_NAME "iTCO_vendor_support" -#define DRV_VERSION "1.01" -#define DRV_RELDATE "11-Nov-2006" +#define DRV_VERSION "1.02" #define PFX DRV_NAME ": " /* Includes */ @@ -78,24 +77,6 @@ MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (n * 20.6 seconds. */ -static void supermicro_old_pre_start(unsigned long acpibase) -{ - unsigned long val32; - - val32 = inl(SMI_EN); - val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */ - outl(val32, SMI_EN); /* Needed to activate watchdog */ -} - -static void supermicro_old_pre_stop(unsigned long acpibase) -{ - unsigned long val32; - - val32 = inl(SMI_EN); - val32 &= 0x00002000; /* Turn on SMI clearing watchdog */ - outl(val32, SMI_EN); /* Needed to deactivate watchdog */ -} - static void supermicro_old_pre_keepalive(unsigned long acpibase) { /* Reload TCO Timer (done in iTCO_wdt_keepalive) + */ @@ -247,18 +228,14 @@ static void supermicro_new_pre_set_heartbeat(unsigned int heartbeat) void iTCO_vendor_pre_start(unsigned long acpibase, unsigned int heartbeat) { - if (vendorsupport == SUPERMICRO_OLD_BOARD) - supermicro_old_pre_start(acpibase); - else if (vendorsupport == SUPERMICRO_NEW_BOARD) + if (vendorsupport == SUPERMICRO_NEW_BOARD) supermicro_new_pre_start(heartbeat); } EXPORT_SYMBOL(iTCO_vendor_pre_start); void iTCO_vendor_pre_stop(unsigned long acpibase) { - if (vendorsupport == SUPERMICRO_OLD_BOARD) - supermicro_old_pre_stop(acpibase); - else if (vendorsupport == SUPERMICRO_NEW_BOARD) + if (vendorsupport == SUPERMICRO_NEW_BOARD) supermicro_new_pre_stop(); } EXPORT_SYMBOL(iTCO_vendor_pre_stop); diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index bfb93bc2ca9..75483000a87 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -1,7 +1,7 @@ /* * intel TCO Watchdog Driver (Used in i82801 and i6300ESB chipsets) * - * (c) Copyright 2006-2007 Wim Van Sebroeck . + * (c) Copyright 2006-2008 Wim Van Sebroeck . * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -56,8 +56,7 @@ /* Module and version information */ #define DRV_NAME "iTCO_wdt" -#define DRV_VERSION "1.03" -#define DRV_RELDATE "30-Apr-2008" +#define DRV_VERSION "1.04" #define PFX DRV_NAME ": " /* Includes */ @@ -311,6 +310,7 @@ static int iTCO_wdt_unset_NO_REBOOT_bit(void) static int iTCO_wdt_start(void) { unsigned int val; + unsigned long val32; spin_lock(&iTCO_wdt_private.io_lock); @@ -323,6 +323,18 @@ static int iTCO_wdt_start(void) return -EIO; } + /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */ + val32 = inl(SMI_EN); + val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */ + outl(val32, SMI_EN); + + /* Force the timer to its reload value by writing to the TCO_RLD + register */ + if (iTCO_wdt_private.iTCO_version == 2) + outw(0x01, TCO_RLD); + else if (iTCO_wdt_private.iTCO_version == 1) + outb(0x01, TCO_RLD); + /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */ val = inw(TCO1_CNT); val &= 0xf7ff; @@ -338,6 +350,7 @@ static int iTCO_wdt_start(void) static int iTCO_wdt_stop(void) { unsigned int val; + unsigned long val32; spin_lock(&iTCO_wdt_private.io_lock); @@ -349,6 +362,11 @@ static int iTCO_wdt_stop(void) outw(val, TCO1_CNT); val = inw(TCO1_CNT); + /* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */ + val32 = inl(SMI_EN); + val32 &= 0x00002000; + outl(val32, SMI_EN); + /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ iTCO_wdt_set_NO_REBOOT_bit(); @@ -459,7 +477,6 @@ static int iTCO_wdt_open(struct inode *inode, struct file *file) /* * Reload and activate timer */ - iTCO_wdt_keepalive(); iTCO_wdt_start(); return nonseekable_open(inode, file); } @@ -604,7 +621,6 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, int ret; u32 base_address; unsigned long RCBA; - unsigned long val32; /* * Find the ACPI/PM base I/O address which is the base @@ -644,17 +660,13 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ iTCO_wdt_set_NO_REBOOT_bit(); - /* Set the TCO_EN bit in SMI_EN register */ + /* The TCO logic uses the TCO_EN bit in the SMI_EN register */ if (!request_region(SMI_EN, 4, "iTCO_wdt")) { printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n", SMI_EN); ret = -EIO; goto out; } - val32 = inl(SMI_EN); - val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */ - outl(val32, SMI_EN); - release_region(SMI_EN, 4); /* The TCO I/O registers reside in a 32-byte range pointed to by the TCOBASE value */ @@ -662,7 +674,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n", TCOBASE); ret = -EIO; - goto out; + goto unreg_smi_en; } printk(KERN_INFO PFX @@ -701,6 +713,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, unreg_region: release_region(TCOBASE, 0x20); +unreg_smi_en: + release_region(SMI_EN, 4); out: if (iTCO_wdt_private.iTCO_version == 2) iounmap(iTCO_wdt_private.gcs); @@ -718,6 +732,7 @@ static void __devexit iTCO_wdt_cleanup(void) /* Deregister */ misc_deregister(&iTCO_wdt_miscdev); release_region(TCOBASE, 0x20); + release_region(SMI_EN, 4); if (iTCO_wdt_private.iTCO_version == 2) iounmap(iTCO_wdt_private.gcs); pci_dev_put(iTCO_wdt_private.pdev); @@ -782,8 +797,8 @@ static int __init iTCO_wdt_init_module(void) { int err; - printk(KERN_INFO PFX "Intel TCO WatchDog Timer Driver v%s (%s)\n", - DRV_VERSION, DRV_RELDATE); + printk(KERN_INFO PFX "Intel TCO WatchDog Timer Driver v%s\n", + DRV_VERSION); err = platform_driver_register(&iTCO_wdt_driver); if (err) -- cgit v1.2.3 From c6904ddb976d99b77d91b78a0ce5bdfffb416c49 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Wed, 19 Nov 2008 20:02:02 +0000 Subject: [WATCHDOG] iTCO_wdt : correct status clearing The iTCO_wdt code was not clearing the correct bits. It now clears the timeout status bit and then the SECOND_TO_STS bit and then the BOOT_STS bit. Note: we should first clear the SECOND_TO_STS bit before clearing the BOOT_STS bit. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 75483000a87..2b5409f5b4e 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -684,8 +684,9 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, TCOBASE); /* Clear out the (probably old) status */ - outb(0, TCO1_STS); - outb(3, TCO2_STS); + outb(8, TCO1_STS); /* Clear the Time Out Status bit */ + outb(2, TCO2_STS); /* Clear SECOND_TO_STS bit */ + outb(4, TCO2_STS); /* Clear BOOT_STS bit */ /* Make sure the watchdog is not running */ iTCO_wdt_stop(); -- cgit v1.2.3 From 28d41f53f05c51d4f445129de325b1072ee25b8b Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Wed, 19 Nov 2008 22:25:53 +0000 Subject: [WATCHDOG] iTCO_wdt: add PCI ID's for ICH9 & ICH10 chipsets Add support for the following I/O controller hubs: ICH7DH, ICH9M, ICH9M-E, ICH10, ICH10R, ICH10D and ICH10DO. Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 118 +++++++++++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 2b5409f5b4e..26173a270e9 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -20,34 +20,41 @@ * 82801BAM (ICH2-M) : document number 290687-002, 298242-027, * 82801CA (ICH3-S) : document number 290733-003, 290739-013, * 82801CAM (ICH3-M) : document number 290716-001, 290718-007, - * 82801DB (ICH4) : document number 290744-001, 290745-020, - * 82801DBM (ICH4-M) : document number 252337-001, 252663-005, + * 82801DB (ICH4) : document number 290744-001, 290745-025, + * 82801DBM (ICH4-M) : document number 252337-001, 252663-008, * 82801E (C-ICH) : document number 273599-001, 273645-002, - * 82801EB (ICH5) : document number 252516-001, 252517-003, - * 82801ER (ICH5R) : document number 252516-001, 252517-003, - * 82801FB (ICH6) : document number 301473-002, 301474-007, - * 82801FR (ICH6R) : document number 301473-002, 301474-007, - * 82801FBM (ICH6-M) : document number 301473-002, 301474-007, - * 82801FW (ICH6W) : document number 301473-001, 301474-007, - * 82801FRW (ICH6RW) : document number 301473-001, 301474-007, - * 82801GB (ICH7) : document number 307013-002, 307014-009, - * 82801GR (ICH7R) : document number 307013-002, 307014-009, - * 82801GDH (ICH7DH) : document number 307013-002, 307014-009, - * 82801GBM (ICH7-M) : document number 307013-002, 307014-009, - * 82801GHM (ICH7-M DH) : document number 307013-002, 307014-009, - * 82801HB (ICH8) : document number 313056-003, 313057-009, - * 82801HR (ICH8R) : document number 313056-003, 313057-009, - * 82801HBM (ICH8M) : document number 313056-003, 313057-009, - * 82801HH (ICH8DH) : document number 313056-003, 313057-009, - * 82801HO (ICH8DO) : document number 313056-003, 313057-009, - * 82801HEM (ICH8M-E) : document number 313056-003, 313057-009, - * 82801IB (ICH9) : document number 316972-001, 316973-006, - * 82801IR (ICH9R) : document number 316972-001, 316973-006, - * 82801IH (ICH9DH) : document number 316972-001, 316973-006, - * 82801IO (ICH9DO) : document number 316972-001, 316973-006, - * 6300ESB (6300ESB) : document number 300641-003, 300884-010, - * 631xESB (631xESB) : document number 313082-001, 313075-005, - * 632xESB (632xESB) : document number 313082-001, 313075-005 + * 82801EB (ICH5) : document number 252516-001, 252517-028, + * 82801ER (ICH5R) : document number 252516-001, 252517-028, + * 6300ESB (6300ESB) : document number 300641-004, 300884-013, + * 82801FB (ICH6) : document number 301473-002, 301474-026, + * 82801FR (ICH6R) : document number 301473-002, 301474-026, + * 82801FBM (ICH6-M) : document number 301473-002, 301474-026, + * 82801FW (ICH6W) : document number 301473-001, 301474-026, + * 82801FRW (ICH6RW) : document number 301473-001, 301474-026, + * 631xESB (631xESB) : document number 313082-001, 313075-006, + * 632xESB (632xESB) : document number 313082-001, 313075-006, + * 82801GB (ICH7) : document number 307013-003, 307014-024, + * 82801GR (ICH7R) : document number 307013-003, 307014-024, + * 82801GDH (ICH7DH) : document number 307013-003, 307014-024, + * 82801GBM (ICH7-M) : document number 307013-003, 307014-024, + * 82801GHM (ICH7-M DH) : document number 307013-003, 307014-024, + * 82801GU (ICH7-U) : document number 307013-003, 307014-024, + * 82801HB (ICH8) : document number 313056-003, 313057-017, + * 82801HR (ICH8R) : document number 313056-003, 313057-017, + * 82801HBM (ICH8M) : document number 313056-003, 313057-017, + * 82801HH (ICH8DH) : document number 313056-003, 313057-017, + * 82801HO (ICH8DO) : document number 313056-003, 313057-017, + * 82801HEM (ICH8M-E) : document number 313056-003, 313057-017, + * 82801IB (ICH9) : document number 316972-004, 316973-012, + * 82801IR (ICH9R) : document number 316972-004, 316973-012, + * 82801IH (ICH9DH) : document number 316972-004, 316973-012, + * 82801IO (ICH9DO) : document number 316972-004, 316973-012, + * 82801IBM (ICH9M) : document number 316972-004, 316973-012, + * 82801IEM (ICH9M-E) : document number 316972-004, 316973-012, + * 82801JIB (ICH10) : document number 319973-002, 319974-002, + * 82801JIR (ICH10R) : document number 319973-002, 319974-002, + * 82801JD (ICH10D) : document number 319973-002, 319974-002, + * 82801JDO (ICH10DO) : document number 319973-002, 319974-002 */ /* @@ -95,19 +102,26 @@ enum iTCO_chipsets { TCO_ICH6, /* ICH6 & ICH6R */ TCO_ICH6M, /* ICH6-M */ TCO_ICH6W, /* ICH6W & ICH6RW */ + TCO_631XESB, /* 631xESB/632xESB */ TCO_ICH7, /* ICH7 & ICH7R */ - TCO_ICH7M, /* ICH7-M */ + TCO_ICH7DH, /* ICH7DH */ + TCO_ICH7M, /* ICH7-M & ICH7-U */ TCO_ICH7MDH, /* ICH7-M DH */ TCO_ICH8, /* ICH8 & ICH8R */ - TCO_ICH8ME, /* ICH8M-E */ TCO_ICH8DH, /* ICH8DH */ TCO_ICH8DO, /* ICH8DO */ TCO_ICH8M, /* ICH8M */ + TCO_ICH8ME, /* ICH8M-E */ TCO_ICH9, /* ICH9 */ TCO_ICH9R, /* ICH9R */ TCO_ICH9DH, /* ICH9DH */ TCO_ICH9DO, /* ICH9DO */ - TCO_631XESB, /* 631xESB/632xESB */ + TCO_ICH9M, /* ICH9M */ + TCO_ICH9ME, /* ICH9M-E */ + TCO_ICH10, /* ICH10 */ + TCO_ICH10R, /* ICH10R */ + TCO_ICH10D, /* ICH10D */ + TCO_ICH10DO, /* ICH10DO */ }; static struct { @@ -128,19 +142,26 @@ static struct { {"ICH6 or ICH6R", 2}, {"ICH6-M", 2}, {"ICH6W or ICH6RW", 2}, + {"631xESB/632xESB", 2}, {"ICH7 or ICH7R", 2}, - {"ICH7-M", 2}, + {"ICH7DH", 2}, + {"ICH7-M or ICH7-U", 2}, {"ICH7-M DH", 2}, {"ICH8 or ICH8R", 2}, - {"ICH8M-E", 2}, {"ICH8DH", 2}, {"ICH8DO", 2}, {"ICH8M", 2}, + {"ICH8M-E", 2}, {"ICH9", 2}, {"ICH9R", 2}, {"ICH9DH", 2}, {"ICH9DO", 2}, - {"631xESB/632xESB", 2}, + {"ICH9M", 2}, + {"ICH9M-E", 2}, + {"ICH10", 2}, + {"ICH10R", 2}, + {"ICH10D", 2}, + {"ICH10DO", 2}, {NULL, 0} }; @@ -174,18 +195,6 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_0, TCO_ICH6)}, { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_1, TCO_ICH6M)}, { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_2, TCO_ICH6W)}, - { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_0, TCO_ICH7)}, - { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M)}, - { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)}, - { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8)}, - { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_1, TCO_ICH8ME)}, - { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH)}, - { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO)}, - { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_4, TCO_ICH8M)}, - { ITCO_PCI_DEVICE(0x2918, TCO_ICH9)}, - { ITCO_PCI_DEVICE(0x2916, TCO_ICH9R)}, - { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2, TCO_ICH9DH)}, - { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_4, TCO_ICH9DO)}, { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB2_0, TCO_631XESB)}, { ITCO_PCI_DEVICE(0x2671, TCO_631XESB)}, { ITCO_PCI_DEVICE(0x2672, TCO_631XESB)}, @@ -202,6 +211,25 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { ITCO_PCI_DEVICE(0x267d, TCO_631XESB)}, { ITCO_PCI_DEVICE(0x267e, TCO_631XESB)}, { ITCO_PCI_DEVICE(0x267f, TCO_631XESB)}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_0, TCO_ICH7)}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_30, TCO_ICH7DH)}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M)}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8)}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH)}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO)}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_4, TCO_ICH8M)}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_1, TCO_ICH8ME)}, + { ITCO_PCI_DEVICE(0x2918, TCO_ICH9)}, + { ITCO_PCI_DEVICE(0x2916, TCO_ICH9R)}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2, TCO_ICH9DH)}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_4, TCO_ICH9DO)}, + { ITCO_PCI_DEVICE(0x2919, TCO_ICH9M)}, + { ITCO_PCI_DEVICE(0x2917, TCO_ICH9ME)}, + { ITCO_PCI_DEVICE(0x3a18, TCO_ICH10)}, + { ITCO_PCI_DEVICE(0x3a16, TCO_ICH10R)}, + { ITCO_PCI_DEVICE(0x3a1a, TCO_ICH10D)}, + { ITCO_PCI_DEVICE(0x3a14, TCO_ICH10DO)}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); -- cgit v1.2.3 From 060264133b946786b4b28a1ba79e6725eaf258f3 Mon Sep 17 00:00:00 2001 From: Bernhard Walle Date: Fri, 14 Nov 2008 15:47:03 +0100 Subject: [WATCHDOG] hpwdt: set the mapped BIOS address space as executable The address provided by the SMBIOS/DMI CRU information is mapped via ioremap() in the virtual address space. However, since the address is executed (i.e. call'd), we need to set that pages as executable. Without that, I get following oops on a HP ProLiant DL385 G2 machine with BIOS from 05/29/2008 when I trigger crashdump: BUG: unable to handle kernel paging request at ffffc20011090c00 IP: [] 0xffffc20011090c00 PGD 12f813067 PUD 7fe6a067 PMD 7effe067 PTE 80000000fffd3173 Oops: 0011 [1] SMP last sysfs file: /sys/devices/system/cpu/cpu3/cache/index2/shared_cpu_map CPU 1 Modules linked in: autofs4 ipv6 af_packet cpufreq_conservative cpufreq_userspace cpufreq_powersave powernow_k8 fuse loop dm_mod rtc_cmos ipmi_si sg rtc_core i2c _piix4 ipmi_msghandler bnx2 sr_mod container button i2c_core hpilo joydev pcspkr rtc_lib shpchp hpwdt cdrom pci_hotplug usbhid hid ff_memless ohci_hcd ehci_hcd uhci_hcd usbcore edd ext3 mbcache jbd fan ide_pci_generic serverworks ide_core p ata_serverworks pata_acpi cciss ata_generic libata scsi_mod dock thermal process or thermal_sys hwmon Supported: Yes Pid: 0, comm: swapper Not tainted 2.6.27.5-HEAD_20081111100657-default #1 RIP: 0010:[] [] 0xffffc20011090c00 RSP: 0018:ffff88012f6f9e68 EFLAGS: 00010046 RAX: 0000000000000d02 RBX: 0000000000000000 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 RBP: ffff88012f6f9e98 R08: 666666666666660a R09: ffffffffa1006fc0 R10: 0000000000000000 R11: ffff88012f6f3ea8 R12: ffffc20011090c00 R13: ffff88012f6f9ee8 R14: 000000000000000e R15: 0000000000000000 FS: 00007ff70b29a6f0(0000) GS:ffff88012f6512c0(0000) knlGS:0000000000000000 CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b CR2: ffffc20011090c00 CR3: 0000000000201000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process swapper (pid: 0, threadinfo ffff88012f6f2000, task ffff88007fa8a1c0) Stack: ffffffffa0f8502b 0000000000000002 ffffffff80738d50 0000000000000000 0000000000000046 0000000000000046 00000000fffffffe ffffffffa0f852ec 0000000000000000 ffffffff804ad9a6 0000000000000000 0000000000000000 Call Trace: Inexact backtrace: [] ? asminline_call+0x2b/0x55 [hpwdt] [] hpwdt_pretimeout+0x3c/0xa0 [hpwdt] [] ? notifier_call_chain+0x29/0x4c [] ? notify_die+0x2d/0x32 [] ? default_do_nmi+0x53/0x1d9 [] ? do_nmi+0x2e/0x43 [] ? nmi+0xa2/0xd0 [] ? native_safe_halt+0x2/0x3 <> [] ? default_idle+0x38/0x54 [] ? c1e_idle+0x118/0x11c [] ? cpu_idle+0xa9/0xf1 Code: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <55> 50 e8 00 00 00 00 58 48 2d 07 10 40 00 48 8b e8 58 e9 68 02 RIP [] 0xffffc20011090c00 RSP CR2: ffffc20011090c00 Kernel panic - not syncing: Fatal exception Signed-off-by: Bernhard Walle Signed-off-by: Wim Van Sebroeck Cc: Ingo Molnar Acked-by: "H. Peter Anvin" Signed-off-by: Thomas Mingarelli Cc: Alan Cox Signed-off-by: Andrew Morton --- drivers/watchdog/hpwdt.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index a3765e0be4a..f6cff7b5a54 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -40,6 +40,7 @@ #include #include #include +#include #define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */ #define CRU_BIOS_SIGNATURE_VALUE 0x55524324 @@ -394,6 +395,8 @@ static void __devinit dmi_find_cru(const struct dmi_header *dm) smbios_cru64_ptr->double_offset; cru_rom_addr = ioremap(cru_physical_address, smbios_cru64_ptr->double_length); + set_memory_x((unsigned long)cru_rom_addr & PAGE_MASK, + smbios_cru64_ptr->double_length >> PAGE_SHIFT); } } } -- cgit v1.2.3 From be1ffce3527d800ad50b955ede6eb44811cefd03 Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Fri, 21 Nov 2008 01:24:38 -0800 Subject: rtc: rtc-starfire fixes Changes: - remove locks, rtc class provides them - remove unused include - if the rtc can't handle set_time, the driver should not fake it Signed-off-by: Alessandro Zummo Signed-off-by: David S. Miller --- drivers/rtc/rtc-starfire.c | 66 +++++++++------------------------------------- 1 file changed, 13 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-starfire.c b/drivers/rtc/rtc-starfire.c index 7ccb0dd700a..5be98bfd7ed 100644 --- a/drivers/rtc/rtc-starfire.c +++ b/drivers/rtc/rtc-starfire.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include @@ -16,11 +15,6 @@ MODULE_AUTHOR("David S. Miller "); MODULE_DESCRIPTION("Starfire RTC driver"); MODULE_LICENSE("GPL"); -struct starfire_rtc { - struct rtc_device *rtc; - spinlock_t lock; -}; - static u32 starfire_get_time(void) { static char obp_gettod[32]; @@ -35,64 +29,31 @@ static u32 starfire_get_time(void) static int starfire_read_time(struct device *dev, struct rtc_time *tm) { - struct starfire_rtc *p = dev_get_drvdata(dev); - unsigned long flags, secs; - - spin_lock_irqsave(&p->lock, flags); - secs = starfire_get_time(); - spin_unlock_irqrestore(&p->lock, flags); - - rtc_time_to_tm(secs, tm); - - return 0; -} - -static int starfire_set_time(struct device *dev, struct rtc_time *tm) -{ - unsigned long secs; - int err; - - err = rtc_tm_to_time(tm, &secs); - if (err) - return err; - - /* Do nothing, time is set using the service processor - * console on this platform. - */ - return 0; + rtc_time_to_tm(starfire_get_time(), tm); + return rtc_valid_tm(tm); } static const struct rtc_class_ops starfire_rtc_ops = { .read_time = starfire_read_time, - .set_time = starfire_set_time, }; -static int __devinit starfire_rtc_probe(struct platform_device *pdev) +static int __init starfire_rtc_probe(struct platform_device *pdev) { - struct starfire_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL); - - if (!p) - return -ENOMEM; + struct rtc_device *rtc = rtc_device_register("starfire", &pdev->dev, + &starfire_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); - spin_lock_init(&p->lock); + platform_set_drvdata(pdev, rtc); - p->rtc = rtc_device_register("starfire", &pdev->dev, - &starfire_rtc_ops, THIS_MODULE); - if (IS_ERR(p->rtc)) { - int err = PTR_ERR(p->rtc); - kfree(p); - return err; - } - platform_set_drvdata(pdev, p); return 0; } -static int __devexit starfire_rtc_remove(struct platform_device *pdev) +static int __exit starfire_rtc_remove(struct platform_device *pdev) { - struct starfire_rtc *p = platform_get_drvdata(pdev); + struct rtc_device *rtc = platform_get_drvdata(pdev); - rtc_device_unregister(p->rtc); - kfree(p); + rtc_device_unregister(rtc); return 0; } @@ -102,13 +63,12 @@ static struct platform_driver starfire_rtc_driver = { .name = "rtc-starfire", .owner = THIS_MODULE, }, - .probe = starfire_rtc_probe, - .remove = __devexit_p(starfire_rtc_remove), + .remove = __exit_p(starfire_rtc_remove), }; static int __init starfire_rtc_init(void) { - return platform_driver_register(&starfire_rtc_driver); + return platform_driver_probe(&starfire_rtc_driver, starfire_rtc_probe); } static void __exit starfire_rtc_exit(void) -- cgit v1.2.3 From 208fbec5bec1de4fce48aab41efde11ba25ab04c Mon Sep 17 00:00:00 2001 From: Cord Walter Date: Thu, 20 Nov 2008 13:46:57 +0000 Subject: axnet_cs / pcnet_cs: moving PCMCIA_DEVICE_PROD_ID for Netgear FA411 Hi, after noticing that my Netgear FA411 (PCMCIA-NIC) [1] stopped working with the release of the 2.6.25 kernel (sidux-version), I checked the respective driver sources and noticed that the pcnet_cs driver bailed out with "use axnet_cs instead" for the Netgear FA411, but axnet_cs doesn't claim this ID. I compiled a kernel with the PCMCIA-ID for the netgear card moved to axnet_cs from pcnet_cs which worked. I then contacted sidux-kernel maintainer Stefan Lippers-Hollmann who turned the info into this patch and integrated it into the kernel: This works for me and AFAIK there were no reports of any breakage for other devices on sidux-support. This looks like a trivial patch, but since I have very limited experience with kernel modifications I might be woefully wrong there. But if there are no side effects of this patch, is it possible to get it into the official kernel? I can provide more detailed information on the affected hardware if necessary. -cord [1] Socket 1 Device 0: [axnet_cs] (bus ID: 1.0) Configuration: state: on Product Name: NETGEAR FA411 Fast Ethernet Identification: manf_id: 0x0149 card_id: 0x0411 function: 6 (network) prod_id(1): "NETGEAR" (0x9aa79dc3) prod_id(2): "FA411" (0x40fad875) prod_id(3): "Fast Ethernet" (0xb4be14e3) prod_id(4): --- (---) From: Stefan Lippers-Hollmann Date: Sat, 1 Nov 2008 23:53:04 +0000 Subject: PCMCIA: move PCMCIA ID for Netgear FA411 from pcnet_cs to axnet_cs: Since kernel 2.6.25, commit 61da96be07ec860e260ca4af0199b9d48d000b80 (pcnet_cs: if AX88190-based card, printk "use axnet_cs instead" message.), pcnet_cs bails out with "use axnet_cs instead" for the Netgear FA411, but axnet_cs doesn't claim this ID. Socket 1 Device 0: [axnet_cs] (bus ID: 1.0) Configuration: state: on Product Name: NETGEAR FA411 Fast Ethernet Identification: manf_id: 0x0149 card_id: 0x0411 function: 6 (network) prod_id(1): "NETGEAR" (0x9aa79dc3) prod_id(2): "FA411" (0x40fad875) prod_id(3): "Fast Ethernet" (0xb4be14e3) prod_id(4): --- (---) Cc: stable [2.6.25, 2.6.26, 2.6.27] Signed-off-by: Stefan Lippers-Hollmann Signed-off-by: Cord Walter Signed-off-by: David S. Miller --- drivers/net/pcmcia/axnet_cs.c | 1 + drivers/net/pcmcia/pcnet_cs.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index b37a498939a..713091e2b89 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -779,6 +779,7 @@ static struct pcmcia_device_id axnet_ids[] = { PCMCIA_DEVICE_PROD_ID12("IO DATA", "ETXPCM", 0x547e66dc, 0x233adac2), PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V3)", 0x0733cc81, 0x232019a8), PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC3-TX", 0x481e0094, 0xf91af609), + PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA411", 0x9aa79dc3, 0x40fad875), PCMCIA_DEVICE_PROD_ID12("PCMCIA", "100BASE", 0x281f1c5d, 0x7c2add04), PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEtherCard", 0x281f1c5d, 0x7ef26116), PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FEP501", 0x281f1c5d, 0x2e272058), diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index e40d6301aa7..ce486f09449 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1693,7 +1693,6 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover NE4100", 0x36e1191f, 0xa6617ec8), PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J12", 0x18df0ba0, 0xbc912d76), PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA410TX", 0x9aa79dc3, 0x60e5bc0e), - PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA411", 0x9aa79dc3, 0x40fad875), PCMCIA_DEVICE_PROD_ID12("Network Everywhere", "Fast Ethernet 10/100 PC Card", 0x820a67b6, 0x31ed1a5f), PCMCIA_DEVICE_PROD_ID12("NextCom K.K.", "Next Hawk", 0xaedaec74, 0xad050ef1), PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100Mbps Ethernet Card", 0x281f1c5d, 0x6e41773b), -- cgit v1.2.3 From 38ae07e44bb2dc86770555a1acafcb937ec74478 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 21 Nov 2008 16:33:25 -0800 Subject: net/hp-plus: fix link errors Fix hp-plus driver link errors. Builds as loadable module and kernel image driver. All drivers that use 8390.o or 8390p.o that will build on i386 with MCA/PCI/EISA/ISA were built successfully both =m and =y. drivers/built-in.o: In function `hpp_open': hp-plus.c:(.text+0xac06c): undefined reference to `eip_interrupt' hp-plus.c:(.text+0xac0d7): undefined reference to `eip_open' drivers/built-in.o: In function `hpp_close': hp-plus.c:(.text+0xac1bb): undefined reference to `eip_close' drivers/built-in.o: In function `hpp_probe1': hp-plus.c:(.init.text+0xa98a): undefined reference to `NS8390p_init' drivers/built-in.o: In function `hp_plus_probe': (.init.text+0xa9fe): undefined reference to `__alloc_eip_netdev' Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller --- drivers/net/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/Makefile b/drivers/net/Makefile index f19acf8b922..017383ad5ec 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -114,7 +114,7 @@ obj-$(CONFIG_EL2) += 3c503.o 8390p.o obj-$(CONFIG_NE2000) += ne.o 8390p.o obj-$(CONFIG_NE2_MCA) += ne2.o 8390p.o obj-$(CONFIG_HPLAN) += hp.o 8390p.o -obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390.o +obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390p.o obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o obj-$(CONFIG_ULTRAMCA) += smc-mca.o 8390.o obj-$(CONFIG_ULTRA32) += smc-ultra32.o 8390.o -- cgit v1.2.3 From fde5be353e872fe6088d2b1951e56cdfda2042ff Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sun, 23 Nov 2008 12:03:20 +0100 Subject: HID: remove setup mutex, fix possible deadlock It causes recursive locking warning and is unneeded after introduction of STARTED flag. * Resume vs. stop is effectively solved by DISCONNECT flag. * No problem in suspend vs. start -- urb is submitted even after open which is possible after connect which is called after start. * Resume vs. start solved by STARTED flag. * Suspend vs. stop -- no problem in killing urb and timer twice. Reported-by: Alan Stern Signed-off-by: Jiri Slaby Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 18 ++---------------- drivers/hid/usbhid/usbhid.h | 1 - 2 files changed, 2 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index d746bf8284d..606369ea24c 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -796,7 +796,6 @@ static int usbhid_start(struct hid_device *hid) if (insize > HID_MAX_BUFFER_SIZE) insize = HID_MAX_BUFFER_SIZE; - mutex_lock(&usbhid->setup); if (hid_alloc_buffers(dev, hid)) { ret = -ENOMEM; goto fail; @@ -876,7 +875,6 @@ static int usbhid_start(struct hid_device *hid) hid_dump_device(hid); set_bit(HID_STARTED, &usbhid->iofl); - mutex_unlock(&usbhid->setup); return 0; @@ -888,7 +886,6 @@ fail: usbhid->urbout = NULL; usbhid->urbctrl = NULL; hid_free_buffers(dev, hid); - mutex_unlock(&usbhid->setup); return ret; } @@ -899,7 +896,6 @@ static void usbhid_stop(struct hid_device *hid) if (WARN_ON(!usbhid)) return; - mutex_lock(&usbhid->setup); clear_bit(HID_STARTED, &usbhid->iofl); spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ set_bit(HID_DISCONNECTED, &usbhid->iofl); @@ -928,7 +924,6 @@ static void usbhid_stop(struct hid_device *hid) usbhid->urbout = NULL; hid_free_buffers(hid_to_usb_dev(hid), hid); - mutex_unlock(&usbhid->setup); } static struct hid_ll_driver usb_hid_driver = { @@ -1016,7 +1011,6 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) hid->driver_data = usbhid; usbhid->hid = hid; - mutex_init(&usbhid->setup); /* needed on suspend/resume */ ret = hid_add_device(hid); if (ret) { @@ -1051,18 +1045,14 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) struct hid_device *hid = usb_get_intfdata (intf); struct usbhid_device *usbhid = hid->driver_data; - mutex_lock(&usbhid->setup); - if (!test_bit(HID_STARTED, &usbhid->iofl)) { - mutex_unlock(&usbhid->setup); + if (!test_bit(HID_STARTED, &usbhid->iofl)) return 0; - } spin_lock_irq(&usbhid->inlock); /* Sync with error handler */ set_bit(HID_SUSPENDED, &usbhid->iofl); spin_unlock_irq(&usbhid->inlock); del_timer_sync(&usbhid->io_retry); usb_kill_urb(usbhid->urbin); - mutex_unlock(&usbhid->setup); dev_dbg(&intf->dev, "suspend\n"); return 0; } @@ -1073,16 +1063,12 @@ static int hid_resume(struct usb_interface *intf) struct usbhid_device *usbhid = hid->driver_data; int status; - mutex_lock(&usbhid->setup); - if (!test_bit(HID_STARTED, &usbhid->iofl)) { - mutex_unlock(&usbhid->setup); + if (!test_bit(HID_STARTED, &usbhid->iofl)) return 0; - } clear_bit(HID_SUSPENDED, &usbhid->iofl); usbhid->retry_delay = 0; status = hid_start_in(hid); - mutex_unlock(&usbhid->setup); dev_dbg(&intf->dev, "resume status %d\n", status); return status; } diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 55973ff5400..332abcdf995 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h @@ -74,7 +74,6 @@ struct usbhid_device { dma_addr_t outbuf_dma; /* Output buffer dma */ spinlock_t outlock; /* Output fifo spinlock */ - struct mutex setup; unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ struct timer_list io_retry; /* Retry timer */ unsigned long stop_retry; /* Time to give up, in jiffies */ -- cgit v1.2.3 From 47fd6f7c94e15eb5f97dd1cbb0427a46b03c8185 Mon Sep 17 00:00:00 2001 From: Jaya Kumar Date: Tue, 18 Nov 2008 02:32:36 +0100 Subject: [ARM] 5335/1: pxa25x_udc: Fix is_vbus_present to return 1 or 0 the use of is_blah() suggests a 1 or 0 return. This assumption is made in pxa25x_udc code such as: dev->vbus = is_vbus_present(); where dev->vbus is a bitfield. This fix allows pxa25x_udc_probe to correctly detect vbus. Other changes were to make its use consistent in the rest of the code. Signed-off-by: Jaya Kumar Signed-off-by: Russell King --- drivers/usb/gadget/pxa25x_udc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index da6e93c201d..2dbc0db0b46 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -141,7 +141,11 @@ static int is_vbus_present(void) if (mach->gpio_vbus) { int value = gpio_get_value(mach->gpio_vbus); - return mach->gpio_vbus_inverted ? !value : value; + + if (mach->gpio_vbus_inverted) + return !value; + else + return !!value; } if (mach->udc_is_connected) return mach->udc_is_connected(); @@ -982,7 +986,7 @@ static int pxa25x_udc_vbus_session(struct usb_gadget *_gadget, int is_active) struct pxa25x_udc *udc; udc = container_of(_gadget, struct pxa25x_udc, gadget); - udc->vbus = (is_active != 0); + udc->vbus = is_active; DMSG("vbus %s\n", is_active ? "supplied" : "inactive"); pullup(udc); return 0; @@ -1399,12 +1403,8 @@ lubbock_vbus_irq(int irq, void *_dev) static irqreturn_t udc_vbus_irq(int irq, void *_dev) { struct pxa25x_udc *dev = _dev; - int vbus = gpio_get_value(dev->mach->gpio_vbus); - if (dev->mach->gpio_vbus_inverted) - vbus = !vbus; - - pxa25x_udc_vbus_session(&dev->gadget, vbus); + pxa25x_udc_vbus_session(&dev->gadget, is_vbus_present()); return IRQ_HANDLED; } -- cgit v1.2.3 From ece4af18e07a5cea592ca095844783db4a349cb2 Mon Sep 17 00:00:00 2001 From: Qinghuang Feng Date: Sun, 23 Nov 2008 15:46:55 -0800 Subject: driver/net/*: remove redundant argument comments remove redundant argument comments in files of drivers/net/* Signed-off-by: Qinghuang Feng Signed-off-by: David S. Miller --- drivers/net/e1000e/netdev.c | 1 - drivers/net/igb/igb_main.c | 4 ---- drivers/net/ixgbe/ixgbe_main.c | 1 - drivers/net/pcmcia/axnet_cs.c | 1 - drivers/net/sis900.c | 1 - drivers/net/spider_net.c | 4 ---- 6 files changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 91795f78c3e..122539a0e1f 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -345,7 +345,6 @@ no_buffers: /** * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers * @adapter: address of board private structure - * @rx_ring: pointer to receive ring structure * @cleaned_count: number of buffers to allocate this pass **/ diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 1cbae85b142..20d27e622ec 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1980,7 +1980,6 @@ static void igb_configure_rx(struct igb_adapter *adapter) /** * igb_free_tx_resources - Free Tx Resources per Queue - * @adapter: board private structure * @tx_ring: Tx descriptor ring for a specific queue * * Free all transmit software resources @@ -2033,7 +2032,6 @@ static void igb_unmap_and_free_tx_resource(struct igb_adapter *adapter, /** * igb_clean_tx_ring - Free Tx Buffers - * @adapter: board private structure * @tx_ring: ring to be cleaned **/ static void igb_clean_tx_ring(struct igb_ring *tx_ring) @@ -2080,7 +2078,6 @@ static void igb_clean_all_tx_rings(struct igb_adapter *adapter) /** * igb_free_rx_resources - Free Rx Resources - * @adapter: board private structure * @rx_ring: ring to clean the resources from * * Free all receive software resources @@ -2120,7 +2117,6 @@ static void igb_free_all_rx_resources(struct igb_adapter *adapter) /** * igb_clean_rx_ring - Free Rx Buffers per Queue - * @adapter: board private structure * @rx_ring: ring to free buffers from **/ static void igb_clean_rx_ring(struct igb_ring *rx_ring) diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 36f2bb666bf..b2a7ea88712 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1320,7 +1320,6 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) * ixgbe_intr - legacy mode Interrupt Handler * @irq: interrupt number * @data: pointer to a network interface device structure - * @pt_regs: CPU registers structure **/ static irqreturn_t ixgbe_intr(int irq, void *data) { diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 713091e2b89..0418045166c 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -1175,7 +1175,6 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) * ax_interrupt - handle the interrupts from an 8390 * @irq: interrupt number * @dev_id: a pointer to the net_device - * @regs: unused * * Handle the ether interface interrupts. We pull packets from * the 8390 via the card specific functions and fire them at the networking diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index fa3a460f8e2..8e8337e8b07 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c @@ -1630,7 +1630,6 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev) * sis900_interrupt - sis900 interrupt handler * @irq: the irq number * @dev_instance: the client data object - * @regs: snapshot of processor context * * The interrupt handler does all of the Rx thread work, * and cleans up after the Tx thread diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index b6435d0d71f..07599b49235 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -672,7 +672,6 @@ write_hash: /** * spider_net_prepare_tx_descr - fill tx descriptor with skb data * @card: card structure - * @descr: descriptor structure to fill out * @skb: packet to use * * returns 0 on success, <0 on failure. @@ -867,7 +866,6 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal) /** * spider_net_kick_tx_dma - enables TX DMA processing * @card: card structure - * @descr: descriptor address to enable TX processing at * * This routine will start the transmit DMA running if * it is not already running. This routine ned only be @@ -1637,7 +1635,6 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg, * spider_net_interrupt - interrupt handler for spider_net * @irq: interrupt number * @ptr: pointer to net_device - * @regs: PU registers * * returns IRQ_HANDLED, if interrupt was for driver, or IRQ_NONE, if no * interrupt found raised by card. @@ -2419,7 +2416,6 @@ spider_net_undo_pci_setup(struct spider_net_card *card) /** * spider_net_setup_pci_dev - sets up the device in terms of PCI operations - * @card: card structure * @pdev: PCI device * * Returns the card structure or NULL if any errors occur -- cgit v1.2.3 From 5147d14e995c097571d383fe1287fb33345a51ee Mon Sep 17 00:00:00 2001 From: Qinghuang Feng Date: Sun, 23 Nov 2008 15:47:24 -0800 Subject: drivers/net/chelsio/sge.c: remove redundant argument comments remove redundant argument comments Signed-off-by: Qinghuang Feng Signed-off-by: David S. Miller --- drivers/net/chelsio/sge.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index d6c7d2aa761..7092df50ff7 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -1035,10 +1035,6 @@ MODULE_PARM_DESC(copybreak, "Receive copy threshold"); * @pdev: the PCI device that received the packet * @fl: the SGE free list holding the packet * @len: the actual packet length, excluding any SGE padding - * @dma_pad: padding at beginning of buffer left by SGE DMA - * @skb_pad: padding to be used if the packet is copied - * @copy_thres: length threshold under which a packet should be copied - * @drop_thres: # of remaining buffers before we start dropping packets * * Get the next packet from a free list and complete setup of the * sk_buff. If the packet is small we make a copy and recycle the -- cgit v1.2.3 From fe875358a6cd01c4599e321dd6dc767b11c42eac Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 24 Nov 2008 13:37:05 +0200 Subject: [MTD] [NAND] OMAP: OneNAND: header file relocation Signed-off-by: Adrian Hunter Signed-off-by: David Woodhouse --- drivers/mtd/onenand/omap2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index e39b21d3e16..28034ef08a8 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -35,16 +35,16 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include -#include +#include -#include +#include #define DRIVER_NAME "omap2-onenand" -- cgit v1.2.3 From 98522a7be97f2b23451342e36c39f412f0461e24 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 18 Nov 2008 06:33:08 -0300 Subject: V4L/DVB (9689): gspca: Memory leak when disconnect while streaming. As a side effect, the sd routine stop0 is called on disconnect. This permits the subdriver to free its resources. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/conex.c | 3 +++ drivers/media/video/gspca/finepix.c | 8 ++++++++ drivers/media/video/gspca/gspca.c | 17 ++++++++--------- drivers/media/video/gspca/gspca.h | 2 +- drivers/media/video/gspca/pac7311.c | 3 +++ drivers/media/video/gspca/spca501.c | 3 +++ drivers/media/video/gspca/spca505.c | 4 ++++ drivers/media/video/gspca/spca561.c | 3 +++ drivers/media/video/gspca/vc032x.c | 3 +++ drivers/media/video/gspca/zc3xx.c | 3 +++ 10 files changed, 39 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c index a9d51ba7c57..de28354ea5b 100644 --- a/drivers/media/video/gspca/conex.c +++ b/drivers/media/video/gspca/conex.c @@ -846,10 +846,13 @@ static int sd_start(struct gspca_dev *gspca_dev) return 0; } +/* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { int retry = 50; + if (!gspca_dev->present) + return; reg_w_val(gspca_dev, 0x0000, 0x00); reg_r(gspca_dev, 0x0002, 1); reg_w_val(gspca_dev, 0x0053, 0x00); diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c index 65d3cbfe6b2..607942fd797 100644 --- a/drivers/media/video/gspca/finepix.c +++ b/drivers/media/video/gspca/finepix.c @@ -276,6 +276,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev) /* Stop the state machine */ if (dev->state != FPIX_NOP) wait_for_completion(&dev->can_close); +} + +/* called on streamoff with alt 0 and disconnect */ +static void sd_stop0(struct gspca_dev *gspca_dev) +{ + struct usb_fpix *dev = (struct usb_fpix *) gspca_dev; usb_free_urb(dev->control_urb); dev->control_urb = NULL; @@ -385,6 +391,7 @@ static int sd_start(struct gspca_dev *gspca_dev) error: /* Free the ressources */ sd_stopN(gspca_dev); + sd_stop0(gspca_dev); return ret; } @@ -425,6 +432,7 @@ static const struct sd_desc sd_desc = { .init = sd_init, .start = sd_start, .stopN = sd_stopN, + .stop0 = sd_stop0, }; /* -- device connect -- */ diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index e48fbfc8ad0..f28d2f4acea 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -646,15 +646,14 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev) { gspca_dev->streaming = 0; atomic_set(&gspca_dev->nevent, 0); - if (gspca_dev->present) { - if (gspca_dev->sd_desc->stopN) - gspca_dev->sd_desc->stopN(gspca_dev); - destroy_urbs(gspca_dev); - gspca_set_alt0(gspca_dev); - if (gspca_dev->sd_desc->stop0) - gspca_dev->sd_desc->stop0(gspca_dev); - PDEBUG(D_STREAM, "stream off OK"); - } + if (gspca_dev->present + && gspca_dev->sd_desc->stopN) + gspca_dev->sd_desc->stopN(gspca_dev); + destroy_urbs(gspca_dev); + gspca_set_alt0(gspca_dev); + if (gspca_dev->sd_desc->stop0) + gspca_dev->sd_desc->stop0(gspca_dev); + PDEBUG(D_STREAM, "stream off OK"); } static void gspca_set_default_mode(struct gspca_dev *gspca_dev) diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 1d9dc90b479..c35d7b97112 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -97,7 +97,7 @@ struct sd_desc { cam_pkt_op pkt_scan; /* optional operations */ cam_v_op stopN; /* called on stream off - main alt */ - cam_v_op stop0; /* called on stream off - alt 0 */ + cam_v_op stop0; /* called on stream off & disconnect - alt 0 */ cam_v_op dq_callback; /* called when a frame has been dequeued */ cam_jpg_op get_jcomp; cam_jpg_op set_jcomp; diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c index e5ff9a6199e..fbd45e235d9 100644 --- a/drivers/media/video/gspca/pac7311.c +++ b/drivers/media/video/gspca/pac7311.c @@ -749,10 +749,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */ } +/* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (!gspca_dev->present) + return; if (sd->sensor == SENSOR_PAC7302) { reg_w(gspca_dev, 0xff, 0x01); reg_w(gspca_dev, 0x78, 0x40); diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c index b742f260c7c..e29954c1c38 100644 --- a/drivers/media/video/gspca/spca501.c +++ b/drivers/media/video/gspca/spca501.c @@ -2022,8 +2022,11 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00); } +/* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { + if (!gspca_dev->present) + return; reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00); } diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c index b345749213c..895b9fe4018 100644 --- a/drivers/media/video/gspca/spca505.c +++ b/drivers/media/video/gspca/spca505.c @@ -742,8 +742,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_write(gspca_dev->dev, 0x02, 0x00, 0x00); } +/* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { + if (!gspca_dev->present) + return; + /* This maybe reset or power control */ reg_write(gspca_dev->dev, 0x03, 0x03, 0x20); reg_write(gspca_dev->dev, 0x03, 0x01, 0x0); diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 020a03c466c..c3de4e44123 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c @@ -766,10 +766,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev) } } +/* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (!gspca_dev->present) + return; if (sd->chip_revision == Rev012A) { reg_w_val(gspca_dev->dev, 0x8118, 0x29); reg_w_val(gspca_dev->dev, 0x8114, 0x08); diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c index be46d923254..17af353ddd1 100644 --- a/drivers/media/video/gspca/vc032x.c +++ b/drivers/media/video/gspca/vc032x.c @@ -1633,10 +1633,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev) reg_w(dev, 0xa0, 0x09, 0xb003); } +/* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { struct usb_device *dev = gspca_dev->dev; + if (!gspca_dev->present) + return; reg_w(dev, 0x89, 0xffff, 0xffff); } diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 8b3101d347c..0befacf4985 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c @@ -7336,10 +7336,13 @@ static int sd_start(struct gspca_dev *gspca_dev) return 0; } +/* called on streamoff with alt 0 and on disconnect */ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; + if (!gspca_dev->present) + return; send_unknown(gspca_dev->dev, sd->sensor); } -- cgit v1.2.3 From 5c4fa002b1c7b40f65fa911ae17a823ec9e26ab2 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Tue, 18 Nov 2008 15:52:31 -0300 Subject: V4L/DVB (9690): gspca: Lock the subdrivers via module_get/put. The previous subdriver protection against rmmod was done via the file operations table in the device descriptor. On device disconnection while streaming, the device structure was freed at close time, and the module_put still used the module name in the freed area. Now, explicit module get/put are done on open and close. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 13 ++++++++++--- drivers/media/video/gspca/gspca.h | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index f28d2f4acea..a565f376483 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -874,6 +874,13 @@ static int dev_open(struct inode *inode, struct file *file) ret = -EBUSY; goto out; } + + /* protect the subdriver against rmmod */ + if (!try_module_get(gspca_dev->module)) { + ret = -ENODEV; + goto out; + } + gspca_dev->users++; /* one more user */ @@ -920,6 +927,7 @@ static int dev_close(struct inode *inode, struct file *file) gspca_dev->memory = GSPCA_MEMORY_NO; } file->private_data = NULL; + module_put(gspca_dev->module); mutex_unlock(&gspca_dev->queue_lock); PDEBUG(D_STREAM, "close done"); @@ -1870,9 +1878,8 @@ int gspca_dev_probe(struct usb_interface *intf, /* init video stuff */ memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template); gspca_dev->vdev.parent = &dev->dev; - memcpy(&gspca_dev->fops, &dev_fops, sizeof gspca_dev->fops); - gspca_dev->vdev.fops = &gspca_dev->fops; - gspca_dev->fops.owner = module; /* module protection */ + gspca_dev->vdev.fops = &dev_fops; + gspca_dev->module = module; gspca_dev->present = 1; ret = video_register_device(&gspca_dev->vdev, VFL_TYPE_GRABBER, diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index c35d7b97112..2ae1ad7c148 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -121,7 +121,7 @@ struct gspca_frame { struct gspca_dev { struct video_device vdev; /* !! must be the first item */ - struct file_operations fops; + struct module *module; /* subdriver handling the device */ struct usb_device *dev; struct kref kref; struct file *capt_file; /* file doing video capture */ -- cgit v1.2.3 From e07a1d8ab20a059fefbfd1558db43701bca560d7 Mon Sep 17 00:00:00 2001 From: Jean-Francois Moine Date: Wed, 19 Nov 2008 06:37:53 -0300 Subject: V4L/DVB (9691): gspca: Move the video device to a separate area. The video device was part of the gspca device. On device disconnection while streaming, the device structure is freed at close time. In this case, the remaining close job on the video device run out of allocated memory. Signed-off-by: Jean-Francois Moine Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/gspca.c | 28 +++++++++++++--------------- drivers/media/video/gspca/gspca.h | 2 +- 2 files changed, 14 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index a565f376483..748a87e82e4 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -862,7 +862,7 @@ static int dev_open(struct inode *inode, struct file *file) int ret; PDEBUG(D_STREAM, "%s open", current->comm); - gspca_dev = (struct gspca_dev *) video_devdata(file); + gspca_dev = video_drvdata(file); if (mutex_lock_interruptible(&gspca_dev->queue_lock)) return -ERESTARTSYS; if (!gspca_dev->present) { @@ -890,10 +890,10 @@ static int dev_open(struct inode *inode, struct file *file) #ifdef GSPCA_DEBUG /* activate the v4l2 debug */ if (gspca_debug & D_V4L2) - gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL + gspca_dev->vdev->debug |= V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG; else - gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL + gspca_dev->vdev->debug &= ~(V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG); #endif ret = 0; @@ -1755,11 +1755,6 @@ out: return ret; } -static void dev_release(struct video_device *vfd) -{ - /* nothing */ -} - static struct file_operations dev_fops = { .owner = THIS_MODULE, .open = dev_open, @@ -1807,7 +1802,7 @@ static struct video_device gspca_template = { .name = "gspca main driver", .fops = &dev_fops, .ioctl_ops = &dev_ioctl_ops, - .release = dev_release, /* mandatory */ + .release = video_device_release, .minor = -1, }; @@ -1876,16 +1871,18 @@ int gspca_dev_probe(struct usb_interface *intf, init_waitqueue_head(&gspca_dev->wq); /* init video stuff */ - memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template); - gspca_dev->vdev.parent = &dev->dev; - gspca_dev->vdev.fops = &dev_fops; + gspca_dev->vdev = video_device_alloc(); + memcpy(gspca_dev->vdev, &gspca_template, sizeof gspca_template); + gspca_dev->vdev->parent = &dev->dev; gspca_dev->module = module; gspca_dev->present = 1; - ret = video_register_device(&gspca_dev->vdev, + video_set_drvdata(gspca_dev->vdev, gspca_dev); + ret = video_register_device(gspca_dev->vdev, VFL_TYPE_GRABBER, video_nr); if (ret < 0) { err("video_register_device err %d", ret); + video_device_release(gspca_dev->vdev); goto out; } @@ -1893,7 +1890,8 @@ int gspca_dev_probe(struct usb_interface *intf, PDEBUG(D_PROBE, "probe ok"); return 0; out: - kref_put(&gspca_dev->kref, gspca_delete); + kfree(gspca_dev->usb_buf); + kfree(gspca_dev); return ret; } EXPORT_SYMBOL(gspca_dev_probe); @@ -1911,7 +1909,7 @@ void gspca_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); /* We don't want people trying to open up the device */ - video_unregister_device(&gspca_dev->vdev); + video_unregister_device(gspca_dev->vdev); gspca_dev->present = 0; gspca_dev->streaming = 0; diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index 2ae1ad7c148..d25e8d69373 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h @@ -120,7 +120,7 @@ struct gspca_frame { }; struct gspca_dev { - struct video_device vdev; /* !! must be the first item */ + struct video_device *vdev; struct module *module; /* subdriver handling the device */ struct usb_device *dev; struct kref kref; -- cgit v1.2.3 From 7a8f4ccfd572a11f609439dc6a75165b441641bc Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 21 Nov 2008 17:14:37 -0300 Subject: V4L/DVB (9732): sms1xxx: use new firmware for Hauppauge WinTV MiniStick New firmware image brings enhanced tuning performance. Firmware is available for download at the following location: http://www.steventoth.net/linux/sms1xxx Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/siano/sms-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c index 6f9b7736044..e98d6caf2c2 100644 --- a/drivers/media/dvb/siano/sms-cards.c +++ b/drivers/media/dvb/siano/sms-cards.c @@ -95,7 +95,7 @@ static struct sms_board sms_boards[] = { [SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = { .name = "Hauppauge WinTV MiniStick", .type = SMS_NOVA_B0, - .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-01.fw", + .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", }, }; -- cgit v1.2.3 From 50f3beb50abe0cc0228363af804e50e710b3e5b0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 24 Nov 2008 08:45:57 -0300 Subject: V4L/DVB (9742): em28xx-alsa: implement another locking schema Instead of using a spinlock, it is better to call the proper pcm stream locking schema. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 37 ++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index ac3292d7646..dfac2e042a5 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -75,7 +75,9 @@ static void em28xx_audio_isocirq(struct urb *urb) struct em28xx *dev = urb->context; int i; unsigned int oldptr; +#ifdef NO_PCM_LOCK unsigned long flags; +#endif int period_elapsed = 0; int status; unsigned char *cp; @@ -96,9 +98,26 @@ static void em28xx_audio_isocirq(struct urb *urb) if (!length) continue; +#ifdef NO_PCM_LOCK spin_lock_irqsave(&dev->adev->slock, flags); - +#endif oldptr = dev->adev->hwptr_done_capture; + if (oldptr + length >= runtime->buffer_size) { + unsigned int cnt = + runtime->buffer_size - oldptr; + memcpy(runtime->dma_area + oldptr * stride, cp, + cnt * stride); + memcpy(runtime->dma_area, cp + cnt * stride, + length * stride - cnt * stride); + } else { + memcpy(runtime->dma_area + oldptr * stride, cp, + length * stride); + } + +#ifndef NO_PCM_LOCK + snd_pcm_stream_lock(substream); +#endif + dev->adev->hwptr_done_capture += length; if (dev->adev->hwptr_done_capture >= runtime->buffer_size) @@ -113,19 +132,11 @@ static void em28xx_audio_isocirq(struct urb *urb) period_elapsed = 1; } +#ifdef NO_PCM_LOCK spin_unlock_irqrestore(&dev->adev->slock, flags); - - if (oldptr + length >= runtime->buffer_size) { - unsigned int cnt = - runtime->buffer_size - oldptr; - memcpy(runtime->dma_area + oldptr * stride, cp, - cnt * stride); - memcpy(runtime->dma_area, cp + cnt * stride, - length * stride - cnt * stride); - } else { - memcpy(runtime->dma_area + oldptr * stride, cp, - length * stride); - } +#else + snd_pcm_stream_unlock(substream); +#endif } if (period_elapsed) snd_pcm_period_elapsed(substream); -- cgit v1.2.3 From 8442c87d2f6c73cdc9a391e4dd9390523d242bda Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 23 Nov 2008 22:35:57 -0500 Subject: Input: replace spin_lock_bh with spin_lock_irqsave in ml_ff_playback ml_ff_playback() uses spin_(un)lock_bh. However this function is called with interrupts disabled from erase_effect() in drivers/input/ff-core.c:196. This is not permitted, and will result in a WARN_ON in the bottom half handling code. This patch changes this function to just use spin_lock_irqsave() instead, solving the problem and simplifying the locking logic. This was reported as entry #106559 in kerneloops.org Reported-by: kerneloops.org Signed-off-by: Arjan van de Ven Signed-off-by: Dmitry Torokhov --- drivers/input/ff-memless.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index 6790e975a98..bc4e40f3ede 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -397,8 +397,9 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) { struct ml_device *ml = dev->ff->private; struct ml_effect_state *state = &ml->states[effect_id]; + unsigned long flags; - spin_lock_bh(&ml->timer_lock); + spin_lock_irqsave(&ml->timer_lock, flags); if (value > 0) { debug("initiated play"); @@ -424,7 +425,7 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) ml_play_effects(ml); } - spin_unlock_bh(&ml->timer_lock); + spin_unlock_irqrestore(&ml->timer_lock, flags); return 0; } -- cgit v1.2.3 From 7c463586427bbbad726ba561bae4ba5acada2481 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 4 Nov 2008 02:03:27 -0800 Subject: drm/i915: Manage PIPESTAT to control vblank interrupts instead of IMR. The pipestat fields affect reporting of all vblank-related interrupts, so we have to reset them during the irq_handler, and while enabling vblank interrupts. Otherwise, if a pipe status field had been set to non-zero before enabling reporting, we would never see an interrupt again. This patch adds i915_enable_pipestat and i915_disable_pipestat to abstract out the steps needed to change the reported interrupts. Signed-off-by: Keith Packard Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_drv.h | 8 ++ drivers/gpu/drm/i915/i915_irq.c | 211 ++++++++++++++++------------------- drivers/gpu/drm/i915/i915_opregion.c | 18 ++- 3 files changed, 115 insertions(+), 122 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ef1c0b8f8d0..ed1edcf8704 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -132,6 +132,7 @@ typedef struct drm_i915_private { int user_irq_refcount; /** Cached value of IMR to avoid reads in updating the bitfield */ u32 irq_mask_reg; + u32 pipestat[2]; int tex_lru_log_granularity; int allow_batchbuffer; @@ -446,6 +447,13 @@ extern int i915_vblank_swap(struct drm_device *dev, void *data, struct drm_file *file_priv); extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask); +void +i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); + +void +i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); + + /* i915_mem.c */ extern int i915_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 82752d6177a..ca3ed183390 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -33,11 +33,23 @@ #define MAX_NOPID ((u32)~0) -/** These are the interrupts used by the driver */ -#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT | \ - I915_ASLE_INTERRUPT | \ - I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) +/** + * Interrupts that are always left unmasked. + * + * Since pipe events are edge-triggered from the PIPESTAT register to IIR, + * we leave them always unmasked in IMR and then control enabling them through + * PIPESTAT alone. + */ +#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \ + I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \ + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) + +/** Interrupts that we mask and unmask at runtime. */ +#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT) + +/** These are all of the interrupts used by the driver */ +#define I915_INTERRUPT_ENABLE_MASK (I915_INTERRUPT_ENABLE_FIX | \ + I915_INTERRUPT_ENABLE_VAR) void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask) @@ -59,6 +71,41 @@ i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask) } } +static inline u32 +i915_pipestat(int pipe) +{ + if (pipe == 0) + return PIPEASTAT; + if (pipe == 1) + return PIPEBSTAT; + BUG_ON(1); +} + +void +i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) +{ + if ((dev_priv->pipestat[pipe] & mask) != mask) { + u32 reg = i915_pipestat(pipe); + + dev_priv->pipestat[pipe] |= mask; + /* Enable the interrupt, clear any pending status */ + I915_WRITE(reg, dev_priv->pipestat[pipe] | (mask >> 16)); + (void) I915_READ(reg); + } +} + +void +i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) +{ + if ((dev_priv->pipestat[pipe] & mask) != 0) { + u32 reg = i915_pipestat(pipe); + + dev_priv->pipestat[pipe] &= ~mask; + I915_WRITE(reg, dev_priv->pipestat[pipe]); + (void) I915_READ(reg); + } +} + /** * i915_pipe_enabled - check if a pipe is enabled * @dev: DRM device @@ -122,9 +169,11 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) struct drm_device *dev = (struct drm_device *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 iir; - u32 pipea_stats, pipeb_stats; + u32 pipea_stats = 0, pipeb_stats = 0; int vblank = 0; + unsigned long irqflags; + spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); atomic_inc(&dev_priv->irq_received); if (dev->pdev->msi_enabled) @@ -136,44 +185,20 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) I915_WRITE(IMR, dev_priv->irq_mask_reg); (void) I915_READ(IMR); } + spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); return IRQ_NONE; } /* - * Clear the PIPE(A|B)STAT regs before the IIR otherwise - * we may get extra interrupts. + * Clear the PIPE(A|B)STAT regs before the IIR */ if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) { pipea_stats = I915_READ(PIPEASTAT); - if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)) - pipea_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE | - PIPE_VBLANK_INTERRUPT_ENABLE); - else if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS| - PIPE_VBLANK_INTERRUPT_STATUS)) { - vblank++; - drm_handle_vblank(dev, 0); - } - I915_WRITE(PIPEASTAT, pipea_stats); } + if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) { pipeb_stats = I915_READ(PIPEBSTAT); - /* Ack the event */ - I915_WRITE(PIPEBSTAT, pipeb_stats); - - /* The vblank interrupt gets enabled even if we didn't ask for - it, so make sure it's shut down again */ - if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)) - pipeb_stats &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE | - PIPE_VBLANK_INTERRUPT_ENABLE); - else if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS| - PIPE_VBLANK_INTERRUPT_STATUS)) { - vblank++; - drm_handle_vblank(dev, 1); - } - - if (pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) - opregion_asle_intr(dev); I915_WRITE(PIPEBSTAT, pipeb_stats); } @@ -182,6 +207,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) I915_WRITE(IMR, dev_priv->irq_mask_reg); (void) I915_READ(IIR); /* Flush posted writes */ + spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + if (dev_priv->sarea_priv) dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); @@ -191,7 +218,18 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) DRM_WAKEUP(&dev_priv->irq_queue); } - if (iir & I915_ASLE_INTERRUPT) + if (pipea_stats & I915_VBLANK_INTERRUPT_STATUS) { + vblank++; + drm_handle_vblank(dev, 0); + } + + if (pipeb_stats & I915_VBLANK_INTERRUPT_STATUS) { + vblank++; + drm_handle_vblank(dev, 1); + } + + if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) || + (iir & I915_ASLE_INTERRUPT)) opregion_asle_intr(dev); return IRQ_HANDLED; @@ -330,48 +368,16 @@ int i915_irq_wait(struct drm_device *dev, void *data, int i915_enable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u32 pipestat_reg = 0; - u32 pipestat; - u32 interrupt = 0; unsigned long irqflags; - switch (pipe) { - case 0: - pipestat_reg = PIPEASTAT; - interrupt = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; - break; - case 1: - pipestat_reg = PIPEBSTAT; - interrupt = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; - break; - default: - DRM_ERROR("tried to enable vblank on non-existent pipe %d\n", - pipe); - return 0; - } - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); - /* Enabling vblank events in IMR comes before PIPESTAT write, or - * there's a race where the PIPESTAT vblank bit gets set to 1, so - * the OR of enabled PIPESTAT bits goes to 1, so the PIPExEVENT in - * ISR flashes to 1, but the IIR bit doesn't get set to 1 because - * IMR masks it. It doesn't ever get set after we clear the masking - * in IMR because the ISR bit is edge, not level-triggered, on the - * OR of PIPESTAT bits. - */ - i915_enable_irq(dev_priv, interrupt); - pipestat = I915_READ(pipestat_reg); if (IS_I965G(dev)) - pipestat |= PIPE_START_VBLANK_INTERRUPT_ENABLE; + i915_enable_pipestat(dev_priv, pipe, + PIPE_START_VBLANK_INTERRUPT_ENABLE); else - pipestat |= PIPE_VBLANK_INTERRUPT_ENABLE; - /* Clear any stale interrupt status */ - pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS | - PIPE_VBLANK_INTERRUPT_STATUS); - I915_WRITE(pipestat_reg, pipestat); - (void) I915_READ(pipestat_reg); /* Posting read */ + i915_enable_pipestat(dev_priv, pipe, + PIPE_VBLANK_INTERRUPT_ENABLE); spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); - return 0; } @@ -381,37 +387,12 @@ int i915_enable_vblank(struct drm_device *dev, int pipe) void i915_disable_vblank(struct drm_device *dev, int pipe) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u32 pipestat_reg = 0; - u32 pipestat; - u32 interrupt = 0; unsigned long irqflags; - switch (pipe) { - case 0: - pipestat_reg = PIPEASTAT; - interrupt = I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; - break; - case 1: - pipestat_reg = PIPEBSTAT; - interrupt = I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; - break; - default: - DRM_ERROR("tried to disable vblank on non-existent pipe %d\n", - pipe); - return; - break; - } - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); - i915_disable_irq(dev_priv, interrupt); - pipestat = I915_READ(pipestat_reg); - pipestat &= ~(PIPE_START_VBLANK_INTERRUPT_ENABLE | - PIPE_VBLANK_INTERRUPT_ENABLE); - /* Clear any stale interrupt status */ - pipestat |= (PIPE_START_VBLANK_INTERRUPT_STATUS | - PIPE_VBLANK_INTERRUPT_STATUS); - I915_WRITE(pipestat_reg, pipestat); - (void) I915_READ(pipestat_reg); /* Posting read */ + i915_disable_pipestat(dev_priv, pipe, + PIPE_VBLANK_INTERRUPT_ENABLE | + PIPE_START_VBLANK_INTERRUPT_ENABLE); spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); } @@ -476,8 +457,11 @@ void i915_driver_irq_preinstall(struct drm_device * dev) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; I915_WRITE(HWSTAM, 0xeffe); + I915_WRITE(PIPEASTAT, 0); + I915_WRITE(PIPEBSTAT, 0); I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); + (void) I915_READ(IER); } int i915_driver_irq_postinstall(struct drm_device *dev) @@ -485,23 +469,28 @@ int i915_driver_irq_postinstall(struct drm_device *dev) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int ret, num_pipes = 2; - /* Set initial unmasked IRQs to just the selected vblank pipes. */ - dev_priv->irq_mask_reg = ~0; - ret = drm_vblank_init(dev, num_pipes); if (ret) return ret; dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; - dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; - dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ - dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK; + /* Unmask the interrupts that we always want on. */ + dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX; + + dev_priv->pipestat[0] = 0; + dev_priv->pipestat[1] = 0; + + /* Disable pipe interrupt enables, clear pending pipe status */ + I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff); + I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff); + /* Clear pending interrupt status */ + I915_WRITE(IIR, I915_READ(IIR)); - I915_WRITE(IMR, dev_priv->irq_mask_reg); I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK); + I915_WRITE(IMR, dev_priv->irq_mask_reg); (void) I915_READ(IER); opregion_enable_asle(dev); @@ -513,7 +502,6 @@ int i915_driver_irq_postinstall(struct drm_device *dev) void i915_driver_irq_uninstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u32 temp; if (!dev_priv) return; @@ -521,13 +509,12 @@ void i915_driver_irq_uninstall(struct drm_device * dev) dev_priv->vblank_pipe = 0; I915_WRITE(HWSTAM, 0xffffffff); + I915_WRITE(PIPEASTAT, 0); + I915_WRITE(PIPEBSTAT, 0); I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); - temp = I915_READ(PIPEASTAT); - I915_WRITE(PIPEASTAT, temp); - temp = I915_READ(PIPEBSTAT); - I915_WRITE(PIPEBSTAT, temp); - temp = I915_READ(IIR); - I915_WRITE(IIR, temp); + I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff); + I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff); + I915_WRITE(IIR, I915_READ(IIR)); } diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c index 1787a0c7e3a..13ae731a33d 100644 --- a/drivers/gpu/drm/i915/i915_opregion.c +++ b/drivers/gpu/drm/i915/i915_opregion.c @@ -235,17 +235,15 @@ void opregion_enable_asle(struct drm_device *dev) struct opregion_asle *asle = dev_priv->opregion.asle; if (asle) { - u32 pipeb_stats = I915_READ(PIPEBSTAT); if (IS_MOBILE(dev)) { - /* Many devices trigger events with a write to the - legacy backlight controller, so we need to ensure - that it's able to generate interrupts */ - I915_WRITE(PIPEBSTAT, pipeb_stats |= - I915_LEGACY_BLC_EVENT_ENABLE); - i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT | - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT); - } else - i915_enable_irq(dev_priv, I915_ASLE_INTERRUPT); + unsigned long irqflags; + + spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + i915_enable_pipestat(dev_priv, 1, + I915_LEGACY_BLC_EVENT_ENABLE); + spin_unlock_irqrestore(&dev_priv->user_irq_lock, + irqflags); + } asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN | ASLE_PFMB_EN; -- cgit v1.2.3 From cdfbc41f6d602fc0105fb2b4e0645cc1aa274c12 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 4 Nov 2008 15:50:30 -0800 Subject: drm/i915: Remove IMR masking during interrupt handler, and restart it if needed. The IMR masking was a technique recommended for avoiding getting stuck with no interrupts generated again in MSI mode. It kept new IIR bits from getting set between the IIR read and the IIR write, which would have otherwise prevented an MSI from ever getting generated again. However, this caused a problem for vblank as the IMR mask would keep the pipe event interrupt from getting reflected in IIR, even after the IMR mask was brought back down. Instead, just check the state of IIR after we ack the interrupts we're going to handle, and restart if we didn't get IIR all the way to zero. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_irq.c | 108 +++++++++++++++++++++++----------------- 1 file changed, 61 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ca3ed183390..654d42fabec 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -168,69 +168,83 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u32 iir; - u32 pipea_stats = 0, pipeb_stats = 0; + u32 iir, new_iir; + u32 pipea_stats, pipeb_stats; int vblank = 0; unsigned long irqflags; - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); atomic_inc(&dev_priv->irq_received); - if (dev->pdev->msi_enabled) - I915_WRITE(IMR, ~0); iir = I915_READ(IIR); - if (iir == 0) { - if (dev->pdev->msi_enabled) { - I915_WRITE(IMR, dev_priv->irq_mask_reg); - (void) I915_READ(IMR); - } - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + if (iir == 0) return IRQ_NONE; - } - - /* - * Clear the PIPE(A|B)STAT regs before the IIR - */ - if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) { - pipea_stats = I915_READ(PIPEASTAT); - I915_WRITE(PIPEASTAT, pipea_stats); - } - if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) { - pipeb_stats = I915_READ(PIPEBSTAT); - I915_WRITE(PIPEBSTAT, pipeb_stats); - } + do { + pipea_stats = 0; + pipeb_stats = 0; + /* + * Clear the PIPE(A|B)STAT regs before the IIR + */ + if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) { + spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + pipea_stats = I915_READ(PIPEASTAT); + I915_WRITE(PIPEASTAT, pipea_stats); + spin_unlock_irqrestore(&dev_priv->user_irq_lock, + irqflags); + } - I915_WRITE(IIR, iir); - if (dev->pdev->msi_enabled) - I915_WRITE(IMR, dev_priv->irq_mask_reg); - (void) I915_READ(IIR); /* Flush posted writes */ + if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) { + spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + pipeb_stats = I915_READ(PIPEBSTAT); + I915_WRITE(PIPEBSTAT, pipeb_stats); + spin_unlock_irqrestore(&dev_priv->user_irq_lock, + irqflags); + } - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + I915_WRITE(IIR, iir); + new_iir = I915_READ(IIR); /* Flush posted writes */ - if (dev_priv->sarea_priv) - dev_priv->sarea_priv->last_dispatch = - READ_BREADCRUMB(dev_priv); + if (dev_priv->sarea_priv) + dev_priv->sarea_priv->last_dispatch = + READ_BREADCRUMB(dev_priv); - if (iir & I915_USER_INTERRUPT) { - dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev); - DRM_WAKEUP(&dev_priv->irq_queue); - } + if (iir & I915_USER_INTERRUPT) { + dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev); + DRM_WAKEUP(&dev_priv->irq_queue); + } - if (pipea_stats & I915_VBLANK_INTERRUPT_STATUS) { - vblank++; - drm_handle_vblank(dev, 0); - } + if (pipea_stats & I915_VBLANK_INTERRUPT_STATUS) { + vblank++; + drm_handle_vblank(dev, 0); + } - if (pipeb_stats & I915_VBLANK_INTERRUPT_STATUS) { - vblank++; - drm_handle_vblank(dev, 1); - } + if (pipeb_stats & I915_VBLANK_INTERRUPT_STATUS) { + vblank++; + drm_handle_vblank(dev, 1); + } - if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) || - (iir & I915_ASLE_INTERRUPT)) - opregion_asle_intr(dev); + if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) || + (iir & I915_ASLE_INTERRUPT)) + opregion_asle_intr(dev); + + /* With MSI, interrupts are only generated when iir + * transitions from zero to nonzero. If another bit got + * set while we were handling the existing iir bits, then + * we would never get another interrupt. + * + * This is fine on non-MSI as well, as if we hit this path + * we avoid exiting the interrupt handler only to generate + * another one. + * + * Note that for MSI this could cause a stray interrupt report + * if an interrupt landed in the time between writing IIR and + * the posting read. This should be rare enough to never + * trigger the 99% of 100,000 interrupts test for disabling + * stray interrupts. + */ + iir = new_iir; + } while (iir != 0); return IRQ_HANDLED; } -- cgit v1.2.3 From 28dfe52a6e8a1495067c4331358700a170d0ee86 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 13 Nov 2008 15:00:55 -0800 Subject: drm/i915: Avoid BUG_ONs on VT switch with a wedged chipset. Instead, just warn that bad things are happening and do our best to clean up the mess without the GPU's help. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 53 ++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6b4a2bd2064..edc805afde0 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -31,6 +31,8 @@ #include "i915_drv.h" #include +#define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) + static int i915_gem_object_set_domain(struct drm_gem_object *obj, uint32_t read_domains, @@ -2299,29 +2301,52 @@ i915_gem_idle(struct drm_device *dev) i915_gem_retire_requests(dev); - /* Active and flushing should now be empty as we've - * waited for a sequence higher than any pending execbuffer - */ - BUG_ON(!list_empty(&dev_priv->mm.active_list)); - BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); + if (!dev_priv->mm.wedged) { + /* Active and flushing should now be empty as we've + * waited for a sequence higher than any pending execbuffer + */ + WARN_ON(!list_empty(&dev_priv->mm.active_list)); + WARN_ON(!list_empty(&dev_priv->mm.flushing_list)); + /* Request should now be empty as we've also waited + * for the last request in the list + */ + WARN_ON(!list_empty(&dev_priv->mm.request_list)); + } - /* Request should now be empty as we've also waited - * for the last request in the list + /* Empty the active and flushing lists to inactive. If there's + * anything left at this point, it means that we're wedged and + * nothing good's going to happen by leaving them there. So strip + * the GPU domains and just stuff them onto inactive. */ - BUG_ON(!list_empty(&dev_priv->mm.request_list)); + while (!list_empty(&dev_priv->mm.active_list)) { + struct drm_i915_gem_object *obj_priv; + + obj_priv = list_first_entry(&dev_priv->mm.active_list, + struct drm_i915_gem_object, + list); + obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS; + i915_gem_object_move_to_inactive(obj_priv->obj); + } + + while (!list_empty(&dev_priv->mm.flushing_list)) { + struct drm_i915_gem_object *obj_priv; + + obj_priv = list_first_entry(&dev_priv->mm.active_list, + struct drm_i915_gem_object, + list); + obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS; + i915_gem_object_move_to_inactive(obj_priv->obj); + } + - /* Move all buffers out of the GTT. */ + /* Move all inactive buffers out of the GTT. */ ret = i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list); + WARN_ON(!list_empty(&dev_priv->mm.inactive_list)); if (ret) { mutex_unlock(&dev->struct_mutex); return ret; } - BUG_ON(!list_empty(&dev_priv->mm.active_list)); - BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); - BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); - BUG_ON(!list_empty(&dev_priv->mm.request_list)); - i915_gem_cleanup_ringbuffer(dev); mutex_unlock(&dev->struct_mutex); -- cgit v1.2.3 From 2678d9d6964b29ecd1975870c7a850242b29bc5c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 20 Nov 2008 22:54:54 -0800 Subject: drm/i915: Subtract total pinned bytes from available aperture size The old code was wandering through the active list looking for pinned buffers; there may be other pinned buffers around. Fortunately, we keep a count of the total amount of pinned memory and can use that instead. Signed-off-by: Keith Packard Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index edc805afde0..6e4c6dd5065 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -85,20 +85,14 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_gem_get_aperture *args = data; - struct drm_i915_gem_object *obj_priv; if (!(dev->driver->driver_features & DRIVER_GEM)) return -ENODEV; args->aper_size = dev->gtt_total; - args->aper_available_size = args->aper_size; - - list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) { - if (obj_priv->pin_count > 0) - args->aper_available_size -= obj_priv->obj->size; - } + args->aper_available_size = (args->aper_size - + atomic_read(&dev->pin_memory)); return 0; } -- cgit v1.2.3 From 05eff845a28499762075d3a72e238a31f4d2407c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 19 Nov 2008 14:03:05 -0800 Subject: drm/i915: Always read pipestat in irq_handler Because we write pipestat before iir, it's possible that a pipestat interrupt will occur between the pipestat write and the iir write. This leaves pipestat with an interrupt status not visible in iir. This may cause an interrupt flood as we never clear the pipestat event. Signed-off-by: Keith Packard Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_irq.c | 55 +++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 654d42fabec..c3673581db5 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -170,37 +170,54 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 iir, new_iir; u32 pipea_stats, pipeb_stats; + u32 vblank_status; + u32 vblank_enable; int vblank = 0; unsigned long irqflags; + int irq_received; + int ret = IRQ_NONE; atomic_inc(&dev_priv->irq_received); iir = I915_READ(IIR); - if (iir == 0) - return IRQ_NONE; + if (IS_I965G(dev)) { + vblank_status = I915_START_VBLANK_INTERRUPT_STATUS; + vblank_enable = PIPE_START_VBLANK_INTERRUPT_ENABLE; + } else { + vblank_status = I915_VBLANK_INTERRUPT_STATUS; + vblank_enable = I915_VBLANK_INTERRUPT_ENABLE; + } - do { - pipea_stats = 0; - pipeb_stats = 0; + for (;;) { + irq_received = iir != 0; + + /* Can't rely on pipestat interrupt bit in iir as it might + * have been cleared after the pipestat interrupt was received. + * It doesn't set the bit in iir again, but it still produces + * interrupts (for non-MSI). + */ + spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + pipea_stats = I915_READ(PIPEASTAT); + pipeb_stats = I915_READ(PIPEBSTAT); /* * Clear the PIPE(A|B)STAT regs before the IIR */ - if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) { - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); - pipea_stats = I915_READ(PIPEASTAT); + if (pipea_stats & 0x8000ffff) { I915_WRITE(PIPEASTAT, pipea_stats); - spin_unlock_irqrestore(&dev_priv->user_irq_lock, - irqflags); + irq_received = 1; } - if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) { - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); - pipeb_stats = I915_READ(PIPEBSTAT); + if (pipeb_stats & 0x8000ffff) { I915_WRITE(PIPEBSTAT, pipeb_stats); - spin_unlock_irqrestore(&dev_priv->user_irq_lock, - irqflags); + irq_received = 1; } + spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + + if (!irq_received) + break; + + ret = IRQ_HANDLED; I915_WRITE(IIR, iir); new_iir = I915_READ(IIR); /* Flush posted writes */ @@ -214,12 +231,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) DRM_WAKEUP(&dev_priv->irq_queue); } - if (pipea_stats & I915_VBLANK_INTERRUPT_STATUS) { + if (pipea_stats & vblank_status) { vblank++; drm_handle_vblank(dev, 0); } - if (pipeb_stats & I915_VBLANK_INTERRUPT_STATUS) { + if (pipeb_stats & vblank_status) { vblank++; drm_handle_vblank(dev, 1); } @@ -244,9 +261,9 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) * stray interrupts. */ iir = new_iir; - } while (iir != 0); + } - return IRQ_HANDLED; + return ret; } static int i915_emit_irq(struct drm_device * dev) -- cgit v1.2.3 From 6133047aa64d2fd5b3b79dff74f696ded45615b2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 20 Nov 2008 23:14:48 -0800 Subject: drm/i915: execbuffer pins objects, no need to ensure they're still in the GTT Before we had the notion of pinning objects, we had a kludge around to make sure all of the objects were still resident in the GTT before we committed to executing a batch buffer. We don't need this any longer, and it sticks an error return in the middle of object domain computations that must be associated with a subsequent flush/invalidate emmission into the ring. Signed-off-by: Keith Packard Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6e4c6dd5065..54bb0d0e49b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1866,17 +1866,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, for (i = 0; i < args->buffer_count; i++) { struct drm_gem_object *obj = object_list[i]; - struct drm_i915_gem_object *obj_priv = obj->driver_private; - - if (obj_priv->gtt_space == NULL) { - /* We evicted the buffer in the process of validating - * our set of buffers in. We could try to recover by - * kicking them everything out and trying again from - * the start. - */ - ret = -ENOMEM; - goto err; - } /* make sure all previous memory operations have passed */ ret = i915_gem_object_set_domain(obj, -- cgit v1.2.3 From 52440211dcdc52c0b757f8b34d122e11b12cdd50 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 18 Nov 2008 09:30:25 -0800 Subject: drm: move drm vblank initialization/cleanup to driver load/unload drm vblank initialization keeps track of the changes in driver-supplied frame counts across vt switch and mode setting, but only if you let it by not tearing down the drm vblank structure. Signed-off-by: Keith Packard Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_drv.c | 2 ++ drivers/gpu/drm/drm_irq.c | 4 +--- drivers/gpu/drm/i915/i915_dma.c | 7 +++++++ drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_irq.c | 5 ----- drivers/gpu/drm/mga/mga_dma.c | 8 ++++++++ drivers/gpu/drm/mga/mga_irq.c | 5 ----- drivers/gpu/drm/r128/r128_drv.c | 6 ++++++ drivers/gpu/drm/r128/r128_drv.h | 1 + drivers/gpu/drm/r128/r128_irq.c | 2 +- drivers/gpu/drm/radeon/radeon_cp.c | 6 ++++++ drivers/gpu/drm/radeon/radeon_irq.c | 5 ----- drivers/gpu/drm/via/via_irq.c | 1 - drivers/gpu/drm/via/via_map.c | 11 ++++++++++- 14 files changed, 44 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 3ab1e9cc469..996097acb5e 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -305,6 +305,8 @@ static void drm_cleanup(struct drm_device * dev) return; } + drm_vblank_cleanup(dev); + drm_lastclose(dev); if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 15c8dabc3e9..1e787f894b3 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -94,7 +94,7 @@ static void vblank_disable_fn(unsigned long arg) } } -static void drm_vblank_cleanup(struct drm_device *dev) +void drm_vblank_cleanup(struct drm_device *dev) { /* Bail if the driver didn't call drm_vblank_init() */ if (dev->num_crtcs == 0) @@ -278,8 +278,6 @@ int drm_irq_uninstall(struct drm_device * dev) free_irq(dev->pdev->irq, dev); - drm_vblank_cleanup(dev); - return 0; } EXPORT_SYMBOL(drm_irq_uninstall); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 0d215e38606..ba89b42f790 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -856,6 +856,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) spin_lock_init(&dev_priv->user_irq_lock); + ret = drm_vblank_init(dev, I915_NUM_PIPE); + + if (ret) { + (void) i915_driver_unload(dev); + return ret; + } + return ret; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ed1edcf8704..b24d522f490 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -47,6 +47,8 @@ enum pipe { PIPE_B, }; +#define I915_NUM_PIPE 2 + /* Interface history: * * 1.1: Original. diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c3673581db5..fe3d9cc72bf 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -498,11 +498,6 @@ void i915_driver_irq_preinstall(struct drm_device * dev) int i915_driver_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - int ret, num_pipes = 2; - - ret = drm_vblank_init(dev, num_pipes); - if (ret) - return ret; dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c index c1d12dbfa8d..b49c5ff2958 100644 --- a/drivers/gpu/drm/mga/mga_dma.c +++ b/drivers/gpu/drm/mga/mga_dma.c @@ -396,6 +396,7 @@ int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf) int mga_driver_load(struct drm_device * dev, unsigned long flags) { drm_mga_private_t *dev_priv; + int ret; dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER); if (!dev_priv) @@ -415,6 +416,13 @@ int mga_driver_load(struct drm_device * dev, unsigned long flags) dev->types[7] = _DRM_STAT_PRIMARY; dev->types[8] = _DRM_STAT_SECONDARY; + ret = drm_vblank_init(dev, 1); + + if (ret) { + (void) mga_driver_unload(dev); + return ret; + } + return 0; } diff --git a/drivers/gpu/drm/mga/mga_irq.c b/drivers/gpu/drm/mga/mga_irq.c index bab42f41188..daa6041a483 100644 --- a/drivers/gpu/drm/mga/mga_irq.c +++ b/drivers/gpu/drm/mga/mga_irq.c @@ -152,11 +152,6 @@ void mga_driver_irq_preinstall(struct drm_device * dev) int mga_driver_irq_postinstall(struct drm_device *dev) { drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - int ret; - - ret = drm_vblank_init(dev, 1); - if (ret) - return ret; DRM_INIT_WAITQUEUE(&dev_priv->fence_queue); diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index 3265d53ba91..601f4c0e5da 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c @@ -45,6 +45,7 @@ static struct drm_driver driver = { DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, .dev_priv_size = sizeof(drm_r128_buf_priv_t), + .load = r128_driver_load, .preclose = r128_driver_preclose, .lastclose = r128_driver_lastclose, .get_vblank_counter = r128_get_vblank_counter, @@ -84,6 +85,11 @@ static struct drm_driver driver = { .patchlevel = DRIVER_PATCHLEVEL, }; +int r128_driver_load(struct drm_device * dev, unsigned long flags) +{ + return drm_vblank_init(dev, 1); +} + static int __init r128_init(void) { driver.num_ioctls = r128_max_ioctl; diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h index 5898b274279..797a26c42da 100644 --- a/drivers/gpu/drm/r128/r128_drv.h +++ b/drivers/gpu/drm/r128/r128_drv.h @@ -159,6 +159,7 @@ extern void r128_driver_irq_preinstall(struct drm_device * dev); extern int r128_driver_irq_postinstall(struct drm_device *dev); extern void r128_driver_irq_uninstall(struct drm_device * dev); extern void r128_driver_lastclose(struct drm_device * dev); +extern int r128_driver_load(struct drm_device * dev, unsigned long flags); extern void r128_driver_preclose(struct drm_device * dev, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/r128/r128_irq.c b/drivers/gpu/drm/r128/r128_irq.c index d7349012a68..69810fb8ac4 100644 --- a/drivers/gpu/drm/r128/r128_irq.c +++ b/drivers/gpu/drm/r128/r128_irq.c @@ -102,7 +102,7 @@ void r128_driver_irq_preinstall(struct drm_device * dev) int r128_driver_irq_postinstall(struct drm_device *dev) { - return drm_vblank_init(dev, 1); + return 0; } void r128_driver_irq_uninstall(struct drm_device * dev) diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index abdc1ae3846..dcebb4bee7a 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -1757,6 +1757,12 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) if (ret != 0) return ret; + ret = drm_vblank_init(dev, 2); + if (ret) { + radeon_driver_unload(dev); + return ret; + } + DRM_DEBUG("%s card detected\n", ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); return ret; diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c index 5079f7054a2..97c0599fdb1 100644 --- a/drivers/gpu/drm/radeon/radeon_irq.c +++ b/drivers/gpu/drm/radeon/radeon_irq.c @@ -337,15 +337,10 @@ int radeon_driver_irq_postinstall(struct drm_device *dev) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; - int ret; atomic_set(&dev_priv->swi_emitted, 0); DRM_INIT_WAITQUEUE(&dev_priv->swi_queue); - ret = drm_vblank_init(dev, 2); - if (ret) - return ret; - dev->max_vblank_count = 0x001fffff; radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c index 665d319b927..c248c1d3726 100644 --- a/drivers/gpu/drm/via/via_irq.c +++ b/drivers/gpu/drm/via/via_irq.c @@ -314,7 +314,6 @@ int via_driver_irq_postinstall(struct drm_device *dev) if (!dev_priv) return -EINVAL; - drm_vblank_init(dev, 1); status = VIA_READ(VIA_REG_INTERRUPT); VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL | dev_priv->irq_enable_mask); diff --git a/drivers/gpu/drm/via/via_map.c b/drivers/gpu/drm/via/via_map.c index a967556be01..2c4f0b48579 100644 --- a/drivers/gpu/drm/via/via_map.c +++ b/drivers/gpu/drm/via/via_map.c @@ -107,8 +107,17 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset) ret = drm_sman_init(&dev_priv->sman, 2, 12, 8); if (ret) { drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); + return ret; } - return ret; + + ret = drm_vblank_init(dev, 1); + if (ret) { + drm_sman_takedown(&dev_priv->sman); + drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER); + return ret; + } + + return 0; } int via_driver_unload(struct drm_device *dev) -- cgit v1.2.3 From 7953031da4200323ab5d85bd514054ca4ba9d225 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 24 Nov 2008 18:11:16 -0800 Subject: ARM: OMAP: Remove broken LCD driver for SX1 Recently the omap McBSP code was cleaned up to get rid of direct McBSP register tinkering by the drivers. Looks like lcd_sx1.c never got converted, and now it breaks builds. It seems the lcd_sx1.c driver is attempting SPI mode, but doing it in a different way compared to omap_mcbsp_set_spi_mode(). Remove the broken driver, patches welcome to add it back when done properly by patching both mcbsp.c and lcd_sx1.c. Cc: Vovan888@gmail.com Cc: linux-fbdev-devel@lists.sourceforge.net Signed-off-by: Tony Lindgren --- drivers/video/omap/Makefile | 1 - drivers/video/omap/lcd_sx1.c | 327 ------------------------------------------- 2 files changed, 328 deletions(-) delete mode 100644 drivers/video/omap/lcd_sx1.c (limited to 'drivers') diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile index 99da8b6d2c3..ed13889c116 100644 --- a/drivers/video/omap/Makefile +++ b/drivers/video/omap/Makefile @@ -23,7 +23,6 @@ objs-y$(CONFIG_MACH_OMAP_PALMZ71) += lcd_palmz71.o objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o -objs-y$(CONFIG_MACH_SX1) += lcd_sx1.o omapfb-objs := $(objs-yy) diff --git a/drivers/video/omap/lcd_sx1.c b/drivers/video/omap/lcd_sx1.c deleted file mode 100644 index e55de201b8f..00000000000 --- a/drivers/video/omap/lcd_sx1.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * LCD panel support for the Siemens SX1 mobile phone - * - * Current version : Vovan888@gmail.com, great help from FCA00000 - * - * 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, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -/* - * OMAP310 GPIO registers - */ -#define GPIO_DATA_INPUT 0xfffce000 -#define GPIO_DATA_OUTPUT 0xfffce004 -#define GPIO_DIR_CONTROL 0xfffce008 -#define GPIO_INT_CONTROL 0xfffce00c -#define GPIO_INT_MASK 0xfffce010 -#define GPIO_INT_STATUS 0xfffce014 -#define GPIO_PIN_CONTROL 0xfffce018 - - -#define A_LCD_SSC_RD 3 -#define A_LCD_SSC_SD 7 -#define _A_LCD_RESET 9 -#define _A_LCD_SSC_CS 12 -#define _A_LCD_SSC_A0 13 - -#define DSP_REG 0xE1017024 - -const unsigned char INIT_1[12] = { - 0x1C, 0x02, 0x88, 0x00, 0x1E, 0xE0, 0x00, 0xDC, 0x00, 0x02, 0x00 -}; - -const unsigned char INIT_2[127] = { - 0x15, 0x00, 0x29, 0x00, 0x3E, 0x00, 0x51, 0x00, - 0x65, 0x00, 0x7A, 0x00, 0x8D, 0x00, 0xA1, 0x00, - 0xB6, 0x00, 0xC7, 0x00, 0xD8, 0x00, 0xEB, 0x00, - 0xFB, 0x00, 0x0B, 0x01, 0x1B, 0x01, 0x27, 0x01, - 0x34, 0x01, 0x41, 0x01, 0x4C, 0x01, 0x55, 0x01, - 0x5F, 0x01, 0x68, 0x01, 0x70, 0x01, 0x78, 0x01, - 0x7E, 0x01, 0x86, 0x01, 0x8C, 0x01, 0x94, 0x01, - 0x9B, 0x01, 0xA1, 0x01, 0xA4, 0x01, 0xA9, 0x01, - 0xAD, 0x01, 0xB2, 0x01, 0xB7, 0x01, 0xBC, 0x01, - 0xC0, 0x01, 0xC4, 0x01, 0xC8, 0x01, 0xCB, 0x01, - 0xCF, 0x01, 0xD2, 0x01, 0xD5, 0x01, 0xD8, 0x01, - 0xDB, 0x01, 0xE0, 0x01, 0xE3, 0x01, 0xE6, 0x01, - 0xE8, 0x01, 0xEB, 0x01, 0xEE, 0x01, 0xF1, 0x01, - 0xF3, 0x01, 0xF8, 0x01, 0xF9, 0x01, 0xFC, 0x01, - 0x00, 0x02, 0x03, 0x02, 0x07, 0x02, 0x09, 0x02, - 0x0E, 0x02, 0x13, 0x02, 0x1C, 0x02, 0x00 -}; - -const unsigned char INIT_3[15] = { - 0x14, 0x26, 0x33, 0x3D, 0x45, 0x4D, 0x53, 0x59, - 0x5E, 0x63, 0x67, 0x6D, 0x71, 0x78, 0xFF -}; - -static void epson_sendbyte(int flag, unsigned char byte) -{ - int i, shifter = 0x80; - - if (!flag) - gpio_set_value(_A_LCD_SSC_A0, 0); - mdelay(2); - gpio_set_value(A_LCD_SSC_RD, 1); - - gpio_set_value(A_LCD_SSC_SD, flag); - - OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200); - OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202); - for (i = 0; i < 8; i++) { - OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2200); - gpio_set_value(A_LCD_SSC_SD, shifter & byte); - OMAP_MCBSP_WRITE(OMAP1510_MCBSP3_BASE, PCR0, 0x2202); - shifter >>= 1; - } - gpio_set_value(_A_LCD_SSC_A0, 1); -} - -static void init_system(void) -{ - omap_mcbsp_request(OMAP_MCBSP3); - omap_mcbsp_stop(OMAP_MCBSP3); -} - -static void setup_GPIO(void) -{ - /* new wave */ - gpio_request(A_LCD_SSC_RD, "lcd_ssc_rd"); - gpio_request(A_LCD_SSC_SD, "lcd_ssc_sd"); - gpio_request(_A_LCD_RESET, "lcd_reset"); - gpio_request(_A_LCD_SSC_CS, "lcd_ssc_cs"); - gpio_request(_A_LCD_SSC_A0, "lcd_ssc_a0"); - - /* set GPIOs to output, with initial data */ - gpio_direction_output(A_LCD_SSC_RD, 1); - gpio_direction_output(A_LCD_SSC_SD, 0); - gpio_direction_output(_A_LCD_RESET, 0); - gpio_direction_output(_A_LCD_SSC_CS, 1); - gpio_direction_output(_A_LCD_SSC_A0, 1); -} - -static void display_init(void) -{ - int i; - - omap_cfg_reg(MCBSP3_CLKX); - - mdelay(2); - setup_GPIO(); - mdelay(2); - - /* reset LCD */ - gpio_set_value(A_LCD_SSC_SD, 1); - epson_sendbyte(0, 0x25); - - gpio_set_value(_A_LCD_RESET, 0); - mdelay(10); - gpio_set_value(_A_LCD_RESET, 1); - - gpio_set_value(_A_LCD_SSC_CS, 1); - mdelay(2); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD, phase 1 */ - epson_sendbyte(0, 0xCA); - for (i = 0; i < 10; i++) - epson_sendbyte(1, INIT_1[i]); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 2 */ - epson_sendbyte(0, 0xCB); - for (i = 0; i < 125; i++) - epson_sendbyte(1, INIT_2[i]); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 2a */ - epson_sendbyte(0, 0xCC); - for (i = 0; i < 14; i++) - epson_sendbyte(1, INIT_3[i]); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 3 */ - epson_sendbyte(0, 0xBC); - epson_sendbyte(1, 0x08); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 4 */ - epson_sendbyte(0, 0x07); - epson_sendbyte(1, 0x05); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 5 */ - epson_sendbyte(0, 0x94); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 6 */ - epson_sendbyte(0, 0xC6); - epson_sendbyte(1, 0x80); - gpio_set_value(_A_LCD_SSC_CS, 1); - mdelay(100); /* used to be 1000 */ - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 7 */ - epson_sendbyte(0, 0x16); - epson_sendbyte(1, 0x02); - epson_sendbyte(1, 0x00); - epson_sendbyte(1, 0xB1); - epson_sendbyte(1, 0x00); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 8 */ - epson_sendbyte(0, 0x76); - epson_sendbyte(1, 0x00); - epson_sendbyte(1, 0x00); - epson_sendbyte(1, 0xDB); - epson_sendbyte(1, 0x00); - gpio_set_value(_A_LCD_SSC_CS, 1); - gpio_set_value(_A_LCD_SSC_CS, 0); - - /* init LCD phase 9 */ - epson_sendbyte(0, 0xAF); - gpio_set_value(_A_LCD_SSC_CS, 1); -} - -static int sx1_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) -{ - return 0; -} - -static void sx1_panel_cleanup(struct lcd_panel *panel) -{ -} - -static void sx1_panel_disable(struct lcd_panel *panel) -{ - printk(KERN_INFO "SX1: LCD panel disable\n"); - sx1_setmmipower(0); - gpio_set_value(_A_LCD_SSC_CS, 1); - - epson_sendbyte(0, 0x25); - gpio_set_value(_A_LCD_SSC_CS, 0); - - epson_sendbyte(0, 0xAE); - gpio_set_value(_A_LCD_SSC_CS, 1); - mdelay(100); - gpio_set_value(_A_LCD_SSC_CS, 0); - - epson_sendbyte(0, 0x95); - gpio_set_value(_A_LCD_SSC_CS, 1); -} - -static int sx1_panel_enable(struct lcd_panel *panel) -{ - printk(KERN_INFO "lcd_sx1: LCD panel enable\n"); - init_system(); - display_init(); - - sx1_setmmipower(1); - sx1_setbacklight(0x18); - sx1_setkeylight (0x06); - return 0; -} - - -static unsigned long sx1_panel_get_caps(struct lcd_panel *panel) -{ - return 0; -} - -struct lcd_panel sx1_panel = { - .name = "sx1", - .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | - OMAP_LCDC_INV_HSYNC | OMAP_LCDC_INV_PIX_CLOCK | - OMAP_LCDC_INV_OUTPUT_EN, - - .x_res = 176, - .y_res = 220, - .data_lines = 16, - .bpp = 16, - .hsw = 5, - .hfp = 5, - .hbp = 5, - .vsw = 2, - .vfp = 1, - .vbp = 1, - .pixel_clock = 1500, - - .init = sx1_panel_init, - .cleanup = sx1_panel_cleanup, - .enable = sx1_panel_enable, - .disable = sx1_panel_disable, - .get_caps = sx1_panel_get_caps, -}; - -static int sx1_panel_probe(struct platform_device *pdev) -{ - omapfb_register_panel(&sx1_panel); - return 0; -} - -static int sx1_panel_remove(struct platform_device *pdev) -{ - return 0; -} - -static int sx1_panel_suspend(struct platform_device *pdev, pm_message_t mesg) -{ - return 0; -} - -static int sx1_panel_resume(struct platform_device *pdev) -{ - return 0; -} - -struct platform_driver sx1_panel_driver = { - .probe = sx1_panel_probe, - .remove = sx1_panel_remove, - .suspend = sx1_panel_suspend, - .resume = sx1_panel_resume, - .driver = { - .name = "lcd_sx1", - .owner = THIS_MODULE, - }, -}; - -static int sx1_panel_drv_init(void) -{ - return platform_driver_register(&sx1_panel_driver); -} - -static void sx1_panel_drv_cleanup(void) -{ - platform_driver_unregister(&sx1_panel_driver); -} - -module_init(sx1_panel_drv_init); -module_exit(sx1_panel_drv_cleanup); -- cgit v1.2.3 From 11c6dd2c723a9ff9bdd4ee11b2798a08abc94e98 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 25 Nov 2008 01:00:47 -0800 Subject: phylib: Add Vitesse VSC8221 SGMII PHY PHY is mostly compatible with the existing VSC8244 PHY. The init sequence is different and the interrupt mask lacks some bits present in the VSC8244. Rather than making a copy of the existing VSC234x config_intr function and change one constant, I modify it to select the interrupt mask based on which driver is calling it. This lets it be used by both drivers. Signed-off-by: Trent Piepho Signed-off-by: David S. Miller --- drivers/net/phy/vitesse.c | 64 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c index 8874497b6bb..dd3b2447e85 100644 --- a/drivers/net/phy/vitesse.c +++ b/drivers/net/phy/vitesse.c @@ -34,6 +34,8 @@ #define MII_VSC8244_IMASK_DUPLEX 0x1000 #define MII_VSC8244_IMASK_MASK 0xf000 +#define MII_VSC8221_IMASK_MASK 0xa000 + /* Vitesse Interrupt Status Register */ #define MII_VSC8244_ISTAT 0x1a #define MII_VSC8244_ISTAT_STATUS 0x8000 @@ -49,6 +51,12 @@ #define MII_VSC8244_AUXCONSTAT_GBIT 0x0010 #define MII_VSC8244_AUXCONSTAT_100 0x0008 +#define MII_VSC8221_AUXCONSTAT_INIT 0x0004 /* need to set this bit? */ +#define MII_VSC8221_AUXCONSTAT_RESERVED 0x0004 + +#define PHY_ID_VSC8244 0x000fc6c0 +#define PHY_ID_VSC8221 0x000fc550 + MODULE_DESCRIPTION("Vitesse PHY driver"); MODULE_AUTHOR("Kriston Carson"); MODULE_LICENSE("GPL"); @@ -95,13 +103,15 @@ static int vsc824x_ack_interrupt(struct phy_device *phydev) return (err < 0) ? err : 0; } -static int vsc824x_config_intr(struct phy_device *phydev) +static int vsc82xx_config_intr(struct phy_device *phydev) { int err; if (phydev->interrupts == PHY_INTERRUPT_ENABLED) err = phy_write(phydev, MII_VSC8244_IMASK, - MII_VSC8244_IMASK_MASK); + phydev->drv->phy_id == PHY_ID_VSC8244 ? + MII_VSC8244_IMASK_MASK : + MII_VSC8221_IMASK_MASK); else { /* * The Vitesse PHY cannot clear the interrupt @@ -120,7 +130,7 @@ static int vsc824x_config_intr(struct phy_device *phydev) /* Vitesse 824x */ static struct phy_driver vsc8244_driver = { - .phy_id = 0x000fc6c0, + .phy_id = PHY_ID_VSC8244, .name = "Vitesse VSC8244", .phy_id_mask = 0x000fffc0, .features = PHY_GBIT_FEATURES, @@ -129,19 +139,55 @@ static struct phy_driver vsc8244_driver = { .config_aneg = &genphy_config_aneg, .read_status = &genphy_read_status, .ack_interrupt = &vsc824x_ack_interrupt, - .config_intr = &vsc824x_config_intr, + .config_intr = &vsc82xx_config_intr, .driver = { .owner = THIS_MODULE,}, }; -static int __init vsc8244_init(void) +static int vsc8221_config_init(struct phy_device *phydev) { - return phy_driver_register(&vsc8244_driver); + int err; + + err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT, + MII_VSC8221_AUXCONSTAT_INIT); + return err; + + /* Perhaps we should set EXT_CON1 based on the interface? + Options are 802.3Z SerDes or SGMII */ +} + +/* Vitesse 8221 */ +static struct phy_driver vsc8221_driver = { + .phy_id = PHY_ID_VSC8221, + .phy_id_mask = 0x000ffff0, + .name = "Vitesse VSC8221", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &vsc8221_config_init, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &vsc824x_ack_interrupt, + .config_intr = &vsc82xx_config_intr, + .driver = { .owner = THIS_MODULE,}, +}; + +static int __init vsc82xx_init(void) +{ + int err; + + err = phy_driver_register(&vsc8244_driver); + if (err < 0) + return err; + err = phy_driver_register(&vsc8221_driver); + if (err < 0) + phy_driver_unregister(&vsc8244_driver); + return err; } -static void __exit vsc8244_exit(void) +static void __exit vsc82xx_exit(void) { phy_driver_unregister(&vsc8244_driver); + phy_driver_unregister(&vsc8221_driver); } -module_init(vsc8244_init); -module_exit(vsc8244_exit); +module_init(vsc82xx_init); +module_exit(vsc82xx_exit); -- cgit v1.2.3 From 9e0de91011ef6fe6eb3bb63f7ea15f586955660a Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 22 Nov 2008 12:38:24 +0100 Subject: ieee1394: sbp2: another iPod mini quirk entry Add another model ID of a broken firmware to prevent early I/O errors by acesses at the end of the disk. Reported at linux1394-user, http://marc.info/?t=122670842900002 Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index c52f6e6e8af..3f5dbcb2160 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -400,6 +400,11 @@ static const struct { .model_id = 0x000021, .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, }, + /* iPod mini */ { + .firmware_revision = 0x0a2700, + .model_id = 0x000022, + .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, + }, /* iPod mini */ { .firmware_revision = 0x0a2700, .model_id = 0x000023, -- cgit v1.2.3 From 031bb27c4bf77c2f60b3f3dea8cce63ef0d1fba9 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 22 Nov 2008 12:38:58 +0100 Subject: firewire: fw-sbp2: another iPod mini quirk entry Add another model ID of a broken firmware to prevent early I/O errors by acesses at the end of the disk. Reported at linux1394-user, http://marc.info/?t=122670842900002 Signed-off-by: Stefan Richter --- drivers/firewire/fw-sbp2.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 97df6dac3a8..e54403ee59e 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -370,6 +370,11 @@ static const struct { .model = 0x000021, .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, }, + /* iPod mini */ { + .firmware_revision = 0x0a2700, + .model = 0x000022, + .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, + }, /* iPod mini */ { .firmware_revision = 0x0a2700, .model = 0x000023, -- cgit v1.2.3 From e91af0af8677198346d5d29f09ab39bb3b0e3faf Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 19 Nov 2008 01:22:51 +0100 Subject: iwlagn: fix DMA sync For the RX DMA fix for iwlwifi ("iwlagn: fix RX skb alignment") Luis pointed out: > aligned_dma_addr can obviously be > real_dma_addr at this point, what > guarantees we can use it on our own whim? I asked around, and he's right, there may be platforms that do not allow passing such such an address to the DMA API functions. This patch changes it by using the proper dma_sync_single_range_for_cpu API invented for this purpose. Cc: Luis R. Rodriguez Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 444c5cc05f0..c4c0371c763 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1384,9 +1384,11 @@ void iwl_rx_handle(struct iwl_priv *priv) rxq->queue[i] = NULL; - pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->aligned_dma_addr, - priv->hw_params.rx_buf_size, - PCI_DMA_FROMDEVICE); + dma_sync_single_range_for_cpu( + &priv->pci_dev->dev, rxb->real_dma_addr, + rxb->aligned_dma_addr - rxb->real_dma_addr, + priv->hw_params.rx_buf_size, + PCI_DMA_FROMDEVICE); pkt = (struct iwl_rx_packet *)rxb->skb->data; /* Reclaim a command buffer only if this packet is a response -- cgit v1.2.3 From ca0c7e5101fd4f37fed8e851709f08580b92fbb3 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 20 Nov 2008 17:15:12 -0800 Subject: ath9k: Fix SW-IOMMU bounce buffer starvation This should fix the SW-IOMMU bounce buffer starvation seen ok kernel.org bugzilla 11811: http://bugzilla.kernel.org/show_bug.cgi?id=11811 Users on MacBook Pro 3.1/MacBook v2 would see something like: DMA: Out of SW-IOMMU space for 4224 bytes at device 0000:0b:00.0 Unfortunately its only easy to trigger on MacBook Pro 3.1/MacBook v2 so far so its difficult to debug (even with swiotlb=force). We were pci_unmap_single()'ing less bytes than what we called for with pci_map_single() and as such we were starving the swiotlb from its 64MB amount of bounce buffers. We remain consistent and now always use sc->rxbufsize for RX. While at it we update the beacon DMA maps as well to only use the data portion of the skb, previous to this we were pci_map_single()'ing more data for beaconing than what we tell the hardware it can use, therefore pushing more iotlb abuse. Still not sure why this is so easily triggerable on MacBook Pro 3.1, it may be the hardware configuration tends to use more memory > 3GB mark for DMA. Signed-off-by: Maciej Zenczykowski Signed-off-by: Bennyam Malavazi Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/beacon.c | 10 +++++----- drivers/net/wireless/ath9k/recv.c | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index 9e15c30bbc0..4dd1c1bda0f 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c @@ -170,7 +170,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) skb = (struct sk_buff *)bf->bf_mpdu; if (skb) { pci_unmap_single(sc->pdev, bf->bf_dmacontext, - skb_end_pointer(skb) - skb->head, + skb->len, PCI_DMA_TODEVICE); } @@ -193,7 +193,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) bf->bf_buf_addr = bf->bf_dmacontext = pci_map_single(sc->pdev, skb->data, - skb_end_pointer(skb) - skb->head, + skb->len, PCI_DMA_TODEVICE); skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data); @@ -352,7 +352,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) if (bf->bf_mpdu != NULL) { skb = (struct sk_buff *)bf->bf_mpdu; pci_unmap_single(sc->pdev, bf->bf_dmacontext, - skb_end_pointer(skb) - skb->head, + skb->len, PCI_DMA_TODEVICE); dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; @@ -412,7 +412,7 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) bf->bf_buf_addr = bf->bf_dmacontext = pci_map_single(sc->pdev, skb->data, - skb_end_pointer(skb) - skb->head, + skb->len, PCI_DMA_TODEVICE); bf->bf_mpdu = skb; @@ -439,7 +439,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) if (bf->bf_mpdu != NULL) { struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; pci_unmap_single(sc->pdev, bf->bf_dmacontext, - skb_end_pointer(skb) - skb->head, + skb->len, PCI_DMA_TODEVICE); dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 4983402af55..ad5f88879dc 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c @@ -456,7 +456,7 @@ static int ath_rx_indicate(struct ath_softc *sc, if (nskb != NULL) { bf->bf_mpdu = nskb; bf->bf_buf_addr = pci_map_single(sc->pdev, nskb->data, - skb_end_pointer(nskb) - nskb->head, + sc->sc_rxbufsize, PCI_DMA_FROMDEVICE); bf->bf_dmacontext = bf->bf_buf_addr; ATH_RX_CONTEXT(nskb)->ctx_rxbuf = bf; @@ -542,7 +542,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) bf->bf_mpdu = skb; bf->bf_buf_addr = pci_map_single(sc->pdev, skb->data, - skb_end_pointer(skb) - skb->head, + sc->sc_rxbufsize, PCI_DMA_FROMDEVICE); bf->bf_dmacontext = bf->bf_buf_addr; ATH_RX_CONTEXT(skb)->ctx_rxbuf = bf; @@ -1007,7 +1007,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) pci_dma_sync_single_for_cpu(sc->pdev, bf->bf_buf_addr, - skb_tailroom(skb), + sc->sc_rxbufsize, PCI_DMA_FROMDEVICE); pci_unmap_single(sc->pdev, bf->bf_buf_addr, -- cgit v1.2.3 From b4b6cda2298b0c9a0af902312184b775b8867c65 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 20 Nov 2008 17:15:13 -0800 Subject: ath9k: correct expected max RX buffer size We should only tell the hardware its capable of DMA'ing to us only what we asked dev_alloc_skb(). Prior to this it is possible a large RX'd frame could have corrupted DMA data but for us but we were saved only because we were previously also pci_map_single()'ing the same large value. The issue prior to this though was we were unmapping a smaller amount which the prior DMA patch fixed. Signed-off-by: Bennyam Malavazi Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/recv.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index ad5f88879dc..504a0444d89 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c @@ -49,10 +49,12 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) ASSERT(skb != NULL); ds->ds_vdata = skb->data; - /* setup rx descriptors */ + /* setup rx descriptors. The sc_rxbufsize here tells the harware + * how much data it can DMA to us and that we are prepared + * to process */ ath9k_hw_setuprxdesc(ah, ds, - skb_tailroom(skb), /* buffer size */ + sc->sc_rxbufsize, 0); if (sc->sc_rxlink == NULL) @@ -398,6 +400,13 @@ static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, * in rx'd frames. */ + /* Note: the kernel can allocate a value greater than + * what we ask it to give us. We really only need 4 KB as that + * is this hardware supports and in fact we need at least 3849 + * as that is the MAX AMSDU size this hardware supports. + * Unfortunately this means we may get 8 KB here from the + * kernel... and that is actually what is observed on some + * systems :( */ skb = dev_alloc_skb(len + sc->sc_cachelsz - 1); if (skb != NULL) { off = ((unsigned long) skb->data) % sc->sc_cachelsz; -- cgit v1.2.3 From 33ab625f2a23e743161f7ccd8e774ce3d3891339 Mon Sep 17 00:00:00 2001 From: Cheng Renquan Date: Sat, 22 Nov 2008 11:22:49 +0800 Subject: ath5k: fix Security issue in DebugFS part of ath5k MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit http://bugzilla.kernel.org/show_bug.cgi?id=12076 Remove any write access to groups and others, only keep write permission to its owner, usually only root user. Reported-by: Jérôme Poulin Signed-off-by: Cheng Renquan Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/debug.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 19980cbd5d5..ccaeb5c219d 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -417,19 +417,19 @@ ath5k_debug_init_device(struct ath5k_softc *sc) sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy), ath5k_global_debugfs); - sc->debug.debugfs_debug = debugfs_create_file("debug", 0666, + sc->debug.debugfs_debug = debugfs_create_file("debug", S_IWUSR | S_IRUGO, sc->debug.debugfs_phydir, sc, &fops_debug); - sc->debug.debugfs_registers = debugfs_create_file("registers", 0444, + sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUGO, sc->debug.debugfs_phydir, sc, &fops_registers); - sc->debug.debugfs_tsf = debugfs_create_file("tsf", 0666, + sc->debug.debugfs_tsf = debugfs_create_file("tsf", S_IWUSR | S_IRUGO, sc->debug.debugfs_phydir, sc, &fops_tsf); - sc->debug.debugfs_beacon = debugfs_create_file("beacon", 0666, + sc->debug.debugfs_beacon = debugfs_create_file("beacon", S_IWUSR | S_IRUGO, sc->debug.debugfs_phydir, sc, &fops_beacon); - sc->debug.debugfs_reset = debugfs_create_file("reset", 0222, + sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, sc->debug.debugfs_phydir, sc, &fops_reset); } -- cgit v1.2.3 From 02969b38e6f7cef80e71d673d1e512e029a7009f Mon Sep 17 00:00:00 2001 From: Martin Xu Date: Mon, 24 Nov 2008 10:49:27 +0800 Subject: ath5k: disable beacon filter when station is not associated Ath5k driver has too many interrupts per second at idle http://bugzilla.kernel.org/show_bug.cgi?id=11749 Signed-off-by: Martin Xu Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 35 ++++++++++++++++++++++++++++++++++- drivers/net/wireless/ath5k/base.h | 1 + 2 files changed, 35 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index cfd4d052d66..2d14255eb10 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -240,6 +240,10 @@ static u64 ath5k_get_tsf(struct ieee80211_hw *hw); static void ath5k_reset_tsf(struct ieee80211_hw *hw); static int ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); +static void ath5k_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes); static struct ieee80211_ops ath5k_hw_ops = { .tx = ath5k_tx, @@ -256,6 +260,7 @@ static struct ieee80211_ops ath5k_hw_ops = { .get_tx_stats = ath5k_get_tx_stats, .get_tsf = ath5k_get_tsf, .reset_tsf = ath5k_reset_tsf, + .bss_info_changed = ath5k_bss_info_changed, }; /* @@ -2942,7 +2947,7 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, sc->opmode != NL80211_IFTYPE_MESH_POINT && test_bit(ATH_STAT_PROMISC, sc->status)) rfilt |= AR5K_RX_FILTER_PROM; - if (sc->opmode == NL80211_IFTYPE_STATION || + if ((sc->opmode == NL80211_IFTYPE_STATION && sc->assoc) || sc->opmode == NL80211_IFTYPE_ADHOC) { rfilt |= AR5K_RX_FILTER_BEACON; } @@ -3083,4 +3088,32 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) end: return ret; } +static void +set_beacon_filter(struct ieee80211_hw *hw, bool enable) +{ + struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; + u32 rfilt; + rfilt = ath5k_hw_get_rx_filter(ah); + if (enable) + rfilt |= AR5K_RX_FILTER_BEACON; + else + rfilt &= ~AR5K_RX_FILTER_BEACON; + ath5k_hw_set_rx_filter(ah, rfilt); + sc->filter_flags = rfilt; +} +static void ath5k_bss_info_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, + u32 changes) +{ + struct ath5k_softc *sc = hw->priv; + if (changes & BSS_CHANGED_ASSOC) { + mutex_lock(&sc->lock); + sc->assoc = bss_conf->assoc; + if (sc->opmode == NL80211_IFTYPE_STATION) + set_beacon_filter(hw, sc->assoc); + mutex_unlock(&sc->lock); + } +} diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h index 06d1054ca94..facc60ddada 100644 --- a/drivers/net/wireless/ath5k/base.h +++ b/drivers/net/wireless/ath5k/base.h @@ -179,6 +179,7 @@ struct ath5k_softc { struct timer_list calib_tim; /* calibration timer */ int power_level; /* Requested tx power in dbm */ + bool assoc; /* assocate state */ }; #define ath5k_hw_hasbssidmask(_ah) \ -- cgit v1.2.3 From 1d71da164d7fb40fac72c0406a4a531265916fc8 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 25 Nov 2008 21:05:51 -0800 Subject: net: hp-plus uses eip_poll hp-plus uses 8390p.c, so it should use eip_poll(), not ei_poll(). drivers/built-in.o: In function `hpp_probe1': hp-plus.c:(.init.text+0x9cbd): undefined reference to `ei_poll' Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller --- drivers/net/hp-plus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c index fbbd3e660c2..c01e290d09d 100644 --- a/drivers/net/hp-plus.c +++ b/drivers/net/hp-plus.c @@ -230,7 +230,7 @@ static int __init hpp_probe1(struct net_device *dev, int ioaddr) dev->open = &hpp_open; dev->stop = &hpp_close; #ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ei_poll; + dev->poll_controller = eip_poll; #endif ei_status.name = name; -- cgit v1.2.3 From 461cba2d294fe83297edf8a6556912812903dce1 Mon Sep 17 00:00:00 2001 From: Peng Li Date: Tue, 18 Nov 2008 12:39:02 +0800 Subject: drm/i915: Save/restore HWS_PGA on suspend/resume It fixes suspend/resume failure of xf86-video-intel dri2 branch. As dri2 branch doesn't call I830DRIResume() to restore hardware status page anymore, we need to preserve this register across suspend/resume. Signed-off-by: Peng Li Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_suspend.c | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b24d522f490..0a4f39b9a0e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -150,6 +150,7 @@ typedef struct drm_i915_private { u32 saveDSPBCNTR; u32 saveDSPARB; u32 saveRENDERSTANDBY; + u32 saveHWS; u32 savePIPEACONF; u32 savePIPEBCONF; u32 savePIPEASRC; diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 5ddc6e595c0..5d84027ee8f 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -244,6 +244,9 @@ int i915_save_state(struct drm_device *dev) if (IS_I965G(dev) && IS_MOBILE(dev)) dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY); + /* Hardware status page */ + dev_priv->saveHWS = I915_READ(HWS_PGA); + /* Display arbitration control */ dev_priv->saveDSPARB = I915_READ(DSPARB); @@ -373,6 +376,9 @@ int i915_restore_state(struct drm_device *dev) if (IS_I965G(dev) && IS_MOBILE(dev)) I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY); + /* Hardware status page */ + I915_WRITE(HWS_PGA, dev_priv->saveHWS); + /* Display arbitration */ I915_WRITE(DSPARB, dev_priv->saveDSPARB); -- cgit v1.2.3 From bd51126957eeac96d056c670545ff798c89f63f5 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 26 Nov 2008 01:17:01 -0800 Subject: sungem: Fix PCS_MIICTRL register write in gem_init_phy(). Use writel not writeb. Noticed by Hermann Lauer. Signed-off-by: David S. Miller --- drivers/net/sungem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 4291458955e..1349e419673 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -1714,7 +1714,7 @@ static void gem_init_phy(struct gem *gp) /* Reset PCS unit. */ val = readl(gp->regs + PCS_MIICTRL); val |= PCS_MIICTRL_RST; - writeb(val, gp->regs + PCS_MIICTRL); + writel(val, gp->regs + PCS_MIICTRL); limit = 32; while (readl(gp->regs + PCS_MIICTRL) & PCS_MIICTRL_RST) { -- cgit v1.2.3 From cbbd695687caab1082a70d2ae81153fdba7e851c Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 24 Nov 2008 14:44:36 +0200 Subject: [MTD] [NAND] OMAP: OneNAND: header file relocation (part 2) Include and , not files from Signed-off-by: Adrian Hunter Signed-off-by: David Woodhouse --- drivers/mtd/onenand/omap2.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 28034ef08a8..a7e4d985f5e 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -32,16 +32,15 @@ #include #include #include +#include +#include -#include #include #include #include #include #include -#include -#include #include #include -- cgit v1.2.3 From a3d3f73ccbd68b3557c4aaf9f6246ea21d922835 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 26 Nov 2008 10:23:25 +0000 Subject: [MTD] m25p80: fix detection of SPI parts Commit d0e8c47c58575b9131e786edb488fd029eba443e ("m25p80.c extended jedec support") added support for extended ids but in the process managed to break detection of all flashes. The ext jedec id check was inserted into an if statement that lacked braces, and it did not add the required braces. As such, the detection routine always returns the first entry in the SPI flash list. Signed-off-by: Mike Frysinger Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/devices/m25p80.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 76a76751da3..a298fed6ab0 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -574,10 +574,11 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi) for (tmp = 0, info = m25p_data; tmp < ARRAY_SIZE(m25p_data); tmp++, info++) { - if (info->jedec_id == jedec) + if (info->jedec_id == jedec) { if (ext_jedec != 0 && info->ext_id != ext_jedec) continue; return info; + } } dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec); return NULL; -- cgit v1.2.3 From 9168ab861ae3eb8942da61d884a5c1980ba98a5f Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 26 Nov 2008 10:23:35 +0000 Subject: [MTD] m25p80: fix detection of m25p16 flashes Commit d0e8c47c58575b9131e786edb488fd029eba443e ("m25p80.c extended jedec support") added support for extended ids but seems to break on flashes which don't have an extended id defined. If the table does not have an extid defined, then we should ignore it. Signed-off-by: Mike Frysinger Signed-off-by: Michael Hennerich Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/devices/m25p80.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index a298fed6ab0..6188fd4ddcc 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -575,7 +575,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi) tmp < ARRAY_SIZE(m25p_data); tmp++, info++) { if (info->jedec_id == jedec) { - if (ext_jedec != 0 && info->ext_id != ext_jedec) + if (info->ext_id != 0 && info->ext_id != ext_jedec) continue; return info; } -- cgit v1.2.3 From 7854643a91eade84112dca9768eeb8d32463d101 Mon Sep 17 00:00:00 2001 From: Chen Gong Date: Wed, 26 Nov 2008 10:23:57 +0000 Subject: [MTD] m25p80: chip erase != block erase != sector erase This fixes broken terminology added in the "m25p80.c erase enhance" patch, which added a chip erase command but called it "block erase". There are already two block erase commands; blocks are 4KiB or 32KiB. There's also a sector erase (usually 64 KiB). Chip erase typically covers Megabytes. OPCODE_BE ==> OPCODE_CHIP_ERASE erase_block ==> erase_chip [dbrownell@users.sourceforge.net: update sector erase comments too ] Signed-off-by: Chen Gong Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/devices/m25p80.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 6188fd4ddcc..6659b2275c0 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -37,9 +37,9 @@ #define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */ #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ -#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ +#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ #define OPCODE_BE_32K 0x52 /* Erase 32KiB block */ -#define OPCODE_BE 0xc7 /* Erase whole flash block */ +#define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */ #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */ #define OPCODE_RDID 0x9f /* Read JEDEC ID */ @@ -167,7 +167,7 @@ static int wait_till_ready(struct m25p *flash) * * Returns 0 if successful, non-zero otherwise. */ -static int erase_block(struct m25p *flash) +static int erase_chip(struct m25p *flash) { DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB\n", flash->spi->dev.bus_id, __func__, @@ -181,7 +181,7 @@ static int erase_block(struct m25p *flash) write_enable(flash); /* Set up command buffer. */ - flash->command[0] = OPCODE_BE; + flash->command[0] = OPCODE_CHIP_ERASE; spi_write(flash->spi, flash->command, 1); @@ -250,15 +250,18 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) mutex_lock(&flash->lock); - /* REVISIT in some cases we could speed up erasing large regions - * by using OPCODE_SE instead of OPCODE_BE_4K - */ - - /* now erase those sectors */ - if (len == flash->mtd.size && erase_block(flash)) { + /* whole-chip erase? */ + if (len == flash->mtd.size && erase_chip(flash)) { instr->state = MTD_ERASE_FAILED; mutex_unlock(&flash->lock); return -EIO; + + /* REVISIT in some cases we could speed up erasing large regions + * by using OPCODE_SE instead of OPCODE_BE_4K. We may have set up + * to use "small sector erase", but that's not always optimal. + */ + + /* "sector"-at-a-time erase */ } else { while (len) { if (erase_sector(flash, addr)) { -- cgit v1.2.3 From 3136e903fa2d493ebc1b8a8fbdde2d3a17f85acd Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Wed, 26 Nov 2008 10:26:29 +0000 Subject: [MTD] physmap: fix memory leak on physmap_flash_remove by using devres physmap_flash_remove releases only last memory region. This causes memory leak if multiple resources were provided. This patch fixes this leakage by using devm_ functions. Signed-off-by: Atsushi Nemoto Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/maps/physmap.c | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 42d844f8f6b..dfbf3f270ce 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #define MAX_RESOURCES 4 @@ -27,7 +27,6 @@ struct physmap_flash_info { struct mtd_info *mtd[MAX_RESOURCES]; struct mtd_info *cmtd; struct map_info map[MAX_RESOURCES]; - struct resource *res; #ifdef CONFIG_MTD_PARTITIONS int nr_parts; struct mtd_partition *parts; @@ -70,16 +69,7 @@ static int physmap_flash_remove(struct platform_device *dev) #endif map_destroy(info->mtd[i]); } - - if (info->map[i].virt != NULL) - iounmap(info->map[i].virt); - } - - if (info->res != NULL) { - release_resource(info->res); - kfree(info->res); } - return 0; } @@ -101,7 +91,8 @@ static int physmap_flash_probe(struct platform_device *dev) if (physmap_data == NULL) return -ENODEV; - info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL); + info = devm_kzalloc(&dev->dev, sizeof(struct physmap_flash_info), + GFP_KERNEL); if (info == NULL) { err = -ENOMEM; goto err_out; @@ -114,10 +105,10 @@ static int physmap_flash_probe(struct platform_device *dev) (unsigned long long)(dev->resource[i].end - dev->resource[i].start + 1), (unsigned long long)dev->resource[i].start); - info->res = request_mem_region(dev->resource[i].start, - dev->resource[i].end - dev->resource[i].start + 1, - dev->dev.bus_id); - if (info->res == NULL) { + if (!devm_request_mem_region(&dev->dev, + dev->resource[i].start, + dev->resource[i].end - dev->resource[i].start + 1, + dev->dev.bus_id)) { dev_err(&dev->dev, "Could not reserve memory region\n"); err = -ENOMEM; goto err_out; @@ -129,7 +120,8 @@ static int physmap_flash_probe(struct platform_device *dev) info->map[i].bankwidth = physmap_data->width; info->map[i].set_vpp = physmap_data->set_vpp; - info->map[i].virt = ioremap(info->map[i].phys, info->map[i].size); + info->map[i].virt = devm_ioremap(&dev->dev, info->map[i].phys, + info->map[i].size); if (info->map[i].virt == NULL) { dev_err(&dev->dev, "Failed to ioremap flash region\n"); err = EIO; -- cgit v1.2.3 From 545f4e99dee7284ed57c79384c5c1d5ac58dcd59 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Mon, 24 Nov 2008 11:44:27 -0500 Subject: Input: wacom - add support for new USB Tablet PCs Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom.h | 13 +-- drivers/input/tablet/wacom_sys.c | 228 ++++++++++++++++++++++++++++++++++----- drivers/input/tablet/wacom_wac.c | 160 ++++++++++++++++++++++++--- drivers/input/tablet/wacom_wac.h | 4 + 4 files changed, 356 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index ca62ec639f8..677680e9f54 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h @@ -66,6 +66,7 @@ * - Support Intuos3 4x6 * v1.47 (pc) - Added support for Bamboo * v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX + * v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A) */ /* @@ -86,7 +87,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v1.48" +#define DRIVER_VERSION "v1.49" #define DRIVER_AUTHOR "Vojtech Pavlik " #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" #define DRIVER_LICENSE "GPL" @@ -103,15 +104,15 @@ struct wacom { struct usb_device *usbdev; struct usb_interface *intf; struct urb *irq; - struct wacom_wac * wacom_wac; + struct wacom_wac *wacom_wac; struct mutex lock; unsigned int open:1; char phys[32]; }; struct wacom_combo { - struct wacom * wacom; - struct urb * urb; + struct wacom *wacom; + struct urb *urb; }; extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo); @@ -132,7 +133,7 @@ extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wa extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern __u16 wacom_le16_to_cpu(unsigned char *data); extern __u16 wacom_be16_to_cpu(unsigned char *data); -extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id); -extern const struct usb_device_id * get_device_table(void); +extern struct wacom_features *get_wacom_feature(const struct usb_device_id *id); +extern const struct usb_device_id *get_device_table(void); #endif diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 5fbc463baf5..7fe73586e02 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -14,8 +14,41 @@ #include "wacom.h" #include "wacom_wac.h" +/* defines to get HID report descriptor */ +#define HID_DEVICET_HID (USB_TYPE_CLASS | 0x01) +#define HID_DEVICET_REPORT (USB_TYPE_CLASS | 0x02) +#define HID_USAGE_UNDEFINED 0x00 +#define HID_USAGE_PAGE 0x05 +#define HID_USAGE_PAGE_DIGITIZER 0x0d +#define HID_USAGE_PAGE_DESKTOP 0x01 +#define HID_USAGE 0x09 +#define HID_USAGE_X 0x30 +#define HID_USAGE_Y 0x31 +#define HID_USAGE_X_TILT 0x3d +#define HID_USAGE_Y_TILT 0x3e +#define HID_USAGE_FINGER 0x22 +#define HID_USAGE_STYLUS 0x20 +#define HID_COLLECTION 0xc0 + +enum { + WCM_UNDEFINED = 0, + WCM_DESKTOP, + WCM_DIGITIZER, +}; + +struct hid_descriptor { + struct usb_descriptor_header header; + __le16 bcdHID; + u8 bCountryCode; + u8 bNumDescriptors; + u8 bDescriptorType; + __le16 wDescriptorLength; +} __attribute__ ((packed)); + +/* defines to get/set USB message */ #define USB_REQ_GET_REPORT 0x01 #define USB_REQ_SET_REPORT 0x09 +#define WAC_HID_FEATURE_REPORT 0x03 static int usb_get_report(struct usb_interface *intf, unsigned char type, unsigned char id, void *buf, int size) @@ -80,25 +113,21 @@ static void wacom_sys_irq(struct urb *urb) void wacom_report_key(void *wcombo, unsigned int key_type, int key_data) { input_report_key(get_input_dev((struct wacom_combo *)wcombo), key_type, key_data); - return; } void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data) { input_report_abs(get_input_dev((struct wacom_combo *)wcombo), abs_type, abs_data); - return; } void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data) { input_report_rel(get_input_dev((struct wacom_combo *)wcombo), rel_type, rel_data); - return; } void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value) { input_event(get_input_dev((struct wacom_combo *)wcombo), type, code, value); - return; } __u16 wacom_be16_to_cpu(unsigned char *data) @@ -118,7 +147,6 @@ __u16 wacom_le16_to_cpu(unsigned char *data) void wacom_input_sync(void *wcombo) { input_sync(get_input_dev((struct wacom_combo *)wcombo)); - return; } static int wacom_open(struct input_dev *dev) @@ -160,7 +188,7 @@ static void wacom_close(struct input_dev *dev) void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_1) | + input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_1) | BIT_MASK(BTN_5); input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); } @@ -170,7 +198,7 @@ void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac) input_dev->evbit[0] |= BIT_MASK(EV_MSC); input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER); - input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_0) | + input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | BIT_MASK(BTN_4); } @@ -178,7 +206,7 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { input_dev->evbit[0] |= BIT_MASK(EV_REL); input_dev->relbit[0] |= BIT_MASK(REL_WHEEL); - input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) | + input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2); @@ -188,7 +216,7 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_FINGER); - input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_0) | + input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) | BIT_MASK(BTN_1) | BIT_MASK(BTN_2) | BIT_MASK(BTN_3); input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); @@ -196,14 +224,14 @@ void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_4) | + input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_4) | BIT_MASK(BTN_5) | BIT_MASK(BTN_6) | BIT_MASK(BTN_7); input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); } void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9); + input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_8) | BIT_MASK(BTN_9); } void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) @@ -211,7 +239,7 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) input_dev->evbit[0] |= BIT_MASK(EV_MSC) | BIT_MASK(EV_REL); input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); input_dev->relbit[0] |= BIT_MASK(REL_WHEEL); - input_dev->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) | + input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | @@ -228,8 +256,7 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2) | - BIT_MASK(BTN_TOOL_RUBBER); + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2); } void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) @@ -237,15 +264,129 @@ void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER); } +static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, + struct wacom_wac *wacom_wac) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct wacom_features *features = wacom_wac->features; + char limit = 0, result = 0; + int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0; + unsigned char *report; + + report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL); + if (!report) + return -ENOMEM; + + /* retrive report descriptors */ + do { + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, + USB_RECIP_INTERFACE | USB_DIR_IN, + HID_DEVICET_REPORT << 8, + intf->altsetting[0].desc.bInterfaceNumber, /* interface */ + report, + hid_desc->wDescriptorLength, + 5000); /* 5 secs */ + } while (result < 0 && limit++ < 5); + + if (result < 0) + goto out; + + for (i = 0; i < hid_desc->wDescriptorLength; i++) { + + switch (report[i]) { + case HID_USAGE_PAGE: + switch (report[i + 1]) { + case HID_USAGE_PAGE_DIGITIZER: + usage = WCM_DIGITIZER; + i++; + break; + + case HID_USAGE_PAGE_DESKTOP: + usage = WCM_DESKTOP; + i++; + break; + } + break; + + case HID_USAGE: + switch (report[i + 1]) { + case HID_USAGE_X: + if (usage == WCM_DESKTOP) { + if (finger) { + features->touch_x_max = + features->touch_y_max = + wacom_le16_to_cpu(&report[i + 3]); + features->x_max = + wacom_le16_to_cpu(&report[i + 6]); + i += 7; + } else if (pen) { + features->x_max = + wacom_le16_to_cpu(&report[i + 3]); + i += 4; + } + } else if (usage == WCM_DIGITIZER) { + /* max pressure isn't reported + features->pressure_max = (unsigned short) + (report[i+4] << 8 | report[i + 3]); + */ + features->pressure_max = 255; + i += 4; + } + break; + + case HID_USAGE_Y: + if (usage == WCM_DESKTOP) + features->y_max = + wacom_le16_to_cpu(&report[i + 3]); + i += 4; + break; + + case HID_USAGE_FINGER: + finger = 1; + i++; + break; + + case HID_USAGE_STYLUS: + pen = 1; + i++; + break; + + case HID_USAGE_UNDEFINED: + if (usage == WCM_DESKTOP && finger) /* capacity */ + features->pressure_max = + wacom_le16_to_cpu(&report[i + 3]); + i += 4; + break; + } + break; + + case HID_COLLECTION: + /* reset UsagePage ans Finger */ + finger = usage = 0; + break; + } + } + + result = 0; + + out: + kfree(report); + return result; +} + static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); + struct usb_host_interface *interface = intf->cur_altsetting; struct usb_endpoint_descriptor *endpoint; struct wacom *wacom; struct wacom_wac *wacom_wac; + struct wacom_features *features; struct input_dev *input_dev; int error = -ENOMEM; char rep_data[2], limit = 0; + struct hid_descriptor *hid_desc; wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); @@ -268,8 +409,8 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); - wacom_wac->features = get_wacom_feature(id); - BUG_ON(wacom_wac->features->pktlen > 10); + wacom_wac->features = features = get_wacom_feature(id); + BUG_ON(features->pktlen > 10); input_dev->name = wacom_wac->features->name; wacom->wacom_wac = wacom_wac; @@ -282,18 +423,37 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i input_dev->open = wacom_open; input_dev->close = wacom_close; + endpoint = &intf->cur_altsetting->endpoint[0].desc; + + /* TabletPC need to retrieve the physical and logical maximum from report descriptor */ + if (wacom_wac->features->type == TABLETPC) { + if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { + if (usb_get_extra_descriptor(&interface->endpoint[0], + HID_DEVICET_REPORT, &hid_desc)) { + printk("wacom: can not retrive extra class descriptor\n"); + goto fail2; + } + } + error = wacom_parse_hid(intf, hid_desc, wacom_wac); + if (error) + goto fail2; + } + input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS); - input_set_abs_params(input_dev, ABS_X, 0, wacom_wac->features->x_max, 4, 0); - input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0); - input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0); + input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0); + input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0); + if (features->type == TABLETPC) { + input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP); + input_set_abs_params(input_dev, ABS_RX, 0, features->touch_x_max, 4, 0); + input_set_abs_params(input_dev, ABS_RY, 0, features->touch_y_max, 4, 0); + } input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); wacom_init_input_dev(input_dev, wacom_wac); - endpoint = &intf->cur_altsetting->endpoint[0].desc; - usb_fill_int_urb(wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), wacom_wac->data, wacom_wac->features->pktlen, @@ -305,13 +465,22 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i if (error) goto fail3; - /* Ask the tablet to report tablet data. Repeat until it succeeds */ - do { - rep_data[0] = 2; - rep_data[1] = 2; - usb_set_report(intf, 3, 2, rep_data, 2); - usb_get_report(intf, 3, 2, rep_data, 2); - } while (rep_data[1] != 2 && limit++ < 5); + /* + * Ask the tablet to report tablet data if it is not a Tablet PC. + * Repeat until it succeeds + */ + if (wacom_wac->features->type != TABLETPC) { + do { + rep_data[0] = 2; + rep_data[1] = 2; + error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, + 2, rep_data, 2); + if (error >= 0) + error = usb_get_report(intf, + WAC_HID_FEATURE_REPORT, 2, + rep_data, 2); + } while ((error < 0 || rep_data[1] != 2) && limit++ < 5); + } usb_set_intfdata(intf, wacom); return 0; @@ -333,7 +502,8 @@ static void wacom_disconnect(struct usb_interface *intf) usb_kill_urb(wacom->irq); input_unregister_device(wacom->dev); usb_free_urb(wacom->irq); - usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma); + usb_buffer_free(interface_to_usbdev(intf), 10, + wacom->wacom_wac->data, wacom->data_dma); kfree(wacom->wacom_wac); kfree(wacom); } diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index bf3d9a8b2c1..8dc8d1e59be 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -535,31 +535,147 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) return 1; } +int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) +{ + char *data = wacom->data; + int prox = 0, pressure; + static int stylusInProx, touchInProx = 1, touchOut; + struct urb *urb = ((struct wacom_combo *)wcombo)->urb; + + dbg("wacom_tpc_irq: received report #%d", data[0]); + + if (urb->actual_length == 5 || data[0] == 6) { /* Touch data */ + if (urb->actual_length == 5) { /* with touch */ + prox = data[0] & 0x03; + } else { /* with capacity */ + prox = data[1] & 0x03; + } + + if (!stylusInProx) { /* stylus not in prox */ + if (prox) { + if (touchInProx) { + wacom->tool[1] = BTN_TOOL_DOUBLETAP; + wacom->id[0] = TOUCH_DEVICE_ID; + if (urb->actual_length != 5) { + wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); + wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); + wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); + wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6])); + } else { + wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); + wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); + wacom_report_key(wcombo, BTN_TOUCH, 1); + } + wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); + wacom_report_key(wcombo, wacom->tool[1], prox & 0x01); + touchOut = 1; + return 1; + } + } else { + wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); + wacom_report_key(wcombo, wacom->tool[1], prox & 0x01); + wacom_report_key(wcombo, BTN_TOUCH, 0); + touchOut = 0; + touchInProx = 1; + return 1; + } + } else if (touchOut || !prox) { /* force touch out-prox */ + wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID); + wacom_report_key(wcombo, BTN_TOUCH, 0); + touchOut = 0; + touchInProx = 1; + return 1; + } + } else if (data[0] == 2) { /* Penabled */ + prox = data[1] & 0x20; + + touchInProx = 0; + + wacom->id[0] = ERASER_DEVICE_ID; + + /* + * if going from out of proximity into proximity select between the eraser + * and the pen based on the state of the stylus2 button, choose eraser if + * pressed else choose pen. if not a proximity change from out to in, send + * an out of proximity for previous tool then a in for new tool. + */ + if (prox) { /* in prox */ + if (!wacom->tool[0]) { + /* Going into proximity select tool */ + wacom->tool[1] = (data[1] & 0x08) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; + if (wacom->tool[1] == BTN_TOOL_PEN) + wacom->id[0] = STYLUS_DEVICE_ID; + } else if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[1] & 0x08)) { + /* + * was entered with stylus2 pressed + * report out proximity for previous tool + */ + wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); + wacom_report_key(wcombo, wacom->tool[1], 0); + wacom_input_sync(wcombo); + + /* set new tool */ + wacom->tool[1] = BTN_TOOL_PEN; + wacom->id[0] = STYLUS_DEVICE_ID; + return 0; + } + if (wacom->tool[1] != BTN_TOOL_RUBBER) { + /* Unknown tool selected default to pen tool */ + wacom->tool[1] = BTN_TOOL_PEN; + wacom->id[0] = STYLUS_DEVICE_ID; + } + wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); + wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); + wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); + wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); + pressure = ((data[7] & 0x01) << 8) | data[6]; + if (pressure < 0) + pressure = wacom->features->pressure_max + pressure + 1; + wacom_report_abs(wcombo, ABS_PRESSURE, pressure); + wacom_report_key(wcombo, BTN_TOUCH, pressure); + } else { + wacom_report_abs(wcombo, ABS_PRESSURE, 0); + wacom_report_key(wcombo, BTN_STYLUS, 0); + wacom_report_key(wcombo, BTN_STYLUS2, 0); + wacom_report_key(wcombo, BTN_TOUCH, 0); + } + wacom_report_key(wcombo, wacom->tool[1], prox); + wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); + stylusInProx = prox; + wacom->tool[0] = prox; + return 1; + } + return 0; +} + int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) { switch (wacom_wac->features->type) { case PENPARTNER: - return (wacom_penpartner_irq(wacom_wac, wcombo)); - break; + return wacom_penpartner_irq(wacom_wac, wcombo); + case PL: - return (wacom_pl_irq(wacom_wac, wcombo)); - break; + return wacom_pl_irq(wacom_wac, wcombo); + case WACOM_G4: case GRAPHIRE: case WACOM_MO: - return (wacom_graphire_irq(wacom_wac, wcombo)); - break; + return wacom_graphire_irq(wacom_wac, wcombo); + case PTU: - return (wacom_ptu_irq(wacom_wac, wcombo)); - break; + return wacom_ptu_irq(wacom_wac, wcombo); + case INTUOS: case INTUOS3S: case INTUOS3: case INTUOS3L: case CINTIQ: case WACOM_BEE: - return (wacom_intuos_irq(wacom_wac, wcombo)); - break; + return wacom_intuos_irq(wacom_wac, wcombo); + + case TABLETPC: + return wacom_tpc_irq(wacom_wac, wcombo); + default: return 0; } @@ -586,13 +702,15 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w /* fall through */ case INTUOS3S: input_dev_i3s(input_dev, wacom_wac); + /* fall through */ case INTUOS: input_dev_i(input_dev, wacom_wac); break; case PL: case PTU: + case TABLETPC: input_dev_pl(input_dev, wacom_wac); - break; + /* fall through */ case PENPARTNER: input_dev_pt(input_dev, wacom_wac); break; @@ -611,6 +729,7 @@ static struct wacom_features wacom_features[] = { { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 63, WACOM_G4 }, { "Wacom BambooFun 4x5", 9, 14760, 9225, 511, 63, WACOM_MO }, { "Wacom BambooFun 6x8", 9, 21648, 13530, 511, 63, WACOM_MO }, + { "Wacom Bamboo1 Medium",8, 16704, 12064, 511, 63, GRAPHIRE }, { "Wacom Volito", 8, 5104, 3712, 511, 63, GRAPHIRE }, { "Wacom PenStation2", 8, 3250, 2320, 255, 63, GRAPHIRE }, { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE }, @@ -650,6 +769,10 @@ static struct wacom_features wacom_features[] = { { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ }, { "Wacom Cintiq 20WSX", 10, 86680, 54180, 1023, 63, WACOM_BEE }, { "Wacom Cintiq 12WX", 10, 53020, 33440, 1023, 63, WACOM_BEE }, + { "Wacom DTU1931", 8, 37832, 30305, 511, 0, PL }, + { "Wacom ISDv4 90", 8, 26202, 16325, 255, 0, TABLETPC }, + { "Wacom ISDv4 93", 8, 26202, 16325, 255, 0, TABLETPC }, + { "Wacom ISDv4 9A", 8, 26202, 16325, 255, 0, TABLETPC }, { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, { } }; @@ -665,6 +788,7 @@ static struct usb_device_id wacom_ids[] = { { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x17) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x18) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x19) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) }, @@ -704,18 +828,26 @@ static struct usb_device_id wacom_ids[] = { { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC7) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, { } }; -const struct usb_device_id * get_device_table(void) { - const struct usb_device_id * id_table = wacom_ids; +const struct usb_device_id *get_device_table(void) +{ + const struct usb_device_id *id_table = wacom_ids; + return id_table; } -struct wacom_features * get_wacom_feature(const struct usb_device_id * id) { +struct wacom_features * get_wacom_feature(const struct usb_device_id *id) +{ int index = id - wacom_ids; struct wacom_features *wf = &wacom_features[index]; + return wf; } diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 3342bc05847..f9c8b69673b 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -10,6 +10,7 @@ #define WACOM_WAC_H #define STYLUS_DEVICE_ID 0x02 +#define TOUCH_DEVICE_ID 0x03 #define CURSOR_DEVICE_ID 0x06 #define ERASER_DEVICE_ID 0x0A #define PAD_DEVICE_ID 0x0F @@ -27,6 +28,7 @@ enum { CINTIQ, WACOM_BEE, WACOM_MO, + TABLETPC, MAX_TYPE }; @@ -38,6 +40,8 @@ struct wacom_features { int pressure_max; int distance_max; int type; + int touch_x_max; + int touch_y_max; }; struct wacom_wac { -- cgit v1.2.3 From 7b4d469228a92a00e412675817cedd60133de38a Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Thu, 13 Nov 2008 12:00:03 +0300 Subject: ACPI: EC: count interrupts only if called from interrupt handler. fix 2.6.28 EC interrupt storm regression Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index cf41f9fc24a..30f3ef236ec 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -219,7 +219,8 @@ static void gpe_transaction(struct acpi_ec *ec, u8 status) goto unlock; err: /* false interrupt, state didn't change */ - ++ec->curr->irq_count; + if (in_interrupt()) + ++ec->curr->irq_count; unlock: spin_unlock_irqrestore(&ec->curr_lock, flags); } -- cgit v1.2.3 From 558073dd56707864f09d563b64e7c37c021e89d2 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 21 Nov 2008 22:41:01 +0800 Subject: ACPI: battery: Convert discharge energy rate to current properly ACPI battery interface reports its state either in mW or in mA, and discharge rate in your case is reported in mW. power_supply interface does not have such a parameter, so current_now parameter is used for all cases. But in case of mW, reported discharge should be converted into mA. Signed-off-by: Alexey Starikovskiy Tested-by: Ferenc Wagner Signed-off-by: Len Brown --- drivers/acpi/battery.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 1423b0c0cd2..a0a178dd189 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -174,6 +174,15 @@ static int acpi_battery_get_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_CURRENT_NOW: val->intval = battery->current_now * 1000; + /* if power units are mW, convert to mA by + dividing by current voltage (mV/1000) */ + if (!battery->power_unit) { + if (battery->voltage_now) { + val->intval /= battery->voltage_now; + val->intval *= 1000; + } else + val->intval = -1; + } break; case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: -- cgit v1.2.3 From 40599072dca3ec7d4c9ff8271978be169f974638 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 25 Nov 2008 12:05:08 +0100 Subject: ACPI: scheduling in atomic via acpi_evaluate_integer () Now I know why I had strange "scheduling in atomic" problems: acpi_evaluate_integer() does malloc(..., irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL)... which is (of course) broken. There's no way to reliably tell if we need GFP_ATOMIC or not from code, this one for example fails to detect spinlocks held. Fortunately, allocation seems small enough to be done on stack. Signed-off-by: Pavel Machek Acked-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/utils.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index e827be36ee8..f844941089b 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -259,34 +259,26 @@ acpi_evaluate_integer(acpi_handle handle, struct acpi_object_list *arguments, unsigned long long *data) { acpi_status status = AE_OK; - union acpi_object *element; + union acpi_object element; struct acpi_buffer buffer = { 0, NULL }; - if (!data) return AE_BAD_PARAMETER; - element = kzalloc(sizeof(union acpi_object), irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL); - if (!element) - return AE_NO_MEMORY; - buffer.length = sizeof(union acpi_object); - buffer.pointer = element; + buffer.pointer = &element; status = acpi_evaluate_object(handle, pathname, arguments, &buffer); if (ACPI_FAILURE(status)) { acpi_util_eval_error(handle, pathname, status); - kfree(element); return status; } - if (element->type != ACPI_TYPE_INTEGER) { + if (element.type != ACPI_TYPE_INTEGER) { acpi_util_eval_error(handle, pathname, AE_BAD_DATA); - kfree(element); return AE_BAD_DATA; } - *data = element->integer.value; - kfree(element); + *data = element.integer.value; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data)); -- cgit v1.2.3 From 65df78473ffbf3bff5e2034df1638acc4f3ddd50 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 26 Nov 2008 17:53:13 -0500 Subject: ACPI suspend: Blacklist boxes that require us to set SCI_EN directly on resume Some Apple boxes evidently require us to set SCI_EN on resume directly, because if we don't do that, they hung somewhere in the resume code path. Moreover, on these boxes it is not sufficient to use acpi_enable() to turn ACPI on during resume. All of this is against the ACPI specification which states that (1) the BIOS is supposed to return from the S3 sleep state with ACPI enabled (SCI_EN set) and (2) the SCI_EN bit is owned by the hardware and we are not supposed to change it. For this reason, blacklist the affected systems so that the SCI_EN bit is set during resume on them. [NOTE: Unconditional setting SCI_EN for all system on resume doesn't work, because it makes some other systems crash (that's to be expected). Also, it is not entirely clear right now if all of the Apple boxes require this workaround.] This patch fixes the recent regression tracked as http://bugzilla.kernel.org/show_bug.cgi?id=12038 Signed-off-by: Rafael J. Wysocki Tested-by: Tino Keitel Tested-by: Bob Copeland Signed-off-by: Len Brown --- drivers/acpi/sleep/main.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 80c0868d048..28a691cc625 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c @@ -90,6 +90,18 @@ void __init acpi_old_suspend_ordering(void) old_suspend_ordering = true; } +/* + * According to the ACPI specification the BIOS should make sure that ACPI is + * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, + * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI + * on such systems during resume. Unfortunately that doesn't help in + * particularly pathological cases in which SCI_EN has to be set directly on + * resume, although the specification states very clearly that this flag is + * owned by the hardware. The set_sci_en_on_resume variable will be set in such + * cases. + */ +static bool set_sci_en_on_resume; + /** * acpi_pm_disable_gpes - Disable the GPEs. */ @@ -235,7 +247,11 @@ static int acpi_suspend_enter(suspend_state_t pm_state) } /* If ACPI is not enabled by the BIOS, we need to enable it here. */ - acpi_enable(); + if (set_sci_en_on_resume) + acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1); + else + acpi_enable(); + /* Reprogram control registers and execute _BFS */ acpi_leave_sleep_state_prep(acpi_state); @@ -323,6 +339,12 @@ static int __init init_old_suspend_ordering(const struct dmi_system_id *d) return 0; } +static int __init init_set_sci_en_on_resume(const struct dmi_system_id *d) +{ + set_sci_en_on_resume = true; + return 0; +} + static struct dmi_system_id __initdata acpisleep_dmi_table[] = { { .callback = init_old_suspend_ordering, @@ -340,6 +362,22 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"), }, }, + { + .callback = init_set_sci_en_on_resume, + .ident = "Apple MacBook 1,1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), + }, + }, + { + .callback = init_set_sci_en_on_resume, + .ident = "Apple MacMini 1,1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ -- cgit v1.2.3 From 3bdca1b863c1ebcb2244fc0cb683876d7330e62b Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 26 Nov 2008 17:55:15 -0500 Subject: Revert "ACPI: don't enable control method power button as wakeup device when Fixed Power button is used" This reverts commit faee816b1502385dc9bc5abf2960d1cc645844d1. http://bugzilla.kernel.org/show_bug.cgi?id=12091 Signed-off-by: Len Brown --- drivers/acpi/scan.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index bd5253ee5c8..39b7233c348 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -751,16 +751,6 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) if (!acpi_match_device_ids(device, button_device_ids)) device->wakeup.flags.run_wake = 1; - /* - * Don't set Power button GPE as run_wake - * if Fixed Power button is used - */ - if (!strcmp(device->pnp.hardware_id, "PNP0C0C") && - !(acpi_gbl_FADT.flags & ACPI_FADT_POWER_BUTTON)) { - device->wakeup.flags.run_wake = 0; - device->wakeup.flags.valid = 0; - } - end: if (ACPI_FAILURE(status)) device->flags.wake_capable = 0; -- cgit v1.2.3 From 38cfc148e1bc470175b3ad131db7dd7bdcff37ee Mon Sep 17 00:00:00 2001 From: Alessandro Guido Date: Wed, 12 Nov 2008 23:03:28 +0100 Subject: sony-laptop: brightness regression fix After commit 540b8bb9c33935183ceb5bed466a42ad72b2af56: sony-laptop: fingers off backlight if video.ko is serving this functionality I can't set brightness on my sony laptop (nothing in /sys/class/backlight). dmesg says "sony-laptop: Sony: Brightness ignored, must be controlled by ACPI video driver". The function acpi_video_backlight_support returns 0 if we should use the vendor-specific backlight support, while non-0 if the ACPI generic should be used. Because of this, the check introduced by the said commit appears reversed. Signed-off-by: Alessandro Guido Signed-off-by: Len Brown --- drivers/misc/sony-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 7bcb81002dc..2a613d4f3bd 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c @@ -1038,7 +1038,7 @@ static int sony_nc_add(struct acpi_device *device) goto outinput; } - if (!acpi_video_backlight_support()) { + if (acpi_video_backlight_support()) { printk(KERN_INFO DRV_PFX "Sony: Brightness ignored, must be " "controlled by ACPI video driver\n"); } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", -- cgit v1.2.3 From 3fedd90fdf17643df1da473c5da983137d51bbdb Mon Sep 17 00:00:00 2001 From: Alessandro Guido Date: Wed, 12 Nov 2008 23:13:35 +0100 Subject: sony-laptop: printk tweak There's no need to print "Sony: " just after "sony-laptop: " (DRV_PFX). Signed-off-by: Alessandro Guido Signed-off-by: Len Brown --- drivers/misc/sony-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 2a613d4f3bd..571b211608d 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c @@ -1039,7 +1039,7 @@ static int sony_nc_add(struct acpi_device *device) } if (acpi_video_backlight_support()) { - printk(KERN_INFO DRV_PFX "Sony: Brightness ignored, must be " + printk(KERN_INFO DRV_PFX "brightness ignored, must be " "controlled by ACPI video driver\n"); } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", &handle))) { -- cgit v1.2.3 From efbbced361f3ff4ff9e85310ccff894185c4d904 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 26 Nov 2008 15:30:48 -0800 Subject: macvlan: don't broadcast PAUSE frames to macvlan devices PAUSE frames are only relevant for the real device, broadcasting them to all macvlan devices can cause a significant load increase. Reported-by: Ben Greear Tested-by: Ben Greear Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- drivers/net/macvlan.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 42394505bb5..590039cbb14 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -70,6 +70,9 @@ static void macvlan_broadcast(struct sk_buff *skb, struct sk_buff *nskb; unsigned int i; + if (skb->protocol == htons(ETH_P_PAUSE)) + return; + for (i = 0; i < MACVLAN_HASH_SIZE; i++) { hlist_for_each_entry_rcu(vlan, n, &port->vlan_hash[i], hlist) { dev = vlan->dev; -- cgit v1.2.3 From 0081b162023690877e0096ef17a82ba1969befa8 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sun, 9 Nov 2008 10:54:02 -0200 Subject: ACPI: thinkpad-acpi: fix fan sleep/resume path This fixes a regression from v2.6.27, caused by commit 5814f737e1cd2cfa2893badd62189acae3e1e1fd, "ACPI: thinkpad-acpi: attempt to preserve fan state on resume". It is possible for fan_suspend() to fail to properly initialize fan_control_desired_level as required by fan_resume(), resulting on the fan always being set to level 7 on resume if the user didn't touch the fan controller. In order to get fan sleep/resume handling to work right: 1. Fix the fan_suspend handling of the T43 firmware quirk. If it is still undefined, we didn't touch the fan yet and that means we have no business doing it on resume. 2. Store the fan level on its own variable to avoid any possible issues with hijacking fan_control_desired_level (which isn't supposed to have anything other than 0-7 in it, anyway). 3. Change the fan_resume code to me more straightforward to understand (although we DO optimize the boolean logic there, otherwise it looks disgusting). 4. Add comments to help understand what the code is supposed to be doing. 5. Change fan_set_level to be less strict about how auto and full-speed modes are requested. http://bugzilla.kernel.org/show_bug.cgi?id=11982 Signed-off-by: Henrique de Moraes Holschuh Reported-by: Tino Keitel Signed-off-by: Len Brown --- drivers/misc/thinkpad_acpi.c | 57 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 7a4a26b0edd..899766e16fa 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -5318,6 +5318,7 @@ static enum fan_control_commands fan_control_commands; static u8 fan_control_initial_status; static u8 fan_control_desired_level; +static u8 fan_control_resume_level; static int fan_watchdog_maxinterval; static struct mutex fan_mutex; @@ -5440,8 +5441,8 @@ static int fan_set_level(int level) case TPACPI_FAN_WR_ACPI_FANS: case TPACPI_FAN_WR_TPEC: - if ((level != TP_EC_FAN_AUTO) && - (level != TP_EC_FAN_FULLSPEED) && + if (!(level & TP_EC_FAN_AUTO) && + !(level & TP_EC_FAN_FULLSPEED) && ((level < 0) || (level > 7))) return -EINVAL; @@ -6005,38 +6006,67 @@ static void fan_exit(void) static void fan_suspend(pm_message_t state) { + int rc; + if (!fan_control_allowed) return; /* Store fan status in cache */ - fan_get_status_safe(NULL); + fan_control_resume_level = 0; + rc = fan_get_status_safe(&fan_control_resume_level); + if (rc < 0) + printk(TPACPI_NOTICE + "failed to read fan level for later " + "restore during resume: %d\n", rc); + + /* if it is undefined, don't attempt to restore it. + * KEEP THIS LAST */ if (tp_features.fan_ctrl_status_undef) - fan_control_desired_level = TP_EC_FAN_AUTO; + fan_control_resume_level = 0; } static void fan_resume(void) { - u8 saved_fan_level; u8 current_level = 7; bool do_set = false; + int rc; /* DSDT *always* updates status on resume */ tp_features.fan_ctrl_status_undef = 0; - saved_fan_level = fan_control_desired_level; if (!fan_control_allowed || + !fan_control_resume_level || (fan_get_status_safe(¤t_level) < 0)) return; switch (fan_control_access_mode) { case TPACPI_FAN_WR_ACPI_SFAN: - do_set = (saved_fan_level > current_level); + /* never decrease fan level */ + do_set = (fan_control_resume_level > current_level); break; case TPACPI_FAN_WR_ACPI_FANS: case TPACPI_FAN_WR_TPEC: - do_set = ((saved_fan_level & TP_EC_FAN_FULLSPEED) || - (saved_fan_level == 7 && - !(current_level & TP_EC_FAN_FULLSPEED))); + /* never decrease fan level, scale is: + * TP_EC_FAN_FULLSPEED > 7 >= TP_EC_FAN_AUTO + * + * We expect the firmware to set either 7 or AUTO, but we + * handle FULLSPEED out of paranoia. + * + * So, we can safely only restore FULLSPEED or 7, anything + * else could slow the fan. Restoring AUTO is useless, at + * best that's exactly what the DSDT already set (it is the + * slower it uses). + * + * Always keep in mind that the DSDT *will* have set the + * fans to what the vendor supposes is the best level. We + * muck with it only to speed the fan up. + */ + if (fan_control_resume_level != 7 && + !(fan_control_resume_level & TP_EC_FAN_FULLSPEED)) + return; + else + do_set = !(current_level & TP_EC_FAN_FULLSPEED) && + (current_level != fan_control_resume_level); break; default: return; @@ -6044,8 +6074,11 @@ static void fan_resume(void) if (do_set) { printk(TPACPI_NOTICE "restoring fan level to 0x%02x\n", - saved_fan_level); - fan_set_level_safe(saved_fan_level); + fan_control_resume_level); + rc = fan_set_level_safe(fan_control_resume_level); + if (rc < 0) + printk(TPACPI_NOTICE + "failed to restore fan level: %d\n", rc); } } -- cgit v1.2.3 From a6e0887f21bbab337ee32d9c0a84d7c0b6e9141b Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 8 Nov 2008 01:21:10 -0500 Subject: ACPI: delete OSI(Linux) DMI dmesg spam Linux will continue to ignore OSI(Linux), except for a white-list containing a few systems. So delete the black-list, and stop soliciting user-feedback on the console. Signed-off-by: Len Brown --- drivers/acpi/blacklist.c | 401 +---------------------------------------------- drivers/acpi/osl.c | 104 +++--------- 2 files changed, 30 insertions(+), 475 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index ea92bac42c5..09c69806c1f 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -176,16 +176,6 @@ static int __init dmi_enable_osi_linux(const struct dmi_system_id *d) acpi_dmi_osi_linux(1, d); /* enable */ return 0; } -static int __init dmi_disable_osi_linux(const struct dmi_system_id *d) -{ - acpi_dmi_osi_linux(0, d); /* disable */ - return 0; -} -static int __init dmi_unknown_osi_linux(const struct dmi_system_id *d) -{ - acpi_dmi_osi_linux(-1, d); /* unknown */ - return 0; -} static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) { printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); @@ -193,295 +183,21 @@ static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) return 0; } -/* - * Most BIOS that invoke OSI(Linux) do nothing with it. - * But some cause Linux to break. - * Only a couple use it to make Linux run better. - * - * Thus, Linux should continue to disable OSI(Linux) by default, - * should continue to discourage BIOS writers from using it, and - * should whitelist the few existing systems that require it. - * - * If it appears clear a vendor isn't using OSI(Linux) - * for anything constructive, blacklist them by name to disable - * unnecessary dmesg warnings on all of their products. - */ - static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { - /* - * Disable OSI(Linux) warnings on all "Acer, inc." - * - * _OSI(Linux) disables the latest Windows BIOS code: - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5050"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5580"), - * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 3010"), - * _OSI(Linux) effect unknown: - * DMI_MATCH(DMI_PRODUCT_NAME, "Ferrari 5000"), - */ - /* - * note that dmi_check_system() uses strstr() - * to match sub-strings rather than !strcmp(), - * so "Acer" below matches "Acer, inc." above. - */ - /* - * Disable OSI(Linux) warnings on all "Acer" - * - * _OSI(Linux) effect unknown: - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720Z"), - * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5520"), - * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 6460"), - * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 7510"), - * - * _OSI(Linux) is a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5220"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Acer", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - }, - }, - /* - * Disable OSI(Linux) warnings on all "Apple Computer, Inc." - * Disable OSI(Linux) warnings on all "Apple Inc." - * - * _OSI(Linux) confirmed to be a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), - * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"), - * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"), - * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"), - * _OSI(Linux) effect unknown: - * DMI_MATCH(DMI_PRODUCT_NAME, "MacPro2,1"), - * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Apple", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple"), - }, - }, - /* - * Disable OSI(Linux) warnings on all "BenQ" - * - * _OSI(Linux) confirmed to be a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "Joybook S31"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "BenQ", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "BenQ"), - }, - }, - /* - * Disable OSI(Linux) warnings on all "Clevo Co." - * - * _OSI(Linux) confirmed to be a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "M570RU"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Clevo", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Clevo Co."), - }, - }, - /* - * Disable OSI(Linux) warnings on all "COMPAL" - * - * _OSI(Linux) confirmed to be a NOP: - * DMI_MATCH(DMI_BOARD_NAME, "HEL8X"), - * _OSI(Linux) unknown effect: - * DMI_MATCH(DMI_BOARD_NAME, "IFL91"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Compal", - .matches = { - DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), - }, - }, - { /* OSI(Linux) touches USB, unknown side-effect */ - .callback = dmi_disable_osi_linux, - .ident = "Dell Dimension 5150", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Dell DM051"), - }, - }, - { /* OSI(Linux) is a NOP */ - .callback = dmi_disable_osi_linux, - .ident = "Dell i1501", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1501"), - }, - }, - { /* OSI(Linux) effect unknown */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell Latitude D830", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D830"), - }, - }, - { /* OSI(Linux) effect unknown */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell OptiPlex GX620", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX620"), - }, - }, - { /* OSI(Linux) causes some USB initialization to not run */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell OptiPlex 755", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 755"), - }, - }, - { /* OSI(Linux) effect unknown */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell PE 1900", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1900"), - }, - }, - { /* OSI(Linux) is a NOP */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell PE 1950", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"), - }, - }, - { /* OSI(Linux) is a NOP */ - .callback = dmi_disable_osi_linux, - .ident = "Dell PE R200", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R200"), - }, - }, - { /* OSI(Linux) touches USB */ - .callback = dmi_disable_osi_linux, - .ident = "Dell PR 390", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 390"), - }, - }, - { /* OSI(Linux) touches USB */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell PR 390", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 690"), - }, - }, - { /* OSI(Linux) unknown - ASL looks benign, but may effect dock/SMM */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell PR M4300", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Precision M4300"), - }, - }, - { /* OSI(Linux) is a NOP */ - .callback = dmi_disable_osi_linux, - .ident = "Dell Vostro 1000", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1000"), - }, - }, - { /* OSI(Linux) effect unknown */ - .callback = dmi_unknown_osi_linux, - .ident = "Dell PE SC440", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge SC440"), - }, - }, - { /* OSI(Linux) effect unknown */ - .callback = dmi_unknown_osi_linux, - .ident = "Dialogue Flybook V5", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dialogue Technology Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "Flybook V5"), - }, - }, - /* - * Disable OSI(Linux) warnings on all "FUJITSU SIEMENS" - * - * _OSI(Linux) disables latest Windows BIOS code: - * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2510"), - * _OSI(Linux) confirmed to be a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 1536"), - * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 1556"), - * DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 1546"), - * DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), - * _OSI(Linux) unknown effect: - * DMI_MATCH(DMI_PRODUCT_NAME, "Amilo M1425"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Amilo Si 1520"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Fujitsu Siemens", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), - }, - }, { .callback = dmi_disable_osi_vista, .ident = "Fujitsu Siemens", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), - DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), + DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile V5505"), }, }, + /* - * Disable OSI(Linux) warnings on all "Hewlett-Packard" - * - * _OSI(Linux) confirmed to be a NOP: - * .ident = "HP Pavilion tx 1000" - * DMI_MATCH(DMI_BOARD_NAME, "30BF"), - * .ident = "HP Pavilion dv2000" - * DMI_MATCH(DMI_BOARD_NAME, "30B5"), - * .ident = "HP Pavilion dv5000", - * DMI_MATCH(DMI_BOARD_NAME, "30A7"), - * .ident = "HP Pavilion dv6300 30BC", - * DMI_MATCH(DMI_BOARD_NAME, "30BC"), - * .ident = "HP Pavilion dv6000", - * DMI_MATCH(DMI_BOARD_NAME, "30B7"), - * DMI_MATCH(DMI_BOARD_NAME, "30B8"), - * .ident = "HP Pavilion dv9000", - * DMI_MATCH(DMI_BOARD_NAME, "30B9"), - * .ident = "HP Pavilion dv9500", - * DMI_MATCH(DMI_BOARD_NAME, "30CB"), - * .ident = "HP/Compaq Presario C500", - * DMI_MATCH(DMI_BOARD_NAME, "30C6"), - * .ident = "HP/Compaq Presario F500", - * DMI_MATCH(DMI_BOARD_NAME, "30D3"), - * _OSI(Linux) unknown effect: - * .ident = "HP Pavilion dv6500", - * DMI_MATCH(DMI_BOARD_NAME, "30D0"), + * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. + * Linux ignores it, except for the machines enumerated below. */ - { - .callback = dmi_disable_osi_linux, - .ident = "Hewlett-Packard", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - }, - }, + /* * Lenovo has a mix of systems OSI(Linux) situations * and thus we can not wildcard the vendor. @@ -519,113 +235,6 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X61"), }, }, - { - .callback = dmi_disable_osi_linux, - .ident = "Lenovo 3000 V100", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "LENOVO3000 V100"), - }, - }, - { - .callback = dmi_disable_osi_linux, - .ident = "Lenovo 3000 N100", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"), - }, - }, - /* - * Disable OSI(Linux) warnings on all "LG Electronics" - * - * _OSI(Linux) confirmed to be a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "P1-J150B"), - * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"), - * - * unknown: - * DMI_MATCH(DMI_PRODUCT_NAME, "S1-MDGDG"), - * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "LG", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), - }, - }, - /* NEC - OSI(Linux) effect unknown */ - { - .callback = dmi_unknown_osi_linux, - .ident = "NEC VERSA M360", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "NEC Computers SAS"), - DMI_MATCH(DMI_PRODUCT_NAME, "NEC VERSA M360"), - }, - }, - /* Panasonic */ - { - .callback = dmi_unknown_osi_linux, - .ident = "Panasonic", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), - /* Toughbook CF-52 */ - DMI_MATCH(DMI_PRODUCT_NAME, "CF-52CCABVBG"), - }, - }, - /* - * Disable OSI(Linux) warnings on all "Samsung Electronics" - * - * OSI(Linux) disables PNP0C32 and other BIOS code for Windows: - * DMI_MATCH(DMI_PRODUCT_NAME, "R40P/R41P"), - * DMI_MATCH(DMI_PRODUCT_NAME, "R59P/R60P/R61P"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Samsung", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), - }, - }, - /* - * Disable OSI(Linux) warnings on all "Sony Corporation" - * - * _OSI(Linux) is a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NR11S_S"), - * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SZ38GP_C"), - * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SZ650N"), - * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-TZ21MN_N"), - * _OSI(Linux) unknown effect: - * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ11M"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Sony", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - }, - }, - /* - * Disable OSI(Linux) warnings on all "TOSHIBA" - * - * _OSI(Linux) breaks sound (bugzilla 7787): - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P100"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P105"), - * _OSI(Linux) is a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A100"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A210"), - * _OSI(Linux) unknown effect: - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A135"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A200"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P205"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Satellite U305"), - */ - { - .callback = dmi_disable_osi_linux, - .ident = "Toshiba", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), - }, - }, {} }; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 4be252145cb..c8111424dcb 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -97,54 +96,44 @@ static DEFINE_SPINLOCK(acpi_res_lock); static char osi_additional_string[OSI_STRING_LENGTH_MAX]; /* - * "Ode to _OSI(Linux)" + * The story of _OSI(Linux) * - * osi_linux -- Control response to BIOS _OSI(Linux) query. + * From pre-history through Linux-2.6.22, + * Linux responded TRUE upon a BIOS OSI(Linux) query. * - * As Linux evolves, the features that it supports change. - * So an OSI string such as "Linux" is not specific enough - * to be useful across multiple versions of Linux. It - * doesn't identify any particular feature, interface, - * or even any particular version of Linux... + * Unfortunately, reference BIOS writers got wind of this + * and put OSI(Linux) in their example code, quickly exposing + * this string as ill-conceived and opening the door to + * an un-bounded number of BIOS incompatibilities. * - * Unfortunately, Linux-2.6.22 and earlier responded "yes" - * to a BIOS _OSI(Linux) query. When - * a reference mobile BIOS started using it, its use - * started to spread to many vendor platforms. - * As it is not supportable, we need to halt that spread. + * For example, OSI(Linux) was used on resume to re-POST a + * video card on one system, because Linux at that time + * could not do a speedy restore in its native driver. + * But then upon gaining quick native restore capability, + * Linux has no way to tell the BIOS to skip the time-consuming + * POST -- putting Linux at a permanent performance disadvantage. + * On another system, the BIOS writer used OSI(Linux) + * to infer native OS support for IPMI! On other systems, + * OSI(Linux) simply got in the way of Linux claiming to + * be compatible with other operating systems, exposing + * BIOS issues such as skipped device initialization. * - * Today, most BIOS references to _OSI(Linux) are noise -- - * they have no functional effect and are just dead code - * carried over from the reference BIOS. - * - * The next most common case is that _OSI(Linux) harms Linux, - * usually by causing the BIOS to follow paths that are - * not tested during Windows validation. - * - * Finally, there is a short list of platforms - * where OSI(Linux) benefits Linux. - * - * In Linux-2.6.23, OSI(Linux) is first disabled by default. - * DMI is used to disable the dmesg warning about OSI(Linux) - * on platforms where it is known to have no effect. - * But a dmesg warning remains for systems where - * we do not know if OSI(Linux) is good or bad for the system. - * DMI is also used to enable OSI(Linux) for the machines - * that are known to need it. + * So "Linux" turned out to be a really poor chose of + * OSI string, and from Linux-2.6.23 onward we respond FALSE. * * BIOS writers should NOT query _OSI(Linux) on future systems. - * It will be ignored by default, and to get Linux to - * not ignore it will require a kernel source update to - * add a DMI entry, or a boot-time "acpi_osi=Linux" invocation. + * Linux will complain on the console when it sees it, and return FALSE. + * To get Linux to return TRUE for your system will require + * a kernel source update to add a DMI entry, + * or boot with "acpi_osi=Linux" */ -#define OSI_LINUX_ENABLE 0 static struct osi_linux { unsigned int enable:1; unsigned int dmi:1; unsigned int cmdline:1; unsigned int known:1; -} osi_linux = { OSI_LINUX_ENABLE, 0, 0, 0}; +} osi_linux = { 0, 0, 0, 0}; static void __init acpi_request_region (struct acpi_generic_address *addr, unsigned int length, char *desc) @@ -1296,34 +1285,6 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) return (AE_OK); } -/** - * acpi_dmi_dump - dump DMI slots needed for blacklist entry - * - * Returns 0 on success - */ -static int acpi_dmi_dump(void) -{ - - if (!dmi_available) - return -1; - - printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n", - dmi_get_system_info(DMI_SYS_VENDOR)); - printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n", - dmi_get_system_info(DMI_PRODUCT_NAME)); - printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n", - dmi_get_system_info(DMI_PRODUCT_VERSION)); - printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n", - dmi_get_system_info(DMI_BOARD_NAME)); - printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n", - dmi_get_system_info(DMI_BIOS_VENDOR)); - printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n", - dmi_get_system_info(DMI_BIOS_DATE)); - - return 0; -} - - /****************************************************************************** * * FUNCTION: acpi_os_validate_interface @@ -1350,21 +1311,6 @@ acpi_os_validate_interface (char *interface) osi_linux.cmdline ? " via cmdline" : osi_linux.dmi ? " via DMI" : ""); - if (!osi_linux.dmi) { - if (acpi_dmi_dump()) - printk(KERN_NOTICE PREFIX - "[please extract dmidecode output]\n"); - printk(KERN_NOTICE PREFIX - "Please send DMI info above to " - "linux-acpi@vger.kernel.org\n"); - } - if (!osi_linux.known && !osi_linux.cmdline) { - printk(KERN_NOTICE PREFIX - "If \"acpi_osi=%sLinux\" works better, " - "please notify linux-acpi@vger.kernel.org\n", - osi_linux.enable ? "!" : ""); - } - if (osi_linux.enable) return AE_OK; } -- cgit v1.2.3 From 29b65861fbece04cfdf3fee352d5247369131850 Mon Sep 17 00:00:00 2001 From: Wolfgang Grandegger Date: Thu, 27 Nov 2008 09:46:13 +0000 Subject: [MTD] [NAND] fsl_upm: fix build problem with 2.6.28-rc2 The patch fixes following build error: CC drivers/mtd/nand/fsl_upm.o drivers/mtd/nand/fsl_upm.c: In function 'fun_chip_init': drivers/mtd/nand/fsl_upm.c:168: warning: passing argument 2 of 'of_mtd_parse_partitions' from incompatible pointer type drivers/mtd/nand/fsl_upm.c:168: warning: passing argument 3 of 'of_mtd_parse_partitions' from incompatible pointer type drivers/mtd/nand/fsl_upm.c:168: error: too many arguments to function 'of_mtd_parse_partitions' make[1]: *** [drivers/mtd/nand/fsl_upm.o] Error 1 The breakage was introduced in 69fd3a8d098faf41a04930afa83757c0555ee360 ("[MTD] remove unused mtd parameter in of_mtd_parse_partitions()"). While at it, also add a check for the of_mtd_parse_partitions() return value. Signed-off-by: Wolfgang Grandegger Signed-off-by: Anton Vorontsov Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/nand/fsl_upm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 024e3fffd4b..a83192f80eb 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c @@ -163,9 +163,11 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun, ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0); #ifdef CONFIG_MTD_OF_PARTS - if (ret == 0) - ret = of_mtd_parse_partitions(fun->dev, &fun->mtd, - flash_np, &fun->parts); + if (ret == 0) { + ret = of_mtd_parse_partitions(fun->dev, flash_np, &fun->parts); + if (ret < 0) + goto err; + } #endif if (ret > 0) ret = add_mtd_partitions(&fun->mtd, fun->parts, ret); -- cgit v1.2.3 From ee8a1a0a1a5817accd03ced7e7ffde3a4430f485 Mon Sep 17 00:00:00 2001 From: Jan Scholz Date: Wed, 26 Nov 2008 15:33:45 +0100 Subject: HID: Apple ALU wireless keyboards are bluetooth devices While parsing 'hid_blacklist' in the apple alu wireless keyboard is not found. This happens because in the blacklist it is declared with HID_USB_DEVICE although the keyboards are really bluetooth devices. The same holds for 'apple_devices' list. This patch fixes it by changing HID_USB_DEVICE to HID_BLUETOOTH_DEVICE in those two lists. Signed-off-by: Jan Scholz Signed-off-by: Jiri Kosina --- drivers/hid/hid-apple.c | 6 +++--- drivers/hid/hid-core.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 9b97795e45a..aa28aed0e46 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -400,12 +400,12 @@ static const struct hid_device_id apple_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | APPLE_RDESC_JIS }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI), + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO), + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS), + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI), .driver_data = APPLE_HAS_FN }, diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 026a46333fd..40df3e1b4bd 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1241,9 +1241,9 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS) }, -- cgit v1.2.3 From d1846b0e7a1dc26f90fb0d75641aca9abb077ef9 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 28 Nov 2008 15:24:38 +0100 Subject: i2c/isp1301_omap: Build fixes Build fixes for isp1301_omap; no behavior changes: - fix incorrect probe() signature (it changed many months ago) - provide missing functions on H3 and H4 boards - "sparse" fixes (static, NULL-vs-0) The H3 build bits subset some of the stuff that was previously in the OMAP tree but never went to mainline. Signed-off-by: David Brownell Signed-off-by: Jean Delvare --- drivers/i2c/chips/isp1301_omap.c | 65 +++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c index 28902ebd553..e0d56ef2bcb 100644 --- a/drivers/i2c/chips/isp1301_omap.c +++ b/drivers/i2c/chips/isp1301_omap.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -33,7 +34,10 @@ #include #include +#include + #include +#include #ifndef DEBUG @@ -88,14 +92,9 @@ struct isp1301 { /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_MACH_OMAP_H2 - /* board-specific PM hooks */ -#include -#include -#include - +#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3) #if defined(CONFIG_TPS65010) || defined(CONFIG_TPS65010_MODULE) @@ -133,6 +132,33 @@ static inline void notresponding(struct isp1301 *isp) } +#endif + +#if defined(CONFIG_MACH_OMAP_H4) + +static void enable_vbus_draw(struct isp1301 *isp, unsigned mA) +{ + /* H4 controls this by DIP switch S2.4; no soft control. + * ON means the charger is always enabled. Leave it OFF + * unless the OTG port is used only in B-peripheral mode. + */ +} + +static void enable_vbus_source(struct isp1301 *isp) +{ + /* this board won't supply more than 8mA vbus power. + * some boards can switch a 100ma "unit load" (or more). + */ +} + + +/* products will deliver OTG messages with LEDs, GUI, etc */ +static inline void notresponding(struct isp1301 *isp) +{ + printk(KERN_NOTICE "OTG device not responding.\n"); +} + + #endif /*-------------------------------------------------------------------------*/ @@ -334,8 +360,7 @@ static int gadget_suspend(struct isp1301 *isp) * NOTE: guaranteeing certain response times might mean we shouldn't * share keventd's work queue; a realtime task might be safest. */ -void -isp1301_defer_work(struct isp1301 *isp, int work) +static void isp1301_defer_work(struct isp1301 *isp, int work) { int status; @@ -512,7 +537,6 @@ static void update_otg1(struct isp1301 *isp, u8 int_src) otg_ctrl &= ~OTG_XCEIV_INPUTS; otg_ctrl &= ~(OTG_ID|OTG_ASESSVLD|OTG_VBUSVLD); - if (int_src & INTR_SESS_VLD) otg_ctrl |= OTG_ASESSVLD; else if (isp->otg.state == OTG_STATE_A_WAIT_VFALL) { @@ -886,11 +910,11 @@ static int otg_probe(struct platform_device *dev) static int otg_remove(struct platform_device *dev) { - otg_dev = 0; + otg_dev = NULL; return 0; } -struct platform_driver omap_otg_driver = { +static struct platform_driver omap_otg_driver = { .probe = otg_probe, .remove = otg_remove, .driver = { @@ -1212,6 +1236,8 @@ static void isp1301_release(struct device *dev) isp = dev_get_drvdata(dev); + /* FIXME -- not with a "new style" driver, it doesn't!! */ + /* ugly -- i2c hijacks our memory hook to wait_for_completion() */ if (isp->i2c_release) isp->i2c_release(dev); @@ -1233,7 +1259,7 @@ static int __exit isp1301_remove(struct i2c_client *i2c) otg_unbind(isp); #endif if (machine_is_omap_h2()) - omap_free_gpio(2); + gpio_free(2); isp->timer.data = 0; set_bit(WORK_STOP, &isp->todo); @@ -1241,7 +1267,7 @@ static int __exit isp1301_remove(struct i2c_client *i2c) flush_scheduled_work(); put_device(&i2c->dev); - the_transceiver = 0; + the_transceiver = NULL; return 0; } @@ -1295,7 +1321,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host) if (!host) { omap_writew(0, OTG_IRQ_EN); power_down(isp); - isp->otg.host = 0; + isp->otg.host = NULL; return 0; } @@ -1344,7 +1370,9 @@ static int isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) { struct isp1301 *isp = container_of(otg, struct isp1301, otg); +#ifndef CONFIG_USB_OTG u32 l; +#endif if (!otg || isp != the_transceiver) return -ENODEV; @@ -1354,7 +1382,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) if (!isp->otg.default_a) enable_vbus_draw(isp, 0); usb_gadget_vbus_disconnect(isp->otg.gadget); - isp->otg.gadget = 0; + isp->otg.gadget = NULL; power_down(isp); return 0; } @@ -1379,7 +1407,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) power_up(isp); isp->otg.state = OTG_STATE_B_IDLE; - if (machine_is_omap_h2()) + if (machine_is_omap_h2() || machine_is_omap_h3()) isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0); isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING, @@ -1499,7 +1527,8 @@ isp1301_start_hnp(struct otg_transceiver *dev) /*-------------------------------------------------------------------------*/ -static int __init isp1301_probe(struct i2c_client *i2c) +static int __init +isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { int status; struct isp1301 *isp; @@ -1647,7 +1676,7 @@ module_init(isp_init); static void __exit isp_exit(void) { if (the_transceiver) - otg_set_transceiver(0); + otg_set_transceiver(NULL); i2c_del_driver(&isp1301_driver); } module_exit(isp_exit); -- cgit v1.2.3 From 79b93e1359b1414b438f239c6e5e0ad91232e4c8 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 28 Nov 2008 15:24:38 +0100 Subject: i2c: Remove i2c clients in reverse order i2c clients should be removed in reverse order compared to the probe (actually: bind) order. This matters when several clients depend on each other. Signed-off-by: Jean Delvare Tested-by: Guennadi Liakhovetski --- drivers/i2c/i2c-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 5a485c22660..c6a63f46bc1 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -631,7 +631,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) /* detach any active clients. This must be done first, because * it can fail; in which case we give up. */ - list_for_each_entry_safe(client, _n, &adap->clients, list) { + list_for_each_entry_safe_reverse(client, _n, &adap->clients, list) { struct i2c_driver *driver; driver = client->driver; -- cgit v1.2.3 From 7b964f733798960c899dc40911329aee7bee25e4 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 28 Nov 2008 15:24:39 +0100 Subject: i2c-parport: Fix misplaced parport_release call We shouldn't release the parallel port until we are actually done with it. Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-parport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c index 59ba2086d2f..a257cd5cd13 100644 --- a/drivers/i2c/busses/i2c-parport.c +++ b/drivers/i2c/busses/i2c-parport.c @@ -189,8 +189,6 @@ static void i2c_parport_attach (struct parport *port) if (adapter_parm[type].init.val) line_set(port, 1, &adapter_parm[type].init); - parport_release(adapter->pdev); - if (i2c_bit_add_bus(&adapter->adapter) < 0) { printk(KERN_ERR "i2c-parport: Unable to register with I2C\n"); goto ERROR1; @@ -202,6 +200,7 @@ static void i2c_parport_attach (struct parport *port) return; ERROR1: + parport_release(adapter->pdev); parport_unregister_device(adapter->pdev); ERROR0: kfree(adapter); @@ -221,6 +220,7 @@ static void i2c_parport_detach (struct parport *port) if (adapter_parm[type].init.val) line_set(port, 0, &adapter_parm[type].init); + parport_release(adapter->pdev); parport_unregister_device(adapter->pdev); if (prev) prev->next = adapter->next; -- cgit v1.2.3 From 23d0a65cf229acd273b6f5a325c34d758a90d592 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 28 Nov 2008 08:19:09 -0800 Subject: toshiba_acpi: close race in toshiba_acpi driver the toshiba ACPI driver will, in a failure case, free the rfkill state before stopping the polling timer that would use this state. More interesting, in the same failure case handling, it calls the exit function, which also frees the rfkill state, but after stopping the polling. If the race happens, a NULL pointer is passed to rfkill_force_state() which then causes a nice dereference. Fix the race by just not doing the too-early freeing of the rfkill state. This appears to be the cause of a hot issue on kerneloops.org; while I have no solid evidence of that this patch will fix the issue, the race appears rather real. Signed-off-by: Arjan van de Ven Signed-off-by: Len Brown --- drivers/acpi/toshiba_acpi.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index 66aac06f2ac..25f531d892d 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c @@ -848,8 +848,6 @@ static int __init toshiba_acpi_init(void) ret = input_register_polled_device(toshiba_acpi.poll_dev); if (ret) { printk(MY_ERR "unable to register kill-switch input device\n"); - rfkill_free(toshiba_acpi.rfk_dev); - toshiba_acpi.rfk_dev = NULL; toshiba_acpi_exit(); return ret; } -- cgit v1.2.3 From 9a5aa622dd4cd22b5e0fe83e4a9c0c768d4e2dea Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Fri, 28 Nov 2008 21:29:46 -0800 Subject: mlx4_core: Save/restore default port IB capability mask Commit 7ff93f8b ("mlx4_core: Multiple port type support") introduced support for different port types. As part of that support, SET_PORT is invoked to set the port type during driver startup. However, as a side-effect, for IB ports the invocation of this command also sets the port's capability mask to zero (losing the default value set by FW). To fix this, get the default ib port capabilities (via a MAD_IFC Port Info query) during driver startup, and save them for use in the mlx4_SET_PORT command when setting the port-type to Infiniband. This patch fixes problems with subnet manager (SM) failover such as , which occurred because the IsTrapSupported bit in the capability mask was zeroed. Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/net/mlx4/main.c | 8 ++++++++ drivers/net/mlx4/mlx4.h | 1 + drivers/net/mlx4/port.c | 39 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c index 468921b8f4b..90a0281d15e 100644 --- a/drivers/net/mlx4/main.c +++ b/drivers/net/mlx4/main.c @@ -753,6 +753,7 @@ static int mlx4_setup_hca(struct mlx4_dev *dev) struct mlx4_priv *priv = mlx4_priv(dev); int err; int port; + __be32 ib_port_default_caps; err = mlx4_init_uar_table(dev); if (err) { @@ -852,6 +853,13 @@ static int mlx4_setup_hca(struct mlx4_dev *dev) } for (port = 1; port <= dev->caps.num_ports; port++) { + ib_port_default_caps = 0; + err = mlx4_get_port_ib_caps(dev, port, &ib_port_default_caps); + if (err) + mlx4_warn(dev, "failed to get port %d default " + "ib capabilities (%d). Continuing with " + "caps = 0\n", port, err); + dev->caps.ib_port_def_cap[port] = ib_port_default_caps; err = mlx4_SET_PORT(dev, port); if (err) { mlx4_err(dev, "Failed to set port %d, aborting\n", diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index 56a2e213fe6..34c909deaff 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h @@ -385,5 +385,6 @@ void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table); void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table); int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port); +int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps); #endif /* MLX4_H */ diff --git a/drivers/net/mlx4/port.c b/drivers/net/mlx4/port.c index e2fdab42c4c..0a057e5dc63 100644 --- a/drivers/net/mlx4/port.c +++ b/drivers/net/mlx4/port.c @@ -258,6 +258,42 @@ out: } EXPORT_SYMBOL_GPL(mlx4_unregister_vlan); +int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps) +{ + struct mlx4_cmd_mailbox *inmailbox, *outmailbox; + u8 *inbuf, *outbuf; + int err; + + inmailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(inmailbox)) + return PTR_ERR(inmailbox); + + outmailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(outmailbox)) { + mlx4_free_cmd_mailbox(dev, inmailbox); + return PTR_ERR(outmailbox); + } + + inbuf = inmailbox->buf; + outbuf = outmailbox->buf; + memset(inbuf, 0, 256); + memset(outbuf, 0, 256); + inbuf[0] = 1; + inbuf[1] = 1; + inbuf[2] = 1; + inbuf[3] = 1; + *(__be16 *) (&inbuf[16]) = cpu_to_be16(0x0015); + *(__be32 *) (&inbuf[20]) = cpu_to_be32(port); + + err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3, + MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C); + if (!err) + *caps = *(__be32 *) (outbuf + 84); + mlx4_free_cmd_mailbox(dev, inmailbox); + mlx4_free_cmd_mailbox(dev, outmailbox); + return err; +} + int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) { struct mlx4_cmd_mailbox *mailbox; @@ -273,7 +309,8 @@ int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) ((u8 *) mailbox->buf)[3] = 6; ((__be16 *) mailbox->buf)[4] = cpu_to_be16(1 << 15); ((__be16 *) mailbox->buf)[6] = cpu_to_be16(1 << 15); - } + } else + ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port]; err = mlx4_cmd(dev, mailbox->dma, port, is_eth, MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B); -- cgit v1.2.3 From e6358135147807351db3b7782d3e198a1bba8b62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Moulins?= Date: Fri, 28 Nov 2008 22:12:02 -0800 Subject: pppol2tp: Add missing sock_put() in pppol2tp_release() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pppol2tp_sock_to_session() do sock_hold() if the session to release is not NULL. Signed-off-by: Frédéric Moulins Signed-off-by: David S. Miller --- drivers/net/pppol2tp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index 185b1dff10a..e98d9773158 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -1353,6 +1353,7 @@ static int pppol2tp_release(struct socket *sock) kfree_skb(skb); sock_put(sk); } + sock_put(sk); } release_sock(sk); -- cgit v1.2.3 From e47c1feb17e61ef4e2f245c0af0c5a8e2a7798b2 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Wed, 26 Nov 2008 01:34:25 +0100 Subject: ieee1394: fix list corruption (reported at module removal) If there is more than one FireWire controller present, dummy_zero_addr and dummy_max_addr were added multiple times to different lists, thus corrupting the lists. Fix this by allocating them dynamically per host instead of just once globally. (Perhaps a better address space allocation algorithm could rid us of the two dummy address spaces.) Fixes http://bugzilla.kernel.org/show_bug.cgi?id=10129 . Signed-off-by: Stefan Richter --- drivers/ieee1394/highlevel.c | 25 ++++++++++++------------- drivers/ieee1394/hosts.h | 4 ++++ 2 files changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c index 918ffc4fc8a..272543a42a4 100644 --- a/drivers/ieee1394/highlevel.c +++ b/drivers/ieee1394/highlevel.c @@ -46,10 +46,6 @@ static DEFINE_RWLOCK(hl_irqs_lock); static DEFINE_RWLOCK(addr_space_lock); -/* addr_space list will have zero and max already included as bounds */ -static struct hpsb_address_ops dummy_ops = { NULL, NULL, NULL, NULL }; -static struct hpsb_address_serve dummy_zero_addr, dummy_max_addr; - static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host) @@ -481,20 +477,23 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, return retval; } +static struct hpsb_address_ops dummy_ops; + +/* dummy address spaces as lower and upper bounds of the host's a.s. list */ static void init_hpsb_highlevel(struct hpsb_host *host) { - INIT_LIST_HEAD(&dummy_zero_addr.host_list); - INIT_LIST_HEAD(&dummy_zero_addr.hl_list); - INIT_LIST_HEAD(&dummy_max_addr.host_list); - INIT_LIST_HEAD(&dummy_max_addr.hl_list); + INIT_LIST_HEAD(&host->dummy_zero_addr.host_list); + INIT_LIST_HEAD(&host->dummy_zero_addr.hl_list); + INIT_LIST_HEAD(&host->dummy_max_addr.host_list); + INIT_LIST_HEAD(&host->dummy_max_addr.hl_list); - dummy_zero_addr.op = dummy_max_addr.op = &dummy_ops; + host->dummy_zero_addr.op = host->dummy_max_addr.op = &dummy_ops; - dummy_zero_addr.start = dummy_zero_addr.end = 0; - dummy_max_addr.start = dummy_max_addr.end = ((u64) 1) << 48; + host->dummy_zero_addr.start = host->dummy_zero_addr.end = 0; + host->dummy_max_addr.start = host->dummy_max_addr.end = ((u64) 1) << 48; - list_add_tail(&dummy_zero_addr.host_list, &host->addr_space); - list_add_tail(&dummy_max_addr.host_list, &host->addr_space); + list_add_tail(&host->dummy_zero_addr.host_list, &host->addr_space); + list_add_tail(&host->dummy_max_addr.host_list, &host->addr_space); } void highlevel_add_host(struct hpsb_host *host) diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h index e4e8aeb4d77..dd229950acc 100644 --- a/drivers/ieee1394/hosts.h +++ b/drivers/ieee1394/hosts.h @@ -13,6 +13,7 @@ struct module; #include "ieee1394_types.h" #include "csr.h" +#include "highlevel.h" struct hpsb_packet; struct hpsb_iso; @@ -72,6 +73,9 @@ struct hpsb_host { struct { DECLARE_BITMAP(map, 64); } tl_pool[ALL_NODES]; struct csr_control csr; + + struct hpsb_address_serve dummy_zero_addr; + struct hpsb_address_serve dummy_max_addr; }; enum devctl_cmd { -- cgit v1.2.3 From 2642b11295ebcc94843045933061bfbb263fce7f Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 29 Nov 2008 14:55:47 +0100 Subject: ieee1394: sbp2: fix race condition in state change An intermediate transition from _RUNNING to _IN_SHUTDOWN could have been missed by the former code. Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 3f5dbcb2160..a373c18cf7b 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -895,12 +895,13 @@ static void sbp2_host_reset(struct hpsb_host *host) return; read_lock_irqsave(&sbp2_hi_logical_units_lock, flags); + list_for_each_entry(lu, &hi->logical_units, lu_list) - if (likely(atomic_read(&lu->state) != - SBP2LU_STATE_IN_SHUTDOWN)) { - atomic_set(&lu->state, SBP2LU_STATE_IN_RESET); + if (atomic_cmpxchg(&lu->state, + SBP2LU_STATE_RUNNING, SBP2LU_STATE_IN_RESET) + == SBP2LU_STATE_RUNNING) scsi_block_requests(lu->shost); - } + read_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags); } -- cgit v1.2.3 From aac725cf1649d593a13be1edc99ed489f8050a99 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sat, 29 Nov 2008 20:42:28 -0800 Subject: ATM: horizon, fix hrz_probe fail path One fail path in hrz_probe omitted device disable. Fix it. Signed-off-by: Jiri Slaby Signed-off-by: David S. Miller --- drivers/atm/horizon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index 615412364e9..6b969f8c684 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c @@ -2705,7 +2705,7 @@ static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_ /* XXX DEV_LABEL is a guess */ if (!request_region(iobase, HRZ_IO_EXTENT, DEV_LABEL)) { - return -EINVAL; + err = -EINVAL; goto out_disable; } -- cgit v1.2.3 From 6005e3eb89db99f3737c8f5fe3d97f3262ed7919 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:34:14 +0000 Subject: istallion section warnings stli_findeisabrds() and stli_initbrds() are using __init and called only from __init. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/char/istallion.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 44e5d60f517..4b10770fa93 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -3739,7 +3739,7 @@ static int stli_getbrdnr(void) * do is go probing around in the usual places hoping we can find it. */ -static int stli_findeisabrds(void) +static int __init stli_findeisabrds(void) { struct stlibrd *brdp; unsigned int iobase, eid, i; @@ -3935,7 +3935,7 @@ static struct stlibrd *stli_allocbrd(void) * can find. */ -static int stli_initbrds(void) +static int __init stli_initbrds(void) { struct stlibrd *brdp, *nxtbrdp; struct stlconf conf; -- cgit v1.2.3 From 596f1034190565529e507e1eb8df6def1c9f5560 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:34:24 +0000 Subject: fix talitos talitos_remove() can be called from talitos_probe() on failure exit path, so it can't be __devexit. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/crypto/talitos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index b6ad3ac5916..24607669a52 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -1357,7 +1357,7 @@ static int hw_supports(struct device *dev, __be32 desc_hdr_template) return ret; } -static int __devexit talitos_remove(struct of_device *ofdev) +static int talitos_remove(struct of_device *ofdev) { struct device *dev = &ofdev->dev; struct talitos_private *priv = dev_get_drvdata(dev); @@ -1622,7 +1622,7 @@ static struct of_platform_driver talitos_driver = { .name = "talitos", .match_table = talitos_match, .probe = talitos_probe, - .remove = __devexit_p(talitos_remove), + .remove = talitos_remove, }; static int __init talitos_init(void) -- cgit v1.2.3 From d16d7667f9c211e8d9b7e2365cc3d3a83fc6a8e2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:34:34 +0000 Subject: icside section warnings icside_register_v[56] is called from (__devinit) icside_probe Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/ide/icside.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c index 2d848010499..81f70caeb40 100644 --- a/drivers/ide/icside.c +++ b/drivers/ide/icside.c @@ -419,7 +419,7 @@ static void icside_setup_ports(hw_regs_t *hw, void __iomem *base, hw->chipset = ide_acorn; } -static int __init +static int __devinit icside_register_v5(struct icside_state *state, struct expansion_card *ec) { void __iomem *base; @@ -473,7 +473,7 @@ static const struct ide_port_info icside_v6_port_info __initdata = { .swdma_mask = ATA_SWDMA2, }; -static int __init +static int __devinit icside_register_v6(struct icside_state *state, struct expansion_card *ec) { void __iomem *ioc_base, *easi_base; -- cgit v1.2.3 From 2fceab0bd8d82509519e9b842a5a7234b2397fb4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:34:44 +0000 Subject: W1_MASTER_DS1WM should depend on HAVE_CLK Uses clk_...() a lot Acked-by: rmk+kernel@arm.linux.org.uk Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/w1/masters/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index a14d5b6e4c7..90616822cd2 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -36,7 +36,7 @@ config W1_MASTER_DS2482 config W1_MASTER_DS1WM tristate "Maxim DS1WM 1-wire busmaster" - depends on W1 && ARM + depends on W1 && ARM && HAVE_CLK help Say Y here to enable the DS1WM 1-wire driver, such as that in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like -- cgit v1.2.3 From 30037818f7c1e11cb3742fbecd614ef3dc7b27bb Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:34:54 +0000 Subject: advansys fix on ISA-less configs The code if (shost->dma_channel != NO_ISA_DMA) free_dma(shost->dma_channel); in there is triggerable only if we have CONFIG_ISA (we only set ->dma_channel to something other than NO_ISA_DMA under #ifdef CONFIG_ISA). OTOH, free_dma() is not guaranteed to be there in absense of CONFIG_ISA. IOW, driver runs into undefined symbols on PCI-but-not-ISA configs (e.g. on frv) and it's a false positive. Fix: put the entire if () under #ifdef CONFIG_ISA; behaviour doesn't change and dependency on free_dma() disappears for !CONFIG_ISA. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/scsi/advansys.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 218777bfc14..399fe559e4d 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -13872,8 +13872,10 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, advansys_wide_free_mem(boardp); free_irq(boardp->irq, shost); err_free_dma: +#ifdef CONFIG_ISA if (shost->dma_channel != NO_ISA_DMA) free_dma(shost->dma_channel); +#endif err_free_proc: kfree(boardp->prtbuf); err_unmap: @@ -13894,10 +13896,12 @@ static int advansys_release(struct Scsi_Host *shost) ASC_DBG(1, "begin\n"); scsi_remove_host(shost); free_irq(board->irq, shost); +#ifdef CONFIG_ISA if (shost->dma_channel != NO_ISA_DMA) { ASC_DBG(1, "free_dma()\n"); free_dma(shost->dma_channel); } +#endif if (ASC_NARROW_BOARD(board)) { dma_unmap_single(board->dev, board->dvc_var.asc_dvc_var.overrun_dma, -- cgit v1.2.3 From e669dae6141ff97d3c7566207f5de3b487dcf837 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:35:04 +0000 Subject: of_platform_driver noise on sparce switch to __init for those; unlike powerpc sparc has no hotplug support for that stuff and their ->probe() tends to call __init functions while being declared __devinit. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/sbus/char/bbc_i2c.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index f08e169ba1b..054f5dd5893 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -361,7 +361,7 @@ fail: extern int bbc_envctrl_init(struct bbc_i2c_bus *bp); extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp); -static int __devinit bbc_i2c_probe(struct of_device *op, +static int __init bbc_i2c_probe(struct of_device *op, const struct of_device_id *match) { struct bbc_i2c_bus *bp; @@ -386,7 +386,7 @@ static int __devinit bbc_i2c_probe(struct of_device *op, return err; } -static int __devexit bbc_i2c_remove(struct of_device *op) +static int __exit bbc_i2c_remove(struct of_device *op) { struct bbc_i2c_bus *bp = dev_get_drvdata(&op->dev); @@ -417,7 +417,7 @@ static struct of_platform_driver bbc_i2c_driver = { .name = "bbc_i2c", .match_table = bbc_i2c_match, .probe = bbc_i2c_probe, - .remove = __devexit_p(bbc_i2c_remove), + .remove = __exit_p(bbc_i2c_remove), }; static int __init bbc_i2c_init(void) -- cgit v1.2.3 From ced7172ad94713f9023a3c279082402ac7750ba8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:35:14 +0000 Subject: gdth section fixes PCI side of driver should be devinit, not init Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/scsi/gdth.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index c387c15a212..fb247fdfa2b 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -588,7 +588,7 @@ static struct pci_driver gdth_pci_driver = { .remove = gdth_pci_remove_one, }; -static void gdth_pci_remove_one(struct pci_dev *pdev) +static void __devexit gdth_pci_remove_one(struct pci_dev *pdev) { gdth_ha_str *ha = pci_get_drvdata(pdev); @@ -600,7 +600,7 @@ static void gdth_pci_remove_one(struct pci_dev *pdev) pci_disable_device(pdev); } -static int gdth_pci_init_one(struct pci_dev *pdev, +static int __devinit gdth_pci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { ushort vendor = pdev->vendor; @@ -853,7 +853,7 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) #endif /* CONFIG_ISA */ #ifdef CONFIG_PCI -static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr, +static int __devinit gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr, gdth_ha_str *ha) { register gdt6_dpram_str __iomem *dp6_ptr; @@ -1237,7 +1237,7 @@ static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr, /* controller protocol functions */ -static void __init gdth_enable_int(gdth_ha_str *ha) +static void __devinit gdth_enable_int(gdth_ha_str *ha) { ulong flags; gdt2_dpram_str __iomem *dp2_ptr; @@ -1553,7 +1553,7 @@ static int gdth_internal_cmd(gdth_ha_str *ha, unchar service, ushort opcode, /* search for devices */ -static int __init gdth_search_drives(gdth_ha_str *ha) +static int __devinit gdth_search_drives(gdth_ha_str *ha) { ushort cdev_cnt, i; int ok; @@ -4935,7 +4935,7 @@ static int __init gdth_eisa_probe_one(ushort eisa_slot) #endif /* CONFIG_EISA */ #ifdef CONFIG_PCI -static int gdth_pci_probe_one(gdth_pci_str *pcistr, +static int __devinit gdth_pci_probe_one(gdth_pci_str *pcistr, gdth_ha_str **ha_out) { struct Scsi_Host *shp; -- cgit v1.2.3 From 31421a6f6ea88236cb17b6a24aa21e66a6138d4c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:35:24 +0000 Subject: rackmeter section fixes * rackmeter_remove() reference needs devexit_p * rackmeter_setup() is calls devinit and is called only from devinit Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/macintosh/rack-meter.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c index 2c21d4f25cc..a98ab72adf9 100644 --- a/drivers/macintosh/rack-meter.c +++ b/drivers/macintosh/rack-meter.c @@ -288,7 +288,7 @@ static void __devexit rackmeter_stop_cpu_sniffer(struct rackmeter *rm) cancel_rearming_delayed_work(&rm->cpu[1].sniffer); } -static int rackmeter_setup(struct rackmeter *rm) +static int __devinit rackmeter_setup(struct rackmeter *rm) { pr_debug("rackmeter: setting up i2s..\n"); rackmeter_setup_i2s(rm); @@ -582,12 +582,12 @@ static struct of_device_id rackmeter_match[] = { { } }; -static struct macio_driver rackmeter_drv = { +static struct macio_driver rackmeter_driver = { .name = "rackmeter", .owner = THIS_MODULE, .match_table = rackmeter_match, .probe = rackmeter_probe, - .remove = rackmeter_remove, + .remove = __devexit_p(rackmeter_remove), .shutdown = rackmeter_shutdown, }; @@ -596,14 +596,14 @@ static int __init rackmeter_init(void) { pr_debug("rackmeter_init()\n"); - return macio_register_driver(&rackmeter_drv); + return macio_register_driver(&rackmeter_driver); } static void __exit rackmeter_exit(void) { pr_debug("rackmeter_exit()\n"); - macio_unregister_driver(&rackmeter_drv); + macio_unregister_driver(&rackmeter_driver); } module_init(rackmeter_init); -- cgit v1.2.3 From 43ced651d1272ced02ed5f1c2abc79e3354187f6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:35:34 +0000 Subject: ixgbe section fixes ixgbe_init_interrupt_scheme() is called from ixgbe_resume(). Build that with CONFIG_PM and without CONFIG_HOTPLUG and you've got a problem. Several helpers called by it also are misannotated __devinit. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/net/ixgbe/ixgbe_main.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 36f2bb666bf..8ed823ae639 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -2330,7 +2330,7 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter, * Once we know the feature-set enabled for the device, we'll cache * the register offset the descriptor ring is assigned to. **/ -static void __devinit ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) +static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) { int feature_mask = 0, rss_i; int i, txr_idx, rxr_idx; @@ -2367,7 +2367,7 @@ static void __devinit ixgbe_cache_ring_register(struct ixgbe_adapter *adapter) * number of queues at compile-time. The polling_netdev array is * intended for Multiqueue, but should work fine with a single queue. **/ -static int __devinit ixgbe_alloc_queues(struct ixgbe_adapter *adapter) +static int ixgbe_alloc_queues(struct ixgbe_adapter *adapter) { int i; @@ -2408,8 +2408,7 @@ err_tx_ring_allocation: * Attempt to configure the interrupts using the best available * capabilities of the hardware and the kernel. **/ -static int __devinit ixgbe_set_interrupt_capability(struct ixgbe_adapter - *adapter) +static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter) { int err = 0; int vector, v_budget; @@ -2501,7 +2500,7 @@ static void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter) * - Hardware queue count (num_*_queues) * - defined by miscellaneous hardware support/features (RSS, etc.) **/ -static int __devinit ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter) +static int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter) { int err; -- cgit v1.2.3 From 8814b5050d183f00a25a087b550841797c0c2775 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:35:44 +0000 Subject: section misannotation in ibmtr_cs ibmtr_resume() is calling ibmtr_probe(), which is devinit. Whether that's the right thing to do there is a separate question, but since it's PCMCIA and thus will never compile without HOTPLUG... Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/net/pcmcia/ibmtr_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index cf3cca4642f..f51944b28cf 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -349,7 +349,7 @@ static int ibmtr_suspend(struct pcmcia_device *link) return 0; } -static int ibmtr_resume(struct pcmcia_device *link) +static int __devinit ibmtr_resume(struct pcmcia_device *link) { ibmtr_dev_t *info = link->priv; struct net_device *dev = info->dev; -- cgit v1.2.3 From f57628d76bd201a444ca822f3622522a44acbf60 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:36:14 +0000 Subject: section errors in smc911x/smc91x a) ->probe() can be __devinit; no need to put it into .text b) calling __init stuff from it, OTOH, is wrong c) ->remove() is __devexit fodder Acked-by: rmk+kernel@arm.linux.org.uk Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/net/smc911x.c | 10 +++++----- drivers/net/smc91x.c | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index b185cd12269..9a16a79b67d 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -1735,7 +1735,7 @@ static const struct ethtool_ops smc911x_ethtool_ops = { * This routine has a simple purpose -- make the SMC chip generate an * interrupt, so an auto-detect routine can detect it, and find the IRQ, */ -static int __init smc911x_findirq(struct net_device *dev) +static int __devinit smc911x_findirq(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); int timeout = 20; @@ -1799,7 +1799,7 @@ static int __init smc911x_findirq(struct net_device *dev) * o actually GRAB the irq. * o GRAB the region */ -static int __init smc911x_probe(struct net_device *dev) +static int __devinit smc911x_probe(struct net_device *dev) { struct smc911x_local *lp = netdev_priv(dev); int i, retval; @@ -2048,7 +2048,7 @@ err_out: * 0 --> there is a device * anything else, error */ -static int smc911x_drv_probe(struct platform_device *pdev) +static int __devinit smc911x_drv_probe(struct platform_device *pdev) { #ifdef SMC_DYNAMIC_BUS_CONFIG struct smc911x_platdata *pd = pdev->dev.platform_data; @@ -2124,7 +2124,7 @@ out: return ret; } -static int smc911x_drv_remove(struct platform_device *pdev) +static int __devexit smc911x_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct smc911x_local *lp = netdev_priv(ndev); @@ -2195,7 +2195,7 @@ static int smc911x_drv_resume(struct platform_device *dev) static struct platform_driver smc911x_driver = { .probe = smc911x_drv_probe, - .remove = smc911x_drv_remove, + .remove = __devexit_p(smc911x_drv_remove), .suspend = smc911x_drv_suspend, .resume = smc911x_drv_resume, .driver = { diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index fc80f250da3..35c56abf411 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -1696,7 +1696,7 @@ static const struct ethtool_ops smc_ethtool_ops = { * I just deleted auto_irq.c, since it was never built... * --jgarzik */ -static int __init smc_findirq(struct smc_local *lp) +static int __devinit smc_findirq(struct smc_local *lp) { void __iomem *ioaddr = lp->base; int timeout = 20; @@ -1770,7 +1770,7 @@ static int __init smc_findirq(struct smc_local *lp) * o actually GRAB the irq. * o GRAB the region */ -static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr, +static int __devinit smc_probe(struct net_device *dev, void __iomem *ioaddr, unsigned long irq_flags) { struct smc_local *lp = netdev_priv(dev); @@ -2126,7 +2126,7 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device * * 0 --> there is a device * anything else, error */ -static int smc_drv_probe(struct platform_device *pdev) +static int __devinit smc_drv_probe(struct platform_device *pdev) { struct smc91x_platdata *pd = pdev->dev.platform_data; struct smc_local *lp; @@ -2240,7 +2240,7 @@ static int smc_drv_probe(struct platform_device *pdev) return ret; } -static int smc_drv_remove(struct platform_device *pdev) +static int __devexit smc_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct smc_local *lp = netdev_priv(ndev); @@ -2305,7 +2305,7 @@ static int smc_drv_resume(struct platform_device *dev) static struct platform_driver smc_driver = { .probe = smc_drv_probe, - .remove = smc_drv_remove, + .remove = __devexit_p(smc_drv_remove), .suspend = smc_drv_suspend, .resume = smc_drv_resume, .driver = { -- cgit v1.2.3 From 37d33d151428a4ee648c855c0b49368de7804e7f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:36:24 +0000 Subject: rapidio section noise functions calling devinit and called only from devinit Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/rapidio/rio-scan.c | 4 ++-- drivers/rapidio/rio.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index a926c896475..643a6b98462 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -879,7 +879,7 @@ static void rio_update_route_tables(struct rio_mport *port) * link, then start recursive peer enumeration. Returns %0 if * enumeration succeeds or %-EBUSY if enumeration fails. */ -int rio_enum_mport(struct rio_mport *mport) +int __devinit rio_enum_mport(struct rio_mport *mport) { struct rio_net *net = NULL; int rc = 0; @@ -972,7 +972,7 @@ static void rio_enum_timeout(unsigned long data) * peer discovery. Returns %0 if discovery succeeds or %-EBUSY * on failure. */ -int rio_disc_mport(struct rio_mport *mport) +int __devinit rio_disc_mport(struct rio_mport *mport) { struct rio_net *net = NULL; int enum_timeout_flag = 0; diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index 680661abbc4..6395c780008 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -467,7 +467,7 @@ static int __devinit rio_init(void) device_initcall(rio_init); -int rio_init_mports(void) +int __devinit rio_init_mports(void) { int rc = 0; struct rio_mport *port; -- cgit v1.2.3 From b0385146bcdd24b0390c2b60fd05a083888835db Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:36:34 +0000 Subject: uninorth-agp section mess 'aperture' is declared devinitdata (the whole word of it) and is used from ->fetch_size() which can, AFAICS, be used on !HOTPLUG after init time. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/char/agp/uninorth-agp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 0f004b65ec0..03f95ec08f5 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -27,7 +27,7 @@ static int uninorth_rev; static int is_u3; -static char __devinitdata *aperture = NULL; +static char *aperture = NULL; static int uninorth_fetch_size(void) { -- cgit v1.2.3 From 56d74dd5f7ad8b6b0979ce915d51cf03bcc57267 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:36:54 +0000 Subject: tricky one: hisax sections a) hisax_init_pcmcia() needs to be defined only if we have CONFIG_HOTPLUG (no PCMCIA support otherwise) and can be declared __devinit. b) HiSax_inithardware() can go __init c) hisax_register() is passing to checkcard() full-blown hisax_cs_setup_card(): checkcard(i, id, NULL, hisax_d_if->owner, hisax_cs_setup_card); The problem with it is that * hisax_cs_setup_card() is __devinit * hisax_register() is not * hisax_cs_setup_card() is a switch from hell, calling a lot of setup_some_weirdcard() depending on card->typ. _These_ are also __devinit. However, in hisax_register() we have card->typ equal to ISDN_CTYPE_DYNAMIC, which reduces hisax_cs_setup_card() to "nevermind all that crap, just do nothing and return 2". So we add a trimmed-down callback doing just that and passed to checkcard() by hisax_register(). _This_ is non-init (we can stand the impact on .text size). Voila - no section warnings from drivers/isdn Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/isdn/hisax/config.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index 84d75a3f5d1..ded9d0baf60 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -1213,7 +1213,7 @@ static void HiSax_shiftcards(int idx) memcpy(&cards[i], &cards[i + 1], sizeof(cards[i])); } -static int HiSax_inithardware(int *busy_flag) +static int __init HiSax_inithardware(int *busy_flag) { int foundcards = 0; int i = 0; @@ -1542,7 +1542,9 @@ static void __exit HiSax_exit(void) printk(KERN_INFO "HiSax module removed\n"); } -int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card) +#ifdef CONFIG_HOTPLUG + +int __devinit hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card) { u_char ids[16]; int ret = -1; @@ -1563,6 +1565,8 @@ error: } EXPORT_SYMBOL(hisax_init_pcmcia); +#endif + EXPORT_SYMBOL(HiSax_closecard); #include "hisax_if.h" @@ -1580,6 +1584,11 @@ static void hisax_bc_close(struct BCState *bcs); static void hisax_bh(struct work_struct *work); static void EChannel_proc_rcv(struct hisax_d_if *d_if); +static int hisax_setup_card_dynamic(struct IsdnCard *card) +{ + return 2; +} + int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[], char *name, int protocol) { @@ -1599,7 +1608,8 @@ int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[], cards[i].protocol = protocol; sprintf(id, "%s%d", name, i); nrcards++; - retval = checkcard(i, id, NULL, hisax_d_if->owner, hisax_cs_setup_card); + retval = checkcard(i, id, NULL, hisax_d_if->owner, + hisax_setup_card_dynamic); if (retval == 0) { // yuck cards[i].typ = 0; nrcards--; -- cgit v1.2.3 From ad04d31e5fb6b25308e6cdea6baa07d41871a3e0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:37:14 +0000 Subject: pci_setup() is init, not devinit for fsck sake, it's used only when parsing kernel command line... Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/pci/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 28af496b441..061d1ee0046 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2042,7 +2042,7 @@ static int __devinit pci_init(void) return 0; } -static int __devinit pci_setup(char *str) +static int __init pci_setup(char *str) { while (str) { char *k = strchr(str, ','); -- cgit v1.2.3 From ffb78a26169351f6c22cdae481b057d50d5d759b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 22 Nov 2008 17:38:14 +0000 Subject: get xenbus_driver ->probe() "recognized" by modpost ... by giving the instances' names magic suffix recognized by modpost ;-/ Their ->probe() is __devinit Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/input/xen-kbdfront.c | 6 +++--- drivers/net/xen-netfront.c | 6 +++--- drivers/video/xen-fbfront.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c index 3ab6362f043..928d2ed8865 100644 --- a/drivers/input/xen-kbdfront.c +++ b/drivers/input/xen-kbdfront.c @@ -323,7 +323,7 @@ static struct xenbus_device_id xenkbd_ids[] = { { "" } }; -static struct xenbus_driver xenkbd = { +static struct xenbus_driver xenkbd_driver = { .name = "vkbd", .owner = THIS_MODULE, .ids = xenkbd_ids, @@ -342,12 +342,12 @@ static int __init xenkbd_init(void) if (xen_initial_domain()) return -ENODEV; - return xenbus_register_frontend(&xenkbd); + return xenbus_register_frontend(&xenkbd_driver); } static void __exit xenkbd_cleanup(void) { - xenbus_unregister_driver(&xenkbd); + xenbus_unregister_driver(&xenkbd_driver); } module_init(xenkbd_init); diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index c6948d8f53f..6d017adc914 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1785,7 +1785,7 @@ static int __devexit xennet_remove(struct xenbus_device *dev) return 0; } -static struct xenbus_driver netfront = { +static struct xenbus_driver netfront_driver = { .name = "vif", .owner = THIS_MODULE, .ids = netfront_ids, @@ -1805,7 +1805,7 @@ static int __init netif_init(void) printk(KERN_INFO "Initialising Xen virtual ethernet driver.\n"); - return xenbus_register_frontend(&netfront); + return xenbus_register_frontend(&netfront_driver); } module_init(netif_init); @@ -1815,7 +1815,7 @@ static void __exit netif_exit(void) if (xen_initial_domain()) return; - xenbus_unregister_driver(&netfront); + xenbus_unregister_driver(&netfront_driver); } module_exit(netif_exit); diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c index a463b3dd837..2493f05e9f6 100644 --- a/drivers/video/xen-fbfront.c +++ b/drivers/video/xen-fbfront.c @@ -668,7 +668,7 @@ static struct xenbus_device_id xenfb_ids[] = { { "" } }; -static struct xenbus_driver xenfb = { +static struct xenbus_driver xenfb_driver = { .name = "vfb", .owner = THIS_MODULE, .ids = xenfb_ids, @@ -687,12 +687,12 @@ static int __init xenfb_init(void) if (xen_initial_domain()) return -ENODEV; - return xenbus_register_frontend(&xenfb); + return xenbus_register_frontend(&xenfb_driver); } static void __exit xenfb_cleanup(void) { - xenbus_unregister_driver(&xenfb); + xenbus_unregister_driver(&xenfb_driver); } module_init(xenfb_init); -- cgit v1.2.3 From 211f05a034f49586fdd071abd174853217ec29ee Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 23 Nov 2008 16:57:36 -0800 Subject: input: replace spin_lock_bh with spin_lock_irqsave in ml_ff_playback ml_ff_playback() uses spin_(un)lock_bh. However this function is called with interrupts disabled from erase_effect() in drivers/input/ff-core.c:196. This is not permitted, and will result in a WARN_ON in the bottom half handling code. This patch changes this function to just use spin_lock_irqsave() instead, solving the problem and simplifying the locking logic. This was reported as entry #106559 in kerneloops.org Reported-by: kerneloops.org Signed-off-by: Arjan van de Ven Signed-off-by: Linus Torvalds --- drivers/input/ff-memless.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index 6790e975a98..bc4e40f3ede 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -397,8 +397,9 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) { struct ml_device *ml = dev->ff->private; struct ml_effect_state *state = &ml->states[effect_id]; + unsigned long flags; - spin_lock_bh(&ml->timer_lock); + spin_lock_irqsave(&ml->timer_lock, flags); if (value > 0) { debug("initiated play"); @@ -424,7 +425,7 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) ml_play_effects(ml); } - spin_unlock_bh(&ml->timer_lock); + spin_unlock_irqrestore(&ml->timer_lock, flags); return 0; } -- cgit v1.2.3 From 151903d5466fbcfb56ce792c3d5ea0ecbae15d07 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 1 Dec 2008 10:23:21 +1000 Subject: drm/i915: Fix copy'n'pasteo that broke VT switch if flushing was non-empty. Introduced in the "Avoid BUG_ONs on VT switch" commit. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 54bb0d0e49b..d58ddef468f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2314,7 +2314,7 @@ i915_gem_idle(struct drm_device *dev) while (!list_empty(&dev_priv->mm.flushing_list)) { struct drm_i915_gem_object *obj_priv; - obj_priv = list_first_entry(&dev_priv->mm.active_list, + obj_priv = list_first_entry(&dev_priv->mm.flushing_list, struct drm_i915_gem_object, list); obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS; -- cgit v1.2.3 From 269f0532332410e97e3edeb78e6cd3bb940e52b4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 25 Nov 2008 13:34:45 -0800 Subject: Revert "USB: improve ehci_watchdog's side effect in CPU power management" This reverts commit f0d781d59cb621e1795d510039df973d0f8b23fc. It was the wrong thing to do, and does not really do what it said it did. Cc: Yi Yang Cc: David Brownell Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index b11798d17ae..c7d4b5a06bd 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -183,16 +183,14 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) * the async ring; just the I/O watchdog. Note that if a * SHRINK were pending, OFF would never be requested. */ - enum ehci_timer_action oldactions = ehci->actions; + if (timer_pending(&ehci->watchdog) + && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) + & ehci->actions)) + return; if (!test_and_set_bit (action, &ehci->actions)) { unsigned long t; - if (timer_pending(&ehci->watchdog) - && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) - & oldactions)) - return; - switch (action) { case TIMER_IO_WATCHDOG: t = EHCI_IO_JIFFIES; @@ -208,7 +206,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1; break; } - mod_timer(&ehci->watchdog, round_jiffies(t + jiffies)); + mod_timer(&ehci->watchdog, t + jiffies); } } -- cgit v1.2.3 From 0a99e8ac430a27825bd055719765fd0d65cd797f Mon Sep 17 00:00:00 2001 From: Shane Huang Date: Tue, 25 Nov 2008 15:12:33 +0800 Subject: USB: fix SB600 USB subsystem hang bug This patch is required for all AMD SB600 revisions to avoid USB subsystem hang symptom. The USB subsystem hang symptom is observed when the system has multiple USB devices connected to it. In some cases a USB hub may be required to observe this symptom. Reported in bugzilla as #11599, the similar patch for SB700 old revision is: commit b09bc6cbae4dd3a2d35722668ef2c502a7b8b093 Reported-by: raffaele Tested-by: Roman Mamedov Signed-off-by: Shane Huang Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-pci.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 9d0ea573aef..36864f95844 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -169,18 +169,21 @@ static int ehci_pci_setup(struct usb_hcd *hcd) } break; case PCI_VENDOR_ID_ATI: - /* SB700 old version has a bug in EHCI controller, + /* SB600 and old version of SB700 have a bug in EHCI controller, * which causes usb devices lose response in some cases. */ - if (pdev->device == 0x4396) { + if ((pdev->device == 0x4386) || (pdev->device == 0x4396)) { p_smbus = pci_get_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL); if (!p_smbus) break; rev = p_smbus->revision; - if ((rev == 0x3a) || (rev == 0x3b)) { + if ((pdev->device == 0x4386) || (rev == 0x3a) + || (rev == 0x3b)) { u8 tmp; + ehci_info(ehci, "applying AMD SB600/SB700 USB " + "freeze workaround\n"); pci_read_config_byte(pdev, 0x53, &tmp); pci_write_config_byte(pdev, 0x53, tmp | (1<<3)); } -- cgit v1.2.3 From 9ac36da3f8bc646a628bd09326e090defc8b7940 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Thu, 13 Nov 2008 14:57:20 +0300 Subject: USB: fsl_qe_udc: Report disconnect before unbinding Gadgets disable endpoints in their disconnect callbacks, so we must call disconnect before unbinding. This also fixes muram memory leak, since we free muram in the qe_ep_disable(). But mainly the patch fixes following badness: root@b1:~# insmod fsl_qe_udc.ko fsl_qe_udc: Freescale QE/CPM USB Device Controller driver, 1.0 fsl_qe_udc e01006c0.usb: QE USB controller initialized as device root@b1:~# insmod g_ether.ko g_ether gadget: using random self ethernet address g_ether gadget: using random host ethernet address usb0: MAC be:2d:3c:fa:be:f0 usb0: HOST MAC 62:b8:6a:df:38:66 g_ether gadget: Ethernet Gadget, version: Memorial Day 2008 g_ether gadget: g_ether ready fsl_qe_udc e01006c0.usb: fsl_qe_udc bind to driver g_ether g_ether gadget: high speed config #1: CDC Ethernet (ECM) root@b1:~# rmmod g_ether.ko ------------[ cut here ]------------ Badness at drivers/usb/gadget/composite.c:871 [...] NIP [d10c1374] composite_unbind+0x24/0x15c [g_ether] LR [d10a82f4] usb_gadget_unregister_driver+0x128/0x168 [fsl_qe_udc] Call Trace: [cfb93e80] [cfb1f3a0] 0xcfb1f3a0 (unreliable) [cfb93eb0] [d10a82f4] usb_gadget_unregister_driver+0x128/0x168 [fsl_qe_udc] [cfb93ed0] [d10c2a3c] usb_composite_unregister+0x3c/0x4c [g_ether] [cfb93ee0] [c006bde0] sys_delete_module+0x130/0x19c [cfb93f40] [c00142d8] ret_from_syscall+0x0/0x38 [...] fsl_qe_udc e01006c0.usb: unregistered gadget driver 'g_ether' Signed-off-by: Anton Vorontsov Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/fsl_qe_udc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 1fe8b44787b..b3408ff39fb 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -2363,6 +2363,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) nuke(loop_ep, -ESHUTDOWN); spin_unlock_irqrestore(&udc_controller->lock, flags); + /* report disconnect; the controller is already quiesced */ + driver->disconnect(&udc_controller->gadget); + /* unbind gadget and unhook driver. */ driver->unbind(&udc_controller->gadget); udc_controller->gadget.dev.driver = NULL; -- cgit v1.2.3 From 1f15a506f356aa21c29b6a7b0e9e826695273dfc Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Thu, 13 Nov 2008 15:00:46 +0300 Subject: USB: fsl_usb2_udc: Report disconnect before unbinding Gadgets disable endpoints in their disconnect callbacks, so we must call disconnect before unbinding. The patch fixes following badness: root@b1:~# insmod fsl_usb2_udc.ko Freescale High-Speed USB SOC Device Controller driver (Apr 20, 2007) root@b1:~# insmod g_ether.ko g_ether gadget: using random self ethernet address g_ether gadget: using random host ethernet address usb0: MAC 26:07:ba:c0:44:33 usb0: HOST MAC 96:81:0c:05:4d:e3 g_ether gadget: Ethernet Gadget, version: Memorial Day 2008 g_ether gadget: g_ether ready fsl-usb2-udc: bind to driver g_ether g_ether gadget: high speed config #1: CDC Ethernet (ECM) root@b1:~# rmmod g_ether.ko ------------[ cut here ]------------ Badness at drivers/usb/gadget/composite.c:871 [...] NIP [e10c3454] composite_unbind+0x24/0x15c [g_ether] LR [e10aa454] usb_gadget_unregister_driver+0x13c/0x164 [fsl_usb2_udc] Call Trace: [df145e80] [ffffff94] 0xffffff94 (unreliable) [df145eb0] [e10aa454] usb_gadget_unregister_driver+0x13c/0x164 [fsl_usb2_udc] [df145ed0] [e10c4c40] usb_composite_unregister+0x3c/0x4c [g_ether] [df145ee0] [c006bcc0] sys_delete_module+0x130/0x19c [df145f40] [c00142d8] ret_from_syscall+0x0/0x38 [...] unregistered gadget driver 'g_ether' Signed-off-by: Anton Vorontsov Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/fsl_usb2_udc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index 091bb55c9aa..f3c6703cffd 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c @@ -1836,6 +1836,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) nuke(loop_ep, -ESHUTDOWN); spin_unlock_irqrestore(&udc_controller->lock, flags); + /* report disconnect; the controller is already quiesced */ + driver->disconnect(&udc_controller->gadget); + /* unbind gadget and unhook driver. */ driver->unbind(&udc_controller->gadget); udc_controller->gadget.dev.driver = NULL; -- cgit v1.2.3 From a6b7b034d7f20761c55743be2acb762ce09a0c6b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 21 Nov 2008 16:15:12 -0500 Subject: USB: storage: unusual_devs entry for Mio C520-GPS This patch (as1176) adds an unusual_devs entry for the Mio C520 GPS unit. Other devices also based on the Mitac hardware use the same USB interface firmware, so the Vendor and Product names are generalized. This fixes Bugzilla #11583. Signed-off-by: Alan Stern Tested-by: Tamas Kerecsen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 6da9a7a962a..e8e3edaa7cb 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -318,6 +318,18 @@ UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101, US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0), #endif +/* Reported by Tamas Kerecsen + * Obviously the PROM has not been customized by the VAR; + * the Vendor and Product string descriptors are: + * Generic Mass Storage (PROTOTYPE--Remember to change idVendor) + * Generic Manufacturer (PROTOTYPE--Remember to change idVendor) + */ +UNUSUAL_DEV( 0x045e, 0xffff, 0x0000, 0x0000, + "Mitac", + "GPS", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64 ), + /* * This virtual floppy is found in Sun equipment (x4600, x4200m2, etc.) * Reported by Pete Zaitcev -- cgit v1.2.3 From 621b239d75b790ac66854d46b094874f69e6776e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Kunze=20Brise=C3=B1o?= Date: Mon, 24 Nov 2008 11:28:31 -0500 Subject: USB: usb-storage: unusual_devs entry for Nikon D2H MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds an unusual_devs entry for the Nikon D2H camera. From: Tobias Kunze Briseño , Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index e8e3edaa7cb..e61f2bfc64a 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -389,6 +389,13 @@ UNUSUAL_DEV( 0x04b0, 0x0401, 0x0200, 0x0200, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), +/* Reported by Tobias Kunze Briseno */ +UNUSUAL_DEV( 0x04b0, 0x0403, 0x0200, 0x0200, + "NIKON", + "NIKON DSC D2H", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY), + /* Reported by Milinevsky Dmitry */ UNUSUAL_DEV( 0x04b0, 0x0409, 0x0100, 0x0100, "NIKON", -- cgit v1.2.3 From 5bb4bd9895df508ed2bd8b3280252d8a8170e4ac Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 29 Nov 2008 11:46:21 -0800 Subject: USB: serial: add more Onda device ids to option driver Thanks to Domenico Riccio for pointing these out. Cc: Domenico Riccio Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 6fa1ec441b6..809697b3c7f 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -224,6 +224,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po #define ONDA_VENDOR_ID 0x19d2 #define ONDA_PRODUCT_MSA501HS 0x0001 #define ONDA_PRODUCT_ET502HS 0x0002 +#define ONDA_PRODUCT_MT503HS 0x0200 #define BANDRICH_VENDOR_ID 0x1A8D #define BANDRICH_PRODUCT_C100_1 0x1002 @@ -413,6 +414,40 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) }, { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) }, { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0003) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0004) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0005) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0006) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0007) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0008) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0009) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x000a) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x000b) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x000c) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x000d) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x000e) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x000f) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0010) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0011) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0012) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0013) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0014) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0015) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0016) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0017) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0018) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0019) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0020) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0021) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0022) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0023) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0024) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0025) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0026) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0027) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0028) }, + { USB_DEVICE(ONDA_VENDOR_ID, 0x0029) }, + { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MT503HS) }, { USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) }, -- cgit v1.2.3 From 290172e79036fc25a22aaf3da4835ee634886183 Mon Sep 17 00:00:00 2001 From: Bernhard Walle Date: Sun, 26 Oct 2008 15:59:37 +0100 Subject: [WATCHDOG] hpwdt: Fix kdump when using hpwdt When the "hpwdt" module is loaded (even if the /dev/watchdog device is not opened), then kdump does not work. The panic kernel either does not start at all or crash in various places. The problem is that hpwdt_pretimeout is registered with register_die_notifier() with the highest possible priority. Because it returns NOTIFY_STOP, the crash_nmi_callback which is also registered with register_die_notifier() is never executed. This causes the shutdown of other CPUs to fail. Reverting the order is no option: The crash_nmi_callback executes HLT and so never returns normally. Because of that, it must be executed as last notifier, which currently is done. So, that patch returns NOTIFY_OK to keep the crash_nmi_callback executed. Signed-off-by: Bernhard Walle Signed-off-by: Wim Van Sebroeck Signed-off-by: Thomas Mingarelli Cc: Vivek Goyal --- drivers/watchdog/hpwdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index f6cff7b5a54..763c1ea5dce 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -485,7 +485,7 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, "Management Log for details.\n"); } - return NOTIFY_STOP; + return NOTIFY_OK; } /* -- cgit v1.2.3 From 33b07db9f38fe73b3895f8d4db8fdee03e3afec3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 1 Dec 2008 07:55:14 -0800 Subject: Revert "of_platform_driver noise on sparce" This reverts commit e669dae6141ff97d3c7566207f5de3b487dcf837, since it is incomplete, and clashes with fuller patches and the sparc 32/64 unification effort. Requested-by: David Miller Acked-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/sbus/char/bbc_i2c.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index 054f5dd5893..f08e169ba1b 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -361,7 +361,7 @@ fail: extern int bbc_envctrl_init(struct bbc_i2c_bus *bp); extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp); -static int __init bbc_i2c_probe(struct of_device *op, +static int __devinit bbc_i2c_probe(struct of_device *op, const struct of_device_id *match) { struct bbc_i2c_bus *bp; @@ -386,7 +386,7 @@ static int __init bbc_i2c_probe(struct of_device *op, return err; } -static int __exit bbc_i2c_remove(struct of_device *op) +static int __devexit bbc_i2c_remove(struct of_device *op) { struct bbc_i2c_bus *bp = dev_get_drvdata(&op->dev); @@ -417,7 +417,7 @@ static struct of_platform_driver bbc_i2c_driver = { .name = "bbc_i2c", .match_table = bbc_i2c_match, .probe = bbc_i2c_probe, - .remove = __exit_p(bbc_i2c_remove), + .remove = __devexit_p(bbc_i2c_remove), }; static int __init bbc_i2c_init(void) -- cgit v1.2.3 From bce02614cd1b3d669af1195695e503e818b60fae Mon Sep 17 00:00:00 2001 From: Martin Petermann Date: Wed, 26 Nov 2008 18:07:35 +0100 Subject: [SCSI] zfcp: fix remote port status check For an incoming RSCN it was checked by the ZFCP_STATUS_PORT_DID_DID define to re-open a remote port or to test the connection. Since this define was re-used it was also necessary to replace that define with ZFCP_STATUS_PORT_PHYS_OPEN. Signed-off-by: Martin Petermann Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 1a7c80a77ff..c5f4bd217bf 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -125,8 +125,7 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, read_lock_irqsave(&zfcp_data.config_lock, flags); list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) { - /* FIXME: ZFCP_STATUS_PORT_DID_DID check is racy */ - if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_DID_DID)) + if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_PHYS_OPEN)) /* Try to connect to unused ports anyway. */ zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, -- cgit v1.2.3 From 1c1cba17a9078c83a80a099bc207b208d664a13a Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 26 Nov 2008 18:07:36 +0100 Subject: [SCSI] zfcp: Fix opening of wka ports Running two wka_port_get calls in parallel could issue two open_port requests, overwriting the port handle. Don't issue an open_port for the state PORT_OPENING, and only read the data from GOOD responses. Signed-off-by: Christof Schmitt Acked-by: Swen Schillig Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fc.c | 3 ++- drivers/s390/scsi/zfcp_fsf.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index c5f4bd217bf..ae151390cb9 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -50,7 +50,8 @@ static int zfcp_wka_port_get(struct zfcp_wka_port *wka_port) if (mutex_lock_interruptible(&wka_port->mutex)) return -ERESTARTSYS; - if (wka_port->status != ZFCP_WKA_PORT_ONLINE) { + if (wka_port->status == ZFCP_WKA_PORT_OFFLINE || + wka_port->status == ZFCP_WKA_PORT_CLOSING) { wka_port->status = ZFCP_WKA_PORT_OPENING; if (zfcp_fsf_open_wka_port(wka_port)) wka_port->status = ZFCP_WKA_PORT_OFFLINE; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index d024442ee12..48bfd304924 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -1584,6 +1584,7 @@ static void zfcp_fsf_open_wka_port_handler(struct zfcp_fsf_req *req) wka_port->status = ZFCP_WKA_PORT_OFFLINE; break; case FSF_PORT_ALREADY_OPEN: + break; case FSF_GOOD: wka_port->handle = header->port_handle; wka_port->status = ZFCP_WKA_PORT_ONLINE; -- cgit v1.2.3 From 633528c304f20b5c2e3e04d48f620548ce08b12e Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Wed, 26 Nov 2008 18:07:37 +0100 Subject: [SCSI] zfcp: returning an ERR_PTR where a NULL value is expected Aborting a SCSI cmnd might requrie to send a abort_fsf_cmnd. If the creation of this fsf_req fails an ERR_PTR is returned where a NULL value would be expected as an error indicator. This ERR_PTR is dereferenced as valid fsf_req in succeeding processing leading to an error. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 48bfd304924..0343d881bab 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -930,8 +930,10 @@ struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(unsigned long old_req_id, goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND, req_flags, adapter->pool.fsf_req_abort); - if (IS_ERR(req)) + if (IS_ERR(req)) { + req = NULL; goto out; + } if (unlikely(!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_UNBLOCKED))) @@ -2443,8 +2445,10 @@ struct zfcp_fsf_req *zfcp_fsf_send_fcp_ctm(struct zfcp_adapter *adapter, goto out; req = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, adapter->pool.fsf_req_scsi); - if (IS_ERR(req)) + if (IS_ERR(req)) { + req = NULL; goto out; + } req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT; req->data = unit; -- cgit v1.2.3 From 26871c97d52e50dc574bd01967926650643b142a Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Wed, 26 Nov 2008 18:07:38 +0100 Subject: [SCSI] zfcp: verify for correct rport state before scanning for SCSI devs Prevent a SCSI target scan for a rport which have turned invalid in the meantime. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_erp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 35364f64da7..c55dd2728f9 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -1186,7 +1186,9 @@ static void zfcp_erp_scsi_scan(struct work_struct *work) container_of(work, struct zfcp_erp_add_work, work); struct zfcp_unit *unit = p->unit; struct fc_rport *rport = unit->port->rport; - scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, + + if (rport && rport->port_state == FC_PORTSTATE_ONLINE) + scsi_scan_target(&rport->dev, 0, rport->scsi_target_id, scsilun_to_int((struct scsi_lun *)&unit->fcp_lun), 0); atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status); zfcp_unit_put(unit); -- cgit v1.2.3 From 0ac55aa90f2c3bd08e57e52a513b82b18ce0a5bc Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Wed, 26 Nov 2008 18:07:39 +0100 Subject: [SCSI] zfcp: eliminate race between validation and locking The check of having a valid pointer was performed before the processing was secured by the lock. Between those two steps the pointer can turn invalid. During further processing another value is used (referenced by the pointer described above) as a function pointer which is never verified to be valid either, resulting under some circumstances in an invalid function call. This patch is fixing both issues. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 0343d881bab..dc036769040 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -2116,18 +2116,21 @@ static inline void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req) static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req) { - struct scsi_cmnd *scpnt = req->data; + struct scsi_cmnd *scpnt; struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *) &(req->qtcb->bottom.io.fcp_rsp); u32 sns_len; char *fcp_rsp_info = (unsigned char *) &fcp_rsp_iu[1]; unsigned long flags; - if (unlikely(!scpnt)) - return; - read_lock_irqsave(&req->adapter->abort_lock, flags); + scpnt = req->data; + if (unlikely(!scpnt)) { + read_unlock_irqrestore(&req->adapter->abort_lock, flags); + return; + } + if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ABORTED)) { set_host_byte(scpnt, DID_SOFT_ERROR); set_driver_byte(scpnt, SUGGEST_RETRY); -- cgit v1.2.3 From fca55b6fb587e42c7761ee30bd1a6c313a9270c9 Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Wed, 26 Nov 2008 18:07:40 +0100 Subject: [SCSI] zfcp: fix deadlock between wq triggered port scan and ERP Waiting for the ERP to be finished in a task running in the global kernel work-queue is a bad idea, especially if the ERP needs to run another job in this work-queue before it can finish. -> deadlock. This patch removes the necessity to wait for a finished ERP from the scan task and moves the job scheduling to the end of the ERP. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_erp.c | 3 ++- drivers/s390/scsi/zfcp_fc.c | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index c55dd2728f9..c557ba34e1a 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -720,7 +720,6 @@ static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *act, goto failed_openfcp; atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &act->adapter->status); - schedule_work(&act->adapter->scan_work); return ZFCP_ERP_SUCCEEDED; @@ -1284,6 +1283,8 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) case ZFCP_ERP_ACTION_REOPEN_ADAPTER: if (result != ZFCP_ERP_SUCCEEDED) zfcp_erp_rports_del(adapter); + else + schedule_work(&adapter->scan_work); zfcp_adapter_put(adapter); break; } diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index ae151390cb9..8aab3091a7b 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -610,7 +610,6 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter) int ret, i; struct zfcp_gpn_ft *gpn_ft; - zfcp_erp_wait(adapter); /* wait until adapter is finished with ERP */ if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT) return 0; -- cgit v1.2.3 From f7a65e92e4bef3ccf9e008ed8cd52d914b6a4adb Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Thu, 27 Nov 2008 11:44:07 +0100 Subject: [SCSI] zfcp: prevent double decrement on host_busy while being busy The zfcp_scsi_queuecommand was not acting according to the standard when the respective unit was not available. In this case an -EBUSY was returned, which is not valid in itself, and in addition scsi_done was called. This combination is not allowed and was leading to a double finish of the request and therefor double decrement of the host_busy counter. Signed-off-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index e46fd3e9f68..468c880f8b6 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -88,7 +88,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, ret = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, 0, ZFCP_REQ_AUTO_CLEANUP); if (unlikely(ret == -EBUSY)) - zfcp_scsi_command_fail(scpnt, DID_NO_CONNECT); + return SCSI_MLQUEUE_DEVICE_BUSY; else if (unlikely(ret < 0)) return SCSI_MLQUEUE_HOST_BUSY; -- cgit v1.2.3 From 296fa7f6a3f3342d40df7713e74246198295654b Mon Sep 17 00:00:00 2001 From: Will Newton Date: Mon, 1 Dec 2008 11:36:06 +0000 Subject: drivers/char/tty_io.c: Avoid panic when no console is configured. When no console is configured tty_open tries to call kref_get on a NULL pointer, return ENODEV instead. Signed-off-by: Will Newton Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 59f472143f0..1412a8d1e58 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1795,12 +1795,15 @@ retry_open: } #endif if (device == MKDEV(TTYAUX_MAJOR, 1)) { - driver = tty_driver_kref_get(console_device(&index)); - if (driver) { - /* Don't let /dev/console block */ - filp->f_flags |= O_NONBLOCK; - noctty = 1; - goto got_driver; + struct tty_driver *console_driver = console_device(&index); + if (console_driver) { + driver = tty_driver_kref_get(console_driver); + if (driver) { + /* Don't let /dev/console block */ + filp->f_flags |= O_NONBLOCK; + noctty = 1; + goto got_driver; + } } mutex_unlock(&tty_mutex); return -ENODEV; -- cgit v1.2.3 From e5404586a499f7dce915456e85ff94b2df7a3b1c Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Mon, 1 Dec 2008 11:36:16 +0000 Subject: Add kref to fake tty used by USB console We alloc a fake tty in usb serial console setup function. we should init the tty's kref otherwise we will face WARN_ON after following invoke of tty_port_tty_set --> tty_kref_get. Signed-off-by: Kevin Hao Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/usb/serial/console.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 5b20de130e0..5b95009d2fb 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -135,6 +135,7 @@ static int usb_console_setup(struct console *co, char *options) err("no more memory"); goto reset_open_count; } + kref_init(&tty->kref); termios = kzalloc(sizeof(*termios), GFP_KERNEL); if (!termios) { retval = -ENOMEM; -- cgit v1.2.3 From 8fbd64e2eeb81d4b94be935a15d6d4829ec62aa2 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 30 Nov 2008 10:15:37 -0600 Subject: [SCSI] aacraid: switch to block timeout aacraid updates the timeout in its slave configure routine if it is too small. This now needs to update the request queue timeout in block. Cc: AACRAID list Signed-off-by: James Bottomley --- drivers/scsi/aacraid/linit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 9aa301c1ed0..162cd927d94 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -427,8 +427,8 @@ static int aac_slave_configure(struct scsi_device *sdev) * Firmware has an individual device recovery time typically * of 35 seconds, give us a margin. */ - if (sdev->timeout < (45 * HZ)) - sdev->timeout = 45 * HZ; + if (sdev->request_queue->rq_timeout < (45 * HZ)) + blk_queue_rq_timeout(sdev->request_queue, 45*HZ); for (cid = 0; cid < aac->maximum_num_containers; ++cid) if (aac->fsa_dev[cid].valid) ++num_lsu; -- cgit v1.2.3 From 97b5648a8bc2aef980645ee39d31bba0933a6112 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 30 Nov 2008 10:20:37 -0600 Subject: [SCSI] ibmvscsi: switch to block timeout ibmvscsi sets the timeout in its slave configure routine for disk devices. This now needs to update the request queue timeout in block. Cc: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 87e09f35d3d..6cad1758243 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1442,7 +1442,7 @@ static int ibmvscsi_slave_configure(struct scsi_device *sdev) spin_lock_irqsave(shost->host_lock, lock_flags); if (sdev->type == TYPE_DISK) { sdev->allow_restart = 1; - sdev->timeout = 60 * HZ; + blk_queue_rq_timeout(sdev->request_queue, 60 * HZ); } scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun); spin_unlock_irqrestore(shost->host_lock, lock_flags); -- cgit v1.2.3 From ee1ab9e945803a607ba5c2a96b69e4820a806552 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 30 Nov 2008 10:27:51 -0600 Subject: [SCSI] megaraid_sas: switch to block timeout megaraid_sas sets the timeout in its slave configure routine for devices on special channels. This now needs to update the request queue timeout in block. Cc: "Yang, Bo" Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index a454f94623d..17ce7abe17e 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -1016,7 +1016,8 @@ static int megasas_slave_configure(struct scsi_device *sdev) * The RAID firmware may require extended timeouts. */ if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS) - sdev->timeout = MEGASAS_DEFAULT_CMD_TIMEOUT * HZ; + blk_queue_rq_timeout(sdev->request_queue, + MEGASAS_DEFAULT_CMD_TIMEOUT * HZ); return 0; } -- cgit v1.2.3 From 9728c0814ecb505546696a659858fdb761375544 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 30 Nov 2008 10:32:26 -0600 Subject: [SCSI] make scsi_eh_try_stu use block timeout scsi_eh_try_stu() was still using the timeout parameter in the device which is now not set (i.e. zero filled) meaning that it waited no time at all for the start unit command to complete (leading the routine to conclude failure every time). This lead to a 2.6.27 regression: http://bugzilla.kernel.org/show_bug.cgi?id=12120 Where firewire devices that were non spec compliant wouldn't spin up. Fix this by using the block queue timeout value instead. Reported-by: Stefan Richter Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 386361778eb..edfaf241c5b 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -932,8 +932,7 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd) int i, rtn = NEEDS_RETRY; for (i = 0; rtn == NEEDS_RETRY && i < 2; i++) - rtn = scsi_send_eh_cmnd(scmd, stu_command, 6, - scmd->device->timeout, 0); + rtn = scsi_send_eh_cmnd(scmd, stu_command, 6, scmd->device->request_queue->rq_timeout, 0); if (rtn == SUCCESS) return 0; -- cgit v1.2.3 From dc5c49bff34e5b5a4334560dc7f7dfeae91d8962 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 30 Nov 2008 10:38:08 -0600 Subject: [SCSI] stex: switch to block timeout stex sets the timeout in its slave configure routine for all devices. This now needs to update the request queue timeout in block. Cc: Ed Lin Signed-off-by: James Bottomley --- drivers/scsi/stex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 3790906a77d..2fa830c0be2 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -477,7 +477,7 @@ stex_slave_config(struct scsi_device *sdev) { sdev->use_10_for_rw = 1; sdev->use_10_for_ms = 1; - sdev->timeout = 60 * HZ; + blk_queue_rq_timeout(sdev->request_queue, 60 * HZ); sdev->tagged_supported = 1; return 0; -- cgit v1.2.3 From 020f97063dd68a8e3b9aac928ac49a438b7416ce Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 1 Dec 2008 17:40:54 +0000 Subject: [ARM] omap: fix a pile of issues This patch fixes a number of sillies, from missing 'const' to using 'return' in void functions, to functions with no arguments not even 'void' and a cast which isn't required. Acked-by: Tony Lindgren Signed-off-by: Russell King --- drivers/video/omap/omapfb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index 5a5e407dc45..1a49519dafa 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c @@ -392,7 +392,7 @@ static void set_fb_fix(struct fb_info *fbi) int bpp; rg = &plane->fbdev->mem_desc.region[plane->idx]; - fbi->screen_base = (char __iomem *)rg->vaddr; + fbi->screen_base = rg->vaddr; fix->smem_start = rg->paddr; fix->smem_len = rg->size; -- cgit v1.2.3 From 6b1f9d647e848060d34c3db408413989f1e460ba Mon Sep 17 00:00:00 2001 From: Joachim Fenkes Date: Mon, 1 Dec 2008 10:05:44 -0800 Subject: IB/ehca: Change misleading error message on memory hotplug The error message printed when the eHCA driver prevents memory hotplug is misleading -- the user might think that hot-removing the lhca, hotplugging memory, then hot-adding the lhca again will work, but it actually doesn't. Signed-off-by: Joachim Fenkes Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ehca/ehca_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index bb02a86aa52..bec7e024935 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c @@ -994,8 +994,7 @@ static int ehca_mem_notifier(struct notifier_block *nb, if (printk_timed_ratelimit(&ehca_dmem_warn_time, 30 * 1000)) ehca_gen_err("DMEM operations are not allowed" - "as long as an ehca adapter is" - "attached to the LPAR"); + "in conjunction with eHCA"); return NOTIFY_BAD; } } -- cgit v1.2.3 From 7ec4f4634a4326c1f8fd172c80c8f59c9b3e90a4 Mon Sep 17 00:00:00 2001 From: Stefan Roscher Date: Mon, 1 Dec 2008 10:05:50 -0800 Subject: IB/ehca: Fix problem with generated flush work completions This fix enables ehca device driver to generate flush work completions even if the application doesn't request completions for all work requests. The current implementation of ehca will generate flush work completions for the wrong work requests if an application uses non signaled work completions. Signed-off-by: Stefan Roscher Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ehca/ehca_classes.h | 4 ++- drivers/infiniband/hw/ehca/ehca_qp.c | 26 ++++++++++++---- drivers/infiniband/hw/ehca/ehca_reqs.c | 51 ++++++++++++++++++------------- 3 files changed, 53 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 4df887af66a..7fc35cf0cdd 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h @@ -163,7 +163,8 @@ struct ehca_mod_qp_parm { /* struct for tracking if cqes have been reported to the application */ struct ehca_qmap_entry { u16 app_wr_id; - u16 reported; + u8 reported; + u8 cqe_req; }; struct ehca_queue_map { @@ -171,6 +172,7 @@ struct ehca_queue_map { unsigned int entries; unsigned int tail; unsigned int left_to_poll; + unsigned int next_wqe_idx; /* Idx to first wqe to be flushed */ }; struct ehca_qp { diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index 9e05ee2db39..cadbf0cdd91 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c @@ -435,9 +435,13 @@ static void reset_queue_map(struct ehca_queue_map *qmap) { int i; - qmap->tail = 0; - for (i = 0; i < qmap->entries; i++) + qmap->tail = qmap->entries - 1; + qmap->left_to_poll = 0; + qmap->next_wqe_idx = 0; + for (i = 0; i < qmap->entries; i++) { qmap->map[i].reported = 1; + qmap->map[i].cqe_req = 0; + } } /* @@ -1121,6 +1125,7 @@ static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue, void *wqe_v; u64 q_ofs; u32 wqe_idx; + unsigned int tail_idx; /* convert real to abs address */ wqe_p = wqe_p & (~(1UL << 63)); @@ -1133,12 +1138,17 @@ static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue, return -EFAULT; } + tail_idx = (qmap->tail + 1) % qmap->entries; wqe_idx = q_ofs / ipz_queue->qe_size; - if (wqe_idx < qmap->tail) - qmap->left_to_poll = (qmap->entries - qmap->tail) + wqe_idx; - else - qmap->left_to_poll = wqe_idx - qmap->tail; + /* check all processed wqes, whether a cqe is requested or not */ + while (tail_idx != wqe_idx) { + if (qmap->map[tail_idx].cqe_req) + qmap->left_to_poll++; + tail_idx = (tail_idx + 1) % qmap->entries; + } + /* save index in queue, where we have to start flushing */ + qmap->next_wqe_idx = wqe_idx; return 0; } @@ -1185,10 +1195,14 @@ static int check_for_left_cqes(struct ehca_qp *my_qp, struct ehca_shca *shca) } else { spin_lock_irqsave(&my_qp->send_cq->spinlock, flags); my_qp->sq_map.left_to_poll = 0; + my_qp->sq_map.next_wqe_idx = (my_qp->sq_map.tail + 1) % + my_qp->sq_map.entries; spin_unlock_irqrestore(&my_qp->send_cq->spinlock, flags); spin_lock_irqsave(&my_qp->recv_cq->spinlock, flags); my_qp->rq_map.left_to_poll = 0; + my_qp->rq_map.next_wqe_idx = (my_qp->rq_map.tail + 1) % + my_qp->rq_map.entries; spin_unlock_irqrestore(&my_qp->recv_cq->spinlock, flags); } diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c index 64928079eaf..00a648f4316 100644 --- a/drivers/infiniband/hw/ehca/ehca_reqs.c +++ b/drivers/infiniband/hw/ehca/ehca_reqs.c @@ -179,6 +179,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp, qmap_entry->app_wr_id = get_app_wr_id(send_wr->wr_id); qmap_entry->reported = 0; + qmap_entry->cqe_req = 0; switch (send_wr->opcode) { case IB_WR_SEND: @@ -203,8 +204,10 @@ static inline int ehca_write_swqe(struct ehca_qp *qp, if ((send_wr->send_flags & IB_SEND_SIGNALED || qp->init_attr.sq_sig_type == IB_SIGNAL_ALL_WR) - && !hidden) + && !hidden) { wqe_p->wr_flag |= WQE_WRFLAG_REQ_SIGNAL_COM; + qmap_entry->cqe_req = 1; + } if (send_wr->opcode == IB_WR_SEND_WITH_IMM || send_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) { @@ -569,6 +572,7 @@ static int internal_post_recv(struct ehca_qp *my_qp, qmap_entry = &my_qp->rq_map.map[rq_map_idx]; qmap_entry->app_wr_id = get_app_wr_id(cur_recv_wr->wr_id); qmap_entry->reported = 0; + qmap_entry->cqe_req = 1; wqe_cnt++; } /* eof for cur_recv_wr */ @@ -706,27 +710,34 @@ repoll: goto repoll; wc->qp = &my_qp->ib_qp; + qmap_tail_idx = get_app_wr_id(cqe->work_request_id); + if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT)) + /* We got a send completion. */ + qmap = &my_qp->sq_map; + else + /* We got a receive completion. */ + qmap = &my_qp->rq_map; + + /* advance the tail pointer */ + qmap->tail = qmap_tail_idx; + if (is_error) { /* * set left_to_poll to 0 because in error state, we will not * get any additional CQEs */ - ehca_add_to_err_list(my_qp, 1); + my_qp->sq_map.next_wqe_idx = (my_qp->sq_map.tail + 1) % + my_qp->sq_map.entries; my_qp->sq_map.left_to_poll = 0; + ehca_add_to_err_list(my_qp, 1); + my_qp->rq_map.next_wqe_idx = (my_qp->rq_map.tail + 1) % + my_qp->rq_map.entries; + my_qp->rq_map.left_to_poll = 0; if (HAS_RQ(my_qp)) ehca_add_to_err_list(my_qp, 0); - my_qp->rq_map.left_to_poll = 0; } - qmap_tail_idx = get_app_wr_id(cqe->work_request_id); - if (!(cqe->w_completion_flags & WC_SEND_RECEIVE_BIT)) - /* We got a send completion. */ - qmap = &my_qp->sq_map; - else - /* We got a receive completion. */ - qmap = &my_qp->rq_map; - qmap_entry = &qmap->map[qmap_tail_idx]; if (qmap_entry->reported) { ehca_warn(cq->device, "Double cqe on qp_num=%#x", @@ -738,10 +749,6 @@ repoll: wc->wr_id = replace_wr_id(cqe->work_request_id, qmap_entry->app_wr_id); qmap_entry->reported = 1; - /* this is a proper completion, we need to advance the tail pointer */ - if (++qmap->tail == qmap->entries) - qmap->tail = 0; - /* if left_to_poll is decremented to 0, add the QP to the error list */ if (qmap->left_to_poll > 0) { qmap->left_to_poll--; @@ -805,13 +812,14 @@ static int generate_flush_cqes(struct ehca_qp *my_qp, struct ib_cq *cq, else qmap = &my_qp->rq_map; - qmap_entry = &qmap->map[qmap->tail]; + qmap_entry = &qmap->map[qmap->next_wqe_idx]; while ((nr < num_entries) && (qmap_entry->reported == 0)) { /* generate flush CQE */ + memset(wc, 0, sizeof(*wc)); - offset = qmap->tail * ipz_queue->qe_size; + offset = qmap->next_wqe_idx * ipz_queue->qe_size; wqe = (struct ehca_wqe *)ipz_qeit_calc(ipz_queue, offset); if (!wqe) { ehca_err(cq->device, "Invalid wqe offset=%#lx on " @@ -850,11 +858,12 @@ static int generate_flush_cqes(struct ehca_qp *my_qp, struct ib_cq *cq, wc->qp = &my_qp->ib_qp; - /* mark as reported and advance tail pointer */ + /* mark as reported and advance next_wqe pointer */ qmap_entry->reported = 1; - if (++qmap->tail == qmap->entries) - qmap->tail = 0; - qmap_entry = &qmap->map[qmap->tail]; + qmap->next_wqe_idx++; + if (qmap->next_wqe_idx == qmap->entries) + qmap->next_wqe_idx = 0; + qmap_entry = &qmap->map[qmap->next_wqe_idx]; wc++; nr++; } -- cgit v1.2.3 From 42ab01c31526ac1d06d193f81a498bf3cf2acfe4 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Mon, 1 Dec 2008 10:09:37 -0800 Subject: IB/mlx4: Fix MTT leakage in resize CQ When resizing a CQ, MTTs associated with the old CQE buffer were not freed. As a result, if any app used resize CQ repeatedly, all MTTs were eventually exhausted, which led to all memory registration operations failing until the driver is reloaded. Once the RESIZE_CQ command returns successfully from FW, FW no longer accesses the old CQ buffer, so it is safe to deallocate the MTT entries used by the old CQ buffer. Finally, if the RESIZE_CQ command fails, the MTTs allocated for the new CQEs buffer also need to be de-allocated. This fixes . Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx4/cq.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c index d0866a3636e..18308494a19 100644 --- a/drivers/infiniband/hw/mlx4/cq.c +++ b/drivers/infiniband/hw/mlx4/cq.c @@ -343,6 +343,7 @@ int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata) { struct mlx4_ib_dev *dev = to_mdev(ibcq->device); struct mlx4_ib_cq *cq = to_mcq(ibcq); + struct mlx4_mtt mtt; int outst_cqe; int err; @@ -376,10 +377,13 @@ int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata) goto out; } + mtt = cq->buf.mtt; + err = mlx4_cq_resize(dev->dev, &cq->mcq, entries, &cq->resize_buf->buf.mtt); if (err) goto err_buf; + mlx4_mtt_cleanup(dev->dev, &mtt); if (ibcq->uobject) { cq->buf = cq->resize_buf->buf; cq->ibcq.cqe = cq->resize_buf->cqe; @@ -406,6 +410,7 @@ int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata) goto out; err_buf: + mlx4_mtt_cleanup(dev->dev, &cq->resize_buf->buf.mtt); if (!ibcq->uobject) mlx4_ib_free_cq_buf(dev, &cq->resize_buf->buf, cq->resize_buf->cqe); -- cgit v1.2.3 From 1eedb4a90c958d8d59e0e4f19c297b445df21cf9 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 29 Nov 2008 22:37:21 +0900 Subject: ata_piix: add borked Tecra M4 to broken suspend list Tecra M4 sometimes forget what it is and reports bogus data via DMI which makes the machine evade broken suspend matching and thus fail suspend/resume. This patch updates piix_broken_suspend() such that it can match such case. As the borked DMI data is a bit generic, matching many entries to make the match more specific is necessary. As the usual DMI matching is limited to four entries, this patch uses hard coded manual matching. This is reported by Alexandru Romanescu. Signed-off-by: Tejun Heo Cc: Alexandru Romanescu Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 8e37be19bbf..d6d97d8f3fa 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -1066,6 +1066,21 @@ static int piix_broken_suspend(void) if (dmi_find_device(DMI_DEV_TYPE_OEM_STRING, oemstrs[i], NULL)) return 1; + /* TECRA M4 sometimes forgets its identify and reports bogus + * DMI information. As the bogus information is a bit + * generic, match as many entries as possible. This manual + * matching is necessary because dmi_system_id.matches is + * limited to four entries. + */ + if (!strcmp(dmi_get_system_info(DMI_SYS_VENDOR), "TOSHIBA") && + !strcmp(dmi_get_system_info(DMI_PRODUCT_NAME), "000000") && + !strcmp(dmi_get_system_info(DMI_PRODUCT_VERSION), "000000") && + !strcmp(dmi_get_system_info(DMI_PRODUCT_SERIAL), "000000") && + !strcmp(dmi_get_system_info(DMI_BOARD_VENDOR), "TOSHIBA") && + !strcmp(dmi_get_system_info(DMI_BOARD_NAME), "Portable PC") && + !strcmp(dmi_get_system_info(DMI_BOARD_VERSION), "Version A0")) + return 1; + return 0; } -- cgit v1.2.3 From 9f14786e27908a176f0568cf2132558efef71b31 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Fri, 28 Nov 2008 20:48:26 +0100 Subject: [libata] pata_rb532_cf: fix and rename register definitions The original standalone driver uses a custom address for the error register. Use it in pata_rb532_cf, too. Rename two register definitions: - The address offset 0x0800 in fact is the ATA base, not ATA command address. - The offset 0x0C00 is not a regular ATA data address, but a buffered one allowing 4-byte IO. Signed-off-by: Phil Sutter Signed-off-by: Jeff Garzik --- drivers/ata/pata_rb532_cf.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index f8b3ffc8ae9..392116c1c16 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -39,9 +39,11 @@ #define RB500_CF_MAXPORTS 1 #define RB500_CF_IO_DELAY 400 -#define RB500_CF_REG_CMD 0x0800 +#define RB500_CF_REG_BASE 0x0800 +#define RB500_CF_REG_ERR 0x080D #define RB500_CF_REG_CTRL 0x080E -#define RB500_CF_REG_DATA 0x0C00 +/* 32bit buffered data register offset */ +#define RB500_CF_REG_DBUF32 0x0C00 struct rb532_cf_info { void __iomem *iobase; @@ -146,13 +148,14 @@ static void rb532_pata_setup_ports(struct ata_host *ah) 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.cmd_addr = info->iobase + RB500_CF_REG_BASE; ap->ioaddr.ctl_addr = info->iobase + RB500_CF_REG_CTRL; ap->ioaddr.altstatus_addr = info->iobase + RB500_CF_REG_CTRL; ata_sff_std_ports(&ap->ioaddr); - ap->ioaddr.data_addr = info->iobase + RB500_CF_REG_DATA; + ap->ioaddr.data_addr = info->iobase + RB500_CF_REG_DBUF32; + ap->ioaddr.error_addr = info->iobase + RB500_CF_REG_ERR; } static __devinit int rb532_pata_driver_probe(struct platform_device *pdev) -- cgit v1.2.3 From 03f60840fa462e92220b093f778b2426ceab23af Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Fri, 28 Nov 2008 20:48:35 +0100 Subject: [libata] pata_rb532_cf: fix signature of the xfer function Per definition, this function should return the number of bytes consumed. As the original parameter "buflen" is being decremented inside the read/write loop, save it in "retlen" at the beginning. Signed-off-by: Phil Sutter Acked-by: Sergei Shtyltov Acked-by: Bartlomiej Zolnierkiewicz Acked-by: Florian Fainelli Signed-off-by: Jeff Garzik --- drivers/ata/pata_rb532_cf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index 392116c1c16..c2e6fb9f2ef 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -74,11 +74,12 @@ static void rb532_pata_exec_command(struct ata_port *ap, rb532_pata_finish_io(ap); } -static void rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf, +static unsigned int rb532_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; + int retlen = buflen; if (write_data) { for (; buflen > 0; buflen--, buf++) @@ -89,6 +90,7 @@ static void rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf, } rb532_pata_finish_io(adev->link->ap); + return retlen; } static void rb532_pata_freeze(struct ata_port *ap) -- cgit v1.2.3 From ac70a964b0e22a95af3628c344815857a01461b7 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 27 Nov 2008 13:36:48 +0900 Subject: libata: blacklist Seagate drives which time out FLUSH_CACHE when used with NCQ Some recent Seagate harddrives have firmware bug which causes FLUSH CACHE to timeout under certain circumstances if NCQ is being used. This can be worked around by disabling NCQ and fixed by updating the firmware. Implement ATA_HORKAGE_FIRMWARE_UPDATE and blacklist these devices. The wiki page has been updated to contain information on this issue. http://ata.wiki.kernel.org/index.php/Known_issues Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 4214bfb13bb..5e2eb740df4 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2492,6 +2492,13 @@ int ata_dev_configure(struct ata_device *dev) } } + if ((dev->horkage & ATA_HORKAGE_FIRMWARE_WARN) && print_info) { + ata_dev_printk(dev, KERN_WARNING, "WARNING: device requires " + "firmware update to be fully functional.\n"); + ata_dev_printk(dev, KERN_WARNING, " contact the vendor " + "or visit http://ata.wiki.kernel.org.\n"); + } + return 0; err_out_nosup: @@ -4042,6 +4049,20 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "ST380817AS", "3.42", ATA_HORKAGE_NONCQ }, { "ST3160023AS", "3.42", ATA_HORKAGE_NONCQ }, + /* Seagate NCQ + FLUSH CACHE firmware bug */ + { "ST31500341AS", "9JU138", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST31000333AS", "9FZ136", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3640623AS", "9FZ164", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3640323AS", "9FZ134", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3320813AS", "9FZ182", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3320613AS", "9FZ162", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + /* Blacklist entries taken from Silicon Image 3124/3132 Windows driver .inf file - also several Linux problem reports */ { "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, }, -- cgit v1.2.3 From faa3bd2e48e594e9475e92fb84bb6ebe6f62f23b Mon Sep 17 00:00:00 2001 From: Douglas Schilling Landgraf Date: Mon, 24 Nov 2008 09:51:20 -0300 Subject: V4L/DVB (9743): em28xx: fix oops audio Replaced usb_kill_usb for usb_unlink_usb (wait until urb to fully stop require USB core to put the calling process to sleep). Oops: http://www.kerneloops.org/raw.php?rawid=71799&msgid= Signed-off-by: Douglas Schilling Landgraf Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index dfac2e042a5..90236bbfe66 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -62,7 +62,7 @@ static int em28xx_isoc_audio_deinit(struct em28xx *dev) dprintk("Stopping isoc\n"); for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { - usb_kill_urb(dev->adev->urb[i]); + usb_unlink_urb(dev->adev->urb[i]); usb_free_urb(dev->adev->urb[i]); dev->adev->urb[i] = NULL; } -- cgit v1.2.3 From 484ab62c5ee805c2bdc405a85a4e64da2722690f Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 24 Nov 2008 09:53:22 -0300 Subject: V4L/DVB (9748): em28xx: fix compile warning Label fail_unreg is no longer used. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 90a11b5ac0b..610f535a257 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -2105,8 +2105,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, return 0; -fail_unreg: - em28xx_release_resources(dev); fail_reg_devices: mutex_unlock(&dev->lock); return retval; -- cgit v1.2.3 From a693b0cdba94f60f7ed43754d2c34151cdd11da5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 1 Dec 2008 18:04:14 -0200 Subject: em28xx: remove backward compat macro added on a previous fix commit 50f3beb50abe0cc0228363af804e50e710b3e5b0 fixed em28xx-alsa locking schema. However, a backport macro was kept. This patch removes the macro, since it is not needed for the module compilation against upstream. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-audio.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 90236bbfe66..7a8d49ef646 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -75,9 +75,6 @@ static void em28xx_audio_isocirq(struct urb *urb) struct em28xx *dev = urb->context; int i; unsigned int oldptr; -#ifdef NO_PCM_LOCK - unsigned long flags; -#endif int period_elapsed = 0; int status; unsigned char *cp; @@ -98,9 +95,6 @@ static void em28xx_audio_isocirq(struct urb *urb) if (!length) continue; -#ifdef NO_PCM_LOCK - spin_lock_irqsave(&dev->adev->slock, flags); -#endif oldptr = dev->adev->hwptr_done_capture; if (oldptr + length >= runtime->buffer_size) { unsigned int cnt = @@ -114,9 +108,7 @@ static void em28xx_audio_isocirq(struct urb *urb) length * stride); } -#ifndef NO_PCM_LOCK snd_pcm_stream_lock(substream); -#endif dev->adev->hwptr_done_capture += length; if (dev->adev->hwptr_done_capture >= @@ -132,11 +124,7 @@ static void em28xx_audio_isocirq(struct urb *urb) period_elapsed = 1; } -#ifdef NO_PCM_LOCK - spin_unlock_irqrestore(&dev->adev->slock, flags); -#else snd_pcm_stream_unlock(substream); -#endif } if (period_elapsed) snd_pcm_period_elapsed(substream); -- cgit v1.2.3 From 36be47d6d8d98f54b6c4f891e9f54fb2bf554584 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 1 Dec 2008 13:13:49 -0800 Subject: parport_serial: fix array overflow The netmos_9xx5_combo type assumes that PCI SSID provides always the correct value for the number of parallel and serial ports, but there are indeed broken devices with wrong numbers, which may result in Oops. This patch simply adds the check of the array range. Reference: Novell bnc#447067 https://bugzilla.novell.com/show_bug.cgi?id=447067 Signed-off-by: Takashi Iwai Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/parport/parport_serial.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c index e2e95b36a60..101ed49a2d1 100644 --- a/drivers/parport/parport_serial.c +++ b/drivers/parport/parport_serial.c @@ -70,6 +70,8 @@ static int __devinit netmos_parallel_init(struct pci_dev *dev, struct parport_pc * parallel ports and is the number of serial ports. */ card->numports = (dev->subsystem_device & 0xf0) >> 4; + if (card->numports > ARRAY_SIZE(card->addr)) + card->numports = ARRAY_SIZE(card->addr); return 0; } -- cgit v1.2.3 From dc924efb52ba9e4dffec5b15ae2242b894198139 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Mon, 1 Dec 2008 13:13:49 -0800 Subject: hwmon: applesmc: make applesmc load automatically on startup make use of the new dmi device loading support to automatically load the applesmc driver based on the dmi_match table. Signed-off-by: Henrik Rydberg Cc: Nicolas Boichat Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/applesmc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index f7dce8b9f64..086c2a5cef0 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -1564,3 +1564,4 @@ module_exit(applesmc_exit); MODULE_AUTHOR("Nicolas Boichat"); MODULE_DESCRIPTION("Apple SMC"); MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(dmi, applesmc_whitelist); -- cgit v1.2.3 From aaacf4bb51b243875b203e6ff73b5047636b4efa Mon Sep 17 00:00:00 2001 From: Wolfgang Ocker Date: Mon, 1 Dec 2008 13:13:52 -0800 Subject: spi: avoid spidev crash when device is removed I saw a kernel oops in spidev_remove() when a spidev device was registered and I unloaded the SPI master driver: Unable to handle kernel paging request for data at address 0x00000004 Faulting instruction address: 0xc01c0c50 Oops: Kernel access of bad area, sig: 11 [#1] CDSPR Modules linked in: spi_ppc4xx(-) NIP: c01c0c50 LR: c01bf9e4 CTR: c01c0c34 REGS: cec89c30 TRAP: 0300 Not tainted (2.6.27.3izt) MSR: 00021000 CR: 24000228 XER: 20000007 DEAR: 00000004, ESR: 00800000 TASK = cf889040[2070] 'rmmod' THREAD: cec88000 GPR00: 00000000 cec89ce0 cf889040 cec8e000 00000004 cec8e000 ffffffff 00000000 GPR08: 0000001c c0336380 00000000 c01c0c34 00000001 1001a338 100e0000 100df49c GPR16: 100b54c0 100df49c 100ddd20 100f05a8 100b5340 100efd68 00000000 00000000 GPR24: 100ec008 100f0428 c0327788 c0327794 cec8e0ac cec8e000 c0336380 00000000 NIP [c01c0c50] spidev_remove+0x1c/0xe4 LR [c01bf9e4] spi_drv_remove+0x2c/0x3c Call Trace: [cec89d00] [c01bf9e4] spi_drv_remove+0x2c/0x3c [cec89d10] [c01859a0] __device_release_driver+0x78/0xb4 [cec89d20] [c0185ab0] device_release_driver+0x28/0x44 [cec89d40] [c0184be8] bus_remove_device+0xac/0xd8 [cec89d60] [c0183094] device_del+0x100/0x194 [cec89d80] [c0183140] device_unregister+0x18/0x30 [cec89da0] [c01bf30c] __unregister+0x20/0x34 [cec89db0] [c0182778] device_for_each_child+0x38/0x74 [cec89de0] [c01bf2d0] spi_unregister_master+0x28/0x44 [cec89e00] [c01bfeac] spi_bitbang_stop+0x1c/0x58 [cec89e20] [d908a5e0] spi_ppc4xx_of_remove+0x24/0x7c [spi_ppc4xx] [...] IMHO a call to spi_set_drvdata() is missing in spidev_probe(). The patch below helped. Signed-off-by: Wolfgang Ocker Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/spidev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 89a43755a45..5d869c4d3eb 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -597,7 +597,9 @@ static int spidev_probe(struct spi_device *spi) } mutex_unlock(&device_list_lock); - if (status != 0) + if (status == 0) + spi_set_drvdata(spi, spidev); + else kfree(spidev); return status; -- cgit v1.2.3 From b7d271df873c5121a4ca1c70dea126b5920ec2f1 Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Mon, 1 Dec 2008 13:13:53 -0800 Subject: spi: mpc52xx_psc_spi chipselect bugfix According to the manual the "tdfOnExit" flag must be set on the last byte we want to send. The PSC controller holds SS low until the flag is set. However, the flag was set always on the last byte of the FIFO, independently if it is the last byte of the transfer. This generates spurious toggling of the SS signals that breaks the protocol of some peripherals. Fix. Signed-off-by: Stefano Babic Acked-by: Grant Likely Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/mpc52xx_psc_spi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c index 0debe11b67b..3b97803e1d1 100644 --- a/drivers/spi/mpc52xx_psc_spi.c +++ b/drivers/spi/mpc52xx_psc_spi.c @@ -142,6 +142,7 @@ static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi, unsigned rfalarm; unsigned send_at_once = MPC52xx_PSC_BUFSIZE; unsigned recv_at_once; + int last_block = 0; if (!t->tx_buf && !t->rx_buf && t->len) return -EINVAL; @@ -151,15 +152,17 @@ static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi, while (rb < t->len) { if (t->len - rb > MPC52xx_PSC_BUFSIZE) { rfalarm = MPC52xx_PSC_RFALARM; + last_block = 0; } else { send_at_once = t->len - sb; rfalarm = MPC52xx_PSC_BUFSIZE - (t->len - rb); + last_block = 1; } dev_dbg(&spi->dev, "send %d bytes...\n", send_at_once); for (; send_at_once; sb++, send_at_once--) { /* set EOF flag before the last word is sent */ - if (send_at_once == 1) + if (send_at_once == 1 && last_block) out_8(&psc->ircr2, 0x01); if (tx_buf) -- cgit v1.2.3 From 6a010b56e9bd2fdb32efd153e1a08305949b6b53 Mon Sep 17 00:00:00 2001 From: Julien Boibessot Date: Mon, 1 Dec 2008 13:13:55 -0800 Subject: spi: fix spi_imx probe oopsing Corrects spi_imx driver oops during initialization/probing: can't use drv_data before it's allocated. Signed-off-by: Julien Boibessot Acked-by: Sascha Hauer Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/spi_imx.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index 0b4db0ce78d..269a55ec52e 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c @@ -1456,7 +1456,7 @@ static int __init spi_imx_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct spi_imx_master *platform_info; struct spi_master *master; - struct driver_data *drv_data = NULL; + struct driver_data *drv_data; struct resource *res; int irq, status = 0; @@ -1467,14 +1467,6 @@ static int __init spi_imx_probe(struct platform_device *pdev) goto err_no_pdata; } - drv_data->clk = clk_get(&pdev->dev, "perclk2"); - if (IS_ERR(drv_data->clk)) { - dev_err(&pdev->dev, "probe - cannot get get\n"); - status = PTR_ERR(drv_data->clk); - goto err_no_clk; - } - clk_enable(drv_data->clk); - /* Allocate master with space for drv_data */ master = spi_alloc_master(dev, sizeof(struct driver_data)); if (!master) { @@ -1495,6 +1487,14 @@ static int __init spi_imx_probe(struct platform_device *pdev) drv_data->dummy_dma_buf = SPI_DUMMY_u32; + drv_data->clk = clk_get(&pdev->dev, "perclk2"); + if (IS_ERR(drv_data->clk)) { + dev_err(&pdev->dev, "probe - cannot get clock\n"); + status = PTR_ERR(drv_data->clk); + goto err_no_clk; + } + clk_enable(drv_data->clk); + /* Find and map resources */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -1630,12 +1630,13 @@ err_no_iomap: kfree(drv_data->ioarea); err_no_iores: - spi_master_put(master); - -err_no_pdata: clk_disable(drv_data->clk); clk_put(drv_data->clk); + err_no_clk: + spi_master_put(master); + +err_no_pdata: err_no_mem: return status; } -- cgit v1.2.3 From 4e253d23003b54c88d0919d6088be74f00eec3c7 Mon Sep 17 00:00:00 2001 From: Jan Nikitenko Date: Mon, 1 Dec 2008 13:13:56 -0800 Subject: spi: au1550_spi full duplex dma fix Fix unsafe order in dma mapping operation: always flush data from the cache *BEFORE* invalidating it, to allow full duplex transfers where the same buffer may be used for both writes and reads. Tested with mmc-spi. Signed-off-by: Jan Nikitenko Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/au1550_spi.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c index 87b73e0169c..b02f25c702f 100644 --- a/drivers/spi/au1550_spi.c +++ b/drivers/spi/au1550_spi.c @@ -369,10 +369,23 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t) dma_rx_addr = t->rx_dma; /* - * check if buffers are already dma mapped, map them otherwise + * check if buffers are already dma mapped, map them otherwise: + * - first map the TX buffer, so cache data gets written to memory + * - then map the RX buffer, so that cache entries (with + * soon-to-be-stale data) get removed * use rx buffer in place of tx if tx buffer was not provided * use temp rx buffer (preallocated or realloc to fit) for rx dma */ + if (t->tx_buf) { + if (t->tx_dma == 0) { /* if DMA_ADDR_INVALID, map it */ + dma_tx_addr = dma_map_single(hw->dev, + (void *)t->tx_buf, + t->len, DMA_TO_DEVICE); + if (dma_mapping_error(hw->dev, dma_tx_addr)) + dev_err(hw->dev, "tx dma map error\n"); + } + } + if (t->rx_buf) { if (t->rx_dma == 0) { /* if DMA_ADDR_INVALID, map it */ dma_rx_addr = dma_map_single(hw->dev, @@ -396,15 +409,8 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t) dma_sync_single_for_device(hw->dev, dma_rx_addr, t->len, DMA_FROM_DEVICE); } - if (t->tx_buf) { - if (t->tx_dma == 0) { /* if DMA_ADDR_INVALID, map it */ - dma_tx_addr = dma_map_single(hw->dev, - (void *)t->tx_buf, - t->len, DMA_TO_DEVICE); - if (dma_mapping_error(hw->dev, dma_tx_addr)) - dev_err(hw->dev, "tx dma map error\n"); - } - } else { + + if (!t->tx_buf) { dma_sync_single_for_device(hw->dev, dma_rx_addr, t->len, DMA_BIDIRECTIONAL); hw->tx = hw->rx; -- cgit v1.2.3 From e39ea8a2def1fcb203ed0183317124348962e351 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 1 Dec 2008 13:13:56 -0800 Subject: spi: fix spi_s3c24xx_gpio device handle lookup The spidev_to_sg() call in spi_s3c24xx_gpio.c was using the wrong method to convert the spi device into the private data for the driver. Fix this by using spi_master_get_devdata. Signed-off-by: Ben Dooks Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/spi_s3c24xx_gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c index cc1f647f579..8bb2b4ee3e5 100644 --- a/drivers/spi/spi_s3c24xx_gpio.c +++ b/drivers/spi/spi_s3c24xx_gpio.c @@ -34,7 +34,7 @@ struct s3c2410_spigpio { static inline struct s3c2410_spigpio *spidev_to_sg(struct spi_device *spi) { - return spi->controller_data; + return spi_master_get_devdata(spi->master); } static inline void setsck(struct spi_device *dev, int on) -- cgit v1.2.3 From b93c35ff39d19f20c47c06c206986afefecc777a Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 1 Dec 2008 13:13:57 -0800 Subject: spi: fix spi_s3c24xx_gpio num_chipselect The spi master driver must have num_chipselect set to allow the bus to initialise. Pass this through the platform data. Signed-off-by: Ben Dooks Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/spi_s3c24xx_gpio.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c index 8bb2b4ee3e5..f2447a5476b 100644 --- a/drivers/spi/spi_s3c24xx_gpio.c +++ b/drivers/spi/spi_s3c24xx_gpio.c @@ -118,6 +118,7 @@ static int s3c2410_spigpio_probe(struct platform_device *dev) /* setup spi bitbang adaptor */ sp->bitbang.master = spi_master_get(master); sp->bitbang.master->bus_num = info->bus_num; + sp->bitbang.master->num_chipselect = info->num_chipselect; sp->bitbang.chipselect = s3c2410_spigpio_chipselect; sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0; -- cgit v1.2.3 From c4c6fa9891f3d1bcaae4f39fb751d5302965b566 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 1 Dec 2008 13:13:58 -0800 Subject: radeonfb: fix problem with color expansion & alignment The engine on some radeon variants locks up if color expansion is called for non aligned source data. This patch enables a feature of the core fbdev to request aligned input pixmaps and uses the HW clipping engine to clip the output to the requested size Addresses http://bugzilla.kernel.org/show_bug.cgi?id=11875 Signed-off-by: Benjamin Herrenschmidt Tested-by: James Cloos Cc: "Rafael J. Wysocki" Cc: "David S. Miller" Cc: Krzysztof Helt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/aty/radeon_accel.c | 21 ++++++++++++--------- drivers/video/aty/radeon_base.c | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c index 8718f7349d6..a547e5d4c8b 100644 --- a/drivers/video/aty/radeon_accel.c +++ b/drivers/video/aty/radeon_accel.c @@ -174,12 +174,12 @@ static void radeonfb_prim_imageblit(struct radeonfb_info *rinfo, const struct fb_image *image, u32 fg, u32 bg) { - unsigned int src_bytes, dwords; + unsigned int dwords; u32 *bits; radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache, rinfo->dp_gui_mc_base | - GMC_BRUSH_NONE | + GMC_BRUSH_NONE | GMC_DST_CLIP_LEAVE | GMC_SRC_DATATYPE_MONO_FG_BG | ROP3_S | GMC_BYTE_ORDER_MSB_TO_LSB | @@ -189,9 +189,6 @@ static void radeonfb_prim_imageblit(struct radeonfb_info *rinfo, radeonfb_set_creg(rinfo, DP_SRC_FRGD_CLR, &rinfo->dp_src_fg_cache, fg); radeonfb_set_creg(rinfo, DP_SRC_BKGD_CLR, &rinfo->dp_src_bg_cache, bg); - radeon_fifo_wait(rinfo, 1); - OUTREG(DST_Y_X, (image->dy << 16) | image->dx); - /* Ensure the dst cache is flushed and the engine idle before * issuing the operation. * @@ -205,13 +202,19 @@ static void radeonfb_prim_imageblit(struct radeonfb_info *rinfo, /* X here pads width to a multiple of 32 and uses the clipper to * adjust the result. Is that really necessary ? Things seem to - * work ok for me without that and the doco doesn't seem to imply + * work ok for me without that and the doco doesn't seem to imply] * there is such a restriction. */ - OUTREG(DST_WIDTH_HEIGHT, (image->width << 16) | image->height); + radeon_fifo_wait(rinfo, 4); + OUTREG(SC_TOP_LEFT, (image->dy << 16) | image->dx); + OUTREG(SC_BOTTOM_RIGHT, ((image->dy + image->height) << 16) | + (image->dx + image->width)); + OUTREG(DST_Y_X, (image->dy << 16) | image->dx); + + OUTREG(DST_HEIGHT_WIDTH, (image->height << 16) | ((image->width + 31) & ~31)); - src_bytes = (((image->width * image->depth) + 7) / 8) * image->height; - dwords = (src_bytes + 3) / 4; + dwords = (image->width + 31) >> 5; + dwords *= image->height; bits = (u32*)(image->data); while(dwords >= 8) { diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 9a5821c65eb..b3ffe8205d2 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -1875,6 +1875,7 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) info->fbops = &radeonfb_ops; info->screen_base = rinfo->fb_base; info->screen_size = rinfo->mapped_vram; + /* Fill fix common fields */ strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id)); info->fix.smem_start = rinfo->fb_base_phys; @@ -1889,8 +1890,25 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) info->fix.mmio_len = RADEON_REGSIZE; info->fix.accel = FB_ACCEL_ATI_RADEON; + /* Allocate colormap */ fb_alloc_cmap(&info->cmap, 256, 0); + /* Setup pixmap used for acceleration */ +#define PIXMAP_SIZE (2048 * 4) + + info->pixmap.addr = kmalloc(PIXMAP_SIZE, GFP_KERNEL); + if (!info->pixmap.addr) { + printk(KERN_ERR "radeonfb: Failed to allocate pixmap !\n"); + noaccel = 1; + goto bail; + } + info->pixmap.size = PIXMAP_SIZE; + info->pixmap.flags = FB_PIXMAP_SYSTEM; + info->pixmap.scan_align = 4; + info->pixmap.buf_align = 4; + info->pixmap.access_align = 32; + +bail: if (noaccel) info->flags |= FBINFO_HWACCEL_DISABLED; -- cgit v1.2.3 From bca404afdc5206c3bb30168315ee8a98a579ec65 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 1 Dec 2008 13:14:05 -0800 Subject: fbdev: fix FB console blanking The commit aef7db4bd5a3b6068dfa05919a3d685199eed116 fixed the problem with recursive locking in fb blanking code if blank is caused by user setting the /sys/class/graphics/fb*/blank. However this broke the fbcon timeout blanking. If you use a driver that defines ->fb_blank operation and at the same time that driver relies on other driver (e.g. backlight or lcd class) to blank the screen, when the fbcon times out and tries to blank the fb, it will call only fb driver blanker and won't notify the other driver. Thus FB output is disabled, but the screen isn't blanked. Restore fbcon blanking and at the same time apply the proper fix for the above problem: if fbcon_blank is called with FBINFO_FLAG_USEREVENT, we are already called through notification from fb_blank, thus we don't have to blank the fb again. Signed-off-by: Dmitry Baryshkov Cc: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index b92947d62ad..67ff370d80a 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -2389,16 +2389,13 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) if (!fbcon_is_inactive(vc, info)) { if (ops->blank_state != blank) { - int ret = 1; - ops->blank_state = blank; fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); ops->cursor_flash = (!blank); - if (info->fbops->fb_blank) - ret = info->fbops->fb_blank(blank, info); - if (ret) - fbcon_generic_blank(vc, info, blank); + if (!(info->flags & FBINFO_MISC_USEREVENT)) + if (fb_blank(info, blank)) + fbcon_generic_blank(vc, info, blank); } if (!blank) -- cgit v1.2.3 From 307d114441f905e4576871ff28d06408a1af1a7e Mon Sep 17 00:00:00 2001 From: Jarkko Lavinen Date: Mon, 1 Dec 2008 13:14:06 -0800 Subject: i82875p_edac: fix overflow device resource setup When I do "modprobe i82875p_edac" on my Asus P4C800 MB on kernels 2.6.26 or later, the module load fails due to BAR 0 collision. On 2.6.25 the module loads just fine. The overflow device on the MB seems to be hidden and its resources are not allocated at normal PCI bus init. Log shows the missing resource problem: EDAC DEBUG: i82875p_probe1() PCI: 0000:00:06.0 reg 10 32bit mmio: [fecf0000, fecf0fff] pci 0000:00:06.0: device not available because of BAR 0 [0xfecf0000-0xfecf0fff] collisions EDAC i82875p: i82875p_setup_overfl_dev(): Failed to enable overflow device The patch below fixes this by calling pci_bus_assign_resources() after the overflow device is revealed and added to the bus. With this patch I am again able to load and use the module. Signed-off-by: Jarkko Lavinen Cc: Doug Thompson Cc: Jesse Barnes Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/i82875p_edac.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index e43bdc43a1b..7f909972fec 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -295,6 +295,7 @@ static int i82875p_setup_overfl_dev(struct pci_dev *pdev, "%s(): pci_bus_add_device() Failed\n", __func__); } + pci_bus_assign_resources(dev->bus); } *ovrfl_pdev = dev; -- cgit v1.2.3 From 09a81269c7aadaec3375a7ebd9647acbb72f5a67 Mon Sep 17 00:00:00 2001 From: Jarkko Lavinen Date: Mon, 1 Dec 2008 13:14:08 -0800 Subject: i82875p_edac: fix module remove Fix module removal bugs of i82875p_edac. Also i82975x_edac code seems to have the same module removal bugs as in i82875p_edac. The problems were: 1. In module removal i82875p_remove_one() is never called. Variable i82875p_registered is newer changed from 1, which guarantees i82875p_remove_one() is not called (and even if it were called, it would be called in wrong order). As a result, the edac_mc workque is not stopped and keeps probing. If kernel debugging options are not enabled, user may not notice anything going wrong. if debugging options are enabled and I do "rmmod i82875p_edac", I get: edac debug: edac_pci_workq_function() checking BUG: unable to handle kernel paging request at f882d16f ... call trace: [] ? edac_mc_workq_function+0x55/0x7e [edac_core] [] ? run_workqueue+0xd7/0x1a5 [] ? run_workqueue+0x92/0x1a5 [] ? edac_mc_workq_function+0x0/0x7e [edac_core] [] ? worker_thread+0xb7/0xc3 [] ? autoremove_wake_function+0x0/0x33 [] ? worker_thread+0x0/0xc3 [] ? kthread+0x3b/0x61 [] ? kthread+0x0/0x61 [] ? kernel_thread_helper+0x7/0x10 Fix for this is to get rid of needles variable i82875p_registered altogether and run i82875p_remove_one() *before* pci_unregister_driver(). 2. edac_mc_del_mc() uses mci after freeing mci edac_mc_del_mc() calls calls edac_remove_sysfs_mci_device(). The kobject refcount of mci drops to 0 and mci is freed. After this mci is accessed via debug print and i82875p_remove_one() still uses mci->pvt and tries to free mci again with edac_mc_free(). The fix for this is add kobject_get(&mci->edac_mci_kobj) after edac_mc_alloc(). Then the mci is still available after returning from edac_mc_del_mc() with refcount 1, and mci->pvt is still available. When i82875p_remove_one() finally calls edac_mc_free(), this will cause kobject_put() and mci is released properly. Signed-off-by: Jarkko Lavinen Cc: Doug Thompson Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/i82875p_edac.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/i82875p_edac.c b/drivers/edac/i82875p_edac.c index 7f909972fec..ebb037b7875 100644 --- a/drivers/edac/i82875p_edac.c +++ b/drivers/edac/i82875p_edac.c @@ -182,8 +182,6 @@ static struct pci_dev *mci_pdev; /* init dev: in case that AGP code has * already registered driver */ -static int i82875p_registered = 1; - static struct edac_pci_ctl_info *i82875p_pci; static void i82875p_get_error_info(struct mem_ctl_info *mci, @@ -410,6 +408,9 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) goto fail0; } + /* Keeps mci available after edac_mc_del_mc() till edac_mc_free() */ + kobject_get(&mci->edac_mci_kobj); + debugf3("%s(): init mci\n", __func__); mci->dev = &pdev->dev; mci->mtype_cap = MEM_FLAG_DDR; @@ -452,6 +453,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx) return 0; fail1: + kobject_put(&mci->edac_mci_kobj); edac_mc_free(mci); fail0: @@ -579,12 +581,11 @@ static void __exit i82875p_exit(void) { debugf3("%s()\n", __func__); + i82875p_remove_one(mci_pdev); + pci_dev_put(mci_pdev); + pci_unregister_driver(&i82875p_driver); - if (!i82875p_registered) { - i82875p_remove_one(mci_pdev); - pci_dev_put(mci_pdev); - } } module_init(i82875p_init); -- cgit v1.2.3 From 9c84ba4e502184d95ab75128d3166f595ea2dea0 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 1 Dec 2008 13:14:08 -0800 Subject: drivers/gpu/drm/i915/i915_irq.c: fix warning drivers/gpu/drm/i915/i915_irq.c: In function 'i915_disable_pipestat': drivers/gpu/drm/i915/i915_irq.c:101: warning: control may reach end of non-void function 'i915_pipestat' being inlined Cc: Dave Airlie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/gpu/drm/i915/i915_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index fe3d9cc72bf..69b9a42da95 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -78,7 +78,7 @@ i915_pipestat(int pipe) return PIPEASTAT; if (pipe == 1) return PIPEBSTAT; - BUG_ON(1); + BUG(); } void -- cgit v1.2.3 From d94762989103b5e29938d8a7b0112e72c4633265 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 1 Dec 2008 23:00:55 +0100 Subject: [MTD] [NAND] drivers/mtd/nand/pasemi_nand.c: Add missing pci_dev_put pci_get_device increments a reference count that should be decremented using pci_dev_put. The semantic patch that finds the problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; statement S,S1; position p1,p2,p3; expression E,E1; type T,T1; expression *ptr != NULL; @@ ( if ((x@p1 = pci_get_device(...)) == NULL) S | x@p1 = pci_get_device(...); ) ... when != pci_dev_put(...,(T)x,...) when != if (...) { <+... pci_dev_put(...,(T)x,...) ...+> } when != true x == NULL || ... when != x = E when != E = (T)x when any ( if (x == NULL || ...) S1 | if@p2 (...) { ... when != pci_dev_put(...,(T1)x,...) when != if (...) { <+... pci_dev_put(...,(T1)x,...) ...+> } when != x = E1 when != E1 = (T1)x ( return \(0\|<+...x...+>\|ptr\); | return@p3 ...; ) } ) @ script:python @ p1 << r.p1; p3 << r.p3; @@ print "* file: %s pci_get_device: %s return: %s" % (p1[0].file,p1[0].line,p3[0].line) // Signed-off-by: Julia Lawall Acked-by: Olof Johansson Signed-off-by: David Woodhouse --- drivers/mtd/nand/pasemi_nand.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index 75c89903902..9bd6c9ac844 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c @@ -141,6 +141,7 @@ static int __devinit pasemi_nand_probe(struct of_device *ofdev, } lpcctl = pci_resource_start(pdev, 0); + pci_dev_put(pdev); if (!request_region(lpcctl, 4, driver_name)) { err = -EBUSY; -- cgit v1.2.3 From 89c223a616cddd9eab792b860f61f99cec53c4e8 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Tue, 18 Nov 2008 20:40:40 +0100 Subject: macfb: Do not overflow fb_fix_screeninfo.id Don't overflow the 16-character fb_fix_screeninfo id string (fixes some console erasing and blanking artifacts). Have the ID default to "Unknown" on machines with no built-in video and no nubus devices. Check for fb_alloc_cmap failure. Signed-off-by: Finn Thain Signed-off-by: Geert Uytterhoeven --- drivers/video/macfb.c | 74 ++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index b790ddff76f..ee380d5f341 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c @@ -164,7 +164,6 @@ static struct fb_var_screeninfo macfb_defined = { }; static struct fb_fix_screeninfo macfb_fix = { - .id = "Macintosh ", .type = FB_TYPE_PACKED_PIXELS, .accel = FB_ACCEL_NONE, }; @@ -760,22 +759,22 @@ static int __init macfb_init(void) switch(ndev->dr_hw) { case NUBUS_DRHW_APPLE_MDC: - strcat( macfb_fix.id, "Display Card" ); + strcpy(macfb_fix.id, "Mac Disp. Card"); macfb_setpalette = mdc_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; break; case NUBUS_DRHW_APPLE_TFB: - strcat( macfb_fix.id, "Toby" ); + strcpy(macfb_fix.id, "Toby"); macfb_setpalette = toby_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; break; case NUBUS_DRHW_APPLE_JET: - strcat( macfb_fix.id, "Jet"); + strcpy(macfb_fix.id, "Jet"); macfb_setpalette = jet_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; break; default: - strcat( macfb_fix.id, "Generic NuBus" ); + strcpy(macfb_fix.id, "Generic NuBus"); break; } } @@ -786,21 +785,11 @@ static int __init macfb_init(void) if (!video_is_nubus) switch( mac_bi_data.id ) { - /* These don't have onboard video. Eventually, we may - be able to write separate framebuffer drivers for - them (tobyfb.c, hiresfb.c, etc, etc) */ - case MAC_MODEL_II: - case MAC_MODEL_IIX: - case MAC_MODEL_IICX: - case MAC_MODEL_IIFX: - strcat( macfb_fix.id, "Generic NuBus" ); - break; - /* Valkyrie Quadras */ case MAC_MODEL_Q630: /* I'm not sure about this one */ case MAC_MODEL_P588: - strcat( macfb_fix.id, "Valkyrie built-in" ); + strcpy(macfb_fix.id, "Valkyrie"); macfb_setpalette = valkyrie_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; valkyrie_cmap_regs = ioremap(DAC_BASE, 0x1000); @@ -823,7 +812,7 @@ static int __init macfb_init(void) case MAC_MODEL_Q700: case MAC_MODEL_Q900: case MAC_MODEL_Q950: - strcat( macfb_fix.id, "DAFB built-in" ); + strcpy(macfb_fix.id, "DAFB"); macfb_setpalette = dafb_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000); @@ -831,7 +820,7 @@ static int __init macfb_init(void) /* LC II uses the V8 framebuffer */ case MAC_MODEL_LCII: - strcat( macfb_fix.id, "V8 built-in" ); + strcpy(macfb_fix.id, "V8"); macfb_setpalette = v8_brazil_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); @@ -843,7 +832,7 @@ static int __init macfb_init(void) case MAC_MODEL_IIVI: case MAC_MODEL_IIVX: case MAC_MODEL_P600: - strcat( macfb_fix.id, "Brazil built-in" ); + strcpy(macfb_fix.id, "Brazil"); macfb_setpalette = v8_brazil_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); @@ -860,7 +849,7 @@ static int __init macfb_init(void) case MAC_MODEL_P460: macfb_setpalette = v8_brazil_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; - strcat( macfb_fix.id, "Sonora built-in" ); + strcpy(macfb_fix.id, "Sonora"); v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); break; @@ -871,7 +860,7 @@ static int __init macfb_init(void) case MAC_MODEL_IISI: macfb_setpalette = rbv_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; - strcat( macfb_fix.id, "RBV built-in" ); + strcpy(macfb_fix.id, "RBV"); rbv_cmap_regs = ioremap(DAC_BASE, 0x1000); break; @@ -880,7 +869,7 @@ static int __init macfb_init(void) case MAC_MODEL_C660: macfb_setpalette = civic_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; - strcat( macfb_fix.id, "Civic built-in" ); + strcpy(macfb_fix.id, "Civic"); civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000); break; @@ -901,7 +890,7 @@ static int __init macfb_init(void) v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); } - strcat( macfb_fix.id, "LC built-in" ); + strcpy(macfb_fix.id, "LC"); break; /* We think this may be like the LC II */ case MAC_MODEL_CCL: @@ -911,18 +900,18 @@ static int __init macfb_init(void) v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); } - strcat( macfb_fix.id, "Color Classic built-in" ); + strcpy(macfb_fix.id, "Color Classic"); break; /* And we *do* mean "weirdos" */ case MAC_MODEL_TV: - strcat( macfb_fix.id, "Mac TV built-in" ); + strcpy(macfb_fix.id, "Mac TV"); break; /* These don't have colour, so no need to worry */ case MAC_MODEL_SE30: case MAC_MODEL_CLII: - strcat( macfb_fix.id, "Monochrome built-in" ); + strcpy(macfb_fix.id, "Monochrome"); break; /* Powerbooks are particularly difficult. Many of @@ -935,7 +924,7 @@ static int __init macfb_init(void) case MAC_MODEL_PB140: case MAC_MODEL_PB145: case MAC_MODEL_PB170: - strcat( macfb_fix.id, "DDC built-in" ); + strcpy(macfb_fix.id, "DDC"); break; /* Internal is GSC, External (if present) is ViSC */ @@ -945,13 +934,13 @@ static int __init macfb_init(void) case MAC_MODEL_PB180: case MAC_MODEL_PB210: case MAC_MODEL_PB230: - strcat( macfb_fix.id, "GSC built-in" ); + strcpy(macfb_fix.id, "GSC"); break; /* Internal is TIM, External is ViSC */ case MAC_MODEL_PB165C: case MAC_MODEL_PB180C: - strcat( macfb_fix.id, "TIM built-in" ); + strcpy(macfb_fix.id, "TIM"); break; /* Internal is CSC, External is Keystone+Ariel. */ @@ -963,12 +952,12 @@ static int __init macfb_init(void) case MAC_MODEL_PB280C: macfb_setpalette = csc_setpalette; macfb_defined.activate = FB_ACTIVATE_NOW; - strcat( macfb_fix.id, "CSC built-in" ); + strcpy(macfb_fix.id, "CSC"); csc_cmap_regs = ioremap(CSC_BASE, 0x1000); break; default: - strcat( macfb_fix.id, "Unknown/Unsupported built-in" ); + strcpy(macfb_fix.id, "Unknown"); break; } @@ -978,16 +967,23 @@ static int __init macfb_init(void) fb_info.pseudo_palette = pseudo_palette; fb_info.flags = FBINFO_DEFAULT; - fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0); + err = fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0); + if (err) + goto fail_unmap; err = register_framebuffer(&fb_info); - if (!err) - printk("fb%d: %s frame buffer device\n", - fb_info.node, fb_info.fix.id); - else { - iounmap(fb_info.screen_base); - iounmap_macfb(); - } + if (err) + goto fail_dealloc; + + printk("fb%d: %s frame buffer device\n", + fb_info.node, fb_info.fix.id); + return 0; + +fail_dealloc: + fb_dealloc_cmap(&fb_info.cmap); +fail_unmap: + iounmap(fb_info.screen_base); + iounmap_macfb(); return err; } -- cgit v1.2.3 From f9e3326dce0ef117308872cd234b903aa19aa40f Mon Sep 17 00:00:00 2001 From: Michael Schmitz Date: Tue, 2 Dec 2008 20:40:02 +0100 Subject: ide: fix the ide_release_lock imbalance ide_release_lock() spits out lots of: ide_release_lock: bug warnings on Atari Falcon. Fix the ide_release_lock imbalance. Signed-off-by: Michael Schmitz Cc: Geert Uytterhoeven Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 7162d67562a..0be7c4eb11c 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -967,14 +967,13 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) ide_startstop_t startstop; int loops = 0; - /* for atari only: POSSIBLY BROKEN HERE(?) */ - ide_get_lock(ide_intr, hwgroup); - /* caller must own ide_lock */ BUG_ON(!irqs_disabled()); while (!hwgroup->busy) { hwgroup->busy = 1; + /* for atari only */ + ide_get_lock(ide_intr, hwgroup); drive = choose_drive(hwgroup); if (drive == NULL) { int sleeping = 0; -- cgit v1.2.3 From 6636487e8dc49a1c43fed336bdc4a2f3d7ce6881 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 2 Dec 2008 20:40:03 +0100 Subject: amd74xx: workaround unreliable AltStatus register for nVidia controllers It seems that on some nVidia controllers using AltStatus register can be unreliable so default to Status register if the PCI device is in Compatibility Mode. In order to achieve this: * Add ide_pci_is_in_compatibility_mode() inline helper to . * Add IDE_HFLAG_BROKEN_ALTSTATUS host flag and set it in amd74xx host driver for nVidia controllers in Compatibility Mode. * Teach actual_try_to_identify() and drive_is_ready() about the new flag. This fixes the regression caused by removal of CONFIG_IDEPCI_SHARE_IRQ config option in 2.6.25 and using AltStatus register unconditionally when available (kernel.org bugs #11659 and #10216). [ Moreover for CONFIG_IDEPCI_SHARE_IRQ=y (which is what most people and distributions use) it never worked correctly. ] Thanks to Remy LABENE and Lars Winterfeld for help with debugging the problem. More info at: http://bugzilla.kernel.org/show_bug.cgi?id=11659 http://bugzilla.kernel.org/show_bug.cgi?id=10216 Reported-by: Remy LABENE Tested-by: Remy LABENE Tested-by: Lars Winterfeld Acked-by: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/amd74xx.c | 11 ++++++++++- drivers/ide/ide-iops.c | 3 ++- drivers/ide/ide-probe.c | 3 ++- 3 files changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c index 81ec73134ed..c6bcd3014a2 100644 --- a/drivers/ide/amd74xx.c +++ b/drivers/ide/amd74xx.c @@ -3,7 +3,7 @@ * IDE driver for Linux. * * Copyright (c) 2000-2002 Vojtech Pavlik - * Copyright (c) 2007 Bartlomiej Zolnierkiewicz + * Copyright (c) 2007-2008 Bartlomiej Zolnierkiewicz * * Based on the work of: * Andre Hedrick @@ -263,6 +263,15 @@ static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_ d.udma_mask = ATA_UDMA5; } + /* + * It seems that on some nVidia controllers using AltStatus + * register can be unreliable so default to Status register + * if the device is in Compatibility Mode. + */ + if (dev->vendor == PCI_VENDOR_ID_NVIDIA && + ide_pci_is_in_compatibility_mode(dev)) + d.host_flags |= IDE_HFLAG_BROKEN_ALTSTATUS; + printk(KERN_INFO "%s %s: UDMA%s controller\n", d.name, pci_name(dev), amd_dma[fls(d.udma_mask) - 1]); diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 5d6ba14e211..142b9573d64 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -468,7 +468,8 @@ int drive_is_ready (ide_drive_t *drive) * an interrupt with another pci card/device. We make no assumptions * about possible isa-pnp and pci-pnp issues yet. */ - if (hwif->io_ports.ctl_addr) + if (hwif->io_ports.ctl_addr && + (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) stat = hwif->tp_ops->read_altstatus(hwif); else /* Note: this may clear a pending IRQ!! */ diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 1649ea54f76..c55bdbd2231 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -266,7 +266,8 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) /* take a deep breath */ msleep(50); - if (io_ports->ctl_addr) { + if (io_ports->ctl_addr && + (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) { a = tp_ops->read_altstatus(hwif); s = tp_ops->read_status(hwif); if ((a ^ s) & ~ATA_IDX) -- cgit v1.2.3 From c7b997b372e8b6e7ee8d91696c74a556754f5fdb Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 2 Dec 2008 20:40:03 +0100 Subject: ide: add SAMSUNG SP0822N with firmware WA100-10 to ivb_list[] Should fix kernel.org bug #10225: http://bugzilla.kernel.org/show_bug.cgi?id=10225 Reported-by: Matthias B. Cc: Alan Cox Acked-by: Sergei Shtyltov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 142b9573d64..6f57de85dcd 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -611,6 +611,7 @@ static const struct drive_list_entry ivb_list[] = { { "TSSTcorp CDDVDW SH-S202N" , "SB01" }, { "TSSTcorp CDDVDW SH-S202H" , "SB00" }, { "TSSTcorp CDDVDW SH-S202H" , "SB01" }, + { "SAMSUNG SP0822N" , "WA100-10" }, { NULL , NULL } }; -- cgit v1.2.3 From e9eb8388306364295308132265c00bea685f409f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 2 Dec 2008 20:40:03 +0100 Subject: ide: respect current DMA setting during resume Respect current DMA setting during resume, otherwise PIO timings may get destroyed if host uses shared PIO/MWDMA timings. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 0be7c4eb11c..702a627b008 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -204,10 +204,8 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * */ if (drive->hwif->dma_ops == NULL) break; - /* - * TODO: respect IDE_DFLAG_USING_DMA - */ - ide_set_dma(drive); + if (drive->dev_flags & IDE_DFLAG_USING_DMA) + ide_set_dma(drive); break; } -- cgit v1.2.3 From 6b7d8fc36272169d1d07a07174f2c8a7909c025e Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 2 Dec 2008 20:40:03 +0100 Subject: ide: fix build for DEBUG_PM Also while at it: * Drop unused arguments from ide_complete_power_step(). * Move DEBUG_PM printk() from ide_end_drive_cmd() to ide_complete_power_step(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 702a627b008..7d275b2af3e 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -132,10 +132,14 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) } EXPORT_SYMBOL(ide_end_request); -static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error) +static void ide_complete_power_step(ide_drive_t *drive, struct request *rq) { struct request_pm_state *pm = rq->data; +#ifdef DEBUG_PM + printk(KERN_INFO "%s: complete_power_step(step: %d)\n", + drive->name, pm->pm_step); +#endif if (drive->media != ide_disk) return; @@ -172,7 +176,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * /* Not supported? Switch to next step now. */ if (ata_id_flush_enabled(drive->id) == 0 || (drive->dev_flags & IDE_DFLAG_WCACHE) == 0) { - ide_complete_power_step(drive, rq, 0, 0); + ide_complete_power_step(drive, rq); return ide_stopped; } if (ata_id_flush_ext_enabled(drive->id)) @@ -191,7 +195,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * if (drive->media != ide_disk) pm->pm_step = IDE_PM_RESTORE_DMA; else - ide_complete_power_step(drive, rq, 0, 0); + ide_complete_power_step(drive, rq); return ide_stopped; case IDE_PM_IDLE: /* Resume step 2 (idle) */ args->tf.command = ATA_CMD_IDLEIMMEDIATE; @@ -320,11 +324,8 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) } } else if (blk_pm_request(rq)) { struct request_pm_state *pm = rq->data; -#ifdef DEBUG_PM - printk("%s: complete_power_step(step: %d, stat: %x, err: %x)\n", - drive->name, rq->pm->pm_step, stat, err); -#endif - ide_complete_power_step(drive, rq, stat, err); + + ide_complete_power_step(drive, rq); if (pm->pm_step == IDE_PM_COMPLETED) ide_complete_pm_request(drive, rq); return; @@ -802,7 +803,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) struct request_pm_state *pm = rq->data; #ifdef DEBUG_PM printk("%s: start_power_step(step: %d)\n", - drive->name, rq->pm->pm_step); + drive->name, pm->pm_step); #endif startstop = ide_start_power_step(drive, rq); if (startstop == ide_stopped && -- cgit v1.2.3 From a3663801b1bb1b6f6e2be5198cc81bc16f1558fd Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 2 Dec 2008 20:40:04 +0100 Subject: ide: remove dead code from drive_is_ready() We guarantee 400ns delay at the time of issuing the command. Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 6f57de85dcd..c41c3b9b6f0 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -457,11 +457,6 @@ int drive_is_ready (ide_drive_t *drive) if (drive->waiting_for_dma) return hwif->dma_ops->dma_test_irq(drive); -#if 0 - /* need to guarantee 400ns since last command was issued */ - udelay(1); -#endif - /* * We do a passive status test under shared PCI interrupts on * cards that truly share the ATA side interrupt, but may also share -- cgit v1.2.3 From 95964018d53f479529dfdc2b46fe30c0a14a00e0 Mon Sep 17 00:00:00 2001 From: Hannes Eder Date: Tue, 2 Dec 2008 20:40:04 +0100 Subject: alim15x3: fix sparse warning Fix this sparse warning: drivers/ide/alim15x3.c:594:2: warning: returning void-valued expression Signed-off-by: Hannes Eder Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/alim15x3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c index e56c7b72f9e..45d2356bb72 100644 --- a/drivers/ide/alim15x3.c +++ b/drivers/ide/alim15x3.c @@ -591,7 +591,7 @@ static int __init ali15x3_ide_init(void) static void __exit ali15x3_ide_exit(void) { - return pci_unregister_driver(&alim15x3_pci_driver); + pci_unregister_driver(&alim15x3_pci_driver); } module_init(ali15x3_ide_init); -- cgit v1.2.3 From 026bde120a161d9035502a47dd311bd572f6d31f Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Tue, 2 Dec 2008 08:06:01 -0600 Subject: sgi-gru: call fs_initcall() if statically linked If xpc.ko and gru.ko are both statically linked into the kernel, then xpc_init() can get called before gru_init() and make a call to one of the gru's exported functions before the gru has initialized itself. The end result is a NULL dereference. Signed-off-by: Dean Nelson Signed-off-by: Linus Torvalds --- drivers/misc/sgi-gru/grufile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c index 5c027b6b4e5..65098380639 100644 --- a/drivers/misc/sgi-gru/grufile.c +++ b/drivers/misc/sgi-gru/grufile.c @@ -481,7 +481,7 @@ struct vm_operations_struct gru_vm_ops = { .fault = gru_fault, }; -module_init(gru_init); +fs_initcall(gru_init); module_exit(gru_exit); module_param(gru_options, ulong, 0644); -- cgit v1.2.3 From efba01803c8570bab11d0d6188a630231d0ddccf Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 3 Dec 2008 00:36:15 -0800 Subject: bnx2: Add workaround to handle missed MSI. The bnx2 chips do not support per MSI vector masking. On 5706/5708, new MSI address/data are stored only when the MSI enable bit is toggled. As a result, SMP affinity no longer works in the latest kernel. A more serious problem is that the driver will no longer receive interrupts when the MSI receiving CPU goes offline. The workaround in this patch only addresses the problem of CPU going offline. When that happens, the driver's timer function will detect that it is making no forward progress on pending interrupt events and will recover from it. Eric Dumazet reported the problem. We also found that if an interrupt is internally asserted while MSI and INTA are disabled, the chip will end up in the same state after MSI is re-enabled. The same workaround is needed for this problem. Signed-off-by: Michael Chan Tested-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 35 ++++++++++++++++++++++++++++++++--- drivers/net/bnx2.h | 6 ++++++ 2 files changed, 38 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index d07e3f14895..a1a3d0e5d2b 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -3144,6 +3144,28 @@ bnx2_has_work(struct bnx2_napi *bnapi) return 0; } +static void +bnx2_chk_missed_msi(struct bnx2 *bp) +{ + struct bnx2_napi *bnapi = &bp->bnx2_napi[0]; + u32 msi_ctrl; + + if (bnx2_has_work(bnapi)) { + msi_ctrl = REG_RD(bp, BNX2_PCICFG_MSI_CONTROL); + if (!(msi_ctrl & BNX2_PCICFG_MSI_CONTROL_ENABLE)) + return; + + if (bnapi->last_status_idx == bp->idle_chk_status_idx) { + REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl & + ~BNX2_PCICFG_MSI_CONTROL_ENABLE); + REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl); + bnx2_msi(bp->irq_tbl[0].vector, bnapi); + } + } + + bp->idle_chk_status_idx = bnapi->last_status_idx; +} + static void bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi) { struct status_block *sblk = bnapi->status_blk.msi; @@ -3218,14 +3240,15 @@ static int bnx2_poll(struct napi_struct *napi, int budget) work_done = bnx2_poll_work(bp, bnapi, work_done, budget); - if (unlikely(work_done >= budget)) - break; - /* bnapi->last_status_idx is used below to tell the hw how * much work has been processed, so we must read it before * checking for more work. */ bnapi->last_status_idx = sblk->status_idx; + + if (unlikely(work_done >= budget)) + break; + rmb(); if (likely(!bnx2_has_work(bnapi))) { netif_rx_complete(bp->dev, napi); @@ -4570,6 +4593,8 @@ bnx2_init_chip(struct bnx2 *bp) for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) bp->bnx2_napi[i].last_status_idx = 0; + bp->idle_chk_status_idx = 0xffff; + bp->rx_mode = BNX2_EMAC_RX_MODE_SORT_MODE; /* Set up how to generate a link change interrupt. */ @@ -5718,6 +5743,10 @@ bnx2_timer(unsigned long data) if (atomic_read(&bp->intr_sem) != 0) goto bnx2_restart_timer; + if ((bp->flags & (BNX2_FLAG_USING_MSI | BNX2_FLAG_ONE_SHOT_MSI)) == + BNX2_FLAG_USING_MSI) + bnx2_chk_missed_msi(bp); + bnx2_send_heart_beat(bp); bp->stats_blk->stat_FwRxDrop = diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 617d9534016..0b032c3c7b6 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -378,6 +378,9 @@ struct l2_fhdr { * pci_config_l definition * offset: 0000 */ +#define BNX2_PCICFG_MSI_CONTROL 0x00000058 +#define BNX2_PCICFG_MSI_CONTROL_ENABLE (1L<<16) + #define BNX2_PCICFG_MISC_CONFIG 0x00000068 #define BNX2_PCICFG_MISC_CONFIG_TARGET_BYTE_SWAP (1L<<2) #define BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP (1L<<3) @@ -6863,6 +6866,9 @@ struct bnx2 { u8 num_tx_rings; u8 num_rx_rings; + + u32 idle_chk_status_idx; + }; #define REG_RD(bp, offset) \ -- cgit v1.2.3 From e93f1be503efd0e44e46fc1fd4c13dbee72a6561 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Wed, 3 Dec 2008 10:47:20 +0000 Subject: [MTD] [NAND] fix OOPS accessing flash operations over STM flash on PXA STM 2Gb flash is a large-page NAND flash. Set operations accordingly. This field is dereferenced without a check in several places resulting in OOPS. Signed-off-by: Denis V. Lunev Acked-by: Eric Miao Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- drivers/mtd/nand/pxa3xx_nand.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index c0fa9c9edf0..15f0a26730a 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -269,6 +269,7 @@ static struct pxa3xx_nand_timing stm2GbX16_timing = { static struct pxa3xx_nand_flash stm2GbX16 = { .timing = &stm2GbX16_timing, + .cmdset = &largepage_cmdset, .page_per_block = 64, .page_size = 2048, .flash_width = 16, -- cgit v1.2.3 From 0e435ac26e3f951d83338ed3d4ab7dc0fe0055bc Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Wed, 3 Dec 2008 12:55:08 +0100 Subject: block: fix setting of max_segment_size and seg_boundary mask Fix setting of max_segment_size and seg_boundary mask for stacked md/dm devices. When stacking devices (LVM over MD over SCSI) some of the request queue parameters are not set up correctly in some cases by default, namely max_segment_size and and seg_boundary mask. If you create MD device over SCSI, these attributes are zeroed. Problem become when there is over this mapping next device-mapper mapping - queue attributes are set in DM this way: request_queue max_segment_size seg_boundary_mask SCSI 65536 0xffffffff MD RAID1 0 0 LVM 65536 -1 (64bit) Unfortunately bio_add_page (resp. bio_phys_segments) calculates number of physical segments according to these parameters. During the generic_make_request() is segment cout recalculated and can increase bio->bi_phys_segments count over the allowed limit. (After bio_clone() in stack operation.) Thi is specially problem in CCISS driver, where it produce OOPS here BUG_ON(creq->nr_phys_segments > MAXSGENTRIES); (MAXSEGENTRIES is 31 by default.) Sometimes even this command is enough to cause oops: dd iflag=direct if=/dev// of=/dev/null bs=128000 count=10 This command generates bios with 250 sectors, allocated in 32 4k-pages (last page uses only 1024 bytes). For LVM layer, it allocates bio with 31 segments (still OK for CCISS), unfortunatelly on lower layer it is recalculated to 32 segments and this violates CCISS restriction and triggers BUG_ON(). The patch tries to fix it by: * initializing attributes above in queue request constructor blk_queue_make_request() * make sure that blk_queue_stack_limits() inherits setting (DM uses its own function to set the limits because it blk_queue_stack_limits() was introduced later. It should probably switch to use generic stack limit function too.) * sets the default seg_boundary value in one place (blkdev.h) * use this mask as default in DM (instead of -1, which differs in 64bit) Bugs related to this: https://bugzilla.redhat.com/show_bug.cgi?id=471639 http://bugzilla.kernel.org/show_bug.cgi?id=8672 Signed-off-by: Milan Broz Reviewed-by: Alasdair G Kergon Cc: Neil Brown Cc: FUJITA Tomonori Cc: Tejun Heo Cc: Mike Miller Signed-off-by: Jens Axboe --- drivers/md/dm-table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index a63161aec48..04e5fd742c2 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -668,7 +668,7 @@ static void check_for_valid_limits(struct io_restrictions *rs) if (!rs->max_segment_size) rs->max_segment_size = MAX_SEGMENT_SIZE; if (!rs->seg_boundary_mask) - rs->seg_boundary_mask = -1; + rs->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK; if (!rs->bounce_pfn) rs->bounce_pfn = -1; } -- cgit v1.2.3 From 532d3b1f86f41834a25373e3ded981d68e4ce17f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 3 Dec 2008 17:16:55 -0700 Subject: ioat: wait for self-test completion As part of the ioat_dma self-test it performs a printk from a completion callback. Depending on the system console configuration this output can take longer than a millisecond causing the self-test to fail. Introduce a completion with a generous timeout to mitigate this failure. Cc: Acked-by: Maciej Sosnowski Signed-off-by: Dan Williams --- drivers/dma/ioat_dma.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index ecd743f7cc6..6607fdd00b1 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c @@ -1341,10 +1341,12 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan) */ #define IOAT_TEST_SIZE 2000 +DECLARE_COMPLETION(test_completion); static void ioat_dma_test_callback(void *dma_async_param) { printk(KERN_ERR "ioatdma: ioat_dma_test_callback(%p)\n", dma_async_param); + complete(&test_completion); } /** @@ -1410,7 +1412,8 @@ static int ioat_dma_self_test(struct ioatdma_device *device) goto free_resources; } device->common.device_issue_pending(dma_chan); - msleep(1); + + wait_for_completion_timeout(&test_completion, msecs_to_jiffies(3000)); if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) { -- cgit v1.2.3 From cd92a17eec752f8c948c4b6ab93dc099ce55b8cb Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 3 Dec 2008 16:20:19 -0800 Subject: iTCO_wdt: fix typo when setting TCO_EN bit The code used '&= 0x00002000' when it tried to set the TCO_EN bit, which obviously didn't set that bit at all, but instead just reset all the other bits in the SMI_EN register. This bug seemingly caused various random behavior, with Frans Pop reporting that X.org just silently hung at startup and Rafael Wysocki reports the fan spinning with full speed. See http://lkml.org/lkml/2008/12/3/178 http://bugzilla.kernel.org/show_bug.cgi?id=12162 The problem seems to have been triggered by "[WATCHDOG] iTCO_wdt : problem with rebooting on new ICH9 based motherboards" (commit 7cd5b08be3c489df11b559fef210b81133764ad4), but the bogus code existed before that too (in the "supermicro_old_pre_stop()" function), it just apparently never showed up due to different logic. In that commit the broken code got moved around and now gets executed much more. Reported-by: Rafael J. Wysocki Tested-by: Frans Pop Cc: Wim Van Sebroeck Signed-off-by: Linus Torvalds --- drivers/watchdog/iTCO_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 26173a270e9..5b395a4ddfd 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -392,7 +392,7 @@ static int iTCO_wdt_stop(void) /* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */ val32 = inl(SMI_EN); - val32 &= 0x00002000; + val32 |= 0x00002000; outl(val32, SMI_EN); /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ -- cgit v1.2.3 From b0b42b16ff2b90f17bc1a4308366c9beba4b276e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 3 Dec 2008 17:17:07 -0700 Subject: dmaengine: protect 'id' from concurrent registrations There is a possibility to have two devices registered with the same id. Cc: Acked-by: Maciej Sosnowski Signed-off-by: Dan Williams --- drivers/dma/dmaengine.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 5317e08221e..65799651737 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -388,7 +388,10 @@ int dma_async_device_register(struct dma_device *device) init_completion(&device->done); kref_init(&device->refcount); + + mutex_lock(&dma_list_mutex); device->dev_id = id++; + mutex_unlock(&dma_list_mutex); /* represent channels in sysfs. Probably want devs too */ list_for_each_entry(chan, &device->channels, device_node) { -- cgit v1.2.3 From a7f014f2de04893f95cfe40fe35f15c8dae4b36e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 25 Nov 2008 14:02:05 -0800 Subject: drm/i915: Respect GM965/GM45 bit-17-instead-of-bit-11 option for swizzling. This fixes readpixels and buffer corruption when swapped out and in by disabling tiling on them. Now that we know that the bit 17 mode isn't just a mistake of older chipsets, we'll need to work on a clever fix so that we can get the performance of tiling on these chipsets, but that will require intrusive changes targeted at the next kernel release, not this one. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem_tiling.c | 7 ++++--- drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index e8b85ac4ca0..a8cb69469c6 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -119,9 +119,10 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) dcc & DCC_CHANNEL_XOR_DISABLE) { swizzle_x = I915_BIT_6_SWIZZLE_9_10; swizzle_y = I915_BIT_6_SWIZZLE_9; - } else if (IS_I965GM(dev) || IS_GM45(dev)) { - /* GM965 only does bit 11-based channel - * randomization + } else if ((IS_I965GM(dev) || IS_GM45(dev)) && + (dcc & DCC_CHANNEL_XOR_BIT_17) == 0) { + /* GM965/GM45 does either bit 11 or bit 17 + * swizzling. */ swizzle_x = I915_BIT_6_SWIZZLE_9_10_11; swizzle_y = I915_BIT_6_SWIZZLE_9_11; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0e476eba36e..9d24aaeb8a4 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -522,6 +522,7 @@ #define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED (2 << 0) #define DCC_ADDRESSING_MODE_MASK (3 << 0) #define DCC_CHANNEL_XOR_DISABLE (1 << 10) +#define DCC_CHANNEL_XOR_BIT_17 (1 << 9) /** 965 MCH register controlling DRAM channel configuration */ #define C0DRB3 0x10206 -- cgit v1.2.3 From ce44b0ea3dc04236d852d78a06f850d1f7b03f3d Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 6 Nov 2008 16:00:31 -0800 Subject: drm/i915: Move flushing list cleanup from flush request retire to request emit. obj_priv->write_domain is "write domain if the GPU went idle now", not "write domain at this moment." By postponing the clear, we confused the concept, required more storage, and potentially emitted more flushes than are required. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_drv.h | 11 ++++-- drivers/gpu/drm/i915/i915_gem.c | 73 ++++++++++++++++++++---------------- drivers/gpu/drm/i915/i915_gem_proc.c | 5 +-- 3 files changed, 50 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0a4f39b9a0e..76d9a706d8f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -244,6 +244,10 @@ typedef struct drm_i915_private { * List of objects currently involved in rendering from the * ringbuffer. * + * Includes buffers having the contents of their GPU caches + * flushed, not necessarily primitives. last_rendering_seqno + * represents when the rendering involved will be completed. + * * A reference is held on the buffer while on this list. */ struct list_head active_list; @@ -253,6 +257,8 @@ typedef struct drm_i915_private { * still have a write_domain which needs to be flushed before * unbinding. * + * last_rendering_seqno is 0 while an object is in this list. + * * A reference is held on the buffer while on this list. */ struct list_head flushing_list; @@ -261,6 +267,8 @@ typedef struct drm_i915_private { * LRU list of objects which are not in the ringbuffer and * are ready to unbind, but are still in the GTT. * + * last_rendering_seqno is 0 while an object is in this list. + * * A reference is not held on the buffer while on this list, * as merely being GTT-bound shouldn't prevent its being * freed, and we'll pull it off the list in the free path. @@ -394,9 +402,6 @@ struct drm_i915_gem_request { /** Time at which this request was emitted, in jiffies. */ unsigned long emitted_jiffies; - /** Cache domains that were flushed at the start of the request. */ - uint32_t flush_domains; - struct list_head list; }; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d58ddef468f..9fd28ebe0aa 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -532,7 +532,7 @@ i915_gem_object_free_page_list(struct drm_gem_object *obj) } static void -i915_gem_object_move_to_active(struct drm_gem_object *obj) +i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno) { struct drm_device *dev = obj->dev; drm_i915_private_t *dev_priv = dev->dev_private; @@ -546,8 +546,20 @@ i915_gem_object_move_to_active(struct drm_gem_object *obj) /* Move from whatever list we were on to the tail of execution. */ list_move_tail(&obj_priv->list, &dev_priv->mm.active_list); + obj_priv->last_rendering_seqno = seqno; } +static void +i915_gem_object_move_to_flushing(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj_priv = obj->driver_private; + + BUG_ON(!obj_priv->active); + list_move_tail(&obj_priv->list, &dev_priv->mm.flushing_list); + obj_priv->last_rendering_seqno = 0; +} static void i915_gem_object_move_to_inactive(struct drm_gem_object *obj) @@ -562,6 +574,7 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj) else list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); + obj_priv->last_rendering_seqno = 0; if (obj_priv->active) { obj_priv->active = 0; drm_gem_object_unreference(obj); @@ -610,10 +623,28 @@ i915_add_request(struct drm_device *dev, uint32_t flush_domains) request->seqno = seqno; request->emitted_jiffies = jiffies; - request->flush_domains = flush_domains; was_empty = list_empty(&dev_priv->mm.request_list); list_add_tail(&request->list, &dev_priv->mm.request_list); + /* Associate any objects on the flushing list matching the write + * domain we're flushing with our flush. + */ + if (flush_domains != 0) { + struct drm_i915_gem_object *obj_priv, *next; + + list_for_each_entry_safe(obj_priv, next, + &dev_priv->mm.flushing_list, list) { + struct drm_gem_object *obj = obj_priv->obj; + + if ((obj->write_domain & flush_domains) == + obj->write_domain) { + obj->write_domain = 0; + i915_gem_object_move_to_active(obj, seqno); + } + } + + } + if (was_empty && !dev_priv->mm.suspended) schedule_delayed_work(&dev_priv->mm.retire_work, HZ); return seqno; @@ -676,30 +707,10 @@ i915_gem_retire_request(struct drm_device *dev, __func__, request->seqno, obj); #endif - if (obj->write_domain != 0) { - list_move_tail(&obj_priv->list, - &dev_priv->mm.flushing_list); - } else { + if (obj->write_domain != 0) + i915_gem_object_move_to_flushing(obj); + else i915_gem_object_move_to_inactive(obj); - } - } - - if (request->flush_domains != 0) { - struct drm_i915_gem_object *obj_priv, *next; - - /* Clear the write domain and activity from any buffers - * that are just waiting for a flush matching the one retired. - */ - list_for_each_entry_safe(obj_priv, next, - &dev_priv->mm.flushing_list, list) { - struct drm_gem_object *obj = obj_priv->obj; - - if (obj->write_domain & request->flush_domains) { - obj->write_domain = 0; - i915_gem_object_move_to_inactive(obj); - } - } - } } @@ -896,17 +907,15 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj) * create a new seqno to wait for. */ if (obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT)) { - uint32_t write_domain = obj->write_domain; + uint32_t seqno, write_domain = obj->write_domain; #if WATCH_BUF DRM_INFO("%s: flushing object %p from write domain %08x\n", __func__, obj, write_domain); #endif i915_gem_flush(dev, 0, write_domain); - i915_gem_object_move_to_active(obj); - obj_priv->last_rendering_seqno = i915_add_request(dev, - write_domain); - BUG_ON(obj_priv->last_rendering_seqno == 0); + seqno = i915_add_request(dev, write_domain); + i915_gem_object_move_to_active(obj, seqno); #if WATCH_LRU DRM_INFO("%s: flush moves to exec list %p\n", __func__, obj); #endif @@ -1927,10 +1936,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, i915_file_priv->mm.last_gem_seqno = seqno; for (i = 0; i < args->buffer_count; i++) { struct drm_gem_object *obj = object_list[i]; - struct drm_i915_gem_object *obj_priv = obj->driver_private; - i915_gem_object_move_to_active(obj); - obj_priv->last_rendering_seqno = seqno; + i915_gem_object_move_to_active(obj, seqno); #if WATCH_LRU DRM_INFO("%s: move to exec list %p\n", __func__, obj); #endif diff --git a/drivers/gpu/drm/i915/i915_gem_proc.c b/drivers/gpu/drm/i915/i915_gem_proc.c index 93de15b4c9a..e8d5abe1250 100644 --- a/drivers/gpu/drm/i915/i915_gem_proc.c +++ b/drivers/gpu/drm/i915/i915_gem_proc.c @@ -166,10 +166,9 @@ static int i915_gem_request_info(char *buf, char **start, off_t offset, list_for_each_entry(gem_request, &dev_priv->mm.request_list, list) { - DRM_PROC_PRINT(" %d @ %d %08x\n", + DRM_PROC_PRINT(" %d @ %d\n", gem_request->seqno, - (int) (jiffies - gem_request->emitted_jiffies), - gem_request->flush_domains); + (int) (jiffies - gem_request->emitted_jiffies)); } if (len > request + offset) return request; -- cgit v1.2.3 From b670d8158283c35842ae1c650f75c375d8710607 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 14 Nov 2008 16:27:47 -0800 Subject: drm/i915: If interrupted while setting object domains, still emit the flush. Otherwise, we would leave the objects in an inconsistent state, such as write_domain == 0 but on the flushing list. Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9fd28ebe0aa..3fe108b7e2f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1880,8 +1880,20 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ret = i915_gem_object_set_domain(obj, obj->pending_read_domains, obj->pending_write_domain); - if (ret) + if (ret) { + /* As we've partially updated domains on our buffers, + * we have to emit the flush we've accumulated + * before exiting, or we'll have broken the + * active/flushing/inactive invariants. + * + * We'll potentially have some things marked as + * being in write domains that they actually aren't, + * but that should be merely a minor performance loss. + */ + flush_domains = i915_gem_dev_set_domain(dev); + (void)i915_add_request(dev, flush_domains); goto err; + } } i915_verify_inactive(dev, __FILE__, __LINE__); -- cgit v1.2.3 From 2ef7eeaa553d88e78d9a4520271f26a7bc0e2968 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 10 Nov 2008 10:53:25 -0800 Subject: drm/i915: Make a single set-to-gtt-domain path. This fixes failure to flush caches in the relocation update path, and failure to wait in the set_domain ioctl, each of which could lead to incorrect rendering. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 115 +++++++++++++++++++++++++++++++++------- 1 file changed, 96 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 3fe108b7e2f..62a059dce85 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -48,6 +48,8 @@ i915_gem_set_domain(struct drm_gem_object *obj, struct drm_file *file_priv, uint32_t read_domains, uint32_t write_domain); +static int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, + int write); static int i915_gem_object_get_page_list(struct drm_gem_object *obj); static void i915_gem_object_free_page_list(struct drm_gem_object *obj); static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); @@ -260,8 +262,7 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj, mutex_unlock(&dev->struct_mutex); return ret; } - ret = i915_gem_set_domain(obj, file_priv, - I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT); + ret = i915_gem_object_set_to_gtt_domain(obj, 1); if (ret) goto fail; @@ -397,7 +398,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, } /** - * Called when user space prepares to use an object + * Called when user space prepares to use an object with the CPU, either + * through the mmap ioctl's mapping or a GTT mapping. */ int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, @@ -405,11 +407,26 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, { struct drm_i915_gem_set_domain *args = data; struct drm_gem_object *obj; + uint32_t read_domains = args->read_domains; + uint32_t write_domain = args->write_domain; int ret; if (!(dev->driver->driver_features & DRIVER_GEM)) return -ENODEV; + /* Only handle setting domains to types used by the CPU. */ + if (write_domain & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) + return -EINVAL; + + if (read_domains & ~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) + return -EINVAL; + + /* Having something in the write domain implies it's in the read + * domain, and only that read domain. Enforce that in the request. + */ + if (write_domain != 0 && read_domains != write_domain) + return -EINVAL; + obj = drm_gem_object_lookup(dev, file_priv, args->handle); if (obj == NULL) return -EBADF; @@ -417,10 +434,15 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, mutex_lock(&dev->struct_mutex); #if WATCH_BUF DRM_INFO("set_domain_ioctl %p(%d), %08x %08x\n", - obj, obj->size, args->read_domains, args->write_domain); + obj, obj->size, read_domains, write_domain); #endif - ret = i915_gem_set_domain(obj, file_priv, - args->read_domains, args->write_domain); + if (read_domains & I915_GEM_DOMAIN_GTT) { + ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0); + } else { + ret = i915_gem_set_domain(obj, file_priv, + read_domains, write_domain); + } + drm_gem_object_unreference(obj); mutex_unlock(&dev->struct_mutex); return ret; @@ -1237,6 +1259,69 @@ i915_gem_clflush_object(struct drm_gem_object *obj) drm_clflush_pages(obj_priv->page_list, obj->size / PAGE_SIZE); } +/** + * Moves a single object to the GTT read, and possibly write domain. + * + * This function returns when the move is complete, including waiting on + * flushes to occur. + */ +static int +i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) +{ + struct drm_device *dev = obj->dev; + struct drm_i915_gem_object *obj_priv = obj->driver_private; + uint32_t flush_domains; + + /* Figure out what GPU domains we need to flush or invalidate for + * moving to GTT. + */ + flush_domains = obj->write_domain & I915_GEM_GPU_DOMAINS; + + /* Queue the GPU write cache flushing we need. */ + if (flush_domains != 0) { + uint32_t seqno; + + obj->write_domain &= ~I915_GEM_GPU_DOMAINS; + i915_gem_flush(dev, 0, flush_domains); + seqno = i915_add_request(dev, flush_domains); + i915_gem_object_move_to_active(obj, seqno); + } + + /* Wait on any GPU rendering and flushing to occur. */ + if (obj_priv->active) { + int ret; + + ret = i915_wait_request(dev, obj_priv->last_rendering_seqno); + if (ret != 0) + return ret; + } + + /* If we're writing through the GTT domain, then CPU and GPU caches + * will need to be invalidated at next use. + */ + if (write) + obj->read_domains &= ~(I915_GEM_GPU_DOMAINS | + I915_GEM_DOMAIN_CPU); + + /* Flush the CPU domain if it's dirty. */ + if (obj->write_domain & I915_GEM_DOMAIN_CPU) { + i915_gem_clflush_object(obj); + drm_agp_chipset_flush(dev); + + obj->write_domain &= ~I915_GEM_DOMAIN_CPU; + } + + /* It should now be out of any other write domains, and we can update + * the domain values for our changes. + */ + BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); + obj->read_domains |= I915_GEM_DOMAIN_GTT; + if (write) + obj->write_domain = I915_GEM_DOMAIN_GTT; + + return 0; +} + /* * Set the next domain for the specified object. This * may not actually perform the necessary flushing/invaliding though, @@ -1634,19 +1719,11 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, continue; } - /* Now that we're going to actually write some data in, - * make sure that any rendering using this buffer's contents - * is completed. - */ - i915_gem_object_wait_rendering(obj); - - /* As we're writing through the gtt, flush - * any CPU writes before we write the relocations - */ - if (obj->write_domain & I915_GEM_DOMAIN_CPU) { - i915_gem_clflush_object(obj); - drm_agp_chipset_flush(dev); - obj->write_domain = 0; + ret = i915_gem_object_set_to_gtt_domain(obj, 1); + if (ret != 0) { + drm_gem_object_unreference(target_obj); + i915_gem_object_unpin(obj); + return -EINVAL; } /* Map the page containing the relocation we're going to -- cgit v1.2.3 From e47c68e9c5d71e2faab8c2b82f57c6c73e6456fd Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 14 Nov 2008 13:35:19 -0800 Subject: drm/i915: Make a single set-to-cpu-domain path and use it wherever needed. This fixes several domain management bugs, including potential lack of cache invalidation for pread, potential failure to wait for set_domain(CPU, 0), and more, along with producing more intelligible code. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_drv.h | 4 +- drivers/gpu/drm/i915/i915_gem.c | 363 +++++++++++++++++++++++----------------- 2 files changed, 215 insertions(+), 152 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 76d9a706d8f..adc972cc6bf 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -379,8 +379,8 @@ struct drm_i915_gem_object { uint32_t agp_type; /** - * Flagging of which individual pages are valid in GEM_DOMAIN_CPU when - * GEM_DOMAIN_CPU is not in the object's read domain. + * If present, while GEM_DOMAIN_CPU is in the read domain this array + * flags which individual pages are valid. */ uint8_t *page_cpu_valid; }; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 62a059dce85..f7e9f2c2934 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -37,19 +37,17 @@ static int i915_gem_object_set_domain(struct drm_gem_object *obj, uint32_t read_domains, uint32_t write_domain); -static int -i915_gem_object_set_domain_range(struct drm_gem_object *obj, - uint64_t offset, - uint64_t size, - uint32_t read_domains, - uint32_t write_domain); -static int -i915_gem_set_domain(struct drm_gem_object *obj, - struct drm_file *file_priv, - uint32_t read_domains, - uint32_t write_domain); +static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); +static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); +static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); static int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write); +static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, + int write); +static int i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, + uint64_t offset, + uint64_t size); +static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj); static int i915_gem_object_get_page_list(struct drm_gem_object *obj); static void i915_gem_object_free_page_list(struct drm_gem_object *obj); static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); @@ -164,8 +162,8 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, mutex_lock(&dev->struct_mutex); - ret = i915_gem_object_set_domain_range(obj, args->offset, args->size, - I915_GEM_DOMAIN_CPU, 0); + ret = i915_gem_object_set_cpu_read_domain_range(obj, args->offset, + args->size); if (ret != 0) { drm_gem_object_unreference(obj); mutex_unlock(&dev->struct_mutex); @@ -321,8 +319,7 @@ i915_gem_shmem_pwrite(struct drm_device *dev, struct drm_gem_object *obj, mutex_lock(&dev->struct_mutex); - ret = i915_gem_set_domain(obj, file_priv, - I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); + ret = i915_gem_object_set_to_cpu_domain(obj, 1); if (ret) { mutex_unlock(&dev->struct_mutex); return ret; @@ -439,8 +436,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, if (read_domains & I915_GEM_DOMAIN_GTT) { ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0); } else { - ret = i915_gem_set_domain(obj, file_priv, - read_domains, write_domain); + ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0); } drm_gem_object_unreference(obj); @@ -477,10 +473,9 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, obj_priv = obj->driver_private; /* Pinned buffers may be scanout, so flush the cache */ - if ((obj->write_domain & I915_GEM_DOMAIN_CPU) && obj_priv->pin_count) { - i915_gem_clflush_object(obj); - drm_agp_chipset_flush(dev); - } + if (obj_priv->pin_count) + i915_gem_object_flush_cpu_write_domain(obj); + drm_gem_object_unreference(obj); mutex_unlock(&dev->struct_mutex); return ret; @@ -925,23 +920,10 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj) struct drm_i915_gem_object *obj_priv = obj->driver_private; int ret; - /* If there are writes queued to the buffer, flush and - * create a new seqno to wait for. + /* This function only exists to support waiting for existing rendering, + * not for emitting required flushes. */ - if (obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT)) { - uint32_t seqno, write_domain = obj->write_domain; -#if WATCH_BUF - DRM_INFO("%s: flushing object %p from write domain %08x\n", - __func__, obj, write_domain); -#endif - i915_gem_flush(dev, 0, write_domain); - - seqno = i915_add_request(dev, write_domain); - i915_gem_object_move_to_active(obj, seqno); -#if WATCH_LRU - DRM_INFO("%s: flush moves to exec list %p\n", __func__, obj); -#endif - } + BUG_ON((obj->write_domain & I915_GEM_GPU_DOMAINS) != 0); /* If there is rendering queued on the buffer being evicted, wait for * it. @@ -981,24 +963,16 @@ i915_gem_object_unbind(struct drm_gem_object *obj) return -EINVAL; } - /* Wait for any rendering to complete - */ - ret = i915_gem_object_wait_rendering(obj); - if (ret) { - DRM_ERROR("wait_rendering failed: %d\n", ret); - return ret; - } - /* Move the object to the CPU domain to ensure that * any possible CPU writes while it's not in the GTT * are flushed when we go to remap it. This will * also ensure that all pending GPU writes are finished * before we unbind. */ - ret = i915_gem_object_set_domain(obj, I915_GEM_DOMAIN_CPU, - I915_GEM_DOMAIN_CPU); + ret = i915_gem_object_set_to_cpu_domain(obj, 1); if (ret) { - DRM_ERROR("set_domain failed: %d\n", ret); + if (ret != -ERESTARTSYS) + DRM_ERROR("set_domain failed: %d\n", ret); return ret; } @@ -1259,6 +1233,51 @@ i915_gem_clflush_object(struct drm_gem_object *obj) drm_clflush_pages(obj_priv->page_list, obj->size / PAGE_SIZE); } +/** Flushes any GPU write domain for the object if it's dirty. */ +static void +i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + uint32_t seqno; + + if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) + return; + + /* Queue the GPU write cache flushing we need. */ + i915_gem_flush(dev, 0, obj->write_domain); + seqno = i915_add_request(dev, obj->write_domain); + obj->write_domain = 0; + i915_gem_object_move_to_active(obj, seqno); +} + +/** Flushes the GTT write domain for the object if it's dirty. */ +static void +i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj) +{ + if (obj->write_domain != I915_GEM_DOMAIN_GTT) + return; + + /* No actual flushing is required for the GTT write domain. Writes + * to it immediately go to main memory as far as we know, so there's + * no chipset flush. It also doesn't land in render cache. + */ + obj->write_domain = 0; +} + +/** Flushes the CPU write domain for the object if it's dirty. */ +static void +i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + + if (obj->write_domain != I915_GEM_DOMAIN_CPU) + return; + + i915_gem_clflush_object(obj); + drm_agp_chipset_flush(dev); + obj->write_domain = 0; +} + /** * Moves a single object to the GTT read, and possibly write domain. * @@ -1268,56 +1287,81 @@ i915_gem_clflush_object(struct drm_gem_object *obj) static int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) { - struct drm_device *dev = obj->dev; struct drm_i915_gem_object *obj_priv = obj->driver_private; - uint32_t flush_domains; + int ret; - /* Figure out what GPU domains we need to flush or invalidate for - * moving to GTT. + i915_gem_object_flush_gpu_write_domain(obj); + /* Wait on any GPU rendering and flushing to occur. */ + ret = i915_gem_object_wait_rendering(obj); + if (ret != 0) + return ret; + + /* If we're writing through the GTT domain, then CPU and GPU caches + * will need to be invalidated at next use. */ - flush_domains = obj->write_domain & I915_GEM_GPU_DOMAINS; + if (write) + obj->read_domains &= I915_GEM_DOMAIN_GTT; - /* Queue the GPU write cache flushing we need. */ - if (flush_domains != 0) { - uint32_t seqno; + i915_gem_object_flush_cpu_write_domain(obj); - obj->write_domain &= ~I915_GEM_GPU_DOMAINS; - i915_gem_flush(dev, 0, flush_domains); - seqno = i915_add_request(dev, flush_domains); - i915_gem_object_move_to_active(obj, seqno); + /* It should now be out of any other write domains, and we can update + * the domain values for our changes. + */ + BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); + obj->read_domains |= I915_GEM_DOMAIN_GTT; + if (write) { + obj->write_domain = I915_GEM_DOMAIN_GTT; + obj_priv->dirty = 1; } + return 0; +} + +/** + * Moves a single object to the CPU read, and possibly write domain. + * + * This function returns when the move is complete, including waiting on + * flushes to occur. + */ +static int +i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) +{ + struct drm_device *dev = obj->dev; + int ret; + + i915_gem_object_flush_gpu_write_domain(obj); /* Wait on any GPU rendering and flushing to occur. */ - if (obj_priv->active) { - int ret; + ret = i915_gem_object_wait_rendering(obj); + if (ret != 0) + return ret; - ret = i915_wait_request(dev, obj_priv->last_rendering_seqno); - if (ret != 0) - return ret; - } + i915_gem_object_flush_gtt_write_domain(obj); - /* If we're writing through the GTT domain, then CPU and GPU caches - * will need to be invalidated at next use. + /* If we have a partially-valid cache of the object in the CPU, + * finish invalidating it and free the per-page flags. */ - if (write) - obj->read_domains &= ~(I915_GEM_GPU_DOMAINS | - I915_GEM_DOMAIN_CPU); + i915_gem_object_set_to_full_cpu_read_domain(obj); - /* Flush the CPU domain if it's dirty. */ - if (obj->write_domain & I915_GEM_DOMAIN_CPU) { + /* Flush the CPU cache if it's still invalid. */ + if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0) { i915_gem_clflush_object(obj); drm_agp_chipset_flush(dev); - obj->write_domain &= ~I915_GEM_DOMAIN_CPU; + obj->read_domains |= I915_GEM_DOMAIN_CPU; } /* It should now be out of any other write domains, and we can update * the domain values for our changes. */ - BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); - obj->read_domains |= I915_GEM_DOMAIN_GTT; - if (write) - obj->write_domain = I915_GEM_DOMAIN_GTT; + BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_CPU) != 0); + + /* If we're writing through the CPU, then the GPU read domains will + * need to be invalidated at next use. + */ + if (write) { + obj->read_domains &= I915_GEM_DOMAIN_CPU; + obj->write_domain = I915_GEM_DOMAIN_CPU; + } return 0; } @@ -1442,7 +1486,9 @@ i915_gem_object_set_domain(struct drm_gem_object *obj, struct drm_i915_gem_object *obj_priv = obj->driver_private; uint32_t invalidate_domains = 0; uint32_t flush_domains = 0; - int ret; + + BUG_ON(read_domains & I915_GEM_DOMAIN_CPU); + BUG_ON(write_domain == I915_GEM_DOMAIN_CPU); #if WATCH_BUF DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n", @@ -1479,34 +1525,11 @@ i915_gem_object_set_domain(struct drm_gem_object *obj, DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n", __func__, flush_domains, invalidate_domains); #endif - /* - * If we're invaliding the CPU cache and flushing a GPU cache, - * then pause for rendering so that the GPU caches will be - * flushed before the cpu cache is invalidated - */ - if ((invalidate_domains & I915_GEM_DOMAIN_CPU) && - (flush_domains & ~(I915_GEM_DOMAIN_CPU | - I915_GEM_DOMAIN_GTT))) { - ret = i915_gem_object_wait_rendering(obj); - if (ret) - return ret; - } i915_gem_clflush_object(obj); } if ((write_domain | flush_domains) != 0) obj->write_domain = write_domain; - - /* If we're invalidating the CPU domain, clear the per-page CPU - * domain list as well. - */ - if (obj_priv->page_cpu_valid != NULL && - (write_domain != 0 || - read_domains & I915_GEM_DOMAIN_CPU)) { - drm_free(obj_priv->page_cpu_valid, obj->size / PAGE_SIZE, - DRM_MEM_DRIVER); - obj_priv->page_cpu_valid = NULL; - } obj->read_domains = read_domains; dev->invalidate_domains |= invalidate_domains; @@ -1521,43 +1544,91 @@ i915_gem_object_set_domain(struct drm_gem_object *obj, } /** - * Set the read/write domain on a range of the object. + * Moves the object from a partially CPU read to a full one. * - * Currently only implemented for CPU reads, otherwise drops to normal - * i915_gem_object_set_domain(). + * Note that this only resolves i915_gem_object_set_cpu_read_domain_range(), + * and doesn't handle transitioning from !(read_domains & I915_GEM_DOMAIN_CPU). */ -static int -i915_gem_object_set_domain_range(struct drm_gem_object *obj, - uint64_t offset, - uint64_t size, - uint32_t read_domains, - uint32_t write_domain) +static void +i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj) { + struct drm_device *dev = obj->dev; struct drm_i915_gem_object *obj_priv = obj->driver_private; - int ret, i; - if (obj->read_domains & I915_GEM_DOMAIN_CPU) - return 0; + if (!obj_priv->page_cpu_valid) + return; - if (read_domains != I915_GEM_DOMAIN_CPU || - write_domain != 0) - return i915_gem_object_set_domain(obj, - read_domains, write_domain); + /* If we're partially in the CPU read domain, finish moving it in. + */ + if (obj->read_domains & I915_GEM_DOMAIN_CPU) { + int i; + + for (i = 0; i <= (obj->size - 1) / PAGE_SIZE; i++) { + if (obj_priv->page_cpu_valid[i]) + continue; + drm_clflush_pages(obj_priv->page_list + i, 1); + } + drm_agp_chipset_flush(dev); + } - /* Wait on any GPU rendering to the object to be flushed. */ + /* Free the page_cpu_valid mappings which are now stale, whether + * or not we've got I915_GEM_DOMAIN_CPU. + */ + drm_free(obj_priv->page_cpu_valid, obj->size / PAGE_SIZE, + DRM_MEM_DRIVER); + obj_priv->page_cpu_valid = NULL; +} + +/** + * Set the CPU read domain on a range of the object. + * + * The object ends up with I915_GEM_DOMAIN_CPU in its read flags although it's + * not entirely valid. The page_cpu_valid member of the object flags which + * pages have been flushed, and will be respected by + * i915_gem_object_set_to_cpu_domain() if it's called on to get a valid mapping + * of the whole object. + * + * This function returns when the move is complete, including waiting on + * flushes to occur. + */ +static int +i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, + uint64_t offset, uint64_t size) +{ + struct drm_i915_gem_object *obj_priv = obj->driver_private; + int i, ret; + + if (offset == 0 && size == obj->size) + return i915_gem_object_set_to_cpu_domain(obj, 0); + + i915_gem_object_flush_gpu_write_domain(obj); + /* Wait on any GPU rendering and flushing to occur. */ ret = i915_gem_object_wait_rendering(obj); - if (ret) + if (ret != 0) return ret; + i915_gem_object_flush_gtt_write_domain(obj); + + /* If we're already fully in the CPU read domain, we're done. */ + if (obj_priv->page_cpu_valid == NULL && + (obj->read_domains & I915_GEM_DOMAIN_CPU) != 0) + return 0; + /* Otherwise, create/clear the per-page CPU read domain flag if we're + * newly adding I915_GEM_DOMAIN_CPU + */ if (obj_priv->page_cpu_valid == NULL) { obj_priv->page_cpu_valid = drm_calloc(1, obj->size / PAGE_SIZE, DRM_MEM_DRIVER); - } + if (obj_priv->page_cpu_valid == NULL) + return -ENOMEM; + } else if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0) + memset(obj_priv->page_cpu_valid, 0, obj->size / PAGE_SIZE); /* Flush the cache on any pages that are still invalid from the CPU's * perspective. */ - for (i = offset / PAGE_SIZE; i <= (offset + size - 1) / PAGE_SIZE; i++) { + for (i = offset / PAGE_SIZE; i <= (offset + size - 1) / PAGE_SIZE; + i++) { if (obj_priv->page_cpu_valid[i]) continue; @@ -1566,6 +1637,13 @@ i915_gem_object_set_domain_range(struct drm_gem_object *obj, obj_priv->page_cpu_valid[i] = 1; } + /* It should now be out of any other write domains, and we can update + * the domain values for our changes. + */ + BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_CPU) != 0); + + obj->read_domains |= I915_GEM_DOMAIN_CPU; + return 0; } @@ -1679,6 +1757,18 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, return -EINVAL; } + if (reloc.write_domain & I915_GEM_DOMAIN_CPU || + reloc.read_domains & I915_GEM_DOMAIN_CPU) { + DRM_ERROR("reloc with read/write CPU domains: " + "obj %p target %d offset %d " + "read %08x write %08x", + obj, reloc.target_handle, + (int) reloc.offset, + reloc.read_domains, + reloc.write_domain); + return -EINVAL; + } + if (reloc.write_domain && target_obj->pending_write_domain && reloc.write_domain != target_obj->pending_write_domain) { DRM_ERROR("Write domain conflict: " @@ -2157,11 +2247,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, /* XXX - flush the CPU caches for pinned objects * as the X server doesn't manage domains yet */ - if (obj->write_domain & I915_GEM_DOMAIN_CPU) { - i915_gem_clflush_object(obj); - drm_agp_chipset_flush(dev); - obj->write_domain = 0; - } + i915_gem_object_flush_cpu_write_domain(obj); args->offset = obj_priv->gtt_offset; drm_gem_object_unreference(obj); mutex_unlock(&dev->struct_mutex); @@ -2263,29 +2349,6 @@ void i915_gem_free_object(struct drm_gem_object *obj) drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); } -static int -i915_gem_set_domain(struct drm_gem_object *obj, - struct drm_file *file_priv, - uint32_t read_domains, - uint32_t write_domain) -{ - struct drm_device *dev = obj->dev; - int ret; - uint32_t flush_domains; - - BUG_ON(!mutex_is_locked(&dev->struct_mutex)); - - ret = i915_gem_object_set_domain(obj, read_domains, write_domain); - if (ret) - return ret; - flush_domains = i915_gem_dev_set_domain(obj->dev); - - if (flush_domains & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT)) - (void) i915_add_request(dev, flush_domains); - - return 0; -} - /** Unbinds all objects that are on the given buffer list. */ static int i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head) -- cgit v1.2.3 From c0d90829288942fa06d7483f9e84059a64605da5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 20 Nov 2008 23:11:08 -0800 Subject: drm/i915: Rename object_set_domain to object_set_to_gpu_domain Now that the CPU and GTT domain operations are isolated to their own functions, the previously general-purpose set_domain function is now used only to set GPU domains. It also has no failure cases, which is important as this eliminates any possible interruption of the computation of new object domains and subsequent emmission of the flushing instructions into the ring. Signed-off-by: Keith Packard Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f7e9f2c2934..50c75327d56 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -33,10 +33,10 @@ #define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) -static int -i915_gem_object_set_domain(struct drm_gem_object *obj, - uint32_t read_domains, - uint32_t write_domain); +static void +i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, + uint32_t read_domains, + uint32_t write_domain); static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); @@ -1477,10 +1477,10 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) * MI_FLUSH * drm_agp_chipset_flush */ -static int -i915_gem_object_set_domain(struct drm_gem_object *obj, - uint32_t read_domains, - uint32_t write_domain) +static void +i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, + uint32_t read_domains, + uint32_t write_domain) { struct drm_device *dev = obj->dev; struct drm_i915_gem_object *obj_priv = obj->driver_private; @@ -1540,7 +1540,6 @@ i915_gem_object_set_domain(struct drm_gem_object *obj, obj->read_domains, obj->write_domain, dev->invalidate_domains, dev->flush_domains); #endif - return 0; } /** @@ -2043,24 +2042,10 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, for (i = 0; i < args->buffer_count; i++) { struct drm_gem_object *obj = object_list[i]; - /* make sure all previous memory operations have passed */ - ret = i915_gem_object_set_domain(obj, - obj->pending_read_domains, - obj->pending_write_domain); - if (ret) { - /* As we've partially updated domains on our buffers, - * we have to emit the flush we've accumulated - * before exiting, or we'll have broken the - * active/flushing/inactive invariants. - * - * We'll potentially have some things marked as - * being in write domains that they actually aren't, - * but that should be merely a minor performance loss. - */ - flush_domains = i915_gem_dev_set_domain(dev); - (void)i915_add_request(dev, flush_domains); - goto err; - } + /* Compute new gpu domains and update invalidate/flushing */ + i915_gem_object_set_to_gpu_domain(obj, + obj->pending_read_domains, + obj->pending_write_domain); } i915_verify_inactive(dev, __FILE__, __LINE__); -- cgit v1.2.3 From 646f0f6e43bf6628b1f0f8ca6c0227ce72e8ef3c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 20 Nov 2008 23:23:03 -0800 Subject: drm/i915: Move the execbuffer domain computations together This eliminates the dev_set_domain function and just in-lines it where its used, with the goal of moving the manipulation and use of invalidate_domains and flush_domains closer together. This also avoids calling add_request unless some domain has been flushed. Signed-off-by: Keith Packard Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 65 +++++++++++++---------------------------- 1 file changed, 21 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 50c75327d56..c171a2d93bb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1646,38 +1646,6 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, return 0; } -/** - * Once all of the objects have been set in the proper domain, - * perform the necessary flush and invalidate operations. - * - * Returns the write domains flushed, for use in flush tracking. - */ -static uint32_t -i915_gem_dev_set_domain(struct drm_device *dev) -{ - uint32_t flush_domains = dev->flush_domains; - - /* - * Now that all the buffers are synced to the proper domains, - * flush and invalidate the collected domains - */ - if (dev->invalidate_domains | dev->flush_domains) { -#if WATCH_EXEC - DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n", - __func__, - dev->invalidate_domains, - dev->flush_domains); -#endif - i915_gem_flush(dev, - dev->invalidate_domains, - dev->flush_domains); - dev->invalidate_domains = 0; - dev->flush_domains = 0; - } - - return flush_domains; -} - /** * Pin an object to the GTT and evaluate the relocations landing in it. */ @@ -2002,13 +1970,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, return -EBUSY; } - /* Zero the gloabl flush/invalidate flags. These - * will be modified as each object is bound to the - * gtt - */ - dev->invalidate_domains = 0; - dev->flush_domains = 0; - /* Look up object handles and perform the relocations */ for (i = 0; i < args->buffer_count; i++) { object_list[i] = drm_gem_object_lookup(dev, file_priv, @@ -2039,10 +2000,17 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, i915_verify_inactive(dev, __FILE__, __LINE__); + /* Zero the global flush/invalidate flags. These + * will be modified as new domains are computed + * for each object + */ + dev->invalidate_domains = 0; + dev->flush_domains = 0; + for (i = 0; i < args->buffer_count; i++) { struct drm_gem_object *obj = object_list[i]; - /* Compute new gpu domains and update invalidate/flushing */ + /* Compute new gpu domains and update invalidate/flush */ i915_gem_object_set_to_gpu_domain(obj, obj->pending_read_domains, obj->pending_write_domain); @@ -2050,8 +2018,19 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, i915_verify_inactive(dev, __FILE__, __LINE__); - /* Flush/invalidate caches and chipset buffer */ - flush_domains = i915_gem_dev_set_domain(dev); + if (dev->invalidate_domains | dev->flush_domains) { +#if WATCH_EXEC + DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n", + __func__, + dev->invalidate_domains, + dev->flush_domains); +#endif + i915_gem_flush(dev, + dev->invalidate_domains, + dev->flush_domains); + if (dev->flush_domains) + (void)i915_add_request(dev, dev->flush_domains); + } i915_verify_inactive(dev, __FILE__, __LINE__); @@ -2071,8 +2050,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ~0); #endif - (void)i915_add_request(dev, flush_domains); - /* Exec the batchbuffer */ ret = i915_dispatch_gem_execbuffer(dev, args, exec_offset); if (ret) { -- cgit v1.2.3 From ac94a962b24a88ea5d00f4697550d9982f300751 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 20 Nov 2008 23:30:27 -0800 Subject: drm/i915: Retry execbuffer pinning after clearing the GTT If we fail to pin all of the buffers in an execbuffer request, go through and clear the GTT and try again to see if its just a matter of fragmentation Signed-off-by: Keith Packard Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 57 +++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c171a2d93bb..174c0c3ba0b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1087,6 +1087,19 @@ i915_gem_evict_something(struct drm_device *dev) return ret; } +static int +i915_gem_evict_everything(struct drm_device *dev) +{ + int ret; + + for (;;) { + ret = i915_gem_evict_something(dev); + if (ret != 0) + break; + } + return ret; +} + static int i915_gem_object_get_page_list(struct drm_gem_object *obj) { @@ -1173,7 +1186,8 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) ret = i915_gem_evict_something(dev); if (ret != 0) { - DRM_ERROR("Failed to evict a buffer %d\n", ret); + if (ret != -ERESTARTSYS) + DRM_ERROR("Failed to evict a buffer %d\n", ret); return ret; } goto search_free; @@ -1922,6 +1936,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, int ret, i, pinned = 0; uint64_t exec_offset; uint32_t seqno, flush_domains; + int pin_tries; #if WATCH_EXEC DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", @@ -1970,7 +1985,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, return -EBUSY; } - /* Look up object handles and perform the relocations */ + /* Look up object handles */ for (i = 0; i < args->buffer_count; i++) { object_list[i] = drm_gem_object_lookup(dev, file_priv, exec_list[i].handle); @@ -1980,17 +1995,39 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ret = -EBADF; goto err; } + } - object_list[i]->pending_read_domains = 0; - object_list[i]->pending_write_domain = 0; - ret = i915_gem_object_pin_and_relocate(object_list[i], - file_priv, - &exec_list[i]); - if (ret) { - DRM_ERROR("object bind and relocate failed %d\n", ret); + /* Pin and relocate */ + for (pin_tries = 0; ; pin_tries++) { + ret = 0; + for (i = 0; i < args->buffer_count; i++) { + object_list[i]->pending_read_domains = 0; + object_list[i]->pending_write_domain = 0; + ret = i915_gem_object_pin_and_relocate(object_list[i], + file_priv, + &exec_list[i]); + if (ret) + break; + pinned = i + 1; + } + /* success */ + if (ret == 0) + break; + + /* error other than GTT full, or we've already tried again */ + if (ret != -ENOMEM || pin_tries >= 1) { + DRM_ERROR("Failed to pin buffers %d\n", ret); goto err; } - pinned = i + 1; + + /* unpin all of our buffers */ + for (i = 0; i < pinned; i++) + i915_gem_object_unpin(object_list[i]); + + /* evict everyone we can from the aperture */ + ret = i915_gem_evict_everything(dev); + if (ret) + goto err; } /* Set the pending read domains for the batch buffer to COMMAND */ -- cgit v1.2.3 From 0235439232cb6f8a54f8976aa8330c1c98ebad0b Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 26 Nov 2008 13:58:13 -0800 Subject: drm/i915: Return error in i915_gem_set_to_gtt_domain if we're not in the GTT. It's only for flushing caches appropriately for GTT access, not for actually getting it there. Prevents potential smashing of cpu read/write domains on unbound objects. Signed-off-by: Eric Anholt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 174c0c3ba0b..3fde82be014 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -435,6 +435,13 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, #endif if (read_domains & I915_GEM_DOMAIN_GTT) { ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0); + + /* Silently promote "you're not bound, there was nothing to do" + * to success, since the client was just asking us to + * make sure everything was done. + */ + if (ret == -EINVAL) + ret = 0; } else { ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0); } @@ -1304,6 +1311,10 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) struct drm_i915_gem_object *obj_priv = obj->driver_private; int ret; + /* Not valid to be called on unbound objects. */ + if (obj_priv->gtt_space == NULL) + return -EINVAL; + i915_gem_object_flush_gpu_write_domain(obj); /* Wait on any GPU rendering and flushing to occur. */ ret = i915_gem_object_wait_rendering(obj); -- cgit v1.2.3 From 1c594c05a75770ab53a329fc4eb99c797a4bc7d7 Mon Sep 17 00:00:00 2001 From: Wilfried Klaebe Date: Wed, 3 Dec 2008 20:57:19 -0800 Subject: b1isa: fix b1isa_exit() to really remove registered capi controllers On "/etc/init.d/capiutils stop", this oops happened. The oops happens on reading /proc/capi/controllers because capi_ctrl->procinfo is called for the wrongly not unregistered controller, which points to b1isa_procinfo(), which was removed on module unload. b1isa_exit() did not call b1isa_remove() for its controllers because io[0] == 0 on module unload despite having been 0x340 on module load. Besides, just removing the controllers that where added on module load time and not those that were added later via b1isa_add_card() is wrong too - the place where all added cards are found is isa_dev[]. relevant dmesg lines: [ 0.000000] Linux version 2.6.27.4 (w@shubashi) (gcc version 4.3.2 (Debian 4.3.2-1) ) #3 Thu Oct 30 16:49:03 CET 2008 [ 67.403555] CAPI Subsystem Rev 1.1.2.8 [ 68.529154] capifs: Rev 1.1.2.3 [ 68.563292] capi20: Rev 1.1.2.7: started up with major 68 (middleware+capifs) [ 77.026936] b1: revision 1.1.2.2 [ 77.049992] b1isa: revision 1.1.2.3 [ 77.722655] kcapi: Controller [001]: b1isa-340 attached [ 77.722671] b1isa: AVM B1 ISA at i/o 0x340, irq 5, revision 255 [ 81.272669] b1isa-340: card 1 "B1" ready. [ 81.272683] b1isa-340: card 1 Protocol: DSS1 [ 81.272689] b1isa-340: card 1 Linetype: point to multipoint [ 81.272695] b1isa-340: B1-card (3.11-03) now active [ 81.272702] kcapi: card [001] "b1isa-340" ready. [ 153.721281] kcapi: card [001] down. [ 154.151889] BUG: unable to handle kernel paging request at e87af000 [ 154.152081] IP: [] [ 154.153292] *pde = 2655b067 *pte = 00000000 [ 154.153307] Oops: 0000 [#1] [ 154.153360] Modules linked in: rfcomm l2cap ppdev lp ipt_MASQUERADE tun capi capifs kernelcapi ac battery nfsd exportfs nfs lockd nfs_acl sunrpc sit tunnel4 bridge stp llc ipt_REJECT ipt_LOG xt_tcpudp xt_state iptable_filter iptable_mangle iptable_nat nf_nat nf_conntrack_ipv4 nf_conntrack ip_tables x_tables nls_utf8 isofs nls_base zlib_inflate loop ipv6 netconsole snd_via82xx dvb_usb_dib0700 gameport dib7000p dib7000m dvb_usb snd_ac97_codec ac97_bus dvb_core mt2266 snd_pcm tuner_xc2028 dib3000mc dibx000_common mt2060 dib0070 snd_page_alloc snd_mpu401_uart snd_seq_midi snd_seq_midi_event btusb snd_rawmidi bluetooth snd_seq snd_timer snd_seq_device snd via686a i2c_viapro soundcore i2c_core parport_pc parport button dm_mirror dm_log dm_snapshot floppy sg ohci1394 uhci_hcd ehci_hcd 8139too mii ieee1394 usbcore sr_mod cdrom sd_mod thermal processor fan [last unloaded: b1] [ 154.153360] [ 154.153360] Pid: 4132, comm: capiinit Not tainted (2.6.27.4 #3) [ 154.153360] EIP: 0060:[] EFLAGS: 00010286 CPU: 0 [ 154.153360] EIP is at 0xe87af000 [ 154.153360] EAX: e6b9ccc8 EBX: e6b9ccc8 ECX: e87a0c67 EDX: e87af000 [ 154.153360] ESI: e142bbc0 EDI: e87a56e0 EBP: e0505f0c ESP: e0505ee4 [ 154.153360] DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068 [ 154.153360] Process capiinit (pid: 4132, ti=e0504000 task=d1196cf0 task.ti=e0504000) [ 154.153360] Stack: e879f650 00000246 e0505ef4 c01472eb e0505f0c 00000246 e7001780 fffffff4 [ 154.153360] fffffff4 e142bbc0 e0505f48 c01a56c6 00000400 b805e000 d102dc80 e142bbe0 [ 154.153360] 00000000 e87a56e0 00000246 e12617ac 00000000 00000000 e1261760 fffffffb [ 154.153360] Call Trace: [ 154.153360] [] ? controller_show+0x20/0x90 [kernelcapi] [ 154.153360] [] ? trace_hardirqs_on+0xb/0x10 [ 154.153360] [] ? seq_read+0x126/0x2f0 [ 154.153360] [] ? seq_read+0x0/0x2f0 [ 154.153360] [] ? proc_reg_read+0x5c/0x90 [ 154.153360] [] ? vfs_read+0x99/0x140 [ 154.153360] [] ? proc_reg_read+0x0/0x90 [ 154.153360] [] ? sys_read+0x3d/0x70 [ 154.153360] [] ? sysenter_do_call+0x12/0x35 [ 154.153360] ======================= [ 154.153360] Code: Bad EIP value. [ 154.153360] EIP: [] 0xe87af000 SS:ESP 0068:e0505ee4 [ 154.153360] ---[ end trace 23750b6c2862de94 ]--- Signed-off-by: Wilfried Klaebe Signed-off-by: Andrew Morton Acked-by: Karsten Keil Signed-off-by: David S. Miller --- drivers/isdn/hardware/avm/b1isa.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/hardware/avm/b1isa.c b/drivers/isdn/hardware/avm/b1isa.c index 1e288eeb5e2..6461a32bc83 100644 --- a/drivers/isdn/hardware/avm/b1isa.c +++ b/drivers/isdn/hardware/avm/b1isa.c @@ -233,10 +233,8 @@ static void __exit b1isa_exit(void) int i; for (i = 0; i < MAX_CARDS; i++) { - if (!io[i]) - break; - - b1isa_remove(&isa_dev[i]); + if (isa_dev[i].resource[0].start) + b1isa_remove(&isa_dev[i]); } unregister_capi_driver(&capi_driver_b1isa); } -- cgit v1.2.3 From bd0914104c61a852baf469b2d807322e5d0459b4 Mon Sep 17 00:00:00 2001 From: Pascal Terjan Date: Mon, 1 Dec 2008 12:24:25 +0000 Subject: hysdn: fix writing outside the field on 64 bits ifa_local is assumed to be unsigned long which lead to writing the address at dev->dev_addr-2 instead of +2 noticed thanks to gcc: drivers/isdn/hysdn/hysdn_net.c: In function `net_open': drivers/isdn/hysdn/hysdn_net.c:91: warning: array subscript is below array bounds Signed-off-by: Pascal Terjan Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/isdn/hysdn/hysdn_net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c index cfa8fa5e44a..3f2a0a20c19 100644 --- a/drivers/isdn/hysdn/hysdn_net.c +++ b/drivers/isdn/hysdn/hysdn_net.c @@ -83,12 +83,12 @@ net_open(struct net_device *dev) /* Fill in the MAC-level header (if not already set) */ if (!card->mac_addr[0]) { - for (i = 0; i < ETH_ALEN - sizeof(unsigned long); i++) + for (i = 0; i < ETH_ALEN; i++) dev->dev_addr[i] = 0xfc; if ((in_dev = dev->ip_ptr) != NULL) { struct in_ifaddr *ifa = in_dev->ifa_list; if (ifa != NULL) - memcpy(dev->dev_addr + (ETH_ALEN - sizeof(unsigned long)), &ifa->ifa_local, sizeof(unsigned long)); + memcpy(dev->dev_addr + (ETH_ALEN - sizeof(ifa->ifa_local)), &ifa->ifa_local, sizeof(ifa->ifa_local)); } } else memcpy(dev->dev_addr, card->mac_addr, ETH_ALEN); -- cgit v1.2.3 From 5176da7e5318669220e4d2fa856223054a3efc9f Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Tue, 2 Dec 2008 05:07:01 +0000 Subject: enc28j60: Fix sporadic packet loss (corrected again) Packet data read from the RX buffer the when the RSV is at the end of the RX buffer does not warp around. This causes packet loss, as the actual data is never read. Fix this by calculating the right packet data location. Thanks to Shachar Shemesh for suggesting the fix. Signed-off-by: Baruch Siach Acked-by: Claudio Lanconelli Signed-off-by: David S. Miller --- drivers/net/enc28j60.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c index e1b441effbb..c414554ac32 100644 --- a/drivers/net/enc28j60.c +++ b/drivers/net/enc28j60.c @@ -568,6 +568,17 @@ static u16 erxrdpt_workaround(u16 next_packet_ptr, u16 start, u16 end) return erxrdpt; } +/* + * Calculate wrap around when reading beyond the end of the RX buffer + */ +static u16 rx_packet_start(u16 ptr) +{ + if (ptr + RSV_SIZE > RXEND_INIT) + return (ptr + RSV_SIZE) - (RXEND_INIT - RXSTART_INIT + 1); + else + return ptr + RSV_SIZE; +} + static void nolock_rxfifo_init(struct enc28j60_net *priv, u16 start, u16 end) { u16 erxrdpt; @@ -938,8 +949,9 @@ static void enc28j60_hw_rx(struct net_device *ndev) skb->dev = ndev; skb_reserve(skb, NET_IP_ALIGN); /* copy the packet from the receive buffer */ - enc28j60_mem_read(priv, priv->next_pk_ptr + sizeof(rsv), - len, skb_put(skb, len)); + enc28j60_mem_read(priv, + rx_packet_start(priv->next_pk_ptr), + len, skb_put(skb, len)); if (netif_msg_pktdata(priv)) dump_packet(__func__, skb->len, skb->data); skb->protocol = eth_type_trans(skb, ndev); -- cgit v1.2.3 From 2cc002c4bbce4d918ab94b494d61c6991c907d5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 3 Dec 2008 22:18:59 -0800 Subject: netx-eth: initialize per device spinlock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The spinlock used in the netx-eth driver was never properly initialized. This was noticed using CONFIG_DEBUG_SPINLOCK=y Signed-off-by: Uwe Kleine-König Acked-by: Sascha Hauer Signed-off-by: David S. Miller --- drivers/net/netx-eth.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c index b9bed82e1d2..b289a0a2b94 100644 --- a/drivers/net/netx-eth.c +++ b/drivers/net/netx-eth.c @@ -401,6 +401,8 @@ static int netx_eth_drv_probe(struct platform_device *pdev) priv->xmac_base = priv->xc->xmac_base; priv->sram_base = priv->xc->sram_base; + spin_lock_init(&priv->lock); + ret = pfifo_request(PFIFO_MASK(priv->id)); if (ret) { printk("unable to request PFIFO\n"); -- cgit v1.2.3 From fd4ce1acd0f8558033b1a6968001552bd7671e6d Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 5 Nov 2008 14:58:42 +0100 Subject: [PATCH 1/2] kill FMODE_NDELAY_NOW Update FMODE_NDELAY before each ioctl call so that we can kill the magic FMODE_NDELAY_NOW. It would be even better to do this directly in setfl(), but for that we'd need to have FMODE_NDELAY for all files, not just block special files. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- drivers/scsi/sd.c | 2 +- drivers/scsi/sr.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index c9e1242eaf2..5081b3981d3 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -757,7 +757,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, * access to the device is prohibited. */ error = scsi_nonblockable_ioctl(sdp, cmd, p, - (mode & FMODE_NDELAY_NOW) != 0); + (mode & FMODE_NDELAY) != 0); if (!scsi_block_when_processing_errors(sdp) || !error) return error; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 62b6633e3a9..45b66b98a51 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -521,7 +521,7 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, * if it doesn't recognise the ioctl */ ret = scsi_nonblockable_ioctl(sdev, cmd, argp, - (mode & FMODE_NDELAY_NOW) != 0); + (mode & FMODE_NDELAY) != 0); if (ret != -ENODEV) return ret; return scsi_ioctl(sdev, cmd, argp); -- cgit v1.2.3 From 2cbed8906fd1f3c6cc17cdf8aac1bfad2da7960c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 30 Nov 2008 01:33:57 -0500 Subject: [PATCH] fix bogus argument of blkdev_put() in pktcdvd final close of ->bdev should match the initial open, i.e. get FMODE_READ | FMODE_NDELAY; FMODE_READ|FMODE_WRITE has been a braino. Signed-off-by: Al Viro --- drivers/block/pktcdvd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index f20bf359b84..edda7b6b077 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2790,7 +2790,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev) return 0; out_mem: - blkdev_put(bdev, FMODE_READ|FMODE_WRITE); + blkdev_put(bdev, FMODE_READ | FMODE_NDELAY); /* This is safe: open() is still holding a reference. */ module_put(THIS_MODULE); return ret; @@ -2975,7 +2975,7 @@ static int pkt_remove_dev(dev_t pkt_dev) pkt_debugfs_dev_remove(pd); pkt_sysfs_dev_remove(pd); - blkdev_put(pd->bdev, FMODE_READ|FMODE_WRITE); + blkdev_put(pd->bdev, FMODE_READ | FMODE_NDELAY); remove_proc_entry(pd->name, pkt_proc); DPRINTK(DRIVER_NAME": writer %s unmapped\n", pd->name); -- cgit v1.2.3 From aaad077638be1a25871bcae5e43952d6b63abfca Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 5 Dec 2008 01:07:51 +0100 Subject: ACPI: Fix ACPI battery regression introduced by commit 558073 Commit 558073dd56707864f09d563b64e7c37c021e89d2 ("ACPI: battery: Convert discharge energy rate to current properly") caused the battery subsystem to report wrong values of the remaining time on battery power and the time until fully charged on Toshiba Portege R500 (and presumably on other boxes too). Fix the issue by correcting the conversion from mW to mA. Signed-off-by: Rafael J. Wysocki Signed-off-by: Linus Torvalds --- drivers/acpi/battery.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index a0a178dd189..4fb3c12ac1d 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -173,14 +173,17 @@ static int acpi_battery_get_property(struct power_supply *psy, val->intval = battery->voltage_now * 1000; break; case POWER_SUPPLY_PROP_CURRENT_NOW: - val->intval = battery->current_now * 1000; - /* if power units are mW, convert to mA by - dividing by current voltage (mV/1000) */ - if (!battery->power_unit) { - if (battery->voltage_now) { + val->intval = battery->current_now; + if (battery->power_unit) { + val->intval *= 1000; + } else { + /* + * If power units are mW, convert to mA by dividing by + * current voltage. + */ + if (battery->voltage_now) val->intval /= battery->voltage_now; - val->intval *= 1000; - } else + else val->intval = -1; } break; -- cgit v1.2.3 From 40a9a8299116297429298e8fcee08235134883f7 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 25 Nov 2008 23:29:03 +0200 Subject: iwlwifi: clean key table in iwl_clear_stations_table function This patch cleans uCode key table bit map iwl_clear_stations_table since all stations are cleared also the key table must be. Since the keys are not removed properly on suspend by mac80211 this may result in exhausting key table on resume leading to memory corruption during removal This patch also fixes a memory corruption problem reported in http://marc.info/?l=linux-wireless&m=122641417231586&w=2 and tracked in http://bugzilla.kernel.org/show_bug.cgi?id=12040. When the key is removed a second time the offset is set to 255 - this index is not valid for the ucode_key_table and corrupts the eeprom pointer (which is 255 bits from ucode_key_table). Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Reported-by: Carlos R. Mafra Reported-by: Lukas Hejtmanek Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 3 +++ drivers/net/wireless/iwlwifi/iwl-sta.c | 24 +++++++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 4c312c55f90..01a84585133 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -290,6 +290,9 @@ void iwl_clear_stations_table(struct iwl_priv *priv) priv->num_stations = 0; memset(priv->stations, 0, sizeof(priv->stations)); + /* clean ucode key table bit map */ + priv->ucode_key_table = 0; + spin_unlock_irqrestore(&priv->sta_lock, flags); } EXPORT_SYMBOL(iwl_clear_stations_table); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 61797f3f8d5..26f7084d301 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -475,7 +475,7 @@ static int iwl_get_free_ucode_key_index(struct iwl_priv *priv) if (!test_and_set_bit(i, &priv->ucode_key_table)) return i; - return -1; + return WEP_INVALID_OFFSET; } int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) @@ -620,6 +620,9 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, /* else, we are overriding an existing key => no need to allocated room * in uCode. */ + WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, + "no space for new kew"); + priv->stations[sta_id].sta.key.key_flags = key_flags; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; @@ -637,6 +640,7 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, { unsigned long flags; __le16 key_flags = 0; + int ret; key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); @@ -664,14 +668,18 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, /* else, we are overriding an existing key => no need to allocated room * in uCode. */ + WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, + "no space for new kew"); + priv->stations[sta_id].sta.key.key_flags = key_flags; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); + spin_unlock_irqrestore(&priv->sta_lock, flags); - IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n"); - return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); + return ret; } static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, @@ -696,6 +704,9 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, /* else, we are overriding an existing key => no need to allocated room * in uCode. */ + WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, + "no space for new kew"); + /* This copy is acutally not needed: we get the key with each TX */ memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); @@ -734,6 +745,13 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, return 0; } + if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) { + IWL_WARNING("Removing wrong key %d 0x%x\n", + keyconf->keyidx, key_flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); + return 0; + } + if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset, &priv->ucode_key_table)) IWL_ERROR("index %d not used in uCode key table.\n", -- cgit v1.2.3 From b8ddafd759e356c839774a8b87011b768deb53b3 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 27 Nov 2008 13:42:20 +0800 Subject: ipw2200: fix netif_*_queue() removal regression In "ipw2200: Call netif_*_queue() interfaces properly", netif_stop_queue() and netif_wake_queue() were removed with the reason "netif_carrier_{on,off}() handles starting and stopping packet flow into the driver". The patch also removes a valid condition check that ipw_tx_skb() cannot be called if device is not in STATUS_ASSOCIATED state. But netif_carrier_off() doesn't guarantee netdev->hard_start_xmit won't be called because linkwatch event is handled in a delayed workqueue. This caused a kernel oops reported by Frank Seidel: https://bugzilla.novell.com/show_bug.cgi?id=397390 This patch fixes the problem by moving the STATUS_ASSOCIATED check back to ipw_tx_skb(). It also adds a missing netif_carrier_off() call to ipw_disassociate(). Signed-off-by: Zhu Yi Signed-off-by: Chatre, Reinette Tested-by: Frank Seidel Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index dcce3542d5a..7a9f901d4ff 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -3897,6 +3897,7 @@ static int ipw_disassociate(void *data) if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) return 0; ipw_send_disassociate(data, 0); + netif_carrier_off(priv->net_dev); return 1; } @@ -10190,6 +10191,9 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, u16 remaining_bytes; int fc; + if (!(priv->status & STATUS_ASSOCIATED)) + goto drop; + hdr_len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); switch (priv->ieee->iw_mode) { case IW_MODE_ADHOC: -- cgit v1.2.3 From cde6901b7b69557a6f90f3183f76eda581af015e Mon Sep 17 00:00:00 2001 From: Shaddy Baddah Date: Fri, 28 Nov 2008 17:10:45 +1100 Subject: zd1211rw: use unaligned safe memcmp() in-place of compare_ether_addr() Under my 2.6.28-rc6 sparc64, when associating to an AP through my zd1211rw device, I was seeing kernel log messages like (not exact output): Kernel unaligned access at TPC[10129b68] zd_mac_rx+0x144/0x32c [zd1211rw] For the zd1211rw module, on RX, the 80211 packet will be located after the PLCP header in the skb data buffer. The PLCP header being 5 bytes long, the 80211 header will start unaligned from an aligned skb buffer. As per Documentation/unaligned-memory-access.txt, we must replace the not unaligned() safe compare_ether_addr() with memcmp() to protect architectures that require alignment. Signed-off-by: Shaddy Baddah Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index fe1867b25ff..cac732f4047 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -615,7 +615,7 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, struct ieee80211_hdr *tx_hdr; tx_hdr = (struct ieee80211_hdr *)skb->data; - if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1))) + if (likely(!memcmp(tx_hdr->addr2, rx_hdr->addr1, ETH_ALEN))) { __skb_unlink(skb, q); tx_status(hw, skb, IEEE80211_TX_STAT_ACK, stats->signal, 1); -- cgit v1.2.3 From f10a3a32ae2edbe94920ce6827f4c2550eb6ed48 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 5 Dec 2008 13:30:03 -0800 Subject: Revert "ACPI: battery: Convert discharge energy rate to current properly" This reverts commit 558073dd56707864f09d563b64e7c37c021e89d2, along with the failed try to fix the regression it caused ("ACPI: Fix ACPI battery regression introduced by commit 558073"), which just made things worse. Commit aaad077638be1a25871bcae5e43952d6b63abfca (that failed "Fix ACPI battery regression") got the voltage conversion confused, and fixed the problem with Rafael's battery monitor apparently just by mistake. So revert them both, getting us back to the 2.6.27 state in this, and let's revisit it when people understand what's going on. Noted-by: Paul Martin Requested-by: Rafael J. Wysocki Cc: Len Brown Cc: Alexey Starikovskiy Signed-off-by: Linus Torvalds --- drivers/acpi/battery.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 4fb3c12ac1d..1423b0c0cd2 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -173,19 +173,7 @@ static int acpi_battery_get_property(struct power_supply *psy, val->intval = battery->voltage_now * 1000; break; case POWER_SUPPLY_PROP_CURRENT_NOW: - val->intval = battery->current_now; - if (battery->power_unit) { - val->intval *= 1000; - } else { - /* - * If power units are mW, convert to mA by dividing by - * current voltage. - */ - if (battery->voltage_now) - val->intval /= battery->voltage_now; - else - val->intval = -1; - } + val->intval = battery->current_now * 1000; break; case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: -- cgit v1.2.3 From c4f0124057bd92d032d2d146034995f15f4297de Mon Sep 17 00:00:00 2001 From: Nick Andrew Date: Fri, 5 Dec 2008 16:34:46 +0000 Subject: Fix incorrect use of loose in tty/serial drivers [Folded together as one diff from 3] It should be 'lose', not 'loose'. Signed-off-by: Nick Andrew Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/serial167.c | 2 +- drivers/serial/mpc52xx_uart.c | 4 ++-- drivers/usb/serial/ftdi_sio.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 3b23270eaa6..a8f15e6be59 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -418,7 +418,7 @@ static irqreturn_t cd2401_rxerr_interrupt(int irq, void *dev_id) TTY_OVERRUN); /* If the flip buffer itself is - overflowing, we still loose + overflowing, we still lose the next incoming character. */ if (tty_buffer_request_room(tty, 1) != diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 6117d3db0b6..28c00c3d58f 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -591,8 +591,8 @@ mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new, /* Update the per-port timeout */ uart_update_timeout(port, new->c_cflag, baud); - /* Do our best to flush TX & RX, so we don't loose anything */ - /* But we don't wait indefinitly ! */ + /* Do our best to flush TX & RX, so we don't lose anything */ + /* But we don't wait indefinitely ! */ j = 5000000; /* Maximum wait */ /* FIXME Can't receive chars since set_termios might be called at early * boot for the console, all stuff is not yet ready to receive at that diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 51d7bdea286..aad1359a3eb 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1498,7 +1498,7 @@ static int ftdi_open(struct tty_struct *tty, priv->interface, buf, 0, WDR_TIMEOUT); /* Termios defaults are set by usb_serial_init. We don't change - port->tty->termios - this would loose speed settings, etc. + port->tty->termios - this would lose speed settings, etc. This is same behaviour as serial.c/rs_open() - Kuba */ /* ftdi_set_termios will send usb control messages */ -- cgit v1.2.3 From 5e333309c59da608d4dd3cbaa67a061d817fdce2 Mon Sep 17 00:00:00 2001 From: Nick Andrew Date: Fri, 5 Dec 2008 16:34:56 +0000 Subject: Fix incorrect use of loose in i2o_block.c Fix incorrect use of loose in i2o_block.c It should be 'lose', not 'loose'. Signed-off-by: Nick Andrew Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/message/i2o/i2o_block.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 84bdc2ee69e..a443e136dc4 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -354,7 +354,7 @@ static inline void i2o_block_sglist_free(struct i2o_block_request *ireq) * @req: the request to prepare * * Allocate the necessary i2o_block_request struct and connect it to - * the request. This is needed that we not loose the SG list later on. + * the request. This is needed that we not lose the SG list later on. * * Returns BLKPREP_OK on success or BLKPREP_DEFER on failure. */ -- cgit v1.2.3 From 2289e6643660601d3b21a22effd04dcca27775e4 Mon Sep 17 00:00:00 2001 From: Qinghuang Feng Date: Fri, 5 Dec 2008 16:35:07 +0000 Subject: drivers/message/i2o/iop.c: cleanup kerneldoc no argument named @msg in i2o_msg_get_wait(), remove it. Signed-off-by: Qinghuang Feng Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/message/i2o/iop.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index be2b5926d26..6e53a30bfd3 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c @@ -49,7 +49,6 @@ static int i2o_hrt_get(struct i2o_controller *c); /** * i2o_msg_get_wait - obtain an I2O message from the IOP * @c: I2O controller - * @msg: pointer to a I2O message pointer * @wait: how long to wait until timeout * * This function waits up to wait seconds for a message slot to be -- cgit v1.2.3 From 1a659880ee755d96eeabe64bded059abed6d5ef5 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 8 Dec 2008 17:42:35 +0100 Subject: Revert "ide: respect current DMA setting during resume" This reverts commit e9eb8388306364295308132265c00bea685f409f since it could break resume (thanks to Paul Collins for the report). I'll look into sorting this out properly for 2.6.29 but for 2.6.28 it is the best to just revert my patch. Reported-by: Paul Collins Cc: rjw@sisk.pl Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 7d275b2af3e..cc35d6dbd41 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -208,8 +208,10 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * */ if (drive->hwif->dma_ops == NULL) break; - if (drive->dev_flags & IDE_DFLAG_USING_DMA) - ide_set_dma(drive); + /* + * TODO: respect IDE_DFLAG_USING_DMA + */ + ide_set_dma(drive); break; } -- cgit v1.2.3 From 53846574799884a04a4498f6342400d5c1423c79 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 8 Dec 2008 17:52:05 +0100 Subject: ide: build-fix for CONFIG_BLK_DEV_IDEDMA_PMAC=n IDE pmac host driver build fails with CONFIG_BLK_DEV_IDEDMA_PMAC=n as reported by Kamalesh: > drivers/ide/pmac.c: In function 'pmac_ide_set_pio_mode': > drivers/ide/pmac.c:527: error: implicit declaration of function 'kauai_lookup_timing' > drivers/ide/pmac.c:527: error: 'shasta_pio_timings' undeclared (first use in this function) > drivers/ide/pmac.c:527: error: (Each undeclared identifier is reported only once > drivers/ide/pmac.c:527: error: for each function it appears in.) > drivers/ide/pmac.c:534: error: 'kauai_pio_timings' undeclared (first use in this function) > drivers/ide/pmac.c: In function 'pmac_ide_do_resume': > drivers/ide/pmac.c:914: error: 'IDE_WAKEUP_DELAY' undeclared (first use in this function) > drivers/ide/pmac.c: At top level: > drivers/ide/pmac.c:1007: error: 'pmac_ide_init_dma' undeclared here (not in a function) > drivers/ide/pmac.c: In function 'pmac_ide_setup_device': > drivers/ide/pmac.c:1107: error: 'IDE_WAKEUP_DELAY' undeclared (first use in this function) > drivers/ide/pmac.c: In function 'pmac_ide_macio_attach': > drivers/ide/pmac.c:1209: error: 'pmac_ide_hwif_t' has no member named 'dma_regs' > drivers/ide/pmac.c:1210: error: 'pmac_ide_hwif_t' has no member named 'dma_regs' > make[2]: *** [drivers/ide/pmac.o] Error 1 Fix it by removing the superfluous config option. Reported-and-tested-by: Kamalesh Babulal Cc: Benjamin Herrenschmidt Cc: Sergei Shtylyov Cc: Stephen Rothwell Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Kconfig | 14 +++----------- drivers/ide/pmac.c | 30 +++--------------------------- 2 files changed, 6 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 6d7401772a8..e6857e01d1b 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -669,10 +669,12 @@ config BLK_DEV_CELLEB endif +# TODO: BLK_DEV_IDEDMA_PCI -> BLK_DEV_IDEDMA_SFF config BLK_DEV_IDE_PMAC tristate "PowerMac on-board IDE support" depends on PPC_PMAC && IDE=y select IDE_TIMINGS + select BLK_DEV_IDEDMA_PCI help This driver provides support for the on-board IDE controller on most of the recent Apple Power Macintoshes and PowerBooks. @@ -689,16 +691,6 @@ config BLK_DEV_IDE_PMAC_ATA100FIRST CD-ROM on hda. This option changes this to more natural hda for hard disk and hdc for CD-ROM. -config BLK_DEV_IDEDMA_PMAC - bool "PowerMac IDE DMA support" - depends on BLK_DEV_IDE_PMAC - select BLK_DEV_IDEDMA_PCI - help - This option allows the driver for the on-board IDE controller on - Power Macintoshes and PowerBooks to use DMA (direct memory access) - to transfer data to and from memory. Saying Y is safe and improves - performance. - config BLK_DEV_IDE_AU1XXX bool "IDE for AMD Alchemy Au1200" depends on SOC_AU1200 @@ -912,7 +904,7 @@ config BLK_DEV_UMC8672 endif config BLK_DEV_IDEDMA - def_bool BLK_DEV_IDEDMA_SFF || BLK_DEV_IDEDMA_PMAC || \ + def_bool BLK_DEV_IDEDMA_SFF || \ BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA endif # IDE diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c index 2e19d629853..7c481bb56fa 100644 --- a/drivers/ide/pmac.c +++ b/drivers/ide/pmac.c @@ -66,7 +66,6 @@ typedef struct pmac_ide_hwif { struct macio_dev *mdev; u32 timings[4]; volatile u32 __iomem * *kauai_fcr; -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC /* Those fields are duplicating what is in hwif. We currently * can't use the hwif ones because of some assumptions that are * beeing done by the generic code about the kind of dma controller @@ -74,8 +73,6 @@ typedef struct pmac_ide_hwif { */ volatile struct dbdma_regs __iomem * dma_regs; struct dbdma_cmd* dma_table_cpu; -#endif - } pmac_ide_hwif_t; enum { @@ -222,8 +219,6 @@ static const char* model_name[] = { #define KAUAI_FCR_UATA_RESET_N 0x00000002 #define KAUAI_FCR_UATA_ENABLE 0x00000001 -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - /* Rounded Multiword DMA timings * * I gave up finding a generic formula for all controller @@ -413,8 +408,6 @@ static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq); static void pmac_ide_selectproc(ide_drive_t *drive); static void pmac_ide_kauai_selectproc(ide_drive_t *drive); -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - #define PMAC_IDE_REG(x) \ ((void __iomem *)((drive)->hwif->io_ports.data_addr + (x))) @@ -584,8 +577,6 @@ pmac_ide_set_pio_mode(ide_drive_t *drive, const u8 pio) pmac_ide_do_update_timings(drive); } -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - /* * Calculate KeyLargo ATA/66 UDMA timings */ @@ -786,7 +777,6 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2, drive->name, speed & 0xf, *timings); #endif } -#endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */ static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed) { @@ -804,7 +794,6 @@ static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed) tl[0] = *timings; tl[1] = *timings2; -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC if (speed >= XFER_UDMA_0) { if (pmif->kind == controller_kl_ata4) ret = set_timings_udma_ata4(&tl[0], speed); @@ -817,7 +806,7 @@ static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed) ret = -1; } else set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed); -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + if (ret) return; @@ -1008,9 +997,7 @@ static const struct ide_port_info pmac_port_info = { .chipset = ide_pmac, .tp_ops = &pmac_tp_ops, .port_ops = &pmac_ide_port_ops, -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC .dma_ops = &pmac_dma_ops, -#endif .host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA | IDE_HFLAG_POST_SET_MODE | IDE_HFLAG_MMIO | @@ -1182,7 +1169,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) pmif->regbase = regbase; pmif->irq = irq; pmif->kauai_fcr = NULL; -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC + if (macio_resource_count(mdev) >= 2) { if (macio_request_resource(mdev, 1, "ide-pmac (dma)")) printk(KERN_WARNING "ide-pmac: can't request DMA " @@ -1192,7 +1179,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) pmif->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x1000); } else pmif->dma_regs = NULL; -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ + dev_set_drvdata(&mdev->ofdev.dev, pmif); memset(&hw, 0, sizeof(hw)); @@ -1300,9 +1287,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id) base = ioremap(rbase, rlen); pmif->regbase = (unsigned long) base + 0x2000; -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC pmif->dma_regs = base + 0x1000; -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ pmif->kauai_fcr = base; pmif->irq = pdev->irq; @@ -1434,8 +1419,6 @@ out: return error; } -#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC - /* * pmac_ide_build_dmatable builds the DBDMA command list * for a transfer and sets the DBDMA channel to point to it. @@ -1723,13 +1706,6 @@ static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif, return 0; } -#else -static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif, - const struct ide_port_info *d) -{ - return -EOPNOTSUPP; -} -#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ module_init(pmac_ide_probe); -- cgit v1.2.3 From a06d568f7c5e40e34ea64881842deb8f4382babf Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 8 Dec 2008 13:46:00 -0700 Subject: async_xor: dma_map destination DMA_BIDIRECTIONAL Mapping the destination multiple times is a misuse of the dma-api. Since the destination may be reused as a source, ensure that it is only mapped once and that it is mapped bidirectionally. This appears to add ugliness on the unmap side in that it always reads back the destination address from the descriptor, but gcc can determine that dma_unmap is a nop and not emit the code that calculates its arguments. Cc: Cc: Saeed Bishara Acked-by: Yuri Tikhonov Signed-off-by: Dan Williams --- drivers/dma/iop-adma.c | 16 +++++++++++++--- drivers/dma/mv_xor.c | 15 ++++++++++++--- 2 files changed, 25 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index c7a9306d951..6be31726220 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c @@ -85,18 +85,28 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc, enum dma_ctrl_flags flags = desc->async_tx.flags; u32 src_cnt; dma_addr_t addr; + dma_addr_t dest; + src_cnt = unmap->unmap_src_cnt; + dest = iop_desc_get_dest_addr(unmap, iop_chan); if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) { - addr = iop_desc_get_dest_addr(unmap, iop_chan); - dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE); + enum dma_data_direction dir; + + if (src_cnt > 1) /* is xor? */ + dir = DMA_BIDIRECTIONAL; + else + dir = DMA_FROM_DEVICE; + + dma_unmap_page(dev, dest, len, dir); } if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) { - src_cnt = unmap->unmap_src_cnt; while (src_cnt--) { addr = iop_desc_get_src_addr(unmap, iop_chan, src_cnt); + if (addr == dest) + continue; dma_unmap_page(dev, addr, len, DMA_TO_DEVICE); } diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 0328da020a1..bcda1742641 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -311,17 +311,26 @@ mv_xor_run_tx_complete_actions(struct mv_xor_desc_slot *desc, enum dma_ctrl_flags flags = desc->async_tx.flags; u32 src_cnt; dma_addr_t addr; + dma_addr_t dest; + src_cnt = unmap->unmap_src_cnt; + dest = mv_desc_get_dest_addr(unmap); if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) { - addr = mv_desc_get_dest_addr(unmap); - dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE); + enum dma_data_direction dir; + + if (src_cnt > 1) /* is xor ? */ + dir = DMA_BIDIRECTIONAL; + else + dir = DMA_FROM_DEVICE; + dma_unmap_page(dev, dest, len, dir); } if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) { - src_cnt = unmap->unmap_src_cnt; while (src_cnt--) { addr = mv_desc_get_src_addr(unmap, src_cnt); + if (addr == dest) + continue; dma_unmap_page(dev, addr, len, DMA_TO_DEVICE); } -- cgit v1.2.3 From fae7043c65d65f3e5b34bac4431c6ccc49190c41 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 9 Dec 2008 15:30:50 +1000 Subject: drm/radeon: don't actually enable the IRQ regs until irq is enabled vblank can try and enable the IRQ registers before we've set the interrupt handler up. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_drv.h | 1 - drivers/gpu/drm/radeon/radeon_irq.c | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 7a183789be9..3bbb871b25d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -299,7 +299,6 @@ typedef struct drm_radeon_private { atomic_t swi_emitted; int vblank_crtc; uint32_t irq_enable_reg; - int irq_enabled; uint32_t r500_disp_irq_reg; struct radeon_surface surfaces[RADEON_MAX_SURFACES]; diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c index 97c0599fdb1..99be11418ac 100644 --- a/drivers/gpu/drm/radeon/radeon_irq.c +++ b/drivers/gpu/drm/radeon/radeon_irq.c @@ -44,7 +44,8 @@ void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state) else dev_priv->irq_enable_reg &= ~mask; - RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); + if (!dev->irq_enabled) + RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); } static void r500_vbl_irq_set_state(struct drm_device *dev, u32 mask, int state) @@ -56,7 +57,8 @@ static void r500_vbl_irq_set_state(struct drm_device *dev, u32 mask, int state) else dev_priv->r500_disp_irq_reg &= ~mask; - RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg); + if (!dev->irq_enabled) + RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg); } int radeon_enable_vblank(struct drm_device *dev, int crtc) @@ -355,8 +357,6 @@ void radeon_driver_irq_uninstall(struct drm_device * dev) if (!dev_priv) return; - dev_priv->irq_enabled = 0; - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) RADEON_WRITE(R500_DxMODE_INT_MASK, 0); /* Disable *all* interrupts */ -- cgit v1.2.3 From 15c35334c9b7a11f66ddf7fea9367884e1f5414f Mon Sep 17 00:00:00 2001 From: Owain Ainsworth Date: Sat, 6 Dec 2008 20:42:20 -0800 Subject: drm/i915: Don't return error in evict_everything when we get to the end. Returning -ENOMEM errored all the way out of execbuf, so the rendering never occurred. Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_gem.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 3fde82be014..ad672d85482 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1104,6 +1104,8 @@ i915_gem_evict_everything(struct drm_device *dev) if (ret != 0) break; } + if (ret == -ENOMEM) + return 0; return ret; } -- cgit v1.2.3 From b60678a75d44fa9d5969f79781bd856ad5858609 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Dec 2008 11:12:28 -0800 Subject: drm/i915: Disable the GM965 MSI errata workaround. Since applying the fix suggested by the errata (disabling MSI), we've had issues with interrupts being stuck on despite IIR being 0 on GM965 hardware. Most reporters of the issue have confirmed that turning MSI back on fixes things, and given the difficulties experienced in getting reliable MSI working on Linux, it's believable that the errata was about software issues and not actual hardware issues. Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_dma.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index ba89b42f790..553dd4bc307 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -847,9 +847,10 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) * and the registers being closely associated. * * According to chipset errata, on the 965GM, MSI interrupts may - * be lost or delayed + * be lost or delayed, but we use them anyways to avoid + * stuck interrupts on some machines. */ - if (!IS_I945G(dev) && !IS_I945GM(dev) && !IS_I965GM(dev)) + if (!IS_I945G(dev) && !IS_I945GM(dev)) pci_enable_msi(dev->pdev); intel_opregion_init(dev); -- cgit v1.2.3 From 2456eb819be7aa2cac73359c2855dfa30e46d75a Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 8 Dec 2008 18:48:42 +0900 Subject: pata_hpt366: fix clock detection pata_hpt366 had its clock detection wrong and detected 25Mhz as 40Mhz and vice-versa. Fix it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/pata_hpt366.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index f2b83eabc7c..a098ba8eaab 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -382,10 +382,10 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) /* PCI clocking determines the ATA timing values to use */ /* info_hpt366 is safe against re-entry so we can scribble on it */ switch((reg1 & 0x700) >> 8) { - case 5: + case 9: hpriv = &hpt366_40; break; - case 9: + case 5: hpriv = &hpt366_25; break; default: -- cgit v1.2.3 From 9ac6212660fa3d8d0d21e782a22b956a6bc78a43 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 3 Dec 2008 09:13:46 +0100 Subject: ATA: piix, fix pointer deref on suspend Hi, I've found this issue in the mmotm 2008-12-02-17-08. -- Commit ata_piix: add borked Tecra M4 to broken suspend list introduced DMI variables checking, but they can be null, so that we possibly dereference null. Check if they are null and avoid checks in that case. Solves: BUG: unable to handle kernel NULL pointer dereference at 0000000000000000 IP: [] piix_pci_device_suspend+0x117/0x230 Signed-off-by: Jiri Slaby Cc: Jeff Garzik Cc: Alexandru Romanescu Cc: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index d6d97d8f3fa..c11936e13dd 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -1072,7 +1072,14 @@ static int piix_broken_suspend(void) * matching is necessary because dmi_system_id.matches is * limited to four entries. */ - if (!strcmp(dmi_get_system_info(DMI_SYS_VENDOR), "TOSHIBA") && + if (dmi_get_system_info(DMI_SYS_VENDOR) && + dmi_get_system_info(DMI_PRODUCT_NAME) && + dmi_get_system_info(DMI_PRODUCT_VERSION) && + dmi_get_system_info(DMI_PRODUCT_SERIAL) && + dmi_get_system_info(DMI_BOARD_VENDOR) && + dmi_get_system_info(DMI_BOARD_NAME) && + dmi_get_system_info(DMI_BOARD_VERSION) && + !strcmp(dmi_get_system_info(DMI_SYS_VENDOR), "TOSHIBA") && !strcmp(dmi_get_system_info(DMI_PRODUCT_NAME), "000000") && !strcmp(dmi_get_system_info(DMI_PRODUCT_VERSION), "000000") && !strcmp(dmi_get_system_info(DMI_PRODUCT_SERIAL), "000000") && -- cgit v1.2.3 From e33ba2c6c668a2be8f192b383186ee7cbb371da0 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 5 Dec 2008 19:41:52 +0000 Subject: pata_sis: Remove bogus cable match Some systems report SIS 5513 as both vendor/id and subvendor/id string. In that case we can't distinguish the system by the id svid/sdid and in fact the entry here breaks some boxes. At some point we need to find another way to detect the Targa Visionary 1000, until then this trades a hang for some users with lower performance for others. Closes: #12092 Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/pata_sis.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index d3423661175..e4be55e047f 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c @@ -56,7 +56,6 @@ static const struct sis_laptop sis_laptop[] = { { 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */ { 0x5513, 0x1734, 0x105F }, /* FSC Amilo A1630 */ { 0x5513, 0x1071, 0x8640 }, /* EasyNote K5305 */ - { 0x5513, 0x1039, 0x5513 }, /* Targa Visionary 1000 */ /* end marker */ { 0, } }; -- cgit v1.2.3 From b604958a98f108dc6a44c32cc8062659bd5fd324 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 5 Dec 2008 19:42:38 +0000 Subject: pata_ninja32: update ID table Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/pata_ninja32.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c index 4e466eae8b4..4dd9a3b031e 100644 --- a/drivers/ata/pata_ninja32.c +++ b/drivers/ata/pata_ninja32.c @@ -44,7 +44,7 @@ #include #define DRV_NAME "pata_ninja32" -#define DRV_VERSION "0.1.1" +#define DRV_VERSION "0.1.3" /** @@ -130,7 +130,8 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id) return rc; pci_set_master(dev); - /* Set up the register mappings */ + /* Set up the register mappings. We use the I/O mapping as only the + older chips also have MMIO on BAR 1 */ base = host->iomap[0]; if (!base) return -ENOMEM; @@ -167,8 +168,12 @@ static int ninja32_reinit_one(struct pci_dev *pdev) #endif static const struct pci_device_id ninja32[] = { + { 0x10FC, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0x1145, 0x8008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0x1145, 0xf008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { 0x1145, 0xf02C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { }, }; -- cgit v1.2.3 From e3389cbc65ecc486d4aea2f0e9114abc0f849be2 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 5 Dec 2008 19:43:03 +0000 Subject: ata: Fix experimental tags Various tags are now way out of date Signed-off-by: Jeff Garzik --- drivers/ata/Kconfig | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 78fbec8ceda..421b7c71e72 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -153,7 +153,7 @@ config SATA_PROMISE If unsure, say N. config SATA_SX4 - tristate "Promise SATA SX4 support" + tristate "Promise SATA SX4 support (Experimental)" depends on PCI && EXPERIMENTAL help This option enables support for Promise Serial ATA SX4. @@ -219,8 +219,8 @@ config PATA_ACPI otherwise unsupported hardware. config PATA_ALI - tristate "ALi PATA support (Experimental)" - depends on PCI && EXPERIMENTAL + tristate "ALi PATA support" + depends on PCI help This option enables support for the ALi ATA interfaces found on the many ALi chipsets. @@ -263,7 +263,7 @@ config PATA_ATIIXP If unsure, say N. config PATA_CMD640_PCI - tristate "CMD640 PCI PATA support (Very Experimental)" + tristate "CMD640 PCI PATA support (Experimental)" depends on PCI && EXPERIMENTAL help This option enables support for the CMD640 PCI IDE @@ -291,8 +291,8 @@ config PATA_CS5520 If unsure, say N. config PATA_CS5530 - tristate "CS5530 PATA support (Experimental)" - depends on PCI && EXPERIMENTAL + tristate "CS5530 PATA support" + depends on PCI help This option enables support for the Cyrix/NatSemi/AMD CS5530 companion chip used with the MediaGX/Geode processor family. @@ -309,8 +309,8 @@ config PATA_CS5535 If unsure, say N. config PATA_CS5536 - tristate "CS5536 PATA support (Experimental)" - depends on PCI && X86 && !X86_64 && EXPERIMENTAL + tristate "CS5536 PATA support" + depends on PCI && X86 && !X86_64 help This option enables support for the AMD CS5536 companion chip used with the Geode LX processor family. @@ -363,7 +363,7 @@ config PATA_HPT37X If unsure, say N. config PATA_HPT3X2N - tristate "HPT 372N/302N PATA support (Very Experimental)" + tristate "HPT 372N/302N PATA support (Experimental)" depends on PCI && EXPERIMENTAL help This option enables support for the N variant HPT PATA @@ -389,8 +389,8 @@ config PATA_HPT3X3_DMA problems with DMA on this chipset. config PATA_ISAPNP - tristate "ISA Plug and Play PATA support (Experimental)" - depends on EXPERIMENTAL && ISAPNP + tristate "ISA Plug and Play PATA support" + depends on ISAPNP help This option enables support for ISA plug & play ATA controllers such as those found on old soundcards. @@ -498,8 +498,8 @@ config PATA_NINJA32 If unsure, say N. config PATA_NS87410 - tristate "Nat Semi NS87410 PATA support (Experimental)" - depends on PCI && EXPERIMENTAL + tristate "Nat Semi NS87410 PATA support" + depends on PCI help This option enables support for the National Semiconductor NS87410 PCI-IDE controller. @@ -507,8 +507,8 @@ config PATA_NS87410 If unsure, say N. config PATA_NS87415 - tristate "Nat Semi NS87415 PATA support (Experimental)" - depends on PCI && EXPERIMENTAL + tristate "Nat Semi NS87415 PATA support" + depends on PCI help This option enables support for the National Semiconductor NS87415 PCI-IDE controller. @@ -544,8 +544,8 @@ config PATA_PCMCIA If unsure, say N. config PATA_PDC_OLD - tristate "Older Promise PATA controller support (Experimental)" - depends on PCI && EXPERIMENTAL + tristate "Older Promise PATA controller support" + depends on PCI help This option enables support for the Promise 20246, 20262, 20263, 20265 and 20267 adapters. @@ -559,7 +559,7 @@ config PATA_QDI Support for QDI 6500 and 6580 PATA controllers on VESA local bus. config PATA_RADISYS - tristate "RADISYS 82600 PATA support (Very Experimental)" + tristate "RADISYS 82600 PATA support (Experimental)" depends on PCI && EXPERIMENTAL help This option enables support for the RADISYS 82600 @@ -586,8 +586,8 @@ config PATA_RZ1000 If unsure, say N. config PATA_SC1200 - tristate "SC1200 PATA support (Very Experimental)" - depends on PCI && EXPERIMENTAL + tristate "SC1200 PATA support" + depends on PCI help This option enables support for the NatSemi/AMD SC1200 SoC companion chip used with the Geode processor family. @@ -620,8 +620,8 @@ config PATA_SIL680 If unsure, say N. config PATA_SIS - tristate "SiS PATA support (Experimental)" - depends on PCI && EXPERIMENTAL + tristate "SiS PATA support" + depends on PCI help This option enables support for SiS PATA controllers -- cgit v1.2.3 From 8c83f80b2d335176f72d8729fe1dfe19c5812cb1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 9 Dec 2008 00:10:11 -0800 Subject: sungem: Make PCS PHY support partially work again. As reported by Hermann Lauer, PCS PHY support in the sungem driver simply doesn't work. When the chip is reset due to open, or some other similar operation, the PCS is reset too but we don't program it back into a running state. The result is no link when the device is brought up. This partially rectifies the situation for the moment, by kicking the PCS after a sungem chip reset so that it will renegotiate and be re-enabled again. The behavior is still a little bit dodgy as the added renegotiate make the link take some time after bringing the interface up, but this is a significant improvement in that things actually work now :-) Based almost entirely upon an initial patch by Hermann. Signed-off-by: David S. Miller --- drivers/net/sungem.c | 129 +++++++++++++++++++++++++++++---------------------- 1 file changed, 73 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 1349e419673..bb7a47829f7 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -1142,6 +1142,70 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } +static void gem_pcs_reset(struct gem *gp) +{ + int limit; + u32 val; + + /* Reset PCS unit. */ + val = readl(gp->regs + PCS_MIICTRL); + val |= PCS_MIICTRL_RST; + writel(val, gp->regs + PCS_MIICTRL); + + limit = 32; + while (readl(gp->regs + PCS_MIICTRL) & PCS_MIICTRL_RST) { + udelay(100); + if (limit-- <= 0) + break; + } + if (limit <= 0) + printk(KERN_WARNING "%s: PCS reset bit would not clear.\n", + gp->dev->name); +} + +static void gem_pcs_reinit_adv(struct gem *gp) +{ + u32 val; + + /* Make sure PCS is disabled while changing advertisement + * configuration. + */ + val = readl(gp->regs + PCS_CFG); + val &= ~(PCS_CFG_ENABLE | PCS_CFG_TO); + writel(val, gp->regs + PCS_CFG); + + /* Advertise all capabilities except assymetric + * pause. + */ + val = readl(gp->regs + PCS_MIIADV); + val |= (PCS_MIIADV_FD | PCS_MIIADV_HD | + PCS_MIIADV_SP | PCS_MIIADV_AP); + writel(val, gp->regs + PCS_MIIADV); + + /* Enable and restart auto-negotiation, disable wrapback/loopback, + * and re-enable PCS. + */ + val = readl(gp->regs + PCS_MIICTRL); + val |= (PCS_MIICTRL_RAN | PCS_MIICTRL_ANE); + val &= ~PCS_MIICTRL_WB; + writel(val, gp->regs + PCS_MIICTRL); + + val = readl(gp->regs + PCS_CFG); + val |= PCS_CFG_ENABLE; + writel(val, gp->regs + PCS_CFG); + + /* Make sure serialink loopback is off. The meaning + * of this bit is logically inverted based upon whether + * you are in Serialink or SERDES mode. + */ + val = readl(gp->regs + PCS_SCTRL); + if (gp->phy_type == phy_serialink) + val &= ~PCS_SCTRL_LOOP; + else + val |= PCS_SCTRL_LOOP; + writel(val, gp->regs + PCS_SCTRL); +} + #define STOP_TRIES 32 /* Must be invoked under gp->lock and gp->tx_lock. */ @@ -1168,6 +1232,9 @@ static void gem_reset(struct gem *gp) if (limit <= 0) printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name); + + if (gp->phy_type == phy_serialink || gp->phy_type == phy_serdes) + gem_pcs_reinit_adv(gp); } /* Must be invoked under gp->lock and gp->tx_lock. */ @@ -1324,7 +1391,7 @@ static int gem_set_link_modes(struct gem *gp) gp->phy_type == phy_serdes) { u32 pcs_lpa = readl(gp->regs + PCS_MIILP); - if (pcs_lpa & PCS_MIIADV_FD) + if ((pcs_lpa & PCS_MIIADV_FD) || gp->phy_type == phy_serdes) full_duplex = 1; speed = SPEED_1000; } @@ -1488,6 +1555,9 @@ static void gem_link_timer(unsigned long data) val = readl(gp->regs + PCS_MIISTAT); if ((val & PCS_MIISTAT_LS) != 0) { + if (gp->lstate == link_up) + goto restart; + gp->lstate = link_up; netif_carrier_on(gp->dev); (void)gem_set_link_modes(gp); @@ -1708,61 +1778,8 @@ static void gem_init_phy(struct gem *gp) if (gp->phy_mii.def && gp->phy_mii.def->ops->init) gp->phy_mii.def->ops->init(&gp->phy_mii); } else { - u32 val; - int limit; - - /* Reset PCS unit. */ - val = readl(gp->regs + PCS_MIICTRL); - val |= PCS_MIICTRL_RST; - writel(val, gp->regs + PCS_MIICTRL); - - limit = 32; - while (readl(gp->regs + PCS_MIICTRL) & PCS_MIICTRL_RST) { - udelay(100); - if (limit-- <= 0) - break; - } - if (limit <= 0) - printk(KERN_WARNING "%s: PCS reset bit would not clear.\n", - gp->dev->name); - - /* Make sure PCS is disabled while changing advertisement - * configuration. - */ - val = readl(gp->regs + PCS_CFG); - val &= ~(PCS_CFG_ENABLE | PCS_CFG_TO); - writel(val, gp->regs + PCS_CFG); - - /* Advertise all capabilities except assymetric - * pause. - */ - val = readl(gp->regs + PCS_MIIADV); - val |= (PCS_MIIADV_FD | PCS_MIIADV_HD | - PCS_MIIADV_SP | PCS_MIIADV_AP); - writel(val, gp->regs + PCS_MIIADV); - - /* Enable and restart auto-negotiation, disable wrapback/loopback, - * and re-enable PCS. - */ - val = readl(gp->regs + PCS_MIICTRL); - val |= (PCS_MIICTRL_RAN | PCS_MIICTRL_ANE); - val &= ~PCS_MIICTRL_WB; - writel(val, gp->regs + PCS_MIICTRL); - - val = readl(gp->regs + PCS_CFG); - val |= PCS_CFG_ENABLE; - writel(val, gp->regs + PCS_CFG); - - /* Make sure serialink loopback is off. The meaning - * of this bit is logically inverted based upon whether - * you are in Serialink or SERDES mode. - */ - val = readl(gp->regs + PCS_SCTRL); - if (gp->phy_type == phy_serialink) - val &= ~PCS_SCTRL_LOOP; - else - val |= PCS_SCTRL_LOOP; - writel(val, gp->regs + PCS_SCTRL); + gem_pcs_reset(gp); + gem_pcs_reinit_adv(gp); } /* Default aneg parameters */ -- cgit v1.2.3 From f3179748a157c21d44d929fd3779421ebfbeaa93 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 9 Dec 2008 15:54:18 +1100 Subject: radeonfb: Disable new color expand acceleration unless explicitely enabled This new color expansion acceleration for radeonfb appears to trigger problems with X on VT switch and suspend/resume on some machines. It might be a problem in the VT layer or in X, but I haven't quite found it yet, so in the meantime, this disables the acceleration by default, reverting to 2.6.27 state. It can be enabled using the "accel_cexp" module parameter or fbdev argument. Signed-off-by: Benjamin Herrenschmidt Acked-by: David S. Miller Signed-off-by: Linus Torvalds --- drivers/video/aty/radeon_accel.c | 3 ++- drivers/video/aty/radeon_base.c | 6 ++++++ drivers/video/aty/radeonfb.h | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c index a547e5d4c8b..8da5e5ab854 100644 --- a/drivers/video/aty/radeon_accel.c +++ b/drivers/video/aty/radeon_accel.c @@ -256,7 +256,8 @@ void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image) return; /* We only do 1 bpp color expansion for now */ - if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1) + if (!accel_cexp || + (info->flags & FBINFO_HWACCEL_DISABLED) || image->depth != 1) goto fallback; /* Fallback if running out of the screen. We may do clipping diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index b3ffe8205d2..d5b27f9d374 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -282,6 +282,8 @@ static int backlight = 1; static int backlight = 0; #endif +int accel_cexp = 0; + /* * prototypes */ @@ -2520,6 +2522,8 @@ static int __init radeonfb_setup (char *options) } else if (!strncmp(this_opt, "ignore_devlist", 14)) { ignore_devlist = 1; #endif + } else if (!strncmp(this_opt, "accel_cexp", 12)) { + accel_cexp = 1; } else mode_option = this_opt; } @@ -2567,6 +2571,8 @@ module_param(monitor_layout, charp, 0); MODULE_PARM_DESC(monitor_layout, "Specify monitor mapping (like XFree86)"); module_param(force_measure_pll, bool, 0); MODULE_PARM_DESC(force_measure_pll, "Force measurement of PLL (debug)"); +module_param(accel_cexp, bool, 0); +MODULE_PARM_DESC(accel_cexp, "Use acceleration engine for color expansion"); #ifdef CONFIG_MTRR module_param(nomtrr, bool, 0); MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers"); diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index ea0b5b47aca..974ca6d8654 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h @@ -638,4 +638,6 @@ static inline void radeonfb_bl_init(struct radeonfb_info *rinfo) {} static inline void radeonfb_bl_exit(struct radeonfb_info *rinfo) {} #endif +extern int accel_cexp; + #endif /* __RADEONFB_H__ */ -- cgit v1.2.3 From 023a407f1cdc8b86903495d7ce0d2abae0f8bce5 Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Tue, 9 Dec 2008 10:51:32 -0600 Subject: [IA64] Fix GRU compile error w/o CONFIG_HUGETLB_PAGE Eliminate compile error when compiling without CONFIG_HUGETLB_PAGE. Signed-off-by: Jack Steiner Signed-off-by: Tony Luck --- drivers/misc/sgi-gru/grufault.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c index 8c389d606c3..3ee698ad859 100644 --- a/drivers/misc/sgi-gru/grufault.c +++ b/drivers/misc/sgi-gru/grufault.c @@ -254,7 +254,11 @@ static int atomic_pte_lookup(struct vm_area_struct *vma, unsigned long vaddr, return 1; *paddr = pte_pfn(pte) << PAGE_SHIFT; +#ifdef CONFIG_HUGETLB_PAGE *pageshift = is_vm_hugetlb_page(vma) ? HPAGE_SHIFT : PAGE_SHIFT; +#else + *pageshift = PAGE_SHIFT; +#endif return 0; err: -- cgit v1.2.3 From ecdbc6906e4c31bc387c64490e31ae3e0f929479 Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Mon, 8 Dec 2008 15:47:20 -0800 Subject: [IA64] Clear up section mismatch for ioc4_ide_attach_one. The generic_defconfig has three section mismatches. This clears up ioc4_ide_attach_one(). Signed-off-by: Robin Holt Signed-off-by: Mike Reid Signed-off-by: Tony Luck --- drivers/ide/sgiioc4.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/sgiioc4.c b/drivers/ide/sgiioc4.c index 7defa0ae201..a687a7dfea6 100644 --- a/drivers/ide/sgiioc4.c +++ b/drivers/ide/sgiioc4.c @@ -550,7 +550,7 @@ static const struct ide_dma_ops sgiioc4_dma_ops = { .dma_timeout = ide_dma_timeout, }; -static const struct ide_port_info sgiioc4_port_info __devinitdata = { +static const struct ide_port_info sgiioc4_port_info __devinitconst = { .name = DRV_NAME, .chipset = ide_pci, .init_dma = ide_dma_sgiioc4, @@ -633,7 +633,7 @@ out: return ret; } -int +int __devinit ioc4_ide_attach_one(struct ioc4_driver_data *idd) { /* PCI-RT does not bring out IDE connection. @@ -645,7 +645,7 @@ ioc4_ide_attach_one(struct ioc4_driver_data *idd) return pci_init_sgiioc4(idd->idd_pdev); } -static struct ioc4_submodule ioc4_ide_submodule = { +static struct ioc4_submodule __devinitdata ioc4_ide_submodule = { .is_name = "IOC4_ide", .is_owner = THIS_MODULE, .is_probe = ioc4_ide_attach_one, -- cgit v1.2.3 From 3c0db899bff2acbf1b36c65763de4d0133910104 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Mon, 8 Dec 2008 16:16:21 -0800 Subject: [IA64] Fix section mismatch ioc3uart_init()/ioc3uart_submodule s/ioc3uart_submodule/ioc3uart_ops/ makes the section mismatch check happy. Signed-off-by: Tony Luck --- drivers/serial/ioc3_serial.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c index 6dd98f9fb89..ae3699d77dd 100644 --- a/drivers/serial/ioc3_serial.c +++ b/drivers/serial/ioc3_serial.c @@ -2149,7 +2149,7 @@ out4: return ret; } -static struct ioc3_submodule ioc3uart_submodule = { +static struct ioc3_submodule ioc3uart_ops = { .name = "IOC3uart", .probe = ioc3uart_probe, .remove = ioc3uart_remove, @@ -2173,7 +2173,7 @@ static int __devinit ioc3uart_init(void) __func__); return ret; } - ret = ioc3_register_submodule(&ioc3uart_submodule); + ret = ioc3_register_submodule(&ioc3uart_ops); if (ret) uart_unregister_driver(&ioc3_uart); return ret; @@ -2181,7 +2181,7 @@ static int __devinit ioc3uart_init(void) static void __devexit ioc3uart_exit(void) { - ioc3_unregister_submodule(&ioc3uart_submodule); + ioc3_unregister_submodule(&ioc3uart_ops); uart_unregister_driver(&ioc3_uart); } -- cgit v1.2.3 From ec9a13cdbfc8cf29502096ca69b65f07184a9b2c Mon Sep 17 00:00:00 2001 From: Nigel Cunningham Date: Tue, 9 Dec 2008 22:40:20 +1100 Subject: ieee1394: node manager causes up to ~3.25s delay in freezing tasks The firewire nodemanager function "nodemgr_host_thread" contains a loop that calls try_to_freeze near the top of the loop, but then delays for up to 3.25 seconds (plus time to do work) before getting back to the top of the loop. When starting a cycle post-boot, this doesn't seem to bite, but it is causing a noticeable delay at boot time, when freezing processes prior to starting to read the image. The following patch adds invocation of try_to_freeze to the subloops that are used in the body of this function. With these additions, the time to freeze when starting to resume at boot time is virtually zero. I'm no expert on firewire, and so don't know that we shouldn't check the return value and jump back to the top of the loop or such like after being frozen, but I submit it for your consideration. Signed-off-by: Nigel Cunningham The delay until nodemgr freezes was up to 0.25s (plus time for node probes) in Linux 2.6.27 and older and up to 3.25s (plus ~) since Linux 2.6.28-rc1, hence much more noticeable. try_to_freeze() without any jump is correct. The surrounding code in the respective loops will catch whether another bus reset happens during the freeze and handle it. Signed-off-by: Stefan Richter --- drivers/ieee1394/nodemgr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 9e39f73282e..d333ae22459 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -1685,6 +1685,7 @@ static int nodemgr_host_thread(void *data) g = get_hpsb_generation(host); for (i = 0; i < 4 ; i++) { msleep_interruptible(63); + try_to_freeze(); if (kthread_should_stop()) goto exit; @@ -1725,6 +1726,7 @@ static int nodemgr_host_thread(void *data) /* Sleep 3 seconds */ for (i = 3000/200; i; i--) { msleep_interruptible(200); + try_to_freeze(); if (kthread_should_stop()) goto exit; -- cgit v1.2.3 From 3b5dd45e947ecd21491e1658fba7bb4bc4a54995 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Mon, 1 Dec 2008 18:17:21 -0700 Subject: PCI: stop leaking 'slot_name' in pci_create_slot In pci_create_slot(), the local variable 'slot_name' is allocated by make_slot_name(), but never freed. We never use it after passing it to the kobject core, so we should free it upon function exit. Cc: stable@kernel.org Signed-off-by: Alex Chiang Signed-off-by: Jesse Barnes --- drivers/pci/slot.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index 4dd1c3e157a..5a8ccb4f604 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -253,6 +253,7 @@ placeholder: __func__, pci_domain_nr(parent), parent->number, slot_nr); out: + kfree(slot_name); up_write(&pci_bus_sem); return slot; err: -- cgit v1.2.3 From 2a42d9dba7842422ffb2c02e75288a8bc2fd5065 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Tue, 9 Dec 2008 13:05:09 +0100 Subject: PCIe: ASPM: Break out of endless loop waiting for PCI config bits to switch Makes a Compaq 6735s boot reliably again. It used to hang in the loop on some boots. Give the link one second to train, otherwise break out of the loop and reset the previously set clock bits. Cc: stable@vger.kernel.org Signed-off-by: Thomas Renninger Signed-off-by: Shaohua Li Signed-off-by: Matthew Garrett Signed-off-by: Jesse Barnes --- drivers/pci/pcie/aspm.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 8f63f4c6b85..9aad608bcf3 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "../pci.h" @@ -161,11 +162,12 @@ static void pcie_check_clock_pm(struct pci_dev *pdev) */ static void pcie_aspm_configure_common_clock(struct pci_dev *pdev) { - int pos, child_pos; + int pos, child_pos, i = 0; u16 reg16 = 0; struct pci_dev *child_dev; int same_clock = 1; - + unsigned long start_jiffies; + u16 child_regs[8], parent_reg; /* * all functions of a slot should have the same Slot Clock * Configuration, so just check one function @@ -191,16 +193,19 @@ static void pcie_aspm_configure_common_clock(struct pci_dev *pdev) child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP); pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKCTL, ®16); + child_regs[i] = reg16; if (same_clock) reg16 |= PCI_EXP_LNKCTL_CCC; else reg16 &= ~PCI_EXP_LNKCTL_CCC; pci_write_config_word(child_dev, child_pos + PCI_EXP_LNKCTL, reg16); + i++; } /* Configure upstream component */ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); + parent_reg = reg16; if (same_clock) reg16 |= PCI_EXP_LNKCTL_CCC; else @@ -212,12 +217,30 @@ static void pcie_aspm_configure_common_clock(struct pci_dev *pdev) pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); /* Wait for link training end */ - while (1) { + /* break out after waiting for 1 second */ + start_jiffies = jiffies; + while ((jiffies - start_jiffies) < HZ) { pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, ®16); if (!(reg16 & PCI_EXP_LNKSTA_LT)) break; cpu_relax(); } + /* training failed -> recover */ + if ((jiffies - start_jiffies) >= HZ) { + dev_printk (KERN_ERR, &pdev->dev, "ASPM: Could not configure" + " common clock\n"); + i = 0; + list_for_each_entry(child_dev, &pdev->subordinate->devices, + bus_list) { + child_pos = pci_find_capability(child_dev, + PCI_CAP_ID_EXP); + pci_write_config_word(child_dev, + child_pos + PCI_EXP_LNKCTL, + child_regs[i]); + i++; + } + pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, parent_reg); + } } /* -- cgit v1.2.3 From fbf0229e946deb9e6c711f9eaa5c8d670c3a28fd Mon Sep 17 00:00:00 2001 From: Hermann Lauer Date: Tue, 9 Dec 2008 15:39:14 -0800 Subject: sungem: improve ethtool output with internal pcs and serdes From: Hermann Lauer Attached is a patch which improves the output of ethtool (see below) to some sensefull values with a sungem fibre card which uses the sungem interal pcs connected to a serdes chip. The seriallink case in the driver is untouched. Most values are hardcoded, because gigabit fibre autoneg is anyways limited and the driver don't really support much at the moment with that hardware. Signed-off-by: David S. Miller --- drivers/net/sungem.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers') diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index bb7a47829f7..fed7eba65ea 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2697,6 +2697,21 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->speed = 0; cmd->duplex = cmd->port = cmd->phy_address = cmd->transceiver = cmd->autoneg = 0; + + /* serdes means usually a Fibre connector, with most fixed */ + if (gp->phy_type == phy_serdes) { + cmd->port = PORT_FIBRE; + cmd->supported = (SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full | + SUPPORTED_FIBRE | SUPPORTED_Autoneg | + SUPPORTED_Pause | SUPPORTED_Asym_Pause); + cmd->advertising = cmd->supported; + cmd->transceiver = XCVR_INTERNAL; + if (gp->lstate == link_up) + cmd->speed = SPEED_1000; + cmd->duplex = DUPLEX_FULL; + cmd->autoneg = 1; + } } cmd->maxtxpkt = cmd->maxrxpkt = 0; -- cgit v1.2.3 From 1d1dc5e83f3299c108a4e44d58cc4bfef48c876a Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Wed, 10 Dec 2008 00:20:38 +0100 Subject: firewire: fw-ohci: fix IOMMU resource exhaustion There is a DMA map/ unmap imbalance whenever a block write request packet is sent and then dequeued with ohci_cancel_packet. The latter may happen frequently if the AR resp tasklet is executed before the AT req tasklet for the same transaction. Add the missing dma_unmap_single. This fixes https://bugzilla.redhat.com/show_bug.cgi?id=475156 Reported-by: Emmanuel Kowalski Tested-by: Emmanuel Kowalski Signed-off-by: Stefan Richter --- drivers/firewire/fw-ohci.c | 11 +++++++---- drivers/firewire/fw-transaction.c | 3 +++ drivers/firewire/fw-transaction.h | 2 ++ 3 files changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 46610b09041..ab9c01e462e 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -974,6 +974,7 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet) packet->ack = RCODE_SEND_ERROR; return -1; } + packet->payload_bus = payload_bus; d[2].req_count = cpu_to_le16(packet->payload_length); d[2].data_address = cpu_to_le32(payload_bus); @@ -1025,7 +1026,6 @@ static int handle_at_packet(struct context *context, struct driver_data *driver_data; struct fw_packet *packet; struct fw_ohci *ohci = context->ohci; - dma_addr_t payload_bus; int evt; if (last->transfer_status == 0) @@ -1038,9 +1038,8 @@ static int handle_at_packet(struct context *context, /* This packet was cancelled, just continue. */ return 1; - payload_bus = le32_to_cpu(last->data_address); - if (payload_bus != 0) - dma_unmap_single(ohci->card.device, payload_bus, + if (packet->payload_bus) + dma_unmap_single(ohci->card.device, packet->payload_bus, packet->payload_length, DMA_TO_DEVICE); evt = le16_to_cpu(last->transfer_status) & 0x1f; @@ -1697,6 +1696,10 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) if (packet->ack != 0) goto out; + if (packet->payload_bus) + dma_unmap_single(ohci->card.device, packet->payload_bus, + packet->payload_length, DMA_TO_DEVICE); + log_ar_at_event('T', packet->speed, packet->header, 0x20); driver_data->packet = NULL; packet->ack = RCODE_CANCELLED; diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 022ac4fabb6..2884f876397 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -207,6 +207,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, packet->speed = speed; packet->generation = generation; packet->ack = 0; + packet->payload_bus = 0; } /** @@ -581,6 +582,8 @@ fw_fill_response(struct fw_packet *response, u32 *request_header, BUG(); return; } + + response->payload_bus = 0; } EXPORT_SYMBOL(fw_fill_response); diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index aed7dbb17cd..839466f0a79 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4) @@ -153,6 +154,7 @@ struct fw_packet { size_t header_length; void *payload; size_t payload_length; + dma_addr_t payload_bus; u32 timestamp; /* -- cgit v1.2.3 From fe102c71a65a503646bcc94ccb6859da613c2f4f Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Tue, 9 Dec 2008 13:14:11 -0800 Subject: rtc: fix missing id_table in rtc-ds1672 and rtc-max6900 drivers Add missing id_table to the drivers in subject. Patch is against the latest git. It should go in with 2.6.28 if possible, the drivers won't work without the id_table bits. Signed-off-by: Alessandro Zummo Reported-by: Imre Kaloz Tested-by: Imre Kaloz Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-ds1672.c | 6 ++++++ drivers/rtc/rtc-max6900.c | 6 ++++++ 2 files changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index 341d7a5b45a..4e91419e891 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c @@ -209,12 +209,18 @@ static int ds1672_probe(struct i2c_client *client, return err; } +static struct i2c_device_id ds1672_id[] = { + { "ds1672", 0 }, + { } +}; + static struct i2c_driver ds1672_driver = { .driver = { .name = "rtc-ds1672", }, .probe = &ds1672_probe, .remove = &ds1672_remove, + .id_table = ds1672_id, }; static int __init ds1672_init(void) diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index 80782798763..a4f6665ab3c 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c @@ -247,12 +247,18 @@ max6900_probe(struct i2c_client *client, const struct i2c_device_id *id) return 0; } +static struct i2c_device_id max6900_id[] = { + { "max6900", 0 }, + { } +}; + static struct i2c_driver max6900_driver = { .driver = { .name = "rtc-max6900", }, .probe = max6900_probe, .remove = max6900_remove, + .id_table = max6900_id, }; static int __init max6900_init(void) -- cgit v1.2.3 From beaa4867eec02e6eb78e9e9ef503d7eff612b068 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Tue, 9 Dec 2008 13:14:17 -0800 Subject: fbcon: fix workqueue shutdown Add a call to cancel_work_sync() in fbcon_exit() to cancel any pending work in the fbcon workqueue. The current implementation of fbcon_exit() sets the fbcon workqueue function info->queue.func to NULL, but does not assure that there is no work pending when it does so. On occasion, depending on system timing, there will still be pending work in the queue when fbcon_exit() is called. This results in a null pointer deference when run_workqueue() tries to call the queue's work function. Fixes errors on shutdown similar to these: Console: switching to colour dummy device 80x25 Unable to handle kernel paging request for data at address 0x00000000 Signed-off-by: Geoff Levand Cc: Krzysztof Helt Cc: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 67ff370d80a..0b2adefe9e3 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -3531,12 +3531,18 @@ static void fbcon_exit(void) softback_buf = 0UL; for (i = 0; i < FB_MAX; i++) { + int pending; + mapped = 0; info = registered_fb[i]; if (info == NULL) continue; + pending = cancel_work_sync(&info->queue); + DPRINTK("fbcon: %s pending work\n", (pending ? "canceled" : + "no")); + for (j = first_fb_vc; j <= last_fb_vc; j++) { if (con2fb_map[j] == i) mapped = 1; -- cgit v1.2.3 From cc61686001b1368724d1c38805c27e5021cd85ed Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 9 Dec 2008 13:14:18 -0800 Subject: rtc twl4030: rename ioctl function when RTC_INTF_DEV=n Fix build error when RTC_INTF_DEV=n: drivers/rtc/rtc-twl4030.c:402: error: 'twl4030_rtc_ioctl' undeclared here (not in a function) make[3]: *** [drivers/rtc/rtc-twl4030.o] Error 1 Signed-off-by: Randy Dunlap Cc: David Brownell Cc: Tony Lindgren Cc: Samuel Ortiz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-twl4030.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl4030.c index abe87a4d266..01d8da9afdc 100644 --- a/drivers/rtc/rtc-twl4030.c +++ b/drivers/rtc/rtc-twl4030.c @@ -337,7 +337,7 @@ static int twl4030_rtc_ioctl(struct device *dev, unsigned int cmd, } #else -#define omap_rtc_ioctl NULL +#define twl4030_rtc_ioctl NULL #endif static irqreturn_t twl4030_rtc_interrupt(int irq, void *rtc) -- cgit v1.2.3 From 52b9582dd5983ac888c494bd3e15b5cd40195c53 Mon Sep 17 00:00:00 2001 From: Balaji Rao Date: Tue, 9 Dec 2008 13:14:22 -0800 Subject: drivers/serial/s3c2440.c: fix typo in MODULE_LICENSE Signed-off-by: Balaji Rao Acked-by: Ben Dooks Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/s3c2440.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/s3c2440.c b/drivers/serial/s3c2440.c index 317d239ab74..29cbb0afef8 100644 --- a/drivers/serial/s3c2440.c +++ b/drivers/serial/s3c2440.c @@ -177,5 +177,5 @@ module_exit(s3c2440_serial_exit); MODULE_DESCRIPTION("Samsung S3C2440,S3C2442 SoC Serial port driver"); MODULE_AUTHOR("Ben Dooks "); -MODULE_LICENSE("GPLi v2"); +MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:s3c2440-uart"); -- cgit v1.2.3 From c1ab6cc68cb7d512ebba3496cd341286d2d7969d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 9 Dec 2008 13:14:31 -0800 Subject: drivers/video/mb862xx/mb862xxfb.c: fix printk sparc64: drivers/video/mb862xx/mb862xxfb.c:929: warning: long long unsigned int format, resource_size_t arg (arg 4) drivers/video/mb862xx/mb862xxfb.c:931: warning: long long unsigned int format, resource_size_t arg (arg 4) We don't know what type the architecture uses to implement u64, hence they cannot be printed. Cc: Anatolij Gustschin Cc: Dmitry Baryshkov Cc: Anton Vorontsov Cc: Matteo Fortini Cc: Krzysztof Helt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/mb862xx/mb862xxfb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c index 38718d95fbb..fb64234a382 100644 --- a/drivers/video/mb862xx/mb862xxfb.c +++ b/drivers/video/mb862xx/mb862xxfb.c @@ -927,9 +927,9 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev, } dev_dbg(dev, "fb phys 0x%llx 0x%lx\n", - (u64)par->fb_base_phys, (ulong)par->mapped_vram); + (unsigned long long)par->fb_base_phys, (ulong)par->mapped_vram); dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n", - (u64)par->mmio_base_phys, (ulong)par->mmio_len); + (unsigned long long)par->mmio_base_phys, (ulong)par->mmio_len); if (mb862xx_pci_gdc_init(par)) goto io_unmap; -- cgit v1.2.3 From cba767175becadc5c4016cceb7bfdd2c7fe722f4 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sat, 6 Dec 2008 04:38:11 +0100 Subject: pktcdvd: remove broken dev_t export of class devices The pktcdvd created class devices only export some sysfs files, but have no char dev_t registered in the driver. At class device creation time they copy the dev_t value of the block device to the char device, wich will register a new char device in the driver core and userspace, with a conflicting dev_t value. In many cases the class devices dev_t just points to a random USB device. This fixes the sysfs "duplicate entry" errors. Signed-off-by: Kay Sievers Acked-by: Peter Osterlund Cc: Al Viro Signed-off-by: Linus Torvalds --- drivers/block/pktcdvd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index edda7b6b077..dc7a8c352da 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -302,7 +302,7 @@ static struct kobj_type kobj_pkt_type_wqueue = { static void pkt_sysfs_dev_new(struct pktcdvd_device *pd) { if (class_pktcdvd) { - pd->dev = device_create(class_pktcdvd, NULL, pd->pkt_dev, NULL, + pd->dev = device_create(class_pktcdvd, NULL, MKDEV(0, 0), NULL, "%s", pd->name); if (IS_ERR(pd->dev)) pd->dev = NULL; -- cgit v1.2.3 From 6c34bc2976b30dc8b56392c020e25bae1f363cab Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 10 Dec 2008 09:26:17 -0800 Subject: Revert "radeonfb: accelerate imageblit and other improvements" This reverts commit b1ee26bab14886350ba12a5c10cbc0696ac679bf, along with the "fixes" for it that all just caused problems: - c4c6fa9891f3d1bcaae4f39fb751d5302965b566 "radeonfb: fix problem with color expansion & alignment" - f3179748a157c21d44d929fd3779421ebfbeaa93 "radeonfb: Disable new color expand acceleration unless explicitely enabled" because even when disabled, it breaks for people. See http://bugzilla.kernel.org/show_bug.cgi?id=12191 for the latest example. Acked-by: Benjamin Herrenschmidt Acked-by: David S. Miller Cc: Krzysztof Halasa Cc: James Cloos Cc: "Rafael J. Wysocki" Cc: Krzysztof Helt Cc: Jean-Luc Coulon Cc: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/aty/radeon_accel.c | 295 ++++++++++------------------------- drivers/video/aty/radeon_backlight.c | 2 +- drivers/video/aty/radeon_base.c | 46 ++---- drivers/video/aty/radeon_pm.c | 6 +- drivers/video/aty/radeonfb.h | 40 ++--- 5 files changed, 122 insertions(+), 267 deletions(-) (limited to 'drivers') diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c index 8da5e5ab854..a469a3d6edc 100644 --- a/drivers/video/aty/radeon_accel.c +++ b/drivers/video/aty/radeon_accel.c @@ -5,61 +5,61 @@ * --dte */ -#define FLUSH_CACHE_WORKAROUND 1 - -void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries) +static void radeon_fixup_offset(struct radeonfb_info *rinfo) { - int i; + u32 local_base; + + /* *** Ugly workaround *** */ + /* + * On some platforms, the video memory is mapped at 0 in radeon chip space + * (like PPCs) by the firmware. X will always move it up so that it's seen + * by the chip to be at the same address as the PCI BAR. + * That means that when switching back from X, there is a mismatch between + * the offsets programmed into the engine. This means that potentially, + * accel operations done before radeonfb has a chance to re-init the engine + * will have incorrect offsets, and potentially trash system memory ! + * + * The correct fix is for fbcon to never call any accel op before the engine + * has properly been re-initialized (by a call to set_var), but this is a + * complex fix. This workaround in the meantime, called before every accel + * operation, makes sure the offsets are in sync. + */ - for (i=0; i<2000000; i++) { - rinfo->fifo_free = INREG(RBBM_STATUS) & 0x7f; - if (rinfo->fifo_free >= entries) - return; - udelay(10); - } - printk(KERN_ERR "radeonfb: FIFO Timeout !\n"); - /* XXX Todo: attempt to reset the engine */ -} + radeon_fifo_wait (1); + local_base = INREG(MC_FB_LOCATION) << 16; + if (local_base == rinfo->fb_local_base) + return; -static inline void radeon_fifo_wait(struct radeonfb_info *rinfo, int entries) -{ - if (entries <= rinfo->fifo_free) - rinfo->fifo_free -= entries; - else - radeon_fifo_update_and_wait(rinfo, entries); -} + rinfo->fb_local_base = local_base; -static inline void radeonfb_set_creg(struct radeonfb_info *rinfo, u32 reg, - u32 *cache, u32 new_val) -{ - if (new_val == *cache) - return; - *cache = new_val; - radeon_fifo_wait(rinfo, 1); - OUTREG(reg, new_val); + radeon_fifo_wait (3); + OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) | + (rinfo->fb_local_base >> 10)); + OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); + OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); } static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo, const struct fb_fillrect *region) { - radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache, - rinfo->dp_gui_mc_base | GMC_BRUSH_SOLID_COLOR | ROP3_P); - radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache, - DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); - radeonfb_set_creg(rinfo, DP_BRUSH_FRGD_CLR, &rinfo->dp_brush_fg_cache, - region->color); - - /* Ensure the dst cache is flushed and the engine idle before - * issuing the operation. - * - * This works around engine lockups on some cards - */ -#if FLUSH_CACHE_WORKAROUND - radeon_fifo_wait(rinfo, 2); + radeon_fifo_wait(4); + + OUTREG(DP_GUI_MASTER_CNTL, + rinfo->dp_gui_master_cntl /* contains, like GMC_DST_32BPP */ + | GMC_BRUSH_SOLID_COLOR + | ROP3_P); + if (radeon_get_dstbpp(rinfo->depth) != DST_8BPP) + OUTREG(DP_BRUSH_FRGD_CLR, rinfo->pseudo_palette[region->color]); + else + OUTREG(DP_BRUSH_FRGD_CLR, region->color); + OUTREG(DP_WRITE_MSK, 0xffffffff); + OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); + + radeon_fifo_wait(2); OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); -#endif - radeon_fifo_wait(rinfo, 2); + + radeon_fifo_wait(2); OUTREG(DST_Y_X, (region->dy << 16) | region->dx); OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height); } @@ -70,14 +70,15 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region) struct fb_fillrect modded; int vxres, vyres; - WARN_ON(rinfo->gfx_mode); - if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode) + if (info->state != FBINFO_STATE_RUNNING) return; if (info->flags & FBINFO_HWACCEL_DISABLED) { cfb_fillrect(info, region); return; } + radeon_fixup_offset(rinfo); + vxres = info->var.xres_virtual; vyres = info->var.yres_virtual; @@ -90,10 +91,6 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region) if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; - if (info->fix.visual == FB_VISUAL_TRUECOLOR || - info->fix.visual == FB_VISUAL_DIRECTCOLOR ) - modded.color = ((u32 *) (info->pseudo_palette))[region->color]; - radeonfb_prim_fillrect(rinfo, &modded); } @@ -112,22 +109,22 @@ static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo, if ( xdir < 0 ) { sx += w-1; dx += w-1; } if ( ydir < 0 ) { sy += h-1; dy += h-1; } - radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache, - rinfo->dp_gui_mc_base | - GMC_BRUSH_NONE | - GMC_SRC_DATATYPE_COLOR | - ROP3_S | - DP_SRC_SOURCE_MEMORY); - radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache, - (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) | - (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0)); - -#if FLUSH_CACHE_WORKAROUND - radeon_fifo_wait(rinfo, 2); + radeon_fifo_wait(3); + OUTREG(DP_GUI_MASTER_CNTL, + rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */ + | GMC_BRUSH_NONE + | GMC_SRC_DSTCOLOR + | ROP3_S + | DP_SRC_SOURCE_MEMORY ); + OUTREG(DP_WRITE_MSK, 0xffffffff); + OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) + | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0)); + + radeon_fifo_wait(2); OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); -#endif - radeon_fifo_wait(rinfo, 3); + + radeon_fifo_wait(3); OUTREG(SRC_Y_X, (sy << 16) | sx); OUTREG(DST_Y_X, (dy << 16) | dx); OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w); @@ -146,14 +143,15 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) modded.width = area->width; modded.height = area->height; - WARN_ON(rinfo->gfx_mode); - if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode) + if (info->state != FBINFO_STATE_RUNNING) return; if (info->flags & FBINFO_HWACCEL_DISABLED) { cfb_copyarea(info, area); return; } + radeon_fixup_offset(rinfo); + vxres = info->var.xres_virtual; vyres = info->var.yres_virtual; @@ -170,116 +168,13 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) radeonfb_prim_copyarea(rinfo, &modded); } -static void radeonfb_prim_imageblit(struct radeonfb_info *rinfo, - const struct fb_image *image, - u32 fg, u32 bg) -{ - unsigned int dwords; - u32 *bits; - - radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache, - rinfo->dp_gui_mc_base | - GMC_BRUSH_NONE | GMC_DST_CLIP_LEAVE | - GMC_SRC_DATATYPE_MONO_FG_BG | - ROP3_S | - GMC_BYTE_ORDER_MSB_TO_LSB | - DP_SRC_SOURCE_HOST_DATA); - radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache, - DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); - radeonfb_set_creg(rinfo, DP_SRC_FRGD_CLR, &rinfo->dp_src_fg_cache, fg); - radeonfb_set_creg(rinfo, DP_SRC_BKGD_CLR, &rinfo->dp_src_bg_cache, bg); - - /* Ensure the dst cache is flushed and the engine idle before - * issuing the operation. - * - * This works around engine lockups on some cards - */ -#if FLUSH_CACHE_WORKAROUND - radeon_fifo_wait(rinfo, 2); - OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); - OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); -#endif - - /* X here pads width to a multiple of 32 and uses the clipper to - * adjust the result. Is that really necessary ? Things seem to - * work ok for me without that and the doco doesn't seem to imply] - * there is such a restriction. - */ - radeon_fifo_wait(rinfo, 4); - OUTREG(SC_TOP_LEFT, (image->dy << 16) | image->dx); - OUTREG(SC_BOTTOM_RIGHT, ((image->dy + image->height) << 16) | - (image->dx + image->width)); - OUTREG(DST_Y_X, (image->dy << 16) | image->dx); - - OUTREG(DST_HEIGHT_WIDTH, (image->height << 16) | ((image->width + 31) & ~31)); - - dwords = (image->width + 31) >> 5; - dwords *= image->height; - bits = (u32*)(image->data); - - while(dwords >= 8) { - radeon_fifo_wait(rinfo, 8); -#if BITS_PER_LONG == 64 - __raw_writeq(*((u64 *)(bits)), rinfo->mmio_base + HOST_DATA0); - __raw_writeq(*((u64 *)(bits+2)), rinfo->mmio_base + HOST_DATA2); - __raw_writeq(*((u64 *)(bits+4)), rinfo->mmio_base + HOST_DATA4); - __raw_writeq(*((u64 *)(bits+6)), rinfo->mmio_base + HOST_DATA6); - bits += 8; -#else - __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0); - __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA1); - __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA2); - __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA3); - __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA4); - __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA5); - __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA6); - __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA7); -#endif - dwords -= 8; - } - while(dwords--) { - radeon_fifo_wait(rinfo, 1); - __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0); - } -} - void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image) { struct radeonfb_info *rinfo = info->par; - u32 fg, bg; - WARN_ON(rinfo->gfx_mode); - if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode) - return; - - if (!image->width || !image->height) + if (info->state != FBINFO_STATE_RUNNING) return; - - /* We only do 1 bpp color expansion for now */ - if (!accel_cexp || - (info->flags & FBINFO_HWACCEL_DISABLED) || image->depth != 1) - goto fallback; - - /* Fallback if running out of the screen. We may do clipping - * in the future */ - if ((image->dx + image->width) > info->var.xres_virtual || - (image->dy + image->height) > info->var.yres_virtual) - goto fallback; - - if (info->fix.visual == FB_VISUAL_TRUECOLOR || - info->fix.visual == FB_VISUAL_DIRECTCOLOR) { - fg = ((u32*)(info->pseudo_palette))[image->fg_color]; - bg = ((u32*)(info->pseudo_palette))[image->bg_color]; - } else { - fg = image->fg_color; - bg = image->bg_color; - } - - radeonfb_prim_imageblit(rinfo, image, fg, bg); - return; - - fallback: - radeon_engine_idle(rinfo); + radeon_engine_idle(); cfb_imageblit(info, image); } @@ -290,8 +185,7 @@ int radeonfb_sync(struct fb_info *info) if (info->state != FBINFO_STATE_RUNNING) return 0; - - radeon_engine_idle(rinfo); + radeon_engine_idle(); return 0; } @@ -367,10 +261,9 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo) /* disable 3D engine */ OUTREG(RB3D_CNTL, 0); - rinfo->fifo_free = 0; radeonfb_engine_reset(rinfo); - radeon_fifo_wait(rinfo, 1); + radeon_fifo_wait (1); if (IS_R300_VARIANT(rinfo)) { OUTREG(RB2D_DSTCACHE_MODE, INREG(RB2D_DSTCACHE_MODE) | RB2D_DC_AUTOFLUSH_ENABLE | @@ -384,7 +277,7 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo) OUTREG(RB2D_DSTCACHE_MODE, 0); } - radeon_fifo_wait(rinfo, 3); + radeon_fifo_wait (3); /* We re-read MC_FB_LOCATION from card as it can have been * modified by XFree drivers (ouch !) */ @@ -395,57 +288,41 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo) OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); - radeon_fifo_wait(rinfo, 1); -#ifdef __BIG_ENDIAN + radeon_fifo_wait (1); +#if defined(__BIG_ENDIAN) OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN); #else OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN); #endif - radeon_fifo_wait(rinfo, 2); + radeon_fifo_wait (2); OUTREG(DEFAULT_SC_TOP_LEFT, 0); OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX | DEFAULT_SC_BOTTOM_MAX)); - /* set default DP_GUI_MASTER_CNTL */ temp = radeon_get_dstbpp(rinfo->depth); - rinfo->dp_gui_mc_base = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS); + rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS); - rinfo->dp_gui_mc_cache = rinfo->dp_gui_mc_base | - GMC_BRUSH_SOLID_COLOR | - GMC_SRC_DATATYPE_COLOR; - radeon_fifo_wait(rinfo, 1); - OUTREG(DP_GUI_MASTER_CNTL, rinfo->dp_gui_mc_cache); + radeon_fifo_wait (1); + OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | + GMC_BRUSH_SOLID_COLOR | + GMC_SRC_DATATYPE_COLOR)); + radeon_fifo_wait (7); /* clear line drawing regs */ - radeon_fifo_wait(rinfo, 2); OUTREG(DST_LINE_START, 0); OUTREG(DST_LINE_END, 0); - /* set brush and source color regs */ - rinfo->dp_brush_fg_cache = 0xffffffff; - rinfo->dp_brush_bg_cache = 0x00000000; - rinfo->dp_src_fg_cache = 0xffffffff; - rinfo->dp_src_bg_cache = 0x00000000; - radeon_fifo_wait(rinfo, 4); - OUTREG(DP_BRUSH_FRGD_CLR, rinfo->dp_brush_fg_cache); - OUTREG(DP_BRUSH_BKGD_CLR, rinfo->dp_brush_bg_cache); - OUTREG(DP_SRC_FRGD_CLR, rinfo->dp_src_fg_cache); - OUTREG(DP_SRC_BKGD_CLR, rinfo->dp_src_bg_cache); - - /* Default direction */ - rinfo->dp_cntl_cache = DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM; - radeon_fifo_wait(rinfo, 1); - OUTREG(DP_CNTL, rinfo->dp_cntl_cache); + /* set brush color regs */ + OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff); + OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000); + + /* set source color regs */ + OUTREG(DP_SRC_FRGD_CLR, 0xffffffff); + OUTREG(DP_SRC_BKGD_CLR, 0x00000000); /* default write mask */ - radeon_fifo_wait(rinfo, 1); OUTREG(DP_WRITE_MSK, 0xffffffff); - /* Default to no swapping of host data */ - radeon_fifo_wait(rinfo, 1); - OUTREG(RBBM_GUICNTL, RBBM_GUICNTL_HOST_DATA_SWAP_NONE); - - /* Make sure it's settled */ - radeon_engine_idle(rinfo); + radeon_engine_idle (); } diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c index f343ba83f0a..1a056adb61c 100644 --- a/drivers/video/aty/radeon_backlight.c +++ b/drivers/video/aty/radeon_backlight.c @@ -66,7 +66,7 @@ static int radeon_bl_update_status(struct backlight_device *bd) level = bd->props.brightness; del_timer_sync(&rinfo->lvds_timer); - radeon_engine_idle(rinfo); + radeon_engine_idle(); lvds_gen_cntl = INREG(LVDS_GEN_CNTL); if (level > 0) { diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index d5b27f9d374..d0f1a7fc2c9 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -282,8 +282,6 @@ static int backlight = 1; static int backlight = 0; #endif -int accel_cexp = 0; - /* * prototypes */ @@ -854,6 +852,7 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var, if (rinfo->asleep) return 0; + radeon_fifo_wait(2); OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset) * var->bits_per_pixel / 8) & ~7); return 0; @@ -883,6 +882,7 @@ static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd, if (rc) return rc; + radeon_fifo_wait(2); if (value & 0x01) { tmp = INREG(LVDS_GEN_CNTL); @@ -940,7 +940,7 @@ int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch) if (rinfo->lock_blank) return 0; - radeon_engine_idle(rinfo); + radeon_engine_idle(); val = INREG(CRTC_EXT_CNTL); val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | @@ -1048,7 +1048,7 @@ static int radeonfb_blank (int blank, struct fb_info *info) if (rinfo->asleep) return 0; - + return radeon_screen_blank(rinfo, blank, 0); } @@ -1074,6 +1074,8 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, pindex = regno; if (!rinfo->asleep) { + radeon_fifo_wait(9); + if (rinfo->bpp == 16) { pindex = regno * 8; @@ -1242,6 +1244,8 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg { int i; + radeon_fifo_wait(20); + /* Workaround from XFree */ if (rinfo->is_mobility) { /* A temporal workaround for the occational blanking on certain laptop @@ -1337,7 +1341,7 @@ static void radeon_lvds_timer_func(unsigned long data) { struct radeonfb_info *rinfo = (struct radeonfb_info *)data; - radeon_engine_idle(rinfo); + radeon_engine_idle(); OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl); } @@ -1355,11 +1359,10 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, if (nomodeset) return; - radeon_engine_idle(rinfo); - if (!regs_only) radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0); + radeon_fifo_wait(31); for (i=0; i<10; i++) OUTREG(common_regs[i].reg, common_regs[i].val); @@ -1387,6 +1390,7 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, radeon_write_pll_regs(rinfo, mode); if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) { + radeon_fifo_wait(10); OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp); OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp); OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid); @@ -1401,6 +1405,7 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, if (!regs_only) radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0); + radeon_fifo_wait(2); OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl); return; @@ -1551,7 +1556,7 @@ static int radeonfb_set_par(struct fb_info *info) /* We always want engine to be idle on a mode switch, even * if we won't actually change the mode */ - radeon_engine_idle(rinfo); + radeon_engine_idle(); hSyncStart = mode->xres + mode->right_margin; hSyncEnd = hSyncStart + mode->hsync_len; @@ -1846,6 +1851,7 @@ static int radeonfb_set_par(struct fb_info *info) return 0; } + static struct fb_ops radeonfb_ops = { .owner = THIS_MODULE, .fb_check_var = radeonfb_check_var, @@ -1869,7 +1875,6 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) info->par = rinfo; info->pseudo_palette = rinfo->pseudo_palette; info->flags = FBINFO_DEFAULT - | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_XPAN @@ -1877,7 +1882,6 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) info->fbops = &radeonfb_ops; info->screen_base = rinfo->fb_base; info->screen_size = rinfo->mapped_vram; - /* Fill fix common fields */ strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id)); info->fix.smem_start = rinfo->fb_base_phys; @@ -1892,25 +1896,8 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) info->fix.mmio_len = RADEON_REGSIZE; info->fix.accel = FB_ACCEL_ATI_RADEON; - /* Allocate colormap */ fb_alloc_cmap(&info->cmap, 256, 0); - /* Setup pixmap used for acceleration */ -#define PIXMAP_SIZE (2048 * 4) - - info->pixmap.addr = kmalloc(PIXMAP_SIZE, GFP_KERNEL); - if (!info->pixmap.addr) { - printk(KERN_ERR "radeonfb: Failed to allocate pixmap !\n"); - noaccel = 1; - goto bail; - } - info->pixmap.size = PIXMAP_SIZE; - info->pixmap.flags = FB_PIXMAP_SYSTEM; - info->pixmap.scan_align = 4; - info->pixmap.buf_align = 4; - info->pixmap.access_align = 32; - -bail: if (noaccel) info->flags |= FBINFO_HWACCEL_DISABLED; @@ -2019,6 +2006,7 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo) u32 tom = INREG(NB_TOM); tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024); + radeon_fifo_wait(6); OUTREG(MC_FB_LOCATION, tom); OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); @@ -2522,8 +2510,6 @@ static int __init radeonfb_setup (char *options) } else if (!strncmp(this_opt, "ignore_devlist", 14)) { ignore_devlist = 1; #endif - } else if (!strncmp(this_opt, "accel_cexp", 12)) { - accel_cexp = 1; } else mode_option = this_opt; } @@ -2571,8 +2557,6 @@ module_param(monitor_layout, charp, 0); MODULE_PARM_DESC(monitor_layout, "Specify monitor mapping (like XFree86)"); module_param(force_measure_pll, bool, 0); MODULE_PARM_DESC(force_measure_pll, "Force measurement of PLL (debug)"); -module_param(accel_cexp, bool, 0); -MODULE_PARM_DESC(accel_cexp, "Use acceleration engine for color expansion"); #ifdef CONFIG_MTRR module_param(nomtrr, bool, 0); MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers"); diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 3df5015f1d1..675abdafc2d 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -2653,9 +2653,9 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) if (!(info->flags & FBINFO_HWACCEL_DISABLED)) { /* Make sure engine is reset */ - radeon_engine_idle(rinfo); + radeon_engine_idle(); radeonfb_engine_reset(rinfo); - radeon_engine_idle(rinfo); + radeon_engine_idle(); } /* Blank display and LCD */ @@ -2767,7 +2767,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev) rinfo->asleep = 0; } else - radeon_engine_idle(rinfo); + radeon_engine_idle(); /* Restore display & engine */ radeon_write_mode (rinfo, &rinfo->state, 1); diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index 974ca6d8654..3ea1b00fdd2 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h @@ -336,15 +336,7 @@ struct radeonfb_info { int mon2_type; u8 *mon2_EDID; - /* accel bits */ - u32 dp_gui_mc_base; - u32 dp_gui_mc_cache; - u32 dp_cntl_cache; - u32 dp_brush_fg_cache; - u32 dp_brush_bg_cache; - u32 dp_src_fg_cache; - u32 dp_src_bg_cache; - u32 fifo_free; + u32 dp_gui_master_cntl; struct pll_info pll; @@ -356,7 +348,6 @@ struct radeonfb_info { int lock_blank; int dynclk; int no_schedule; - int gfx_mode; enum radeon_pm_mode pm_mode; reinit_function_ptr reinit_func; @@ -401,14 +392,8 @@ static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms) #define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr) #define INREG16(addr) readw((rinfo->mmio_base)+addr) #define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr) - -#ifdef CONFIG_PPC -#define INREG(addr) ({ eieio(); ld_le32(rinfo->mmio_base+(addr)); }) -#define OUTREG(addr,val) do { eieio(); st_le32(rinfo->mmio_base+(addr),(val)); } while(0) -#else #define INREG(addr) readl((rinfo->mmio_base)+addr) #define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr) -#endif static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr, u32 val, u32 mask) @@ -550,7 +535,17 @@ static inline u32 radeon_get_dstbpp(u16 depth) * 2D Engine helper routines */ -extern void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries); +static inline void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries) +{ + int i; + + for (i=0; i<2000000; i++) { + if ((INREG(RBBM_STATUS) & 0x7f) >= entries) + return; + udelay(1); + } + printk(KERN_ERR "radeonfb: FIFO Timeout !\n"); +} static inline void radeon_engine_flush (struct radeonfb_info *rinfo) { @@ -563,7 +558,7 @@ static inline void radeon_engine_flush (struct radeonfb_info *rinfo) /* Ensure FIFO is empty, ie, make sure the flush commands * has reached the cache */ - radeon_fifo_update_and_wait(rinfo, 64); + _radeon_fifo_wait (rinfo, 64); /* Wait for the flush to complete */ for (i=0; i < 2000000; i++) { @@ -575,12 +570,12 @@ static inline void radeon_engine_flush (struct radeonfb_info *rinfo) } -static inline void radeon_engine_idle(struct radeonfb_info *rinfo) +static inline void _radeon_engine_idle(struct radeonfb_info *rinfo) { int i; /* ensure FIFO is empty before waiting for idle */ - radeon_fifo_update_and_wait (rinfo, 64); + _radeon_fifo_wait (rinfo, 64); for (i=0; i<2000000; i++) { if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) { @@ -593,6 +588,8 @@ static inline void radeon_engine_idle(struct radeonfb_info *rinfo) } +#define radeon_engine_idle() _radeon_engine_idle(rinfo) +#define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries) #define radeon_msleep(ms) _radeon_msleep(rinfo,ms) @@ -622,7 +619,6 @@ extern void radeonfb_imageblit(struct fb_info *p, const struct fb_image *image); extern int radeonfb_sync(struct fb_info *info); extern void radeonfb_engine_init (struct radeonfb_info *rinfo); extern void radeonfb_engine_reset(struct radeonfb_info *rinfo); -extern void radeon_fixup_mem_offset(struct radeonfb_info *rinfo); /* Other functions */ extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch); @@ -638,6 +634,4 @@ static inline void radeonfb_bl_init(struct radeonfb_info *rinfo) {} static inline void radeonfb_bl_exit(struct radeonfb_info *rinfo) {} #endif -extern int accel_cexp; - #endif /* __RADEONFB_H__ */ -- cgit v1.2.3 From d9d38ca07d5187b3082074934e73f014f5d31409 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Thu, 11 Dec 2008 12:11:20 +0100 Subject: i2c-pmcmsp: Fix endianness misannotation tmp is used as host-endian and is loaded from a be64, fix the cast and the endian accessor used. Signed-off-by: Harvey Harrison Signed-off-by: Andrew Morton Cc: Ben Dooks Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-pmcmsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c index dcf2045b522..0bdb2d7f057 100644 --- a/drivers/i2c/busses/i2c-pmcmsp.c +++ b/drivers/i2c/busses/i2c-pmcmsp.c @@ -486,7 +486,7 @@ static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd( if (cmd->type == MSP_TWI_CMD_WRITE || cmd->type == MSP_TWI_CMD_WRITE_READ) { - __be64 tmp = cpu_to_be64p((u64 *)cmd->write_data); + u64 tmp = be64_to_cpup((__be64 *)cmd->write_data); tmp >>= (MSP_MAX_BYTES_PER_RW - cmd->write_len) * 8; dev_dbg(&pmcmsptwi_adapter.dev, "Writing 0x%016llx\n", tmp); pmcmsptwi_writel(tmp & 0x00000000ffffffffLL, -- cgit v1.2.3 From 2b895c3f35d3ead0e9409b59da94094c7873f96d Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Thu, 11 Dec 2008 12:11:21 +0100 Subject: i2c-highlander: Trivial endian casting fixes Fixes sparse warnings: drivers/i2c/busses/i2c-highlander.c:95:26: warning: incorrect type in argument 1 (different base types) drivers/i2c/busses/i2c-highlander.c:95:26: expected restricted __be16 const [usertype] *p drivers/i2c/busses/i2c-highlander.c:95:26: got unsigned short [usertype] * drivers/i2c/busses/i2c-highlander.c:106:15: warning: incorrect type in assignment (different base types) drivers/i2c/busses/i2c-highlander.c:106:15: expected unsigned short [unsigned] [short] [usertype] drivers/i2c/busses/i2c-highlander.c:106:15: got restricted __be16 Signed-off-by: Harvey Harrison Signed-off-by: Andrew Morton Cc: Ben Dooks Acked-by: Paul Mundt Signed-off-by: Jean Delvare --- drivers/i2c/busses/i2c-highlander.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c index f4d22ae9d29..e5a8dae4a28 100644 --- a/drivers/i2c/busses/i2c-highlander.c +++ b/drivers/i2c/busses/i2c-highlander.c @@ -92,7 +92,7 @@ static void highlander_i2c_setup(struct highlander_i2c_dev *dev) static void smbus_write_data(u8 *src, u16 *dst, int len) { for (; len > 1; len -= 2) { - *dst++ = be16_to_cpup((u16 *)src); + *dst++ = be16_to_cpup((__be16 *)src); src += 2; } @@ -103,7 +103,7 @@ static void smbus_write_data(u8 *src, u16 *dst, int len) static void smbus_read_data(u16 *src, u8 *dst, int len) { for (; len > 1; len -= 2) { - *(u16 *)dst = cpu_to_be16p(src++); + *(__be16 *)dst = cpu_to_be16p(src++); dst += 2; } -- cgit v1.2.3 From 30bb0e0dce78427f3e5cb728d6b5ea73acbefffa Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Thu, 11 Dec 2008 21:28:11 -0800 Subject: e1000e: fix double release of mutex During a reset, releasing the swflag after it failed to be acquired would cause a double unlock of the mutex. Instead, test whether acquisition of the swflag was successful and if not, do not release the swflag. The reset must still be done to bring the device to a quiescent state. This resolves [BUG 12200] BUG: bad unlock balance detected! e1000e http://bugzilla.kernel.org/show_bug.cgi?id=12200 Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/ich8lan.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 523b9716a54..d115a6d30f2 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -1893,12 +1893,17 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) ctrl |= E1000_CTRL_PHY_RST; } ret_val = e1000_acquire_swflag_ich8lan(hw); + /* Whether or not the swflag was acquired, we need to reset the part */ hw_dbg(hw, "Issuing a global reset to ich8lan"); ew32(CTRL, (ctrl | E1000_CTRL_RST)); msleep(20); - /* release the swflag because it is not reset by hardware reset */ - e1000_release_swflag_ich8lan(hw); + if (!ret_val) { + /* release the swflag because it is not reset by + * hardware reset + */ + e1000_release_swflag_ich8lan(hw); + } ret_val = e1000e_get_auto_rd_done(hw); if (ret_val) { -- cgit v1.2.3 From febd7a5c131433ea128b54dd5712e260c79eb3ab Mon Sep 17 00:00:00 2001 From: "Alan D. Brunelle" Date: Tue, 9 Dec 2008 15:52:15 +0100 Subject: Commands needing to be retried require a complete re-initialization. The test-unit-ready portion of this patch was causing boots to fail on my test machine (as in http://lkml.org/lkml/2008/12/5/161). With this patch in place, the system is booting reliably. Mike Anderson found the same problem in the hp_hw_start_stop code, and I applied the same solution in cdrom_read_cdda_bpc. Signed-off-by: Alan D. Brunelle Cc: Mike Anderson Signed-off-by: Jens Axboe --- drivers/cdrom/cdrom.c | 16 ++++++++++------ drivers/scsi/device_handler/scsi_dh_hp_sw.c | 12 ++++++++---- 2 files changed, 18 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index d16b02423d6..7d2e91cccb1 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2081,10 +2081,6 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, if (!q) return -ENXIO; - rq = blk_get_request(q, READ, GFP_KERNEL); - if (!rq) - return -ENOMEM; - cdi->last_sense = 0; while (nframes) { @@ -2096,9 +2092,17 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, len = nr * CD_FRAMESIZE_RAW; + rq = blk_get_request(q, READ, GFP_KERNEL); + if (!rq) { + ret = -ENOMEM; + break; + } + ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL); - if (ret) + if (ret) { + blk_put_request(rq); break; + } rq->cmd[0] = GPCMD_READ_CD; rq->cmd[1] = 1 << 2; @@ -2124,6 +2128,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, if (blk_rq_unmap_user(bio)) ret = -EFAULT; + blk_put_request(rq); if (ret) break; @@ -2133,7 +2138,6 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, ubuf += len; } - blk_put_request(rq); return ret; } diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c index 9aec4ca64e5..f7da7530875 100644 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c @@ -107,6 +107,7 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h) struct request *req; int ret; +retry: req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO); if (!req) return SCSI_DH_RES_TEMP_UNAVAIL; @@ -121,7 +122,6 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h) memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE); req->sense_len = 0; -retry: ret = blk_execute_rq(req->q, NULL, req, 1); if (ret == -EIO) { if (req->sense_len > 0) { @@ -136,8 +136,10 @@ retry: h->path_state = HP_SW_PATH_ACTIVE; ret = SCSI_DH_OK; } - if (ret == SCSI_DH_IMM_RETRY) + if (ret == SCSI_DH_IMM_RETRY) { + blk_put_request(req); goto retry; + } if (ret == SCSI_DH_DEV_OFFLINED) { h->path_state = HP_SW_PATH_PASSIVE; ret = SCSI_DH_OK; @@ -200,6 +202,7 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h) struct request *req; int ret, retry; +retry: req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO); if (!req) return SCSI_DH_RES_TEMP_UNAVAIL; @@ -216,7 +219,6 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h) req->sense_len = 0; retry = h->retries; -retry: ret = blk_execute_rq(req->q, NULL, req, 1); if (ret == -EIO) { if (req->sense_len > 0) { @@ -231,8 +233,10 @@ retry: ret = SCSI_DH_OK; if (ret == SCSI_DH_RETRY) { - if (--retry) + if (--retry) { + blk_put_request(req); goto retry; + } ret = SCSI_DH_IO; } -- cgit v1.2.3 From f75bc06e5d00a827d3ec5d57bbb5b73a4adec855 Mon Sep 17 00:00:00 2001 From: Ingo Brueckl Date: Wed, 10 Dec 2008 23:34:00 +0100 Subject: unicode table for cp437 There is a major bug in the cp437 to unicode translation table. Char 0x7c is mapped to U+00a5 which is the Yen sign and wrong. The right mapping is U+00a6 (broken bar). Furthermore, a mapping for U+00b4 (a widely used character) is missing even though easily possible. The patch fixes these, as well as it provides a few other useful mappings. The changes are as follows: 0x0f (enhancement) enables a sort of currency symbol 0x27 (bug) enables a sort of acute accent which is a widely used character 0x44 (enhancement) enables a sort of icelandic capital letter eth 0x7c (major bug) corrects mapping 0xeb (enhancement) enables a sort of icelandic small letter eth 0xee (enhancement) enables a sort of math 'element of' Signed-off-by: Ingo Brueckl Acked-by: H. Peter Anvin Signed-off-by: Linus Torvalds --- drivers/char/cp437.uni | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/char/cp437.uni b/drivers/char/cp437.uni index 1f06889a96b..bc6163484f6 100644 --- a/drivers/char/cp437.uni +++ b/drivers/char/cp437.uni @@ -27,7 +27,7 @@ 0x0c U+2640 0x0d U+266a 0x0e U+266b -0x0f U+263c +0x0f U+263c U+00a4 0x10 U+25b6 U+25ba 0x11 U+25c0 U+25c4 0x12 U+2195 @@ -55,7 +55,7 @@ 0x24 U+0024 0x25 U+0025 0x26 U+0026 -0x27 U+0027 +0x27 U+0027 U+00b4 0x28 U+0028 0x29 U+0029 0x2a U+002a @@ -84,7 +84,7 @@ 0x41 U+0041 U+00c0 U+00c1 U+00c2 U+00c3 0x42 U+0042 0x43 U+0043 U+00a9 -0x44 U+0044 +0x44 U+0044 U+00d0 0x45 U+0045 U+00c8 U+00ca U+00cb 0x46 U+0046 0x47 U+0047 @@ -140,7 +140,7 @@ 0x79 U+0079 U+00fd 0x7a U+007a 0x7b U+007b -0x7c U+007c U+00a5 +0x7c U+007c U+00a6 0x7d U+007d 0x7e U+007e # @@ -263,10 +263,10 @@ 0xe8 U+03a6 U+00d8 0xe9 U+0398 0xea U+03a9 U+2126 -0xeb U+03b4 +0xeb U+03b4 U+00f0 0xec U+221e 0xed U+03c6 U+00f8 -0xee U+03b5 +0xee U+03b5 U+2208 0xef U+2229 0xf0 U+2261 0xf1 U+00b1 -- cgit v1.2.3 From 1c55f18717304100a5f624c923f7cb6511b4116d Mon Sep 17 00:00:00 2001 From: Ingo Brueckl Date: Wed, 10 Dec 2008 23:35:00 +0100 Subject: console ASCII glyph 1:1 mapping For the console, there is a 1:1 mapping of glyphs which cannot be found in the current font. This seems to be meant as a kind of 'emergency fallback' for fonts without unicode mapping which otherwise would display nothing readable on the screen. At the moment it affects all chars for which no substitution character is defined. In particular this means that for all chars (>= 128) where there is no iso88591-1/unicode character (e.g. control character area) you'll get the very strange 1:1 mapping of the (cp437) graphics card glyphs. I'm pretty sure that the 1:1 mapping should only affect strict ASCII code characters, i.e. chars < 128. The patch limits the mapping as it probably was meant anyway. Signed-off-by: Ingo Brueckl Acked-by: H. Peter Anvin Cc: Egmont Koblinger Signed-off-by: Linus Torvalds --- drivers/char/vt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/vt.c b/drivers/char/vt.c index a5af6072e2b..008176edbd6 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -2274,7 +2274,7 @@ rescan_last_byte: continue; /* nothing to display */ } /* Glyph not found */ - if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) { + if ((!(vc->vc_utf && !vc->vc_disp_ctrl) && c < 128) && !(c & ~charmask)) { /* In legacy mode use the glyph we get by a 1:1 mapping. This would make absolutely no sense with Unicode in mind, but do this for ASCII characters since a font may lack -- cgit v1.2.3 From 25a41b280083259d05d68f61633194344a1f8a9f Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 13 Dec 2008 01:43:59 +0100 Subject: ieee1394: add quirk fix for Freecom HDD According to http://bugzilla.kernel.org/show_bug.cgi?id=12206, Freecom FireWire Hard Drive 1TB reports max_rom=2 but returns garbage if block read requests are used to read the config ROM. Force max_rom=0 to limit them to quadlet read requests. Reported-by: Christian Mueller Signed-off-by: Stefan Richter --- drivers/ieee1394/nodemgr.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index d333ae22459..79ef5fd928a 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -115,8 +115,14 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length, return error; } +#define OUI_FREECOM_TECHNOLOGIES_GMBH 0x0001db + static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci) { + /* Freecom FireWire Hard Drive firmware bug */ + if (be32_to_cpu(bus_info_data[3]) >> 8 == OUI_FREECOM_TECHNOLOGIES_GMBH) + return 0; + return (be32_to_cpu(bus_info_data[2]) >> 8) & 0x3; } -- cgit v1.2.3 From 35024c384ba4faaeac361a1ffee05a1475f9a9ed Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 15 Dec 2008 13:54:14 -0800 Subject: pcmcia: blackfin: fix bug - add missing ; to MODULE macro Cc: Michael Hennerich Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Cc: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/bfin_cf_pcmcia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c index bb7338863fb..b59d4115d20 100644 --- a/drivers/pcmcia/bfin_cf_pcmcia.c +++ b/drivers/pcmcia/bfin_cf_pcmcia.c @@ -334,6 +334,6 @@ static void __exit bfin_cf_exit(void) module_init(bfin_cf_init); module_exit(bfin_cf_exit); -MODULE_AUTHOR("Michael Hennerich ") +MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("BFIN CF/PCMCIA Driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 38aefbc585c5d86df101e7644bff2c47112783d4 Mon Sep 17 00:00:00 2001 From: Frederik Deweerdt Date: Mon, 15 Dec 2008 13:54:19 -0800 Subject: ACPI toshiba: only register rfkill if bt is enabled Part of the rfkill initialization was done whenever BT was on or not. The following patch checks for BT presence before registering the rfkill to the input layer. Some minor cleanups (> 80 char lines) were also added in the process. On Tue, Oct 28, 2008 at 10:10:37PM +0300, Andrey Borzenkov wrote: [...] > [ 66.633036] toshiba_acpi: Toshiba Laptop ACPI Extras version 0.19 > [ 66.633054] toshiba_acpi: HCI method: \_SB_.VALD.GHCI > [ 66.637764] input: Toshiba RFKill Switch as /devices/virtual/input/input3 [...] > [ 113.920753] ------------[ cut here ]------------ > [ 113.920828] kernel BUG at /home/bor/src/linux-git/net/rfkill/rfkill.c:347! > [ 113.920845] invalid opcode: 0000 [#1] > [ 113.920877] last sysfs file: /sys/devices/pci0000:00/0000:00:04.0/host0/target0:0:0/0:0:0:0/block/sda/size > [ 113.920900] Dumping ftrace buffer: > [ 113.920919] (ftrace buffer empty) > [ 113.920933] Modules linked in: af_packet irnet ppp_generic slhc ircomm_tty ircomm binfmt_misc loop dm_mirror dm_region_hash dm_log dm_round_robin dm_multipath dm_mod alim15x3 ide_core nvram toshiba cryptomgr aead crypto_blkcipher michael_mic crypto_algapi orinoco_cs orinoco hermes_dld hermes pcmcia firmware_class snd_ali5451 snd_ac97_codec ac97_bus snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device smsc_ircc2 snd_pcm_oss snd_pcm rtc_cmos irda snd_timer snd_mixer_oss rtc_core snd crc_ccitt yenta_socket rtc_lib rsrc_nonstatic i2c_ali1535 pcmcia_core pcspkr psmouse soundcore i2c_core evdev sr_mod snd_page_alloc alim1535_wdt cdrom fan sg video output toshiba_acpi rfkill thermal backlight ali_agp processor ac button input_polldev battery agpgart ohci_hcd usbcore reiserfs pata_ali libata sd_mod scsi_mod [last unloaded: scsi_wait_scan] > [ 113.921765] > [ 113.921785] Pid: 3272, comm: ipolldevd Not tainted (2.6.28-rc2-1avb #3) PORTEGE 4000 > [ 113.921801] EIP: 0060:[] EFLAGS: 00010246 CPU: 0 > [ 113.921854] EIP is at rfkill_force_state+0x53/0x90 [rfkill] > [ 113.921870] EAX: 00000000 EBX: 00000000 ECX: 00000003 EDX: 00000000 > [ 113.921885] ESI: 00000000 EDI: ddd50300 EBP: d8d7af40 ESP: d8d7af24 > [ 113.921900] DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068 > [ 113.921918] Process ipolldevd (pid: 3272, ti=d8d7a000 task=d8d93c90 task.ti=d8d7a000) > [ 113.921933] Stack: > [ 113.921945] d8d7af38 00000246 dfb029d8 dfb029c0 dfb029d8 dfb029c0 ddd50300 d8d7af5c > [ 113.922014] dfb018e2 01000246 01000000 ddd50300 ddd50314 ddabb8a0 d8d7af68 dfb381c1 > [ 113.922098] 00000000 d8d7afa4 c012ec0a 00000000 00000002 00000000 c012eba8 ddabb8c0 > [ 113.922240] Call Trace: > [ 113.922240] [] ? bt_poll_rfkill+0x5c/0x82 [toshiba_acpi] > [ 113.922240] [] ? input_polled_device_work+0x11/0x40 [input_polldev] > [ 113.922240] [] ? run_workqueue+0xea/0x1f0 > [ 113.922240] [] ? run_workqueue+0x88/0x1f0 > [ 113.922240] [] ? input_polled_device_work+0x0/0x40 [input_polldev] > [ 113.922240] [] ? worker_thread+0x87/0xf0 > [ 113.922240] [] ? autoremove_wake_function+0x0/0x50 > [ 113.922240] [] ? worker_thread+0x0/0xf0 > [ 113.922240] [] ? kthread+0x3f/0x80 > [ 113.922240] [] ? kthread+0x0/0x80 > [ 113.922240] [] ? kernel_thread_helper+0x7/0x10 > [ 113.922240] Code: 43 54 89 73 54 39 c6 74 11 89 d9 ba 01 00 00 00 b8 40 68 aa df e8 3e 35 69 e0 89 f8 e8 77 fd 85 e0 31 c0 83 c4 10 5b 5e 5f 5d c3 <0f> 0b eb fe 89 f6 8d bc 27 00 00 00 00 be f4 4d aa df bb 5f 01 > [ 113.922240] EIP: [] rfkill_force_state+0x53/0x90 [rfkill] SS:ESP 0068:d8d7af24 > [ 113.924700] ---[ end trace 0e404eb40cadd5f0 ]--- Signed-off-by: Frederik Deweerdt Tested-by: Andrey Borzenkov Acked-by: Len Brown Cc: Richard Purdie Acked-by: Philip Langdale Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/toshiba_acpi.c | 54 ++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index 25f531d892d..40e60fc2e59 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c @@ -824,32 +824,36 @@ static int __init toshiba_acpi_init(void) toshiba_acpi_exit(); return -ENOMEM; } - } - /* Register input device for kill switch */ - toshiba_acpi.poll_dev = input_allocate_polled_device(); - if (!toshiba_acpi.poll_dev) { - printk(MY_ERR "unable to allocate kill-switch input device\n"); - toshiba_acpi_exit(); - return -ENOMEM; - } - toshiba_acpi.poll_dev->private = &toshiba_acpi; - toshiba_acpi.poll_dev->poll = bt_poll_rfkill; - toshiba_acpi.poll_dev->poll_interval = 1000; /* msecs */ - - toshiba_acpi.poll_dev->input->name = toshiba_acpi.rfk_name; - toshiba_acpi.poll_dev->input->id.bustype = BUS_HOST; - toshiba_acpi.poll_dev->input->id.vendor = 0x0930; /* Toshiba USB ID */ - set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit); - set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit); - input_report_switch(toshiba_acpi.poll_dev->input, SW_RFKILL_ALL, TRUE); - input_sync(toshiba_acpi.poll_dev->input); - - ret = input_register_polled_device(toshiba_acpi.poll_dev); - if (ret) { - printk(MY_ERR "unable to register kill-switch input device\n"); - toshiba_acpi_exit(); - return ret; + /* Register input device for kill switch */ + toshiba_acpi.poll_dev = input_allocate_polled_device(); + if (!toshiba_acpi.poll_dev) { + printk(MY_ERR + "unable to allocate kill-switch input device\n"); + toshiba_acpi_exit(); + return -ENOMEM; + } + toshiba_acpi.poll_dev->private = &toshiba_acpi; + toshiba_acpi.poll_dev->poll = bt_poll_rfkill; + toshiba_acpi.poll_dev->poll_interval = 1000; /* msecs */ + + toshiba_acpi.poll_dev->input->name = toshiba_acpi.rfk_name; + toshiba_acpi.poll_dev->input->id.bustype = BUS_HOST; + /* Toshiba USB ID */ + toshiba_acpi.poll_dev->input->id.vendor = 0x0930; + set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit); + set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit); + input_report_switch(toshiba_acpi.poll_dev->input, + SW_RFKILL_ALL, TRUE); + input_sync(toshiba_acpi.poll_dev->input); + + ret = input_register_polled_device(toshiba_acpi.poll_dev); + if (ret) { + printk(MY_ERR + "unable to register kill-switch input device\n"); + toshiba_acpi_exit(); + return ret; + } } return 0; -- cgit v1.2.3 From 93d546399c2b7d66a54d5fbd5eee17de19246bf6 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Tue, 16 Dec 2008 09:15:31 +0900 Subject: sh: maple: Do not pass SLAB_POISON to kmem_cache_create() SLAB_POISON is not a valid flag for kmem_create_cache() unless CONFIG_DEBUG_SLAB is set, so remove it from the flags argument. Acked-by: Adrian McMenamin Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- drivers/sh/maple/maple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index d1812d32f47..63f0de29aa1 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c @@ -827,7 +827,7 @@ static int __init maple_bus_init(void) maple_queue_cache = kmem_cache_create("maple_queue_cache", 0x400, 0, - SLAB_POISON|SLAB_HWCACHE_ALIGN, NULL); + SLAB_HWCACHE_ALIGN, NULL); if (!maple_queue_cache) goto cleanup_bothirqs; -- cgit v1.2.3 From 8953f1282793882a5444924f7a273dc72a43d0a3 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 16 Dec 2008 01:44:05 -0800 Subject: tlan: Fix small (< 64 bytes) datagram transmissions The TLAN chip does not support tranmissions smaller than 64 bytes. Smaller transfers need to be padded up to that size. This was broken by commit id 41873e9aff0632d80c74380d58a89e8d420151bd ("tlan: get rid of padding buffer"). Signed-off-by: Sakari Ailus Signed-off-by: David S. Miller --- drivers/net/tlan.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index c41d6876136..cf8cdafda5a 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -1098,6 +1098,7 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev ) dma_addr_t tail_list_phys; u8 *tail_buffer; unsigned long flags; + unsigned int txlen; if ( ! priv->phyOnline ) { TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: %s PHY is not ready\n", @@ -1108,6 +1109,7 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev ) if (skb_padto(skb, TLAN_MIN_FRAME_SIZE)) return 0; + txlen = max(skb->len, (unsigned int)TLAN_MIN_FRAME_SIZE); tail_list = priv->txList + priv->txTail; tail_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txTail; @@ -1125,16 +1127,16 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev ) if ( bbuf ) { tail_buffer = priv->txBuffer + ( priv->txTail * TLAN_MAX_FRAME_SIZE ); - skb_copy_from_linear_data(skb, tail_buffer, skb->len); + skb_copy_from_linear_data(skb, tail_buffer, txlen); } else { tail_list->buffer[0].address = pci_map_single(priv->pciDev, - skb->data, skb->len, + skb->data, txlen, PCI_DMA_TODEVICE); TLan_StoreSKB(tail_list, skb); } - tail_list->frameSize = (u16) skb->len; - tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) skb->len; + tail_list->frameSize = (u16) txlen; + tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) txlen; tail_list->buffer[1].count = 0; tail_list->buffer[1].address = 0; -- cgit v1.2.3 From 2c413a6434dca02387a263dc4ca8009692421998 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Mon, 15 Dec 2008 20:18:52 +0000 Subject: enc28j60: use netif_rx_ni() to deliver RX packets The enc28j60 driver reads incoming packets in the process (workqueue) context, not in a tasklet or the interrupt context. Thus, we should use netif_rx_ni() to deliver those packets to the networking layer, instead of netif_rx(). This way incoming packets don't wait in the incoming queue for the next IRQ to be serviced. Signed-off-by: Baruch Siach Signed-off-by: David S. Miller --- drivers/net/enc28j60.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c index c414554ac32..36cb6e95b46 100644 --- a/drivers/net/enc28j60.c +++ b/drivers/net/enc28j60.c @@ -959,7 +959,7 @@ static void enc28j60_hw_rx(struct net_device *ndev) ndev->stats.rx_packets++; ndev->stats.rx_bytes += len; ndev->last_rx = jiffies; - netif_rx(skb); + netif_rx_ni(skb); } } /* -- cgit v1.2.3 From d10d491f842243e2e3bf5a2714020f9d649e1e38 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 11 Dec 2008 13:42:42 +0900 Subject: libata: fix Seagate NCQ+FLUSH blacklist Due to miscommunication, P/N was mistaken as firmware revision strings. Update it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 65 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 5e2eb740df4..bc6695e3c84 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4050,17 +4050,70 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "ST3160023AS", "3.42", ATA_HORKAGE_NONCQ }, /* Seagate NCQ + FLUSH CACHE firmware bug */ - { "ST31500341AS", "9JU138", ATA_HORKAGE_NONCQ | + { "ST31500341AS", "SD15", ATA_HORKAGE_NONCQ | ATA_HORKAGE_FIRMWARE_WARN }, - { "ST31000333AS", "9FZ136", ATA_HORKAGE_NONCQ | + { "ST31500341AS", "SD16", ATA_HORKAGE_NONCQ | ATA_HORKAGE_FIRMWARE_WARN }, - { "ST3640623AS", "9FZ164", ATA_HORKAGE_NONCQ | + { "ST31500341AS", "SD17", ATA_HORKAGE_NONCQ | ATA_HORKAGE_FIRMWARE_WARN }, - { "ST3640323AS", "9FZ134", ATA_HORKAGE_NONCQ | + { "ST31500341AS", "SD18", ATA_HORKAGE_NONCQ | ATA_HORKAGE_FIRMWARE_WARN }, - { "ST3320813AS", "9FZ182", ATA_HORKAGE_NONCQ | + { "ST31500341AS", "SD19", ATA_HORKAGE_NONCQ | ATA_HORKAGE_FIRMWARE_WARN }, - { "ST3320613AS", "9FZ162", ATA_HORKAGE_NONCQ | + + { "ST31000333AS", "SD15", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST31000333AS", "SD16", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST31000333AS", "SD17", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST31000333AS", "SD18", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST31000333AS", "SD19", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + + { "ST3640623AS", "SD15", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3640623AS", "SD16", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3640623AS", "SD17", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3640623AS", "SD18", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3640623AS", "SD19", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + + { "ST3640323AS", "SD15", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3640323AS", "SD16", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3640323AS", "SD17", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3640323AS", "SD18", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3640323AS", "SD19", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + + { "ST3320813AS", "SD15", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3320813AS", "SD16", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3320813AS", "SD17", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3320813AS", "SD18", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3320813AS", "SD19", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + + { "ST3320613AS", "SD15", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3320613AS", "SD16", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3320613AS", "SD17", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3320613AS", "SD18", ATA_HORKAGE_NONCQ | + ATA_HORKAGE_FIRMWARE_WARN }, + { "ST3320613AS", "SD19", ATA_HORKAGE_NONCQ | ATA_HORKAGE_FIRMWARE_WARN }, /* Blacklist entries taken from Silicon Image 3124/3132 -- cgit v1.2.3 From bab5b32a537edc83ff86bff91e46f328339f49f8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 9 Dec 2008 17:13:19 +0900 Subject: pata_hpt366: fix cable detection, pata_hpt366 is strange in that its two channels occupy two PCI functions and both are primary channels and bit1 of PCI configuration register 0x5A indicates cable for both channels. Signed-off-by: Tejun Heo Cc: Alan Cox Cc: Sergei Shtylyov Signed-off-by: Jeff Garzik --- drivers/ata/pata_hpt366.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index a098ba8eaab..4824821745a 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -211,11 +211,15 @@ static u32 hpt36x_find_mode(struct ata_port *ap, int speed) static int hpt36x_cable_detect(struct ata_port *ap) { - u8 ata66; struct pci_dev *pdev = to_pci_dev(ap->host->dev); + u8 ata66; + /* + * Each channel of pata_hpt366 occupies separate PCI function + * as the primary channel and bit1 indicates the cable type. + */ pci_read_config_byte(pdev, 0x5A, &ata66); - if (ata66 & (1 << ap->port_no)) + if (ata66 & 2) return ATA_CBL_PATA40; return ATA_CBL_PATA80; } -- cgit v1.2.3 From 3ee89f177e3cef0b5b024bcb6df683a3fa7d795f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 9 Dec 2008 17:14:04 +0900 Subject: pata_hpt366: no ATAPI DMA IDE hpt366 driver doesn't allow DMA for ATAPI devices and MWDMA2 on ATAPI device locks up pata_hpt366. Follow the suit. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/pata_hpt366.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index 4824821745a..e0c4f05d7d5 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -183,7 +183,9 @@ static unsigned long hpt366_filter(struct ata_device *adev, unsigned long mask) mask &= ~(0xF8 << ATA_SHIFT_UDMA); if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4)) mask &= ~(0xF0 << ATA_SHIFT_UDMA); - } + } else if (adev->class == ATA_DEV_ATAPI) + mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); + return ata_bmdma_mode_filter(adev, mask); } -- cgit v1.2.3 From a804644a1a31a0b85e4c7d3c49f30419513cb6c1 Mon Sep 17 00:00:00 2001 From: Mike Ditto Date: Tue, 16 Dec 2008 20:17:09 +0000 Subject: i2c-cpm: Detect and report NAK right away instead of timing out Make the driver report an ENXIO error immediately upon NAK instead of waiting for another interrupt and getting a timeout. When reading from a device that is not present or declines to respond to, e.g., a non-existent register address, CPM immediately reports a NAK condition in the TxBD, but the driver kept waiting until a timeout, which takes 1 second and causes an ugly console error message. Signed-off-by: Mike Ditto Acked-by: Jochen Friedrich [ben-linux@fluff.org: reordered description text] Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-cpm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 228f7572306..3fcf78e906d 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -365,6 +365,7 @@ static int cpm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) pmsg = &msgs[tptr]; if (pmsg->flags & I2C_M_RD) ret = wait_event_interruptible_timeout(cpm->i2c_wait, + (in_be16(&tbdf[tptr].cbd_sc) & BD_SC_NAK) || !(in_be16(&rbdf[rptr].cbd_sc) & BD_SC_EMPTY), 1 * HZ); else -- cgit v1.2.3 From be44f01e8af3862767f466f89c12640a2f2b0038 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 31 Oct 2008 16:10:22 +0000 Subject: i2c-s3c2410: fix check for being in suspend. As noted by Julia Lawall , we can never trigger the check for being in suspend due to the result of !readl(i2c->regs + S3C2410_IICCON) & S3C2410_IICCON_IRQEN always being 0. Add suspend/resume hooks to stop i2c transactions happening until the driver has been resumed. Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-s3c2410.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 1fac4e23313..b7434d24904 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -56,6 +56,7 @@ enum s3c24xx_i2c_state { struct s3c24xx_i2c { spinlock_t lock; wait_queue_head_t wait; + unsigned int suspended:1; struct i2c_msg *msg; unsigned int msg_num; @@ -507,7 +508,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int unsigned long timeout; int ret; - if (!(readl(i2c->regs + S3C2410_IICCON) & S3C2410_IICCON_IRQEN)) + if (i2c->suspended) return -EIO; ret = s3c24xx_i2c_set_master(i2c); @@ -986,17 +987,26 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) } #ifdef CONFIG_PM +static int s3c24xx_i2c_suspend_late(struct platform_device *dev, + pm_message_t msg) +{ + struct s3c24xx_i2c *i2c = platform_get_drvdata(dev); + i2c->suspended = 1; + return 0; +} + static int s3c24xx_i2c_resume(struct platform_device *dev) { struct s3c24xx_i2c *i2c = platform_get_drvdata(dev); - if (i2c != NULL) - s3c24xx_i2c_init(i2c); + i2c->suspended = 0; + s3c24xx_i2c_init(i2c); return 0; } #else +#define s3c24xx_i2c_suspend_late NULL #define s3c24xx_i2c_resume NULL #endif @@ -1005,6 +1015,7 @@ static int s3c24xx_i2c_resume(struct platform_device *dev) static struct platform_driver s3c2410_i2c_driver = { .probe = s3c24xx_i2c_probe, .remove = s3c24xx_i2c_remove, + .suspend_late = s3c24xx_i2c_suspend_late, .resume = s3c24xx_i2c_resume, .driver = { .owner = THIS_MODULE, @@ -1015,6 +1026,7 @@ static struct platform_driver s3c2410_i2c_driver = { static struct platform_driver s3c2440_i2c_driver = { .probe = s3c24xx_i2c_probe, .remove = s3c24xx_i2c_remove, + .suspend_late = s3c24xx_i2c_suspend_late, .resume = s3c24xx_i2c_resume, .driver = { .owner = THIS_MODULE, -- cgit v1.2.3 From bb5f133dbc4f04b6388715d364ae5865455166c2 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 16 Dec 2008 15:22:41 -0800 Subject: tlan: Fix pci memory unmapping Fix pci unmapping problem introduced by commit id 8953f1282793882a5444924f7a273dc72a43d0a3 "tlan: Fix small (< 64 bytes) datagram transmissions". Signed-off-by: Sakari Ailus Signed-off-by: David S. Miller --- drivers/net/tlan.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index cf8cdafda5a..e60498232b9 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -1433,7 +1433,9 @@ static u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int ) if ( ! bbuf ) { struct sk_buff *skb = TLan_GetSKB(head_list); pci_unmap_single(priv->pciDev, head_list->buffer[0].address, - skb->len, PCI_DMA_TODEVICE); + max(skb->len, + (unsigned int)TLAN_MIN_FRAME_SIZE), + PCI_DMA_TODEVICE); dev_kfree_skb_any(skb); head_list->buffer[8].address = 0; head_list->buffer[9].address = 0; @@ -2057,9 +2059,12 @@ static void TLan_FreeLists( struct net_device *dev ) list = priv->txList + i; skb = TLan_GetSKB(list); if ( skb ) { - pci_unmap_single(priv->pciDev, - list->buffer[0].address, skb->len, - PCI_DMA_TODEVICE); + pci_unmap_single( + priv->pciDev, + list->buffer[0].address, + max(skb->len, + (unsigned int)TLAN_MIN_FRAME_SIZE), + PCI_DMA_TODEVICE); dev_kfree_skb_any( skb ); list->buffer[8].address = 0; list->buffer[9].address = 0; -- cgit v1.2.3 From 9a3de25544dadab1971847f28f33b1cd0d1770a6 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Tue, 16 Dec 2008 15:42:20 -0800 Subject: drivers/net: starfire: Fix napi ->poll() weight handling starfire napi ->poll() handler can return work == weight after calling netif_rx_complete() (if there is no more work). It is illegal and this patch fixes it. Reported-by: Alexander Huemer Tested-by: Alexander Huemer Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- drivers/net/starfire.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 1d2ef8f4778..5a40f2d78be 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1509,6 +1509,11 @@ static int __netdev_rx(struct net_device *dev, int *quota) desc->status = 0; np->rx_done = (np->rx_done + 1) % DONE_Q_SIZE; } + + if (*quota == 0) { /* out of rx quota */ + retcode = 1; + goto out; + } writew(np->rx_done, np->base + CompletionQConsumerIdx); out: -- cgit v1.2.3 From e8e5752dc0a56a01527055b0c37510b1d6b6b861 Mon Sep 17 00:00:00 2001 From: Krzysztof Halasa Date: Wed, 17 Dec 2008 00:24:13 -0800 Subject: net: kernel BUG at drivers/net/phy/mdio_bus.c:165! kernel BUG at drivers/net/phy/mdio_bus.c:165! Unable to handle kernel NULL pointer dereference at virtual address 00000000 How? mdiobus_alloc() sets bus->state = MDIOBUS_ALLOCATED. mdiobus_register() sets bus->state = MDIOBUS_REGISTERED but then can fail (mdiobus_scan()) returning an error to the caller. The caller aborts correctly with mdiobus_free() which does: if (bus->state == MDIOBUS_ALLOCATED) { kfree(bus); return; } BUG_ON(bus->state != MDIOBUS_UNREGISTERED); Signed-off-by: Krzysztof Halasa Signed-off-by: David S. Miller --- drivers/net/phy/mdio_bus.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 536bda1f428..289fc267edf 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -105,8 +105,6 @@ int mdiobus_register(struct mii_bus *bus) return -EINVAL; } - bus->state = MDIOBUS_REGISTERED; - mutex_init(&bus->mdio_lock); if (bus->reset) @@ -123,6 +121,9 @@ int mdiobus_register(struct mii_bus *bus) } } + if (!err) + bus->state = MDIOBUS_REGISTERED; + pr_info("%s: probed\n", bus->name); return err; -- cgit v1.2.3 From 2fccd2814f8ebc8f1bd325dc46e11c333fc76ab3 Mon Sep 17 00:00:00 2001 From: cwm97m Date: Tue, 16 Dec 2008 20:28:44 +0000 Subject: jme: Fixed a typo Found a typo. Signed-off-by: Wei-Min Chen Signed-off-by: David S. Miller --- drivers/net/jme.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/jme.h b/drivers/net/jme.h index f863aee6648..3f5d9154324 100644 --- a/drivers/net/jme.h +++ b/drivers/net/jme.h @@ -22,7 +22,7 @@ */ #ifndef __JME_H_INCLUDED__ -#define __JME_H_INCLUDEE__ +#define __JME_H_INCLUDED__ #define DRV_NAME "jme" #define DRV_VERSION "1.0.3" -- cgit v1.2.3 From 5413aa467806578bf5f78a83893cb9426b815231 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 3 Dec 2008 16:33:09 -0800 Subject: USB: fix problem with usbtmc driver not loading properly The usbtmc driver forgot to export its device table to userspace. Without this, it is never loaded properly when such a device is seen by the system. Cc: Marcel Janssen Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 8e74657f106..43a863c5cc4 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -51,6 +51,7 @@ static struct usb_device_id usbtmc_devices[] = { { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), }, { 0, } /* terminating entry */ }; +MODULE_DEVICE_TABLE(usb, usbtmc_devices); /* * This structure is the capabilities for the device -- cgit v1.2.3 From 1393fce7189427bdb4d6115ca5566ca8d0fc86f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?CS=C3=89CSY=20L=C3=A1szl=C3=B3?= Date: Tue, 9 Dec 2008 23:39:14 +0100 Subject: USB: storage: unusual_devs.h: Nokia 3109c addition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2.6.26(.x, cannot remember) could handle the microSD card in my Nokia 3109c attached via USB as mass storage, 2.6.27(.x, up to and included 2.6.27.8) cannot. Please find the attached patch which fixes this regression, and a copy of /proc/bus/usb/devices with my phone plugged in running with this patch on Frugalware. T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=0421 ProdID=0063 Rev= 6.01 S: Manufacturer=Nokia S: Product=Nokia 3109c S: SerialNumber=359561013742570 C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=81(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms From: CSÉCSY László Cc: Phil Dibowitz Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index e61f2bfc64a..6573156f72a 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -167,6 +167,13 @@ UNUSUAL_DEV( 0x0421, 0x005d, 0x0001, 0x0600, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Reported by CSECSY Laszlo */ +UNUSUAL_DEV( 0x0421, 0x0063, 0x0001, 0x0601, + "Nokia", + "Nokia 3109c", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Patch for Nokia 5310 capacity */ UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0591, "Nokia", -- cgit v1.2.3 From 48e1a540e1e9ea62a2b3088a69ecf934f3172b14 Mon Sep 17 00:00:00 2001 From: Ozan Sener Date: Mon, 8 Dec 2008 19:15:45 +0200 Subject: USB: Unusual devs patch for Nokia 3500c T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 3 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=0421 ProdID=0060 Rev= 5.51 S: Manufacturer=Nokia S: Product=Nokia 3500c S: SerialNumber=357687010280751 C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=81(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms From: Ozan Sener Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 6573156f72a..06bf064c439 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -167,6 +167,13 @@ UNUSUAL_DEV( 0x0421, 0x005d, 0x0001, 0x0600, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Reported by Ozan Sener */ +UNUSUAL_DEV( 0x0421, 0x0060, 0x0551, 0x0551, + "Nokia", + "3500c", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Reported by CSECSY Laszlo */ UNUSUAL_DEV( 0x0421, 0x0063, 0x0001, 0x0601, "Nokia", -- cgit v1.2.3 From a4b188095912eee83d065f000dfe06f25919750b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 1 Dec 2008 10:23:43 -0500 Subject: usb-storage: update unusual_devs entry for Nokia 5310 This patch (as1179) updates the unusual_devs entry for Nokia's 5310 phone to include a more recent firmware revision. This fixes Bugzilla #12099. Signed-off-by: Alan Stern Tested-by: Robson Roberto Souza Peixoto Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 06bf064c439..bfcc1fe8251 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -182,7 +182,7 @@ UNUSUAL_DEV( 0x0421, 0x0063, 0x0001, 0x0601, US_FL_FIX_CAPACITY ), /* Patch for Nokia 5310 capacity */ -UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0591, +UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0701, "Nokia", "5310", US_SC_DEVICE, US_PR_DEVICE, NULL, -- cgit v1.2.3 From f2ee695554d9b4d163361a63f196ad7d8d0fe935 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 6 Dec 2008 23:46:04 -0800 Subject: USB: tty: SprogII DCC controller identifiers Someone on rmweb reminded me this had been overlooked from ages ago.. Add the identifiers for the Sprog II USB. This is a DCC control interface using the FTDI-SIO hardware: http://www.sprog-dcc.co.uk/. People have been using it with insmod options for ages, this just puts it into the driver data. Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio.h | 3 +++ 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index aad1359a3eb..abbc2d8350a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -166,6 +166,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) }, diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 07a3992abad..70703b706b0 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -75,6 +75,9 @@ /* OpenDCC (www.opendcc.de) product id */ #define FTDI_OPENDCC_PID 0xBFD8 +/* Sprog II (Andrew Crosland's SprogII DCC interface) */ +#define FTDI_SPROG_II 0xF0C8 + /* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */ /* they use the ftdi chipset for the USB interface and the vendor id is the same */ #define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */ -- cgit v1.2.3 From 01ba0856e9352e3c4e1c7d8c0a2a7defb456a5f9 Mon Sep 17 00:00:00 2001 From: Andrew Ewert Date: Thu, 4 Dec 2008 09:09:59 -0600 Subject: USB: ftdi_sio: Adding Ewert Energy System's CANdapter PID The following patch adds in the USB PID for Ewert Energy System's CANdapter device (CANBUS to USB-Serial which uses the FTDI 245R chipset) to the ftdi_sio device driver. The patch was tested successfully on Linux kernel 2.6.27 under Ubuntu. Relevant output from /proc/bus/usb/devices (With patch installed): T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 P: Vendor=0403 ProdID=9f80 Rev= 6.00 S: Manufacturer=Ewert Energy Systems S: Product=CANdapter S: SerialNumber=A6RGB3Z3 C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr= 90mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=ftdi_sio E: Ad=81(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms Signed-off-by: Andrew Ewert Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio.h | 3 +++ 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index abbc2d8350a..fb6f2933b01 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -143,6 +143,7 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) }, diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 70703b706b0..373ee09975b 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -40,6 +40,9 @@ /* AlphaMicro Components AMC-232USB01 device */ #define FTDI_AMC232_PID 0xFF00 /* Product Id */ +/* www.candapter.com Ewert Energy Systems CANdapter device */ +#define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */ + /* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */ /* the VID is the standard ftdi vid (FTDI_VID) */ #define FTDI_SCS_DEVICE_0_PID 0xD010 /* SCS PTC-IIusb */ -- cgit v1.2.3 From 7c12414955e9b44a3e33d54e578bf008caa4475d Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 24 Nov 2008 23:11:03 -0800 Subject: USB: gadget: fix rndis working at high speed Fix a bug specific to highspeed mode in the recently updated RNDIS support: it wasn't setting up the high speed notification endpoint, which prevented high speed RNDIS links from working. Signed-off-by: David Brownell Tested-by: Anand Gadiyar Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_rndis.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 428b5993575..3a8bb53fc47 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -651,6 +651,8 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) fs_in_desc.bEndpointAddress; hs_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress; + hs_notify_desc.bEndpointAddress = + fs_notify_desc.bEndpointAddress; /* copy descriptors, and track endpoint copies */ f->hs_descriptors = usb_copy_descriptors(eth_hs_function); @@ -662,6 +664,8 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) f->hs_descriptors, &hs_in_desc); rndis->hs.out = usb_find_endpoint(eth_hs_function, f->hs_descriptors, &hs_out_desc); + rndis->hs.notify = usb_find_endpoint(eth_hs_function, + f->hs_descriptors, &hs_notify_desc); } rndis->port.open = rndis_open; -- cgit v1.2.3 From 24c0996a6b73e2554104961afcc8659534503e0d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 1 Dec 2008 10:24:41 -0500 Subject: USB: skip Set-Interface(0) if already in altsetting 0 When a driver unbinds from an interface, usbcore always sends a Set-Interface request to reinstall altsetting 0. Unforunately, quite a few devices have buggy firmware that crashes when it receives this request. To avoid such problems, this patch (as1180) arranges to send the Set-Interface request only when the interface is not already in altsetting 0. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 3d7793d9303..8c081308b0e 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -279,7 +279,9 @@ static int usb_unbind_interface(struct device *dev) * altsetting means creating new endpoint device entries). * When either of these happens, defer the Set-Interface. */ - if (!error && intf->dev.power.status == DPM_ON) + if (intf->cur_altsetting->desc.bAlternateSetting == 0) + ; /* Already in altsetting 0 so skip Set-Interface */ + else if (!error && intf->dev.power.status == DPM_ON) usb_set_interface(udev, intf->altsetting[0]. desc.bInterfaceNumber, 0); else -- cgit v1.2.3 From 7c99200142c04d0f1ed3f048014591f841efdaed Mon Sep 17 00:00:00 2001 From: Matthew Arnold Date: Sat, 13 Dec 2008 22:42:53 +1100 Subject: USB: add 5372:2303 to pl2303 This patch adds the "Superial" USB-Serial converter to pl2303 so that it is detected, by the correct driver. Adds the relevant vendor:product (5372:2303) to the device tables in pl2303.c & pl2303.h. The patch has been tested against 2.6.24-22-generic. Signed-off-by: Matthew D Arnold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 1 + drivers/usb/serial/pl2303.h | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 491c8857b64..029b314a1fb 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -91,6 +91,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, + { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index a3bd039c78e..05c909aca8e 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -110,3 +110,7 @@ /* Y.C. Cable U.S.A., Inc - USB to RS-232 */ #define YCCABLE_VENDOR_ID 0x05ad #define YCCABLE_PRODUCT_ID 0x0fba + +/* "Superial" USB - Serial */ +#define SUPERIAL_VENDOR_ID 0x5372 +#define SUPERIAL_PRODUCT_ID 0x2303 -- cgit v1.2.3 From 413ba6fb51fa8dc77be09552e506d00f31234e0d Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 16 Dec 2008 12:25:55 +0100 Subject: USB: set correct configuration in probe of ti_usb_3410_5052 This driver transfers firmware. It may just as well set the correct configuration. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 55 ++--------------------------------- 1 file changed, 3 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 31c42d1cae1..01d0c70d60e 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -16,56 +16,6 @@ * For questions or problems with this driver, contact Texas Instruments * technical support, or Al Borchers , or * Peter Berger . - * - * This driver needs this hotplug script in /etc/hotplug/usb/ti_usb_3410_5052 - * or in /etc/hotplug.d/usb/ti_usb_3410_5052.hotplug to set the device - * configuration. - * - * #!/bin/bash - * - * BOOT_CONFIG=1 - * ACTIVE_CONFIG=2 - * - * if [[ "$ACTION" != "add" ]] - * then - * exit - * fi - * - * CONFIG_PATH=/sys${DEVPATH%/?*}/bConfigurationValue - * - * if [[ 0`cat $CONFIG_PATH` -ne $BOOT_CONFIG ]] - * then - * exit - * fi - * - * PRODUCT=${PRODUCT%/?*} # delete version - * VENDOR_ID=`printf "%d" 0x${PRODUCT%/?*}` - * PRODUCT_ID=`printf "%d" 0x${PRODUCT#*?/}` - * - * PARAM_PATH=/sys/module/ti_usb_3410_5052/parameters - * - * function scan() { - * s=$1 - * shift - * for i - * do - * if [[ $s -eq $i ]] - * then - * return 0 - * fi - * done - * return 1 - * } - * - * IFS=$IFS, - * - * if (scan $VENDOR_ID 1105 `cat $PARAM_PATH/vendor_3410` && - * scan $PRODUCT_ID 13328 `cat $PARAM_PATH/product_3410`) || - * (scan $VENDOR_ID 1105 `cat $PARAM_PATH/vendor_5052` && - * scan $PRODUCT_ID 20562 20818 20570 20575 `cat $PARAM_PATH/product_5052`) - * then - * echo $ACTIVE_CONFIG > $CONFIG_PATH - * fi */ #include @@ -457,9 +407,10 @@ static int ti_startup(struct usb_serial *serial) goto free_tdev; } - /* the second configuration must be set (in sysfs by hotplug script) */ + /* the second configuration must be set */ if (dev->actconfig->desc.bConfigurationValue == TI_BOOT_CONFIG) { - status = -ENODEV; + status = usb_driver_set_configuration(dev, TI_ACTIVE_CONFIG); + status = status ? status : -ENODEV; goto free_tdev; } -- cgit v1.2.3 From af4b8514aafd53d97b05a0a30b7d4cfd2cbb7b81 Mon Sep 17 00:00:00 2001 From: Mike Provencher Date: Tue, 16 Dec 2008 14:30:14 -0600 Subject: USB: pl2303: add id for Hewlett-Packard LD220-HP POS pole display Add id for the Hewlett-Packard LD220-HP POS pole display. Bus 002 Device 002: ID 03f0:3524 Hewlett-Packard Signed-off-by: Mike Provencher Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 1 + drivers/usb/serial/pl2303.h | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 029b314a1fb..1aed584be5e 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -92,6 +92,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 05c909aca8e..54974f446a8 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -114,3 +114,7 @@ /* "Superial" USB - Serial */ #define SUPERIAL_VENDOR_ID 0x5372 #define SUPERIAL_PRODUCT_ID 0x2303 + +/* Hewlett-Packard LD220-HP POS Pole Display */ +#define HP_VENDOR_ID 0x03f0 +#define HP_LD220_PRODUCT_ID 0x3524 -- cgit v1.2.3 From 09a35ce00fa6bbb8bd130a828807e237488aa7ea Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 6 Dec 2008 21:10:51 -0800 Subject: xilinx_hwicap: remove improper wording in license statement GPLv2 doesn't allow additional restrictions to be imposed on any code, so this wording needs to be removed from these files. Signed-off-by: Stephen Neuendorffer Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/char/xilinx_hwicap/buffer_icap.c | 3 --- drivers/char/xilinx_hwicap/buffer_icap.h | 3 --- drivers/char/xilinx_hwicap/fifo_icap.c | 3 --- drivers/char/xilinx_hwicap/fifo_icap.h | 3 --- drivers/char/xilinx_hwicap/xilinx_hwicap.c | 3 --- drivers/char/xilinx_hwicap/xilinx_hwicap.h | 3 --- 6 files changed, 18 deletions(-) (limited to 'drivers') diff --git a/drivers/char/xilinx_hwicap/buffer_icap.c b/drivers/char/xilinx_hwicap/buffer_icap.c index aa7f7962a9a..05d897764f0 100644 --- a/drivers/char/xilinx_hwicap/buffer_icap.c +++ b/drivers/char/xilinx_hwicap/buffer_icap.c @@ -21,9 +21,6 @@ * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Xilinx products are not intended for use in life support appliances, - * devices, or systems. Use in such applications is expressly prohibited. - * * (c) Copyright 2003-2008 Xilinx Inc. * All rights reserved. * diff --git a/drivers/char/xilinx_hwicap/buffer_icap.h b/drivers/char/xilinx_hwicap/buffer_icap.h index 8b0252bf06e..d4f419ee87a 100644 --- a/drivers/char/xilinx_hwicap/buffer_icap.h +++ b/drivers/char/xilinx_hwicap/buffer_icap.h @@ -21,9 +21,6 @@ * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Xilinx products are not intended for use in life support appliances, - * devices, or systems. Use in such applications is expressly prohibited. - * * (c) Copyright 2003-2008 Xilinx Inc. * All rights reserved. * diff --git a/drivers/char/xilinx_hwicap/fifo_icap.c b/drivers/char/xilinx_hwicap/fifo_icap.c index 776b5052847..02225eb19cf 100644 --- a/drivers/char/xilinx_hwicap/fifo_icap.c +++ b/drivers/char/xilinx_hwicap/fifo_icap.c @@ -21,9 +21,6 @@ * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Xilinx products are not intended for use in life support appliances, - * devices, or systems. Use in such applications is expressly prohibited. - * * (c) Copyright 2007-2008 Xilinx Inc. * All rights reserved. * diff --git a/drivers/char/xilinx_hwicap/fifo_icap.h b/drivers/char/xilinx_hwicap/fifo_icap.h index 62bda453c90..4c9dd9a3b62 100644 --- a/drivers/char/xilinx_hwicap/fifo_icap.h +++ b/drivers/char/xilinx_hwicap/fifo_icap.h @@ -21,9 +21,6 @@ * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Xilinx products are not intended for use in life support appliances, - * devices, or systems. Use in such applications is expressly prohibited. - * * (c) Copyright 2007-2008 Xilinx Inc. * All rights reserved. * diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index d1613194909..f40ab699860 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -21,9 +21,6 @@ * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Xilinx products are not intended for use in life support appliances, - * devices, or systems. Use in such applications is expressly prohibited. - * * (c) Copyright 2002 Xilinx Inc., Systems Engineering Group * (c) Copyright 2004 Xilinx Inc., Systems Engineering Group * (c) Copyright 2007-2008 Xilinx Inc. diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h index 24d0d9b938f..8cca11981c5 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.h +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h @@ -21,9 +21,6 @@ * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * - * Xilinx products are not intended for use in life support appliances, - * devices, or systems. Use in such applications is expressly prohibited. - * * (c) Copyright 2003-2007 Xilinx Inc. * All rights reserved. * -- cgit v1.2.3 From 4b4cdf3979c32fa3d042d150f49449c74d048553 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 28 Nov 2008 00:01:28 +0300 Subject: STAGING: Move staging drivers back to staging-specific menu Signed-off-by: Dmitry Baryshkov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index c95b286a123..5d457c96bd7 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -22,6 +22,8 @@ menuconfig STAGING If in doubt, say N here. +if STAGING + config STAGING_EXCLUDE_BUILD bool "Exclude Staging drivers from being built" if STAGING default y @@ -62,3 +64,4 @@ source "drivers/staging/at76_usb/Kconfig" source "drivers/staging/poch/Kconfig" endif # !STAGING_EXCLUDE_BUILD +endif # STAGING -- cgit v1.2.3 From 3298a7388c00227e736d1037328788073c80c7b4 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 17 Dec 2008 19:06:08 -0800 Subject: bnx2: Fix bug in bnx2_free_rx_mem(). DMA memory for the jumbo rx page rings was freed incorrectly using the wrong local variable as the array index. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index a1a3d0e5d2b..9e8222f9e90 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -543,9 +543,9 @@ bnx2_free_rx_mem(struct bnx2 *bp) for (j = 0; j < bp->rx_max_pg_ring; j++) { if (rxr->rx_pg_desc_ring[j]) pci_free_consistent(bp->pdev, RXBD_RING_SIZE, - rxr->rx_pg_desc_ring[i], - rxr->rx_pg_desc_mapping[i]); - rxr->rx_pg_desc_ring[i] = NULL; + rxr->rx_pg_desc_ring[j], + rxr->rx_pg_desc_mapping[j]); + rxr->rx_pg_desc_ring[j] = NULL; } if (rxr->rx_pg_ring) vfree(rxr->rx_pg_ring); -- cgit v1.2.3