Commit 043b4d40 authored by James Morris's avatar James Morris

Merge branch 'master' into next

Conflicts:
	security/keys/keyring.c

Resolved conflict with whitespace fix in find_keyring_by_name()
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parents 29282381 722154e4
...@@ -107,10 +107,6 @@ void (*dev_config) (struct ata_port *, struct ata_device *); ...@@ -107,10 +107,6 @@ void (*dev_config) (struct ata_port *, struct ata_device *);
issue of SET FEATURES - XFER MODE, and prior to operation. issue of SET FEATURES - XFER MODE, and prior to operation.
</para> </para>
<para> <para>
Called by ata_device_add() after ata_dev_identify() determines
a device is present.
</para>
<para>
This entry may be specified as NULL in ata_port_operations. This entry may be specified as NULL in ata_port_operations.
</para> </para>
...@@ -154,8 +150,8 @@ unsigned int (*mode_filter) (struct ata_port *, struct ata_device *, unsigned in ...@@ -154,8 +150,8 @@ unsigned int (*mode_filter) (struct ata_port *, struct ata_device *, unsigned in
<sect2><title>Taskfile read/write</title> <sect2><title>Taskfile read/write</title>
<programlisting> <programlisting>
void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf); void (*sff_tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf); void (*sff_tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
</programlisting> </programlisting>
<para> <para>
...@@ -164,36 +160,35 @@ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf); ...@@ -164,36 +160,35 @@ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
hardware registers / DMA buffers, to obtain the current set of hardware registers / DMA buffers, to obtain the current set of
taskfile register values. taskfile register values.
Most drivers for taskfile-based hardware (PIO or MMIO) use Most drivers for taskfile-based hardware (PIO or MMIO) use
ata_tf_load() and ata_tf_read() for these hooks. ata_sff_tf_load() and ata_sff_tf_read() for these hooks.
</para> </para>
</sect2> </sect2>
<sect2><title>PIO data read/write</title> <sect2><title>PIO data read/write</title>
<programlisting> <programlisting>
void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int); void (*sff_data_xfer) (struct ata_device *, unsigned char *, unsigned int, int);
</programlisting> </programlisting>
<para> <para>
All bmdma-style drivers must implement this hook. This is the low-level All bmdma-style drivers must implement this hook. This is the low-level
operation that actually copies the data bytes during a PIO data operation that actually copies the data bytes during a PIO data
transfer. transfer.
Typically the driver Typically the driver will choose one of ata_sff_data_xfer_noirq(),
will choose one of ata_pio_data_xfer_noirq(), ata_pio_data_xfer(), or ata_sff_data_xfer(), or ata_sff_data_xfer32().
ata_mmio_data_xfer().
</para> </para>
</sect2> </sect2>
<sect2><title>ATA command execute</title> <sect2><title>ATA command execute</title>
<programlisting> <programlisting>
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf); void (*sff_exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
</programlisting> </programlisting>
<para> <para>
causes an ATA command, previously loaded with causes an ATA command, previously loaded with
->tf_load(), to be initiated in hardware. ->tf_load(), to be initiated in hardware.
Most drivers for taskfile-based hardware use ata_exec_command() Most drivers for taskfile-based hardware use ata_sff_exec_command()
for this hook. for this hook.
</para> </para>
...@@ -218,8 +213,8 @@ command. ...@@ -218,8 +213,8 @@ command.
<sect2><title>Read specific ATA shadow registers</title> <sect2><title>Read specific ATA shadow registers</title>
<programlisting> <programlisting>
u8 (*check_status)(struct ata_port *ap); u8 (*sff_check_status)(struct ata_port *ap);
u8 (*check_altstatus)(struct ata_port *ap); u8 (*sff_check_altstatus)(struct ata_port *ap);
</programlisting> </programlisting>
<para> <para>
...@@ -227,20 +222,14 @@ u8 (*check_altstatus)(struct ata_port *ap); ...@@ -227,20 +222,14 @@ u8 (*check_altstatus)(struct ata_port *ap);
hardware. On some hardware, reading the Status register has hardware. On some hardware, reading the Status register has
the side effect of clearing the interrupt condition. the side effect of clearing the interrupt condition.
Most drivers for taskfile-based hardware use Most drivers for taskfile-based hardware use
ata_check_status() for this hook. ata_sff_check_status() for this hook.
</para>
<para>
Note that because this is called from ata_device_add(), at
least a dummy function that clears device interrupts must be
provided for all drivers, even if the controller doesn't
actually have a taskfile status register.
</para> </para>
</sect2> </sect2>
<sect2><title>Select ATA device on bus</title> <sect2><title>Select ATA device on bus</title>
<programlisting> <programlisting>
void (*dev_select)(struct ata_port *ap, unsigned int device); void (*sff_dev_select)(struct ata_port *ap, unsigned int device);
</programlisting> </programlisting>
<para> <para>
...@@ -251,9 +240,7 @@ void (*dev_select)(struct ata_port *ap, unsigned int device); ...@@ -251,9 +240,7 @@ void (*dev_select)(struct ata_port *ap, unsigned int device);
</para> </para>
<para> <para>
Most drivers for taskfile-based hardware use Most drivers for taskfile-based hardware use
ata_std_dev_select() for this hook. Controllers which do not ata_sff_dev_select() for this hook.
support second drives on a port (such as SATA contollers) will
use ata_noop_dev_select().
</para> </para>
</sect2> </sect2>
...@@ -441,13 +428,13 @@ void (*irq_clear) (struct ata_port *); ...@@ -441,13 +428,13 @@ void (*irq_clear) (struct ata_port *);
to struct ata_host_set. to struct ata_host_set.
</para> </para>
<para> <para>
Most legacy IDE drivers use ata_interrupt() for the Most legacy IDE drivers use ata_sff_interrupt() for the
irq_handler hook, which scans all ports in the host_set, irq_handler hook, which scans all ports in the host_set,
determines which queued command was active (if any), and calls determines which queued command was active (if any), and calls
ata_host_intr(ap,qc). ata_sff_host_intr(ap,qc).
</para> </para>
<para> <para>
Most legacy IDE drivers use ata_bmdma_irq_clear() for the Most legacy IDE drivers use ata_sff_irq_clear() for the
irq_clear() hook, which simply clears the interrupt and error irq_clear() hook, which simply clears the interrupt and error
flags in the DMA status register. flags in the DMA status register.
</para> </para>
...@@ -496,10 +483,6 @@ void (*host_stop) (struct ata_host_set *host_set); ...@@ -496,10 +483,6 @@ void (*host_stop) (struct ata_host_set *host_set);
data from port at this time. data from port at this time.
</para> </para>
<para> <para>
Many drivers use ata_port_stop() as this hook, which frees the
PRD table.
</para>
<para>
->host_stop() is called after all ->port_stop() calls ->host_stop() is called after all ->port_stop() calls
have completed. The hook must finalize hardware shutdown, release DMA have completed. The hook must finalize hardware shutdown, release DMA
and other resources, etc. and other resources, etc.
......
...@@ -333,14 +333,14 @@ byte 0: ...@@ -333,14 +333,14 @@ byte 0:
byte 1: byte 1:
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
x15 x14 x13 x12 x11 x10 x9 x8 . . . . . x10 x9 x8
byte 2: byte 2:
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
x7 x6 x5 x4 x4 x2 x1 x0 x7 x6 x5 x4 x4 x2 x1 x0
x15..x0 = absolute x value (horizontal) x10..x0 = absolute x value (horizontal)
byte 3: byte 3:
...@@ -350,14 +350,14 @@ byte 3: ...@@ -350,14 +350,14 @@ byte 3:
byte 4: byte 4:
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
y15 y14 y13 y12 y11 y10 y8 y8 . . . . . . y9 y8
byte 5: byte 5:
bit 7 6 5 4 3 2 1 0 bit 7 6 5 4 3 2 1 0
y7 y6 y5 y4 y3 y2 y1 y0 y7 y6 y5 y4 y3 y2 y1 y0
y15..y0 = absolute y value (vertical) y9..y0 = absolute y value (vertical)
4.2.2 Two finger touch 4.2.2 Two finger touch
......
...@@ -324,6 +324,7 @@ struct dma_async_tx_descriptor * ...@@ -324,6 +324,7 @@ struct dma_async_tx_descriptor *
async_raid6_2data_recov(int disks, size_t bytes, int faila, int failb, async_raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
struct page **blocks, struct async_submit_ctl *submit) struct page **blocks, struct async_submit_ctl *submit)
{ {
void *scribble = submit->scribble;
int non_zero_srcs, i; int non_zero_srcs, i;
BUG_ON(faila == failb); BUG_ON(faila == failb);
...@@ -332,11 +333,13 @@ async_raid6_2data_recov(int disks, size_t bytes, int faila, int failb, ...@@ -332,11 +333,13 @@ async_raid6_2data_recov(int disks, size_t bytes, int faila, int failb,
pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes); pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes);
/* we need to preserve the contents of 'blocks' for the async /* if a dma resource is not available or a scribble buffer is not
* case, so punt to synchronous if a scribble buffer is not available * available punt to the synchronous path. In the 'dma not
* available' case be sure to use the scribble buffer to
* preserve the content of 'blocks' as the caller intended.
*/ */
if (!submit->scribble) { if (!async_dma_find_channel(DMA_PQ) || !scribble) {
void **ptrs = (void **) blocks; void **ptrs = scribble ? scribble : (void **) blocks;
async_tx_quiesce(&submit->depend_tx); async_tx_quiesce(&submit->depend_tx);
for (i = 0; i < disks; i++) for (i = 0; i < disks; i++)
...@@ -406,11 +409,13 @@ async_raid6_datap_recov(int disks, size_t bytes, int faila, ...@@ -406,11 +409,13 @@ async_raid6_datap_recov(int disks, size_t bytes, int faila,
pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes); pr_debug("%s: disks: %d len: %zu\n", __func__, disks, bytes);
/* we need to preserve the contents of 'blocks' for the async /* if a dma resource is not available or a scribble buffer is not
* case, so punt to synchronous if a scribble buffer is not available * available punt to the synchronous path. In the 'dma not
* available' case be sure to use the scribble buffer to
* preserve the content of 'blocks' as the caller intended.
*/ */
if (!scribble) { if (!async_dma_find_channel(DMA_PQ) || !scribble) {
void **ptrs = (void **) blocks; void **ptrs = scribble ? scribble : (void **) blocks;
async_tx_quiesce(&submit->depend_tx); async_tx_quiesce(&submit->depend_tx);
for (i = 0; i < disks; i++) for (i = 0; i < disks; i++)
......
...@@ -424,7 +424,7 @@ static struct pcmcia_device_id pcmcia_devices[] = { ...@@ -424,7 +424,7 @@ static struct pcmcia_device_id pcmcia_devices[] = {
PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420), PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x3e520e17), PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x55d5bffb),
PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 4GB", 0x2e6d1829, 0x531e7d10), PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 4GB", 0x2e6d1829, 0x531e7d10),
PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e), PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b), PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b),
...@@ -446,7 +446,7 @@ static struct pcmcia_device_id pcmcia_devices[] = { ...@@ -446,7 +446,7 @@ static struct pcmcia_device_id pcmcia_devices[] = {
PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1), PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2), PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x9351e59d), PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x7558f133),
PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS8GCF133", 0x709b1bf1, 0xb2f89b47), PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS8GCF133", 0x709b1bf1, 0xb2f89b47),
PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918), PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
......
...@@ -409,7 +409,7 @@ static struct pcmcia_device_id ide_ids[] = { ...@@ -409,7 +409,7 @@ static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420), PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420),
PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178),
PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x3e520e17), PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x55d5bffb),
PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 4GB", 0x2e6d1829, 0x531e7d10), PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 4GB", 0x2e6d1829, 0x531e7d10),
PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e), PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e),
PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b), PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b),
...@@ -431,7 +431,7 @@ static struct pcmcia_device_id ide_ids[] = { ...@@ -431,7 +431,7 @@ static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1), PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2), PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2),
PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x9351e59d), PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x7558f133),
PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS8GCF133", 0x709b1bf1, 0xb2f89b47), PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS8GCF133", 0x709b1bf1, 0xb2f89b47),
PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918), PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
......
...@@ -929,6 +929,24 @@ static const struct input_device_id joydev_ids[] = { ...@@ -929,6 +929,24 @@ static const struct input_device_id joydev_ids[] = {
.evbit = { BIT_MASK(EV_ABS) }, .evbit = { BIT_MASK(EV_ABS) },
.absbit = { BIT_MASK(ABS_THROTTLE) }, .absbit = { BIT_MASK(ABS_THROTTLE) },
}, },
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
INPUT_DEVICE_ID_MATCH_KEYBIT,
.evbit = { BIT_MASK(EV_KEY) },
.keybit = {[BIT_WORD(BTN_JOYSTICK)] = BIT_MASK(BTN_JOYSTICK) },
},
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
INPUT_DEVICE_ID_MATCH_KEYBIT,
.evbit = { BIT_MASK(EV_KEY) },
.keybit = { [BIT_WORD(BTN_GAMEPAD)] = BIT_MASK(BTN_GAMEPAD) },
},
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
INPUT_DEVICE_ID_MATCH_KEYBIT,
.evbit = { BIT_MASK(EV_KEY) },
.keybit = { [BIT_WORD(BTN_TRIGGER_HAPPY)] = BIT_MASK(BTN_TRIGGER_HAPPY) },
},
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
...@@ -98,10 +98,12 @@ ...@@ -98,10 +98,12 @@
* Module and Version Information, Module Parameters * Module and Version Information, Module Parameters
*/ */
#define ATI_REMOTE_VENDOR_ID 0x0bc7 #define ATI_REMOTE_VENDOR_ID 0x0bc7
#define ATI_REMOTE_PRODUCT_ID 0x004 #define LOLA_REMOTE_PRODUCT_ID 0x0002
#define LOLA_REMOTE_PRODUCT_ID 0x002 #define LOLA2_REMOTE_PRODUCT_ID 0x0003
#define MEDION_REMOTE_PRODUCT_ID 0x006 #define ATI_REMOTE_PRODUCT_ID 0x0004
#define NVIDIA_REMOTE_PRODUCT_ID 0x0005
#define MEDION_REMOTE_PRODUCT_ID 0x0006
#define DRIVER_VERSION "2.2.1" #define DRIVER_VERSION "2.2.1"
#define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>" #define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>"
...@@ -142,8 +144,10 @@ MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec ...@@ -142,8 +144,10 @@ MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec
#define err(format, arg...) printk(KERN_ERR format , ## arg) #define err(format, arg...) printk(KERN_ERR format , ## arg)
static struct usb_device_id ati_remote_table[] = { static struct usb_device_id ati_remote_table[] = {
{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) },
{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) },
{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID) },
{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) },
{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID) },
{ USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) }, { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) },
{} /* Terminating entry */ {} /* Terminating entry */
}; };
......
...@@ -64,7 +64,6 @@ static const struct alps_model_info alps_model_data[] = { ...@@ -64,7 +64,6 @@ static const struct alps_model_info alps_model_data[] = {
{ { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf,
ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED },
{ { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */
{ { 0x73, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, /* HP Pavilion dm3 */
{ { 0x52, 0x01, 0x14 }, 0xff, 0xff, { { 0x52, 0x01, 0x14 }, 0xff, 0xff,
ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */
}; };
......
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
printk(KERN_DEBUG format, ##arg); \ printk(KERN_DEBUG format, ##arg); \
} while (0) } while (0)
static bool force_elantech;
module_param_named(force_elantech, force_elantech, bool, 0644);
MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default).");
/* /*
* Send a Synaptics style sliced query command * Send a Synaptics style sliced query command
*/ */
...@@ -182,13 +186,17 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) ...@@ -182,13 +186,17 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
static int old_fingers; static int old_fingers;
if (etd->fw_version_maj == 0x01) { if (etd->fw_version_maj == 0x01) {
/* byte 0: D U p1 p2 1 p3 R L /*
byte 1: f 0 th tw x9 x8 y9 y8 */ * byte 0: D U p1 p2 1 p3 R L
* byte 1: f 0 th tw x9 x8 y9 y8
*/
fingers = ((packet[1] & 0x80) >> 7) + fingers = ((packet[1] & 0x80) >> 7) +
((packet[1] & 0x30) >> 4); ((packet[1] & 0x30) >> 4);
} else { } else {
/* byte 0: n1 n0 p2 p1 1 p3 R L /*
byte 1: 0 0 0 0 x9 x8 y9 y8 */ * byte 0: n1 n0 p2 p1 1 p3 R L
* byte 1: 0 0 0 0 x9 x8 y9 y8
*/
fingers = (packet[0] & 0xc0) >> 6; fingers = (packet[0] & 0xc0) >> 6;
} }
...@@ -202,13 +210,15 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) ...@@ -202,13 +210,15 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
input_report_key(dev, BTN_TOUCH, fingers != 0); input_report_key(dev, BTN_TOUCH, fingers != 0);
/* byte 2: x7 x6 x5 x4 x3 x2 x1 x0 /*
byte 3: y7 y6 y5 y4 y3 y2 y1 y0 */ * byte 2: x7 x6 x5 x4 x3 x2 x1 x0
* byte 3: y7 y6 y5 y4 y3 y2 y1 y0
*/
if (fingers) { if (fingers) {
input_report_abs(dev, ABS_X, input_report_abs(dev, ABS_X,
((packet[1] & 0x0c) << 6) | packet[2]); ((packet[1] & 0x0c) << 6) | packet[2]);
input_report_abs(dev, ABS_Y, ETP_YMAX_V1 - input_report_abs(dev, ABS_Y,
(((packet[1] & 0x03) << 8) | packet[3])); ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3]));
} }
input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); input_report_key(dev, BTN_TOOL_FINGER, fingers == 1);
...@@ -247,34 +257,47 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) ...@@ -247,34 +257,47 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
switch (fingers) { switch (fingers) {
case 1: case 1:
/* byte 1: x15 x14 x13 x12 x11 x10 x9 x8 /*
byte 2: x7 x6 x5 x4 x4 x2 x1 x0 */ * byte 1: . . . . . x10 x9 x8
input_report_abs(dev, ABS_X, (packet[1] << 8) | packet[2]); * byte 2: x7 x6 x5 x4 x4 x2 x1 x0
/* byte 4: y15 y14 y13 y12 y11 y10 y8 y8 */
byte 5: y7 y6 y5 y4 y3 y2 y1 y0 */ input_report_abs(dev, ABS_X,
input_report_abs(dev, ABS_Y, ETP_YMAX_V2 - ((packet[1] & 0x07) << 8) | packet[2]);
((packet[4] << 8) | packet[5])); /*
* byte 4: . . . . . . y9 y8
* byte 5: y7 y6 y5 y4 y3 y2 y1 y0
*/
input_report_abs(dev, ABS_Y,
ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5]));
break; break;
case 2: case 2:
/* The coordinate of each finger is reported separately with /*
a lower resolution for two finger touches */ * The coordinate of each finger is reported separately
/* byte 0: . . ay8 ax8 . . . . * with a lower resolution for two finger touches:
byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 */ * byte 0: . . ay8 ax8 . . . .
* byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0
*/
x1 = ((packet[0] & 0x10) << 4) | packet[1]; x1 = ((packet[0] & 0x10) << 4) | packet[1];
/* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */
y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]);
/* byte 3: . . by8 bx8 . . . . /*
byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 */ * byte 3: . . by8 bx8 . . . .
* byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0
*/
x2 = ((packet[3] & 0x10) << 4) | packet[4]; x2 = ((packet[3] & 0x10) << 4) | packet[4];
/* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */
y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]);
/* For compatibility with the X Synaptics driver scale up one /*
coordinate and report as ordinary mouse movent */ * For compatibility with the X Synaptics driver scale up
* one coordinate and report as ordinary mouse movent
*/
input_report_abs(dev, ABS_X, x1 << 2); input_report_abs(dev, ABS_X, x1 << 2);
input_report_abs(dev, ABS_Y, y1 << 2); input_report_abs(dev, ABS_Y, y1 << 2);
/* For compatibility with the proprietary X Elantech driver /*
report both coordinates as hat coordinates */ * For compatibility with the proprietary X Elantech driver
* report both coordinates as hat coordinates
*/
input_report_abs(dev, ABS_HAT0X, x1); input_report_abs(dev, ABS_HAT0X, x1);
input_report_abs(dev, ABS_HAT0Y, y1); input_report_abs(dev, ABS_HAT0Y, y1);
input_report_abs(dev, ABS_HAT1X, x2); input_report_abs(dev, ABS_HAT1X, x2);
...@@ -596,8 +619,12 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) ...@@ -596,8 +619,12 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
param[0], param[1], param[2]); param[0], param[1], param[2]);
if (param[0] == 0 || param[1] != 0) { if (param[0] == 0 || param[1] != 0) {
pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); if (!force_elantech) {
return -1; pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n");
return -1;
}
pr_debug("elantech.c: Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n");
} }
if (set_properties) { if (set_properties) {
...@@ -666,7 +693,8 @@ int elantech_init(struct psmouse *psmouse) ...@@ -666,7 +693,8 @@ int elantech_init(struct psmouse *psmouse)
* Assume every version greater than this is new EeePC style * Assume every version greater than this is new EeePC style
* hardware with 6 byte packets * hardware with 6 byte packets
*/ */
if (etd->fw_version_maj >= 0x02 && etd->fw_version_min >= 0x30) { if ((etd->fw_version_maj == 0x02 && etd->fw_version_min >= 0x30) ||
etd->fw_version_maj > 0x02) {
etd->hw_version = 2; etd->hw_version = 2;
/* For now show extra debug information */ /* For now show extra debug information */
etd->debug = 1; etd->debug = 1;
......
...@@ -110,6 +110,7 @@ static struct workqueue_struct *kpsmoused_wq; ...@@ -110,6 +110,7 @@ static struct workqueue_struct *kpsmoused_wq;
struct psmouse_protocol { struct psmouse_protocol {
enum psmouse_type type; enum psmouse_type type;
bool maxproto; bool maxproto;
bool ignore_parity; /* Protocol should ignore parity errors from KBC */
const char *name; const char *name;
const char *alias; const char *alias;
int (*detect)(struct psmouse *, bool); int (*detect)(struct psmouse *, bool);
...@@ -288,7 +289,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, ...@@ -288,7 +289,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
if (psmouse->state == PSMOUSE_IGNORE) if (psmouse->state == PSMOUSE_IGNORE)
goto out; goto out;
if (flags & (SERIO_PARITY|SERIO_TIMEOUT)) { if (unlikely((flags & SERIO_TIMEOUT) ||
((flags & SERIO_PARITY) && !psmouse->ignore_parity))) {
if (psmouse->state == PSMOUSE_ACTIVATED) if (psmouse->state == PSMOUSE_ACTIVATED)
printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n", printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n",
flags & SERIO_TIMEOUT ? " timeout" : "", flags & SERIO_TIMEOUT ? " timeout" : "",
...@@ -759,6 +762,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { ...@@ -759,6 +762,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.name = "PS/2", .name = "PS/2",
.alias = "bare", .alias = "bare",
.maxproto = true, .maxproto = true,
.ignore_parity = true,
.detect = ps2bare_detect, .detect = ps2bare_detect,
}, },
#ifdef CONFIG_MOUSE_PS2_LOGIPS2PP #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP
...@@ -786,6 +790,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { ...@@ -786,6 +790,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.name = "ImPS/2", .name = "ImPS/2",
.alias = "imps", .alias = "imps",
.maxproto = true, .maxproto = true,
.ignore_parity = true,
.detect = intellimouse_detect, .detect = intellimouse_detect,
}, },
{ {
...@@ -793,6 +798,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { ...@@ -793,6 +798,7 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.name = "ImExPS/2", .name = "ImExPS/2",
.alias = "exps", .alias = "exps",
.maxproto = true, .maxproto = true,
.ignore_parity = true,
.detect = im_explorer_detect, .detect = im_explorer_detect,
}, },
#ifdef CONFIG_MOUSE_PS2_SYNAPTICS #ifdef CONFIG_MOUSE_PS2_SYNAPTICS
...@@ -1222,6 +1228,7 @@ static void psmouse_disconnect(struct serio *serio) ...@@ -1222,6 +1228,7 @@ static void psmouse_disconnect(struct serio *serio)
static int psmouse_switch_protocol(struct psmouse *psmouse, static int psmouse_switch_protocol(struct psmouse *psmouse,
const struct psmouse_protocol *proto) const struct psmouse_protocol *proto)
{ {
const struct psmouse_protocol *selected_proto;
struct input_dev *input_dev = psmouse->dev; struct input_dev *input_dev = psmouse->dev;
input_dev->dev.parent = &psmouse->ps2dev.serio->dev; input_dev->dev.parent = &psmouse->ps2dev.serio->dev;
...@@ -1245,9 +1252,14 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, ...@@ -1245,9 +1252,14 @@ static int psmouse_switch_protocol(struct psmouse *psmouse,
return -1; return -1;
psmouse->type = proto->type; psmouse->type = proto->type;
} else selected_proto = proto;
} else {
psmouse->type = psmouse_extensions(psmouse, psmouse->type = psmouse_extensions(psmouse,
psmouse_max_proto, true); psmouse_max_proto, true);
selected_proto = psmouse_protocol_by_type(psmouse->type);
}
psmouse->ignore_parity = selected_proto->ignore_parity;
/* /*
* If mouse's packet size is 3 there is no point in polling the * If mouse's packet size is 3 there is no point in polling the
...@@ -1267,7 +1279,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, ...@@ -1267,7 +1279,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse,
psmouse->resync_time = 0; psmouse->resync_time = 0;
snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s", snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s",
psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); selected_proto->name, psmouse->vendor, psmouse->name);
input_dev->name = psmouse->devname; input_dev->name = psmouse->devname;
input_dev->phys = psmouse->phys; input_dev->phys = psmouse->phys;
......
...@@ -47,6 +47,7 @@ struct psmouse { ...@@ -47,6 +47,7 @@ struct psmouse {
unsigned char pktcnt; unsigned char pktcnt;
unsigned char pktsize; unsigned char pktsize;
unsigned char type; unsigned char type;
bool ignore_parity;
bool acks_disable_command; bool acks_disable_command;
unsigned int model; unsigned int model;
unsigned long last; unsigned long last;
......
...@@ -137,7 +137,8 @@ static int synaptics_capability(struct psmouse *psmouse) ...@@ -137,7 +137,8 @@ static int synaptics_capability(struct psmouse *psmouse)
if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap)) if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap))
return -1; return -1;
priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2]; priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2];
priv->ext_cap = 0; priv->ext_cap = priv->ext_cap_0c = 0;
if (!SYN_CAP_VALID(priv->capabilities)) if (!SYN_CAP_VALID(priv->capabilities))
return -1; return -1;
...@@ -150,7 +151,7 @@ static int synaptics_capability(struct psmouse *psmouse) ...@@ -150,7 +151,7 @@ static int synaptics_capability(struct psmouse *psmouse)
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) { if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) {
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) { if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) {
printk(KERN_ERR "Synaptics claims to have extended capabilities," printk(KERN_ERR "Synaptics claims to have extended capabilities,"
" but I'm not able to read them."); " but I'm not able to read them.\n");
} else { } else {
priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2]; priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2];
...@@ -162,6 +163,16 @@ static int synaptics_capability(struct psmouse *psmouse) ...@@ -162,6 +163,16 @@ static int synaptics_capability(struct psmouse *psmouse)
priv->ext_cap &= 0xff0fff; priv->ext_cap &= 0xff0fff;
} }
} }
if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) {
if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) {
printk(KERN_ERR "Synaptics claims to have extended capability 0x0c,"
" but I'm not able to read it.\n");
} else {
priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2];
}
}
return 0; return 0;
} }
...@@ -348,7 +359,15 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data ...@@ -348,7 +359,15 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data
hw->left = (buf[0] & 0x01) ? 1 : 0; hw->left = (buf[0] & 0x01) ? 1 : 0;
hw->right = (buf[0] & 0x02) ? 1 : 0; hw->right = (buf[0] & 0x02) ? 1 : 0;
if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
/*
* Clickpad's button is transmitted as middle button,
* however, since it is primary button, we will report
* it as BTN_LEFT.
*/
hw->left = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
} else if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
if (hw->w == 2) if (hw->w == 2)
hw->scroll = (signed char)(buf[1]); hw->scroll = (signed char)(buf[1]);
...@@ -593,6 +612,12 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) ...@@ -593,6 +612,12 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
dev->absres[ABS_X] = priv->x_res; dev->absres[ABS_X] = priv->x_res;
dev->absres[ABS_Y] = priv->y_res; dev->absres[ABS_Y] = priv->y_res;
if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
/* Clickpads report only left button */
__clear_bit(BTN_RIGHT, dev->keybit);
__clear_bit(BTN_MIDDLE, dev->keybit);
}
} }
static void synaptics_disconnect(struct psmouse *psmouse) static void synaptics_disconnect(struct psmouse *psmouse)
...@@ -697,10 +722,10 @@ int synaptics_init(struct psmouse *psmouse) ...@@ -697,10 +722,10 @@ int synaptics_init(struct psmouse *psmouse)
priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx\n", printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n",
SYN_ID_MODEL(priv->identity), SYN_ID_MODEL(priv->identity),
SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
priv->model_id, priv->capabilities, priv->ext_cap); priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c);
set_input_params(psmouse->dev, priv); set_input_params(psmouse->dev, priv);
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07 #define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07
#define SYN_QUE_RESOLUTION 0x08 #define SYN_QUE_RESOLUTION 0x08
#define SYN_QUE_EXT_CAPAB 0x09 #define SYN_QUE_EXT_CAPAB 0x09
#define SYN_QUE_EXT_CAPAB_0C 0x0c
/* synatics modes */ /* synatics modes */
#define SYN_BIT_ABSOLUTE_MODE (1 << 7) #define SYN_BIT_ABSOLUTE_MODE (1 << 7)
...@@ -48,6 +49,8 @@ ...@@ -48,6 +49,8 @@
#define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47) #define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47)
#define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20)
#define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12)
#define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16)
#define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100100)
/* synaptics modes query bits */ /* synaptics modes query bits */
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
...@@ -96,6 +99,7 @@ struct synaptics_data { ...@@ -96,6 +99,7 @@ struct synaptics_data {
unsigned long int model_id; /* Model-ID */ unsigned long int model_id; /* Model-ID */
unsigned long int capabilities; /* Capabilities */ unsigned long int capabilities; /* Capabilities */
unsigned long int ext_cap; /* Extended Capabilities */ unsigned long int ext_cap; /* Extended Capabilities */
unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */
unsigned long int identity; /* Identification */ unsigned long int identity; /* Identification */
int x_res; /* X resolution in units/mm */ int x_res; /* X resolution in units/mm */
int y_res; /* Y resolution in units/mm */ int y_res; /* Y resolution in units/mm */
......
...@@ -124,14 +124,25 @@ static irqreturn_t eeti_ts_isr(int irq, void *dev_id) ...@@ -124,14 +124,25 @@ static irqreturn_t eeti_ts_isr(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int eeti_ts_open(struct input_dev *dev) static void eeti_ts_start(struct eeti_ts_priv *priv)
{ {
struct eeti_ts_priv *priv = input_get_drvdata(dev);
enable_irq(priv->irq); enable_irq(priv->irq);
/* Read the events once to arm the IRQ */ /* Read the events once to arm the IRQ */
eeti_ts_read(&priv->work); eeti_ts_read(&priv->work);
}
static void eeti_ts_stop(struct eeti_ts_priv *priv)
{
disable_irq(priv->irq);
cancel_work_sync(&priv->work);
}
static int eeti_ts_open(struct input_dev *dev)
{
struct eeti_ts_priv *priv = input_get_drvdata(dev);
eeti_ts_start(priv);
return 0; return 0;
} }
...@@ -140,8 +151,7 @@ static void eeti_ts_close(struct input_dev *dev) ...@@ -140,8 +151,7 @@ static void eeti_ts_close(struct input_dev *dev)
{ {
struct eeti_ts_priv *priv = input_get_drvdata(dev); struct eeti_ts_priv *priv = input_get_drvdata(dev);
disable_irq(priv->irq); eeti_ts_stop(priv);
cancel_work_sync(&priv->work);
} }
static int __devinit eeti_ts_probe(struct i2c_client *client, static int __devinit eeti_ts_probe(struct i2c_client *client,
...@@ -153,10 +163,12 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, ...@@ -153,10 +163,12 @@ static int __devinit eeti_ts_probe(struct i2c_client *client,
unsigned int irq_flags; unsigned int irq_flags;
int err = -ENOMEM; int err = -ENOMEM;
/* In contrast to what's described in the datasheet, there seems /*
* In contrast to what's described in the datasheet, there seems
* to be no way of probing the presence of that device using I2C * to be no way of probing the presence of that device using I2C
* commands. So we need to blindly believe it is there, and wait * commands. So we need to blindly believe it is there, and wait
* for interrupts to occur. */ * for interrupts to occur.
*/
priv = kzalloc(sizeof(*priv), GFP_KERNEL); priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) { if (!priv) {
...@@ -212,9 +224,11 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, ...@@ -212,9 +224,11 @@ static int __devinit eeti_ts_probe(struct i2c_client *client,
goto err2; goto err2;
} }
/* Disable the irq for now. It will be enabled once the input device /*
* is opened. */ * Disable the device for now. It will be enabled once the
disable_irq(priv->irq); * input device is opened.
*/
eeti_ts_stop(priv);
device_init_wakeup(&client->dev, 0); device_init_wakeup(&client->dev, 0);
return 0; return 0;
...@@ -235,6 +249,12 @@ static int __devexit eeti_ts_remove(struct i2c_client *client) ...@@ -235,6 +249,12 @@ static int __devexit eeti_ts_remove(struct i2c_client *client)
struct eeti_ts_priv *priv = i2c_get_clientdata(client); struct eeti_ts_priv *priv = i2c_get_clientdata(client);
free_irq(priv->irq, priv); free_irq(priv->irq, priv);
/*
* eeti_ts_stop() leaves IRQ disabled. We need to re-enable it
* so that device still works if we reload the driver.
*/
enable_irq(priv->irq);
input_unregister_device(priv->input); input_unregister_device(priv->input);
i2c_set_clientdata(client, NULL); i2c_set_clientdata(client, NULL);
kfree(priv); kfree(priv);
...@@ -246,6 +266,14 @@ static int __devexit eeti_ts_remove(struct i2c_client *client) ...@@ -246,6 +266,14 @@ static int __devexit eeti_ts_remove(struct i2c_client *client)
static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg) static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg)
{ {
struct eeti_ts_priv *priv = i2c_get_clientdata(client); struct eeti_ts_priv *priv = i2c_get_clientdata(client);
struct input_dev *input_dev = priv->input;
mutex_lock(&input_dev->mutex);
if (input_dev->users)
eeti_ts_stop(priv);
mutex_unlock(&input_dev->mutex);
if (device_may_wakeup(&client->dev)) if (device_may_wakeup(&client->dev))
enable_irq_wake(priv->irq); enable_irq_wake(priv->irq);
...@@ -256,10 +284,18 @@ static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg) ...@@ -256,10 +284,18 @@ static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg)
static int eeti_ts_resume(struct i2c_client *client) static int eeti_ts_resume(struct i2c_client *client)
{ {
struct eeti_ts_priv *priv = i2c_get_clientdata(client); struct eeti_ts_priv *priv = i2c_get_clientdata(client);
struct input_dev *input_dev = priv->input;
if (device_may_wakeup(&client->dev)) if (device_may_wakeup(&client->dev))
disable_irq_wake(priv->irq); disable_irq_wake(priv->irq);
mutex_lock(&input_dev->mutex);
if (input_dev->users)
eeti_ts_start(priv);
mutex_unlock(&input_dev->mutex);
return 0; return 0;
} }
#else #else
......
...@@ -311,11 +311,6 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget) ...@@ -311,11 +311,6 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget)
processed++; processed++;
} }
if (processed) {
wrw(ep, REG_RXDENQ, processed);
wrw(ep, REG_RXSTSENQ, processed);
}
return processed; return processed;
} }
...@@ -350,6 +345,11 @@ static int ep93xx_poll(struct napi_struct *napi, int budget) ...@@ -350,6 +345,11 @@ static int ep93xx_poll(struct napi_struct *napi, int budget)
goto poll_some_more; goto poll_some_more;
} }
if (rx) {
wrw(ep, REG_RXDENQ, rx);
wrw(ep, REG_RXSTSENQ, rx);
}
return rx; return rx;
} }
......
...@@ -4633,6 +4633,9 @@ static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) ...@@ -4633,6 +4633,9 @@ static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
reg16 &= ~state; reg16 &= ~state;
pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
if (!pdev->bus->self)
return;
pos = pci_pcie_cap(pdev->bus->self); pos = pci_pcie_cap(pdev->bus->self);
pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, &reg16); pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, &reg16);
reg16 &= ~state; reg16 &= ~state;
......
...@@ -1653,7 +1653,7 @@ fec_set_mac_address(struct net_device *dev, void *p) ...@@ -1653,7 +1653,7 @@ fec_set_mac_address(struct net_device *dev, void *p)
(dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24), (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24),
fep->hwp + FEC_ADDR_LOW); fep->hwp + FEC_ADDR_LOW);
writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24), writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24),
fep + FEC_ADDR_HIGH); fep->hwp + FEC_ADDR_HIGH);
return 0; return 0;
} }
......
...@@ -88,6 +88,11 @@ config LSI_ET1011C_PHY ...@@ -88,6 +88,11 @@ config LSI_ET1011C_PHY
---help--- ---help---
Supports the LSI ET1011C PHY. Supports the LSI ET1011C PHY.
config MICREL_PHY
tristate "Driver for Micrel PHYs"
---help---
Supports the KSZ9021, VSC8201, KS8001 PHYs.
config FIXED_PHY config FIXED_PHY
bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
depends on PHYLIB=y depends on PHYLIB=y
......
...@@ -20,4 +20,5 @@ obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o ...@@ -20,4 +20,5 @@ obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
obj-$(CONFIG_NATIONAL_PHY) += national.o obj-$(CONFIG_NATIONAL_PHY) += national.o
obj-$(CONFIG_STE10XP) += ste10Xp.o obj-$(CONFIG_STE10XP) += ste10Xp.o
obj-$(CONFIG_MICREL_PHY) += micrel.o
obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
/*
* drivers/net/phy/micrel.c
*
* Driver for Micrel PHYs
*
* Author: David J. Choi
*
* Copyright (c) 2010 Micrel, 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
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* Support : ksz9021 , vsc8201, ks8001
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/phy.h>
#define PHY_ID_KSZ9021 0x00221611
#define PHY_ID_VSC8201 0x000FC413
#define PHY_ID_KS8001 0x0022161A
static int kszphy_config_init(struct phy_device *phydev)
{
return 0;
}
static struct phy_driver ks8001_driver = {
.phy_id = PHY_ID_KS8001,
.phy_id_mask = 0x00fffff0,
.features = PHY_BASIC_FEATURES,
.flags = PHY_POLL,
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
.driver = { .owner = THIS_MODULE,},
};
static struct phy_driver vsc8201_driver = {
.phy_id = PHY_ID_VSC8201,
.name = "Micrel VSC8201",
.phy_id_mask = 0x00fffff0,
.features = PHY_BASIC_FEATURES,
.flags = PHY_POLL,
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
.driver = { .owner = THIS_MODULE,},
};
static struct phy_driver ksz9021_driver = {
.phy_id = PHY_ID_KSZ9021,
.phy_id_mask = 0x000fff10,
.name = "Micrel KSZ9021 Gigabit PHY",
.features = PHY_GBIT_FEATURES | SUPPORTED_Pause,
.flags = PHY_POLL,
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
.driver = { .owner = THIS_MODULE, },
};
static int __init ksphy_init(void)
{
int ret;
ret = phy_driver_register(&ks8001_driver);
if (ret)
goto err1;
ret = phy_driver_register(&vsc8201_driver);
if (ret)
goto err2;
ret = phy_driver_register(&ksz9021_driver);
if (ret)
goto err3;
return 0;
err3:
phy_driver_unregister(&vsc8201_driver);
err2:
phy_driver_unregister(&ks8001_driver);
err1:
return ret;
}
static void __exit ksphy_exit(void)
{
phy_driver_unregister(&ks8001_driver);
phy_driver_unregister(&vsc8201_driver);
phy_driver_unregister(&ksz9021_driver);
}
module_init(ksphy_init);
module_exit(ksphy_exit);
MODULE_DESCRIPTION("Micrel PHY driver");
MODULE_AUTHOR("David J. Choi");
MODULE_LICENSE("GPL");
...@@ -405,6 +405,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf, ...@@ -405,6 +405,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf,
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
ssize_t ret; ssize_t ret;
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
struct iovec iov;
ret = count; ret = count;
...@@ -448,7 +449,9 @@ static ssize_t ppp_read(struct file *file, char __user *buf, ...@@ -448,7 +449,9 @@ static ssize_t ppp_read(struct file *file, char __user *buf,
if (skb->len > count) if (skb->len > count)
goto outf; goto outf;
ret = -EFAULT; ret = -EFAULT;
if (copy_to_user(buf, skb->data, skb->len)) iov.iov_base = buf;
iov.iov_len = count;
if (skb_copy_datagram_iovec(skb, 0, &iov, skb->len))
goto outf; goto outf;
ret = skb->len; ret = skb->len;
...@@ -1567,13 +1570,22 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb) ...@@ -1567,13 +1570,22 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
struct channel *pch = chan->ppp; struct channel *pch = chan->ppp;
int proto; int proto;
if (!pch || skb->len == 0) { if (!pch) {
kfree_skb(skb); kfree_skb(skb);
return; return;
} }
proto = PPP_PROTO(skb);
read_lock_bh(&pch->upl); read_lock_bh(&pch->upl);
if (!pskb_may_pull(skb, 2)) {
kfree_skb(skb);
if (pch->ppp) {
++pch->ppp->dev->stats.rx_length_errors;
ppp_receive_error(pch->ppp);
}
goto done;
}
proto = PPP_PROTO(skb);
if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) { if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) {
/* put it on the channel queue */ /* put it on the channel queue */
skb_queue_tail(&pch->file.rq, skb); skb_queue_tail(&pch->file.rq, skb);
...@@ -1585,6 +1597,8 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb) ...@@ -1585,6 +1597,8 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
} else { } else {
ppp_do_recv(pch->ppp, skb, pch); ppp_do_recv(pch->ppp, skb, pch);
} }
done:
read_unlock_bh(&pch->upl); read_unlock_bh(&pch->upl);
} }
...@@ -1617,7 +1631,8 @@ ppp_input_error(struct ppp_channel *chan, int code) ...@@ -1617,7 +1631,8 @@ ppp_input_error(struct ppp_channel *chan, int code)
static void static void
ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
{ {
if (pskb_may_pull(skb, 2)) { /* note: a 0-length skb is used as an error indication */
if (skb->len > 0) {
#ifdef CONFIG_PPP_MULTILINK #ifdef CONFIG_PPP_MULTILINK
/* XXX do channel-level decompression here */ /* XXX do channel-level decompression here */
if (PPP_PROTO(skb) == PPP_MP) if (PPP_PROTO(skb) == PPP_MP)
...@@ -1625,15 +1640,10 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) ...@@ -1625,15 +1640,10 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
else else
#endif /* CONFIG_PPP_MULTILINK */ #endif /* CONFIG_PPP_MULTILINK */
ppp_receive_nonmp_frame(ppp, skb); ppp_receive_nonmp_frame(ppp, skb);
return; } else {
kfree_skb(skb);
ppp_receive_error(ppp);
} }
if (skb->len > 0)
/* note: a 0-length skb is used as an error indication */
++ppp->dev->stats.rx_length_errors;
kfree_skb(skb);
ppp_receive_error(ppp);
} }
static void static void
......
...@@ -1042,14 +1042,14 @@ static void rtl8169_vlan_rx_register(struct net_device *dev, ...@@ -1042,14 +1042,14 @@ static void rtl8169_vlan_rx_register(struct net_device *dev,
} }
static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
struct sk_buff *skb) struct sk_buff *skb, int polling)
{ {
u32 opts2 = le32_to_cpu(desc->opts2); u32 opts2 = le32_to_cpu(desc->opts2);
struct vlan_group *vlgrp = tp->vlgrp; struct vlan_group *vlgrp = tp->vlgrp;
int ret; int ret;
if (vlgrp && (opts2 & RxVlanTag)) { if (vlgrp && (opts2 & RxVlanTag)) {
vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); __vlan_hwaccel_rx(skb, vlgrp, swab16(opts2 & 0xffff), polling);
ret = 0; ret = 0;
} else } else
ret = -1; ret = -1;
...@@ -1066,7 +1066,7 @@ static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, ...@@ -1066,7 +1066,7 @@ static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
} }
static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
struct sk_buff *skb) struct sk_buff *skb, int polling)
{ {
return -1; return -1;
} }
...@@ -4445,12 +4445,20 @@ static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff, ...@@ -4445,12 +4445,20 @@ static inline bool rtl8169_try_rx_copy(struct sk_buff **sk_buff,
return done; return done;
} }
/*
* Warning : rtl8169_rx_interrupt() might be called :
* 1) from NAPI (softirq) context
* (polling = 1 : we should call netif_receive_skb())
* 2) from process context (rtl8169_reset_task())
* (polling = 0 : we must call netif_rx() instead)
*/
static int rtl8169_rx_interrupt(struct net_device *dev, static int rtl8169_rx_interrupt(struct net_device *dev,
struct rtl8169_private *tp, struct rtl8169_private *tp,
void __iomem *ioaddr, u32 budget) void __iomem *ioaddr, u32 budget)
{ {
unsigned int cur_rx, rx_left; unsigned int cur_rx, rx_left;
unsigned int delta, count; unsigned int delta, count;
int polling = (budget != ~(u32)0) ? 1 : 0;
cur_rx = tp->cur_rx; cur_rx = tp->cur_rx;
rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
...@@ -4512,8 +4520,12 @@ static int rtl8169_rx_interrupt(struct net_device *dev, ...@@ -4512,8 +4520,12 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
skb_put(skb, pkt_size); skb_put(skb, pkt_size);
skb->protocol = eth_type_trans(skb, dev); skb->protocol = eth_type_trans(skb, dev);
if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) {
netif_receive_skb(skb); if (likely(polling))
netif_receive_skb(skb);
else
netif_rx(skb);
}
dev->stats.rx_bytes += pkt_size; dev->stats.rx_bytes += pkt_size;
dev->stats.rx_packets++; dev->stats.rx_packets++;
......
...@@ -2353,17 +2353,36 @@ static int sbmac_init(struct platform_device *pldev, long long base) ...@@ -2353,17 +2353,36 @@ static int sbmac_init(struct platform_device *pldev, long long base)
sc->mii_bus = mdiobus_alloc(); sc->mii_bus = mdiobus_alloc();
if (sc->mii_bus == NULL) { if (sc->mii_bus == NULL) {
sbmac_uninitctx(sc); err = -ENOMEM;
return -ENOMEM; goto uninit_ctx;
} }
sc->mii_bus->name = sbmac_mdio_string;
snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx);
sc->mii_bus->priv = sc;
sc->mii_bus->read = sbmac_mii_read;
sc->mii_bus->write = sbmac_mii_write;
sc->mii_bus->irq = sc->phy_irq;
for (i = 0; i < PHY_MAX_ADDR; ++i)
sc->mii_bus->irq[i] = SBMAC_PHY_INT;
sc->mii_bus->parent = &pldev->dev;
/*
* Probe PHY address
*/
err = mdiobus_register(sc->mii_bus);
if (err) {
printk(KERN_ERR "%s: unable to register MDIO bus\n",
dev->name);
goto free_mdio;
}
dev_set_drvdata(&pldev->dev, sc->mii_bus);
err = register_netdev(dev); err = register_netdev(dev);
if (err) { if (err) {
printk(KERN_ERR "%s.%d: unable to register netdev\n", printk(KERN_ERR "%s.%d: unable to register netdev\n",
sbmac_string, idx); sbmac_string, idx);
mdiobus_free(sc->mii_bus); goto unreg_mdio;
sbmac_uninitctx(sc);
return err;
} }
pr_info("%s.%d: registered as %s\n", sbmac_string, idx, dev->name); pr_info("%s.%d: registered as %s\n", sbmac_string, idx, dev->name);
...@@ -2379,19 +2398,15 @@ static int sbmac_init(struct platform_device *pldev, long long base) ...@@ -2379,19 +2398,15 @@ static int sbmac_init(struct platform_device *pldev, long long base)
pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %pM\n", pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %pM\n",
dev->name, base, eaddr); dev->name, base, eaddr);
sc->mii_bus->name = sbmac_mdio_string;
snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx);
sc->mii_bus->priv = sc;
sc->mii_bus->read = sbmac_mii_read;
sc->mii_bus->write = sbmac_mii_write;
sc->mii_bus->irq = sc->phy_irq;
for (i = 0; i < PHY_MAX_ADDR; ++i)
sc->mii_bus->irq[i] = SBMAC_PHY_INT;
sc->mii_bus->parent = &pldev->dev;
dev_set_drvdata(&pldev->dev, sc->mii_bus);
return 0; return 0;
unreg_mdio:
mdiobus_unregister(sc->mii_bus);
dev_set_drvdata(&pldev->dev, NULL);
free_mdio:
mdiobus_free(sc->mii_bus);
uninit_ctx:
sbmac_uninitctx(sc);
return err;
} }
...@@ -2417,16 +2432,6 @@ static int sbmac_open(struct net_device *dev) ...@@ -2417,16 +2432,6 @@ static int sbmac_open(struct net_device *dev)
goto out_err; goto out_err;
} }
/*
* Probe PHY address
*/
err = mdiobus_register(sc->mii_bus);
if (err) {
printk(KERN_ERR "%s: unable to register MDIO bus\n",
dev->name);
goto out_unirq;
}
sc->sbm_speed = sbmac_speed_none; sc->sbm_speed = sbmac_speed_none;
sc->sbm_duplex = sbmac_duplex_none; sc->sbm_duplex = sbmac_duplex_none;
sc->sbm_fc = sbmac_fc_none; sc->sbm_fc = sbmac_fc_none;
...@@ -2457,11 +2462,7 @@ static int sbmac_open(struct net_device *dev) ...@@ -2457,11 +2462,7 @@ static int sbmac_open(struct net_device *dev)
return 0; return 0;
out_unregister: out_unregister:
mdiobus_unregister(sc->mii_bus);
out_unirq:
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
out_err: out_err:
return err; return err;
} }
...@@ -2650,9 +2651,6 @@ static int sbmac_close(struct net_device *dev) ...@@ -2650,9 +2651,6 @@ static int sbmac_close(struct net_device *dev)
phy_disconnect(sc->phy_dev); phy_disconnect(sc->phy_dev);
sc->phy_dev = NULL; sc->phy_dev = NULL;
mdiobus_unregister(sc->mii_bus);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
sbdma_emptyring(&(sc->sbm_txdma)); sbdma_emptyring(&(sc->sbm_txdma));
...@@ -2760,6 +2758,7 @@ static int __exit sbmac_remove(struct platform_device *pldev) ...@@ -2760,6 +2758,7 @@ static int __exit sbmac_remove(struct platform_device *pldev)
unregister_netdev(dev); unregister_netdev(dev);
sbmac_uninitctx(sc); sbmac_uninitctx(sc);
mdiobus_unregister(sc->mii_bus);
mdiobus_free(sc->mii_bus); mdiobus_free(sc->mii_bus);
iounmap(sc->sbm_base); iounmap(sc->sbm_base);
free_netdev(dev); free_netdev(dev);
......
...@@ -400,7 +400,6 @@ config USB_IPHETH ...@@ -400,7 +400,6 @@ config USB_IPHETH
config USB_SIERRA_NET config USB_SIERRA_NET
tristate "USB-to-WWAN Driver for Sierra Wireless modems" tristate "USB-to-WWAN Driver for Sierra Wireless modems"
depends on USB_USBNET depends on USB_USBNET
default y
help help
Choose this option if you have a Sierra Wireless USB-to-WWAN device. Choose this option if you have a Sierra Wireless USB-to-WWAN device.
......
...@@ -240,7 +240,7 @@ static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 valu ...@@ -240,7 +240,7 @@ static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 valu
goto out; goto out;
dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg); dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg);
dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1c : 0x14); dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1a : 0x12);
for (i = 0; i < DM_TIMEOUT; i++) { for (i = 0; i < DM_TIMEOUT; i++) {
u8 tmp; u8 tmp;
......
...@@ -789,6 +789,9 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) ...@@ -789,6 +789,9 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
/* prepare sync message from template */ /* prepare sync message from template */
memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg)); memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg));
/* initiate the sync sequence */
sierra_net_dosync(dev);
return 0; return 0;
} }
......
...@@ -246,7 +246,7 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, ...@@ -246,7 +246,7 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
u32 idx, i; u32 idx, i;
i = (*index) % ring_limit; i = (*index) % ring_limit;
(*index) = idx = le32_to_cpu(ring_control->device_idx[1]); (*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]);
idx %= ring_limit; idx %= ring_limit;
while (i != idx) { while (i != idx) {
......
...@@ -778,6 +778,7 @@ int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len, ...@@ -778,6 +778,7 @@ int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len,
struct iovec *data); struct iovec *data);
void sctp_chunk_free(struct sctp_chunk *); void sctp_chunk_free(struct sctp_chunk *);
void *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data); void *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data);
void *sctp_addto_chunk_fixed(struct sctp_chunk *, int len, const void *data);
struct sctp_chunk *sctp_chunkify(struct sk_buff *, struct sctp_chunk *sctp_chunkify(struct sk_buff *,
const struct sctp_association *, const struct sctp_association *,
struct sock *); struct sock *);
......
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
printk(KERN_DEBUG msg); } while (0) printk(KERN_DEBUG msg); } while (0)
#else #else
/* Validate arguments and do nothing */ /* Validate arguments and do nothing */
static void inline int __attribute__ ((format (printf, 2, 3))) static inline void __attribute__ ((format (printf, 2, 3)))
SOCK_DEBUG(struct sock *sk, const char *msg, ...) SOCK_DEBUG(struct sock *sk, const char *msg, ...)
{ {
} }
......
...@@ -774,7 +774,7 @@ void flush_delayed_work(struct delayed_work *dwork) ...@@ -774,7 +774,7 @@ void flush_delayed_work(struct delayed_work *dwork)
{ {
if (del_timer_sync(&dwork->timer)) { if (del_timer_sync(&dwork->timer)) {
struct cpu_workqueue_struct *cwq; struct cpu_workqueue_struct *cwq;
cwq = wq_per_cpu(keventd_wq, get_cpu()); cwq = wq_per_cpu(get_wq_data(&dwork->work)->wq, get_cpu());
__queue_work(cwq, &dwork->work); __queue_work(cwq, &dwork->work);
put_cpu(); put_cpu();
} }
......
...@@ -2153,7 +2153,7 @@ static int init_kmem_cache_nodes(struct kmem_cache *s, gfp_t gfpflags) ...@@ -2153,7 +2153,7 @@ static int init_kmem_cache_nodes(struct kmem_cache *s, gfp_t gfpflags)
int local_node; int local_node;
if (slab_state >= UP && (s < kmalloc_caches || if (slab_state >= UP && (s < kmalloc_caches ||
s > kmalloc_caches + KMALLOC_CACHES)) s >= kmalloc_caches + KMALLOC_CACHES))
local_node = page_to_nid(virt_to_page(s)); local_node = page_to_nid(virt_to_page(s));
else else
local_node = 0; local_node = 0;
......
...@@ -200,7 +200,7 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol, ...@@ -200,7 +200,7 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
inet_sk(sk)->pinet6 = np = inet6_sk_generic(sk); inet_sk(sk)->pinet6 = np = inet6_sk_generic(sk);
np->hop_limit = -1; np->hop_limit = -1;
np->mcast_hops = -1; np->mcast_hops = IPV6_DEFAULT_MCASTHOPS;
np->mc_loop = 1; np->mc_loop = 1;
np->pmtudisc = IPV6_PMTUDISC_WANT; np->pmtudisc = IPV6_PMTUDISC_WANT;
np->ipv6only = net->ipv6.sysctl.bindv6only; np->ipv6only = net->ipv6.sysctl.bindv6only;
......
...@@ -108,7 +108,7 @@ static const struct sctp_paramhdr prsctp_param = { ...@@ -108,7 +108,7 @@ static const struct sctp_paramhdr prsctp_param = {
cpu_to_be16(sizeof(struct sctp_paramhdr)), cpu_to_be16(sizeof(struct sctp_paramhdr)),
}; };
/* A helper to initialize to initialize an op error inside a /* A helper to initialize an op error inside a
* provided chunk, as most cause codes will be embedded inside an * provided chunk, as most cause codes will be embedded inside an
* abort chunk. * abort chunk.
*/ */
...@@ -125,6 +125,29 @@ void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code, ...@@ -125,6 +125,29 @@ void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err); chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);
} }
/* A helper to initialize an op error inside a
* provided chunk, as most cause codes will be embedded inside an
* abort chunk. Differs from sctp_init_cause in that it won't oops
* if there isn't enough space in the op error chunk
*/
int sctp_init_cause_fixed(struct sctp_chunk *chunk, __be16 cause_code,
size_t paylen)
{
sctp_errhdr_t err;
__u16 len;
/* Cause code constants are now defined in network order. */
err.cause = cause_code;
len = sizeof(sctp_errhdr_t) + paylen;
err.length = htons(len);
if (skb_tailroom(chunk->skb) > len)
return -ENOSPC;
chunk->subh.err_hdr = sctp_addto_chunk_fixed(chunk,
sizeof(sctp_errhdr_t),
&err);
return 0;
}
/* 3.3.2 Initiation (INIT) (1) /* 3.3.2 Initiation (INIT) (1)
* *
* This chunk is used to initiate a SCTP association between two * This chunk is used to initiate a SCTP association between two
...@@ -1132,6 +1155,24 @@ static struct sctp_chunk *sctp_make_op_error_space( ...@@ -1132,6 +1155,24 @@ static struct sctp_chunk *sctp_make_op_error_space(
return retval; return retval;
} }
/* Create an Operation Error chunk of a fixed size,
* specifically, max(asoc->pathmtu, SCTP_DEFAULT_MAXSEGMENT)
* This is a helper function to allocate an error chunk for
* for those invalid parameter codes in which we may not want
* to report all the errors, if the incomming chunk is large
*/
static inline struct sctp_chunk *sctp_make_op_error_fixed(
const struct sctp_association *asoc,
const struct sctp_chunk *chunk)
{
size_t size = asoc ? asoc->pathmtu : 0;
if (!size)
size = SCTP_DEFAULT_MAXSEGMENT;
return sctp_make_op_error_space(asoc, chunk, size);
}
/* Create an Operation Error chunk. */ /* Create an Operation Error chunk. */
struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc, struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
const struct sctp_chunk *chunk, const struct sctp_chunk *chunk,
...@@ -1374,6 +1415,18 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data) ...@@ -1374,6 +1415,18 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data)
return target; return target;
} }
/* Append bytes to the end of a chunk. Returns NULL if there isn't sufficient
* space in the chunk
*/
void *sctp_addto_chunk_fixed(struct sctp_chunk *chunk,
int len, const void *data)
{
if (skb_tailroom(chunk->skb) > len)
return sctp_addto_chunk(chunk, len, data);
else
return NULL;
}
/* Append bytes from user space to the end of a chunk. Will panic if /* Append bytes from user space to the end of a chunk. Will panic if
* chunk is not big enough. * chunk is not big enough.
* Returns a kernel err value. * Returns a kernel err value.
...@@ -1977,13 +2030,12 @@ static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc, ...@@ -1977,13 +2030,12 @@ static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc,
* returning multiple unknown parameters. * returning multiple unknown parameters.
*/ */
if (NULL == *errp) if (NULL == *errp)
*errp = sctp_make_op_error_space(asoc, chunk, *errp = sctp_make_op_error_fixed(asoc, chunk);
ntohs(chunk->chunk_hdr->length));
if (*errp) { if (*errp) {
sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, sctp_init_cause_fixed(*errp, SCTP_ERROR_UNKNOWN_PARAM,
WORD_ROUND(ntohs(param.p->length))); WORD_ROUND(ntohs(param.p->length)));
sctp_addto_chunk(*errp, sctp_addto_chunk_fixed(*errp,
WORD_ROUND(ntohs(param.p->length)), WORD_ROUND(ntohs(param.p->length)),
param.v); param.v);
} else { } else {
......
...@@ -20,6 +20,11 @@ ...@@ -20,6 +20,11 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include "internal.h" #include "internal.h"
#define rcu_dereference_locked_keyring(keyring) \
(rcu_dereference_protected( \
(keyring)->payload.subscriptions, \
rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem)))
/* /*
* when plumbing the depths of the key tree, this sets a hard limit set on how * when plumbing the depths of the key tree, this sets a hard limit set on how
* deep we're willing to go * deep we're willing to go
...@@ -199,8 +204,7 @@ static long keyring_read(const struct key *keyring, ...@@ -199,8 +204,7 @@ static long keyring_read(const struct key *keyring,
int loop, ret; int loop, ret;
ret = 0; ret = 0;
klist = keyring->payload.subscriptions; klist = rcu_dereference_locked_keyring(keyring);
if (klist) { if (klist) {
/* calculate how much data we could return */ /* calculate how much data we could return */
qty = klist->nkeys * sizeof(key_serial_t); qty = klist->nkeys * sizeof(key_serial_t);
...@@ -524,9 +528,8 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check) ...@@ -524,9 +528,8 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
struct key *keyring; struct key *keyring;
int bucket; int bucket;
keyring = ERR_PTR(-EINVAL);
if (!name) if (!name)
goto error; return ERR_PTR(-EINVAL);
bucket = keyring_hash(name); bucket = keyring_hash(name);
...@@ -553,17 +556,18 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check) ...@@ -553,17 +556,18 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
KEY_SEARCH) < 0) KEY_SEARCH) < 0)
continue; continue;
/* we've got a match */ /* we've got a match but we might end up racing with
atomic_inc(&keyring->usage); * key_cleanup() if the keyring is currently 'dead'
read_unlock(&keyring_name_lock); * (ie. it has a zero usage count) */
goto error; if (!atomic_inc_not_zero(&keyring->usage))
continue;
goto out;
} }
} }
read_unlock(&keyring_name_lock);
keyring = ERR_PTR(-ENOKEY); keyring = ERR_PTR(-ENOKEY);
out:
error: read_unlock(&keyring_name_lock);
return keyring; return keyring;
} /* end find_keyring_by_name() */ } /* end find_keyring_by_name() */
...@@ -719,8 +723,7 @@ int __key_link(struct key *keyring, struct key *key) ...@@ -719,8 +723,7 @@ int __key_link(struct key *keyring, struct key *key)
} }
/* see if there's a matching key we can displace */ /* see if there's a matching key we can displace */
klist = keyring->payload.subscriptions; klist = rcu_dereference_locked_keyring(keyring);
if (klist && klist->nkeys > 0) { if (klist && klist->nkeys > 0) {
struct key_type *type = key->type; struct key_type *type = key->type;
...@@ -764,8 +767,6 @@ int __key_link(struct key *keyring, struct key *key) ...@@ -764,8 +767,6 @@ int __key_link(struct key *keyring, struct key *key)
if (ret < 0) if (ret < 0)
goto error2; goto error2;
klist = keyring->payload.subscriptions;
if (klist && klist->nkeys < klist->maxkeys) { if (klist && klist->nkeys < klist->maxkeys) {
/* there's sufficient slack space to add directly */ /* there's sufficient slack space to add directly */
atomic_inc(&key->usage); atomic_inc(&key->usage);
...@@ -867,7 +868,7 @@ int key_unlink(struct key *keyring, struct key *key) ...@@ -867,7 +868,7 @@ int key_unlink(struct key *keyring, struct key *key)
down_write(&keyring->sem); down_write(&keyring->sem);
klist = keyring->payload.subscriptions; klist = rcu_dereference_locked_keyring(keyring);
if (klist) { if (klist) {
/* search the keyring for the key */ /* search the keyring for the key */
for (loop = 0; loop < klist->nkeys; loop++) for (loop = 0; loop < klist->nkeys; loop++)
...@@ -958,7 +959,7 @@ int keyring_clear(struct key *keyring) ...@@ -958,7 +959,7 @@ int keyring_clear(struct key *keyring)
/* detach the pointer block with the locks held */ /* detach the pointer block with the locks held */
down_write(&keyring->sem); down_write(&keyring->sem);
klist = keyring->payload.subscriptions; klist = rcu_dereference_locked_keyring(keyring);
if (klist) { if (klist) {
/* adjust the quota */ /* adjust the quota */
key_payload_reserve(keyring, key_payload_reserve(keyring,
...@@ -990,7 +991,9 @@ EXPORT_SYMBOL(keyring_clear); ...@@ -990,7 +991,9 @@ EXPORT_SYMBOL(keyring_clear);
*/ */
static void keyring_revoke(struct key *keyring) static void keyring_revoke(struct key *keyring)
{ {
struct keyring_list *klist = keyring->payload.subscriptions; struct keyring_list *klist;
klist = rcu_dereference_locked_keyring(keyring);
/* adjust the quota */ /* adjust the quota */
key_payload_reserve(keyring, 0); key_payload_reserve(keyring, 0);
...@@ -1024,7 +1027,7 @@ void keyring_gc(struct key *keyring, time_t limit) ...@@ -1024,7 +1027,7 @@ void keyring_gc(struct key *keyring, time_t limit)
down_write(&keyring->sem); down_write(&keyring->sem);
klist = keyring->payload.subscriptions; klist = rcu_dereference_locked_keyring(keyring);
if (!klist) if (!klist)
goto no_klist; goto no_klist;
......
...@@ -94,7 +94,7 @@ static int call_sbin_request_key(struct key_construction *cons, ...@@ -94,7 +94,7 @@ static int call_sbin_request_key(struct key_construction *cons,
} }
/* attach the auth key to the session keyring */ /* attach the auth key to the session keyring */
ret = __key_link(keyring, authkey); ret = key_link(keyring, authkey);
if (ret < 0) if (ret < 0)
goto error_link; goto error_link;
......
...@@ -1160,6 +1160,7 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, ...@@ -1160,6 +1160,7 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,
{ {
struct snd_timer_user *tu = timeri->callback_data; struct snd_timer_user *tu = timeri->callback_data;
struct snd_timer_tread r1; struct snd_timer_tread r1;
unsigned long flags;
if (event >= SNDRV_TIMER_EVENT_START && if (event >= SNDRV_TIMER_EVENT_START &&
event <= SNDRV_TIMER_EVENT_PAUSE) event <= SNDRV_TIMER_EVENT_PAUSE)
...@@ -1169,9 +1170,9 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri, ...@@ -1169,9 +1170,9 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,
r1.event = event; r1.event = event;
r1.tstamp = *tstamp; r1.tstamp = *tstamp;
r1.val = resolution; r1.val = resolution;
spin_lock(&tu->qlock); spin_lock_irqsave(&tu->qlock, flags);
snd_timer_user_append_to_tqueue(tu, &r1); snd_timer_user_append_to_tqueue(tu, &r1);
spin_unlock(&tu->qlock); spin_unlock_irqrestore(&tu->qlock, flags);
kill_fasync(&tu->fasync, SIGIO, POLL_IN); kill_fasync(&tu->fasync, SIGIO, POLL_IN);
wake_up(&tu->qchange_sleep); wake_up(&tu->qchange_sleep);
} }
......
...@@ -93,7 +93,7 @@ static int __devinit snd_card_es968_pnp(int dev, struct snd_card_es968 *acard, ...@@ -93,7 +93,7 @@ static int __devinit snd_card_es968_pnp(int dev, struct snd_card_es968 *acard,
return err; return err;
} }
port[dev] = pnp_port_start(pdev, 0); port[dev] = pnp_port_start(pdev, 0);
dma8[dev] = pnp_dma(pdev, 1); dma8[dev] = pnp_dma(pdev, 0);
irq[dev] = pnp_irq(pdev, 0); irq[dev] = pnp_irq(pdev, 0);
return 0; return 0;
......
...@@ -766,7 +766,7 @@ static int build_input(struct hda_codec *codec) ...@@ -766,7 +766,7 @@ static int build_input(struct hda_codec *codec)
for (n = 0; n < AUTO_PIN_LAST; n++) { for (n = 0; n < AUTO_PIN_LAST; n++) {
if (!spec->adc_nid[n]) if (!spec->adc_nid[n])
continue; continue;
err = snd_hda_add_nid(codec, kctl, 0, spec->adc_nid[i]); err = snd_hda_add_nid(codec, kctl, 0, spec->adc_nid[n]);
if (err < 0) if (err < 0)
return err; return err;
} }
......
...@@ -1195,9 +1195,10 @@ static int patch_cxt5045(struct hda_codec *codec) ...@@ -1195,9 +1195,10 @@ static int patch_cxt5045(struct hda_codec *codec)
switch (codec->subsystem_id >> 16) { switch (codec->subsystem_id >> 16) {
case 0x103c: case 0x103c:
case 0x1631:
case 0x1734: case 0x1734:
/* HP & Fujitsu-Siemens laptops have really bad sound over 0dB /* HP, Packard Bell, & Fujitsu-Siemens laptops have really bad
* on NID 0x17. Fix max PCM level to 0 dB * sound over 0dB on NID 0x17. Fix max PCM level to 0 dB
* (originally it has 0x2b steps with 0dB offset 0x14) * (originally it has 0x2b steps with 0dB offset 0x14)
*/ */
snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
...@@ -2842,6 +2843,9 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { ...@@ -2842,6 +2843,9 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
CXT5066_DELL_LAPTOP), CXT5066_DELL_LAPTOP),
SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO),
SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5),
SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD),
{} {}
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment